mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-08 23:18:15 -05:00
Add a Generate Genesis State Command to Prysmctl (#11259)
* genesis tool * done with tool * delete old tool * no fatal * fix up * Update cmd/prysmctl/testnet/generate_genesis.go Co-authored-by: Radosław Kapka <rkapka@wp.pl> * radek feedback * more feedback * required * fix up * gaz * radek feedback Co-authored-by: Radosław Kapka <rkapka@wp.pl>
This commit is contained in:
@@ -13,6 +13,7 @@ go_library(
|
||||
deps = [
|
||||
"//cmd/prysmctl/checkpoint:go_default_library",
|
||||
"//cmd/prysmctl/p2p:go_default_library",
|
||||
"//cmd/prysmctl/testnet:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
],
|
||||
|
||||
@@ -5,6 +5,7 @@ import (
|
||||
|
||||
"github.com/prysmaticlabs/prysm/v3/cmd/prysmctl/checkpoint"
|
||||
"github.com/prysmaticlabs/prysm/v3/cmd/prysmctl/p2p"
|
||||
"github.com/prysmaticlabs/prysm/v3/cmd/prysmctl/testnet"
|
||||
log "github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
@@ -23,5 +24,6 @@ func main() {
|
||||
|
||||
func init() {
|
||||
prysmctlCommands = append(prysmctlCommands, checkpoint.Commands...)
|
||||
prysmctlCommands = append(prysmctlCommands, testnet.Commands...)
|
||||
prysmctlCommands = append(prysmctlCommands, p2p.Commands...)
|
||||
}
|
||||
|
||||
34
cmd/prysmctl/testnet/BUILD.bazel
Normal file
34
cmd/prysmctl/testnet/BUILD.bazel
Normal file
@@ -0,0 +1,34 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = [
|
||||
"generate_genesis.go",
|
||||
"testnet.go",
|
||||
],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v3/cmd/prysmctl/testnet",
|
||||
visibility = ["//visibility:public"],
|
||||
deps = [
|
||||
"//config/params:go_default_library",
|
||||
"//io/file:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/interop:go_default_library",
|
||||
"@com_github_ghodss_yaml//:go_default_library",
|
||||
"@com_github_pkg_errors//:go_default_library",
|
||||
"@com_github_prysmaticlabs_fastssz//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
"@com_github_urfave_cli_v2//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["generate_genesis_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//crypto/bls:go_default_library",
|
||||
"//runtime/interop:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
],
|
||||
)
|
||||
265
cmd/prysmctl/testnet/generate_genesis.go
Normal file
265
cmd/prysmctl/testnet/generate_genesis.go
Normal file
@@ -0,0 +1,265 @@
|
||||
package testnet
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/pkg/errors"
|
||||
fastssz "github.com/prysmaticlabs/fastssz"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/io/file"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/runtime/interop"
|
||||
"github.com/sirupsen/logrus"
|
||||
"github.com/urfave/cli/v2"
|
||||
)
|
||||
|
||||
var (
|
||||
generateGenesisStateFlags = struct {
|
||||
DepositJsonFile string
|
||||
ChainConfigFile string
|
||||
ConfigName string
|
||||
NumValidators uint64
|
||||
GenesisTime uint64
|
||||
OutputSSZ string
|
||||
OutputJSON string
|
||||
OutputYaml string
|
||||
}{}
|
||||
log = logrus.WithField("prefix", "genesis")
|
||||
outputSSZFlag = &cli.StringFlag{
|
||||
Name: "output-ssz",
|
||||
Destination: &generateGenesisStateFlags.OutputSSZ,
|
||||
Usage: "Output filename of the SSZ marshaling of the generated genesis state",
|
||||
Value: "",
|
||||
}
|
||||
outputYamlFlag = &cli.StringFlag{
|
||||
Name: "output-yaml",
|
||||
Destination: &generateGenesisStateFlags.OutputYaml,
|
||||
Usage: "Output filename of the YAML marshaling of the generated genesis state",
|
||||
Value: "",
|
||||
}
|
||||
outputJsonFlag = &cli.StringFlag{
|
||||
Name: "output-json",
|
||||
Destination: &generateGenesisStateFlags.OutputJSON,
|
||||
Usage: "Output filename of the JSON marshaling of the generated genesis state",
|
||||
Value: "",
|
||||
}
|
||||
generateGenesisStateCmd = &cli.Command{
|
||||
Name: "generate-genesis",
|
||||
Usage: "Generate a beacon chain genesis state",
|
||||
Action: cliActionGenerateGenesisState,
|
||||
Flags: []cli.Flag{
|
||||
&cli.StringFlag{
|
||||
Name: "chain-config-file",
|
||||
Destination: &generateGenesisStateFlags.ChainConfigFile,
|
||||
Usage: "The path to a YAML file with chain config values",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "deposit-json-file",
|
||||
Destination: &generateGenesisStateFlags.DepositJsonFile,
|
||||
Usage: "Path to deposit_data.json file generated by the staking-deposit-cli tool for optionally specifying validators in genesis state",
|
||||
},
|
||||
&cli.StringFlag{
|
||||
Name: "config-name",
|
||||
Usage: "Config kind to be used for generating the genesis state. Default: mainnet. Options include mainnet, interop, minimal, prater, ropsten, sepolia. --chain-config-file will override this flag.",
|
||||
Destination: &generateGenesisStateFlags.ConfigName,
|
||||
Value: params.MainnetName,
|
||||
},
|
||||
&cli.Uint64Flag{
|
||||
Name: "num-validators",
|
||||
Usage: "Number of validators to deterministically generate in the genesis state",
|
||||
Destination: &generateGenesisStateFlags.NumValidators,
|
||||
Required: true,
|
||||
},
|
||||
&cli.Uint64Flag{
|
||||
Name: "genesis-time",
|
||||
Destination: &generateGenesisStateFlags.GenesisTime,
|
||||
Usage: "Unix timestamp seconds used as the genesis time in the genesis state. If unset, defaults to now()",
|
||||
},
|
||||
outputSSZFlag,
|
||||
outputYamlFlag,
|
||||
outputJsonFlag,
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
// Represents a json object of hex string and uint64 values for
|
||||
// validators on Ethereum. This file can be generated using the official staking-deposit-cli.
|
||||
type depositDataJSON struct {
|
||||
PubKey string `json:"pubkey"`
|
||||
Amount uint64 `json:"amount"`
|
||||
WithdrawalCredentials string `json:"withdrawal_credentials"`
|
||||
DepositDataRoot string `json:"deposit_data_root"`
|
||||
Signature string `json:"signature"`
|
||||
}
|
||||
|
||||
func cliActionGenerateGenesisState(cliCtx *cli.Context) error {
|
||||
if generateGenesisStateFlags.GenesisTime == 0 {
|
||||
log.Info("No genesis time specified, defaulting to now()")
|
||||
}
|
||||
outputJson := generateGenesisStateFlags.OutputJSON
|
||||
outputYaml := generateGenesisStateFlags.OutputYaml
|
||||
outputSSZ := generateGenesisStateFlags.OutputSSZ
|
||||
noOutputFlag := outputSSZ == "" && outputJson == "" && outputYaml == ""
|
||||
if noOutputFlag {
|
||||
return fmt.Errorf(
|
||||
"no %s, %s, %s flag(s) specified. At least one is required",
|
||||
outputJsonFlag.Name,
|
||||
outputYamlFlag.Name,
|
||||
outputSSZFlag.Name,
|
||||
)
|
||||
}
|
||||
if err := setGlobalParams(); err != nil {
|
||||
return fmt.Errorf("could not set config params: %v", err)
|
||||
}
|
||||
genesisState, err := generateGenesis(cliCtx.Context)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not generate genesis state: %v", err)
|
||||
}
|
||||
if outputJson != "" {
|
||||
if err := writeToOutputFile(outputJson, genesisState, json.Marshal); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if outputYaml != "" {
|
||||
if err := writeToOutputFile(outputJson, genesisState, yaml.Marshal); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if outputSSZ != "" {
|
||||
marshalFn := func(o interface{}) ([]byte, error) {
|
||||
marshaler, ok := o.(fastssz.Marshaler)
|
||||
if !ok {
|
||||
return nil, errors.New("not a marshaler")
|
||||
}
|
||||
return marshaler.MarshalSSZ()
|
||||
}
|
||||
if err := writeToOutputFile(outputSSZ, genesisState, marshalFn); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
log.Info("Command completed")
|
||||
return nil
|
||||
}
|
||||
|
||||
func setGlobalParams() error {
|
||||
chainConfigFile := generateGenesisStateFlags.ChainConfigFile
|
||||
if chainConfigFile != "" {
|
||||
log.Infof("Specified a chain config file: %s", chainConfigFile)
|
||||
return params.LoadChainConfigFile(chainConfigFile, nil)
|
||||
}
|
||||
cfg, err := params.ByName(generateGenesisStateFlags.ConfigName)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to find config using name %s: %v", generateGenesisStateFlags.ConfigName, err)
|
||||
}
|
||||
return params.SetActive(cfg.Copy())
|
||||
}
|
||||
|
||||
func generateGenesis(ctx context.Context) (*ethpb.BeaconState, error) {
|
||||
genesisTime := generateGenesisStateFlags.GenesisTime
|
||||
numValidators := generateGenesisStateFlags.NumValidators
|
||||
depositJsonFile := generateGenesisStateFlags.DepositJsonFile
|
||||
if depositJsonFile != "" {
|
||||
expanded, err := file.ExpandPath(depositJsonFile)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
inputJSON, err := os.Open(expanded) // #nosec G304
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
defer func() {
|
||||
if err := inputJSON.Close(); err != nil {
|
||||
log.WithError(err).Printf("Could not close file %s", depositJsonFile)
|
||||
}
|
||||
}()
|
||||
log.Printf("Generating genesis state from input JSON deposit data %s", depositJsonFile)
|
||||
return genesisStateFromJSONValidators(ctx, inputJSON, genesisTime)
|
||||
}
|
||||
if numValidators == 0 {
|
||||
return nil, fmt.Errorf(
|
||||
"expected --num-validators > 0 to have been provided",
|
||||
)
|
||||
}
|
||||
// If no JSON input is specified, we create the state deterministically from interop keys.
|
||||
genesisState, _, err := interop.GenerateGenesisState(ctx, genesisTime, numValidators)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return genesisState, err
|
||||
}
|
||||
|
||||
func genesisStateFromJSONValidators(ctx context.Context, r io.Reader, genesisTime uint64) (*ethpb.BeaconState, error) {
|
||||
enc, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var depositJSON []*depositDataJSON
|
||||
if err := json.Unmarshal(enc, &depositJSON); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
depositDataList := make([]*ethpb.Deposit_Data, len(depositJSON))
|
||||
depositDataRoots := make([][]byte, len(depositJSON))
|
||||
for i, val := range depositJSON {
|
||||
data, dataRootBytes, err := depositJSONToDepositData(val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
depositDataList[i] = data
|
||||
depositDataRoots[i] = dataRootBytes
|
||||
}
|
||||
beaconState, _, err := interop.GenerateGenesisStateFromDepositData(ctx, genesisTime, depositDataList, depositDataRoots)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
func depositJSONToDepositData(input *depositDataJSON) (depositData *ethpb.Deposit_Data, dataRoot []byte, err error) {
|
||||
pubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(input.PubKey, "0x"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
withdrawalbytes, err := hex.DecodeString(strings.TrimPrefix(input.WithdrawalCredentials, "0x"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
signatureBytes, err := hex.DecodeString(strings.TrimPrefix(input.Signature, "0x"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dataRootBytes, err := hex.DecodeString(strings.TrimPrefix(input.DepositDataRoot, "0x"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
depositData = ðpb.Deposit_Data{
|
||||
PublicKey: pubKeyBytes,
|
||||
WithdrawalCredentials: withdrawalbytes,
|
||||
Amount: input.Amount,
|
||||
Signature: signatureBytes,
|
||||
}
|
||||
dataRoot = dataRootBytes
|
||||
return
|
||||
}
|
||||
|
||||
func writeToOutputFile(
|
||||
fPath string,
|
||||
data interface{},
|
||||
marshalFn func(o interface{}) ([]byte, error),
|
||||
) error {
|
||||
encoded, err := marshalFn(data)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if err := file.WriteFile(fPath, encoded); err != nil {
|
||||
return err
|
||||
}
|
||||
log.Printf("Done writing genesis state to %s", fPath)
|
||||
return nil
|
||||
}
|
||||
@@ -1,7 +1,8 @@
|
||||
package main
|
||||
package testnet
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"testing"
|
||||
@@ -17,8 +18,9 @@ func Test_genesisStateFromJSONValidators(t *testing.T) {
|
||||
jsonData := createGenesisDepositData(t, numKeys)
|
||||
jsonInput, err := json.Marshal(jsonData)
|
||||
require.NoError(t, err)
|
||||
ctx := context.Background()
|
||||
genesisState, err := genesisStateFromJSONValidators(
|
||||
bytes.NewReader(jsonInput), 0, /* genesis time defaults to time.Now() */
|
||||
ctx, bytes.NewReader(jsonInput), 0, /* genesis time defaults to time.Now() */
|
||||
)
|
||||
require.NoError(t, err)
|
||||
for i, val := range genesisState.Validators {
|
||||
@@ -26,7 +28,7 @@ func Test_genesisStateFromJSONValidators(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func createGenesisDepositData(t *testing.T, numKeys int) []*DepositDataJSON {
|
||||
func createGenesisDepositData(t *testing.T, numKeys int) []*depositDataJSON {
|
||||
pubKeys := make([]bls.PublicKey, numKeys)
|
||||
privKeys := make([]bls.SecretKey, numKeys)
|
||||
for i := 0; i < numKeys; i++ {
|
||||
@@ -37,11 +39,11 @@ func createGenesisDepositData(t *testing.T, numKeys int) []*DepositDataJSON {
|
||||
}
|
||||
dataList, _, err := interop.DepositDataFromKeys(privKeys, pubKeys)
|
||||
require.NoError(t, err)
|
||||
jsonData := make([]*DepositDataJSON, numKeys)
|
||||
jsonData := make([]*depositDataJSON, numKeys)
|
||||
for i := 0; i < numKeys; i++ {
|
||||
dataRoot, err := dataList[i].HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
jsonData[i] = &DepositDataJSON{
|
||||
jsonData[i] = &depositDataJSON{
|
||||
PubKey: fmt.Sprintf("%#x", dataList[i].PublicKey),
|
||||
Amount: dataList[i].Amount,
|
||||
WithdrawalCredentials: fmt.Sprintf("%#x", dataList[i].WithdrawalCredentials),
|
||||
13
cmd/prysmctl/testnet/testnet.go
Normal file
13
cmd/prysmctl/testnet/testnet.go
Normal file
@@ -0,0 +1,13 @@
|
||||
package testnet
|
||||
|
||||
import "github.com/urfave/cli/v2"
|
||||
|
||||
var Commands = []*cli.Command{
|
||||
{
|
||||
Name: "testnet",
|
||||
Usage: "commands for dealing with Ethereum beacon chain testnets",
|
||||
Subcommands: []*cli.Command{
|
||||
generateGenesisStateCmd,
|
||||
},
|
||||
},
|
||||
}
|
||||
@@ -1,65 +0,0 @@
|
||||
load("@prysm//tools/go:def.bzl", "go_library", "go_test")
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary")
|
||||
load("@io_bazel_rules_docker//go:image.bzl", "go_image")
|
||||
load("@io_bazel_rules_docker//container:container.bzl", "container_bundle")
|
||||
load("@io_bazel_rules_docker//contrib:push-all.bzl", "docker_push")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["main.go"],
|
||||
importpath = "github.com/prysmaticlabs/prysm/v3/tools/genesis-state-gen",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"//config/params:go_default_library",
|
||||
"//io/file:go_default_library",
|
||||
"//proto/prysm/v1alpha1:go_default_library",
|
||||
"//runtime/interop:go_default_library",
|
||||
"@com_github_ghodss_yaml//:go_default_library",
|
||||
"@com_github_sirupsen_logrus//:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "genesis-state-gen",
|
||||
embed = [":go_default_library"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
go_image(
|
||||
name = "image",
|
||||
base = select({
|
||||
"//tools:base_image_alpine": "//tools:alpine_cc_image",
|
||||
"//tools:base_image_cc": "//tools:cc_image",
|
||||
"//conditions:default": "//tools:cc_image",
|
||||
}),
|
||||
binary = ":genesis-state-gen",
|
||||
tags = ["manual"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
container_bundle(
|
||||
name = "image_bundle",
|
||||
images = {
|
||||
"gcr.io/prysmaticlabs/prysm/genesis-state-gen:latest": ":image",
|
||||
"gcr.io/prysmaticlabs/prysm/genesis-state-gen:{DOCKER_TAG}": ":image",
|
||||
},
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
docker_push(
|
||||
name = "push_images",
|
||||
bundle = ":image_bundle",
|
||||
tags = ["manual"],
|
||||
)
|
||||
|
||||
go_test(
|
||||
name = "go_default_test",
|
||||
srcs = ["main_test.go"],
|
||||
embed = [":go_default_library"],
|
||||
deps = [
|
||||
"//crypto/bls:go_default_library",
|
||||
"//runtime/interop:go_default_library",
|
||||
"//testing/assert:go_default_library",
|
||||
"//testing/require:go_default_library",
|
||||
],
|
||||
)
|
||||
@@ -1,201 +0,0 @@
|
||||
package main
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/ghodss/yaml"
|
||||
"github.com/prysmaticlabs/prysm/v3/config/params"
|
||||
"github.com/prysmaticlabs/prysm/v3/io/file"
|
||||
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v3/runtime/interop"
|
||||
log "github.com/sirupsen/logrus"
|
||||
)
|
||||
|
||||
// DepositDataJSON representing a json object of hex string and uint64 values for
|
||||
// validators on Ethereum. This file can be generated using the official eth2.0-deposit-cli.
|
||||
type DepositDataJSON struct {
|
||||
PubKey string `json:"pubkey"`
|
||||
Amount uint64 `json:"amount"`
|
||||
WithdrawalCredentials string `json:"withdrawal_credentials"`
|
||||
DepositDataRoot string `json:"deposit_data_root"`
|
||||
Signature string `json:"signature"`
|
||||
}
|
||||
|
||||
var (
|
||||
depositJSONFile = flag.String(
|
||||
"deposit-json-file",
|
||||
"",
|
||||
"Path to deposit_data.json file generated by the eth2.0-deposit-cli tool",
|
||||
)
|
||||
numValidators = flag.Int("num-validators", 0, "Number of validators to deterministically generate in the generated genesis state")
|
||||
useMainnetConfig = flag.Bool("mainnet-config", false, "Select whether genesis state should be generated with mainnet or minimal (default) params")
|
||||
genesisTime = flag.Uint64("genesis-time", 0, "Unix timestamp used as the genesis time in the generated genesis state (defaults to now)")
|
||||
sszOutputFile = flag.String("output-ssz", "", "Output filename of the SSZ marshaling of the generated genesis state")
|
||||
yamlOutputFile = flag.String("output-yaml", "", "Output filename of the YAML marshaling of the generated genesis state")
|
||||
jsonOutputFile = flag.String("output-json", "", "Output filename of the JSON marshaling of the generated genesis state")
|
||||
configName = flag.String("config-name", params.MinimalName, "ConfigName for the BeaconChainConfig that will be used for interop, inc GenesisForkVersion of generated genesis state")
|
||||
configFile = flag.String("chain-config-file", "", "Path to a chain config file for setting global params")
|
||||
)
|
||||
|
||||
func main() {
|
||||
flag.Parse()
|
||||
if *genesisTime == 0 {
|
||||
log.Print("No --genesis-time specified, defaulting to now")
|
||||
}
|
||||
if *sszOutputFile == "" && *yamlOutputFile == "" && *jsonOutputFile == "" {
|
||||
log.Println("Expected --output-ssz, --output-yaml, or --output-json to have been provided, received nil")
|
||||
return
|
||||
}
|
||||
if *useMainnetConfig {
|
||||
if err := params.SetActive(params.MainnetConfig().Copy()); err != nil {
|
||||
log.Fatalf("unable to set mainnet config active, err=%s", err.Error())
|
||||
}
|
||||
} else {
|
||||
if *configFile != "" {
|
||||
if err := params.LoadChainConfigFile(*configFile, nil); err != nil {
|
||||
log.Fatal(err)
|
||||
}
|
||||
} else {
|
||||
cfg, err := params.ByName(*configName)
|
||||
if err != nil {
|
||||
log.Fatalf("unable to find config using name %s, err=%s", *configName, err.Error())
|
||||
}
|
||||
if err := params.SetActive(cfg.Copy()); err != nil {
|
||||
log.Fatalf("unable to set %s config active, err=%s", cfg.ConfigName, err.Error())
|
||||
}
|
||||
}
|
||||
}
|
||||
var genesisState *ethpb.BeaconState
|
||||
var err error
|
||||
if *depositJSONFile != "" {
|
||||
inputFile := *depositJSONFile
|
||||
expanded, err := file.ExpandPath(inputFile)
|
||||
if err != nil {
|
||||
log.WithError(err).Printf("Could not expand file path %s", inputFile)
|
||||
return
|
||||
}
|
||||
inputJSON, err := os.Open(expanded) // #nosec G304
|
||||
if err != nil {
|
||||
log.WithError(err).Print("Could not open JSON file for reading")
|
||||
return
|
||||
}
|
||||
defer func() {
|
||||
if err := inputJSON.Close(); err != nil {
|
||||
log.WithError(err).Printf("Could not close file %s", inputFile)
|
||||
}
|
||||
}()
|
||||
log.Printf("Generating genesis state from input JSON deposit data %s", inputFile)
|
||||
genesisState, err = genesisStateFromJSONValidators(inputJSON, *genesisTime)
|
||||
if err != nil {
|
||||
log.WithError(err).Print("Could not generate genesis beacon state")
|
||||
return
|
||||
}
|
||||
} else {
|
||||
if *numValidators == 0 {
|
||||
log.Println("Expected --num-validators to have been provided, received 0")
|
||||
return
|
||||
}
|
||||
// If no JSON input is specified, we create the state deterministically from interop keys.
|
||||
genesisState, _, err = interop.GenerateGenesisState(context.Background(), *genesisTime, uint64(*numValidators))
|
||||
if err != nil {
|
||||
log.WithError(err).Print("Could not generate genesis beacon state")
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
if *sszOutputFile != "" {
|
||||
encodedState, err := genesisState.MarshalSSZ()
|
||||
if err != nil {
|
||||
log.WithError(err).Print("Could not ssz marshal the genesis beacon state")
|
||||
return
|
||||
}
|
||||
if err := file.WriteFile(*sszOutputFile, encodedState); err != nil {
|
||||
log.WithError(err).Print("Could not write encoded genesis beacon state to file")
|
||||
return
|
||||
}
|
||||
log.Printf("Done writing to %s", *sszOutputFile)
|
||||
}
|
||||
if *yamlOutputFile != "" {
|
||||
encodedState, err := yaml.Marshal(genesisState)
|
||||
if err != nil {
|
||||
log.WithError(err).Print("Could not yaml marshal the genesis beacon state")
|
||||
return
|
||||
}
|
||||
if err := file.WriteFile(*yamlOutputFile, encodedState); err != nil {
|
||||
log.WithError(err).Print("Could not write encoded genesis beacon state to file")
|
||||
return
|
||||
}
|
||||
log.Printf("Done writing to %s", *yamlOutputFile)
|
||||
}
|
||||
if *jsonOutputFile != "" {
|
||||
encodedState, err := json.Marshal(genesisState)
|
||||
if err != nil {
|
||||
log.WithError(err).Print("Could not json marshal the genesis beacon state")
|
||||
return
|
||||
}
|
||||
if err := file.WriteFile(*jsonOutputFile, encodedState); err != nil {
|
||||
log.WithError(err).Print("Could not write encoded genesis beacon state to file")
|
||||
return
|
||||
}
|
||||
log.Printf("Done writing to %s", *jsonOutputFile)
|
||||
}
|
||||
}
|
||||
|
||||
func genesisStateFromJSONValidators(r io.Reader, genesisTime uint64) (*ethpb.BeaconState, error) {
|
||||
enc, err := io.ReadAll(r)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var depositJSON []*DepositDataJSON
|
||||
if err := json.Unmarshal(enc, &depositJSON); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
depositDataList := make([]*ethpb.Deposit_Data, len(depositJSON))
|
||||
depositDataRoots := make([][]byte, len(depositJSON))
|
||||
for i, val := range depositJSON {
|
||||
data, dataRootBytes, err := depositJSONToDepositData(val)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
depositDataList[i] = data
|
||||
depositDataRoots[i] = dataRootBytes
|
||||
}
|
||||
beaconState, _, err := interop.GenerateGenesisStateFromDepositData(context.Background(), genesisTime, depositDataList, depositDataRoots)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return beaconState, nil
|
||||
}
|
||||
|
||||
func depositJSONToDepositData(input *DepositDataJSON) (depositData *ethpb.Deposit_Data, dataRoot []byte, err error) {
|
||||
pubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(input.PubKey, "0x"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
withdrawalbytes, err := hex.DecodeString(strings.TrimPrefix(input.WithdrawalCredentials, "0x"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
signatureBytes, err := hex.DecodeString(strings.TrimPrefix(input.Signature, "0x"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
dataRootBytes, err := hex.DecodeString(strings.TrimPrefix(input.DepositDataRoot, "0x"))
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
depositData = ðpb.Deposit_Data{
|
||||
PublicKey: pubKeyBytes,
|
||||
WithdrawalCredentials: withdrawalbytes,
|
||||
Amount: input.Amount,
|
||||
Signature: signatureBytes,
|
||||
}
|
||||
dataRoot = dataRootBytes
|
||||
return
|
||||
}
|
||||
Reference in New Issue
Block a user