From 20ed47a107c5d85c4c950be91684a1fa7ecd69af Mon Sep 17 00:00:00 2001 From: Raul Jordan Date: Fri, 19 Aug 2022 09:26:25 +0000 Subject: [PATCH] Add a Generate Genesis State Command to Prysmctl (#11259) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * 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 * radek feedback * more feedback * required * fix up * gaz * radek feedback Co-authored-by: RadosÅ‚aw Kapka --- cmd/prysmctl/BUILD.bazel | 1 + cmd/prysmctl/main.go | 2 + cmd/prysmctl/testnet/BUILD.bazel | 34 +++ cmd/prysmctl/testnet/generate_genesis.go | 265 ++++++++++++++++++ .../prysmctl/testnet/generate_genesis_test.go | 12 +- cmd/prysmctl/testnet/testnet.go | 13 + tools/genesis-state-gen/BUILD.bazel | 65 ----- tools/genesis-state-gen/main.go | 201 ------------- 8 files changed, 322 insertions(+), 271 deletions(-) create mode 100644 cmd/prysmctl/testnet/BUILD.bazel create mode 100644 cmd/prysmctl/testnet/generate_genesis.go rename tools/genesis-state-gen/main_test.go => cmd/prysmctl/testnet/generate_genesis_test.go (83%) create mode 100644 cmd/prysmctl/testnet/testnet.go delete mode 100644 tools/genesis-state-gen/BUILD.bazel delete mode 100644 tools/genesis-state-gen/main.go diff --git a/cmd/prysmctl/BUILD.bazel b/cmd/prysmctl/BUILD.bazel index 2569118997e2..d78bc8891d3c 100644 --- a/cmd/prysmctl/BUILD.bazel +++ b/cmd/prysmctl/BUILD.bazel @@ -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", ], diff --git a/cmd/prysmctl/main.go b/cmd/prysmctl/main.go index 4e5a134a1139..3ae579a26e7d 100644 --- a/cmd/prysmctl/main.go +++ b/cmd/prysmctl/main.go @@ -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...) } diff --git a/cmd/prysmctl/testnet/BUILD.bazel b/cmd/prysmctl/testnet/BUILD.bazel new file mode 100644 index 000000000000..81206492c396 --- /dev/null +++ b/cmd/prysmctl/testnet/BUILD.bazel @@ -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", + ], +) diff --git a/cmd/prysmctl/testnet/generate_genesis.go b/cmd/prysmctl/testnet/generate_genesis.go new file mode 100644 index 000000000000..1c319222ba04 --- /dev/null +++ b/cmd/prysmctl/testnet/generate_genesis.go @@ -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 +} diff --git a/tools/genesis-state-gen/main_test.go b/cmd/prysmctl/testnet/generate_genesis_test.go similarity index 83% rename from tools/genesis-state-gen/main_test.go rename to cmd/prysmctl/testnet/generate_genesis_test.go index 729bbcffe174..baeff3fe2388 100644 --- a/tools/genesis-state-gen/main_test.go +++ b/cmd/prysmctl/testnet/generate_genesis_test.go @@ -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), diff --git a/cmd/prysmctl/testnet/testnet.go b/cmd/prysmctl/testnet/testnet.go new file mode 100644 index 000000000000..f414951b03ea --- /dev/null +++ b/cmd/prysmctl/testnet/testnet.go @@ -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, + }, + }, +} diff --git a/tools/genesis-state-gen/BUILD.bazel b/tools/genesis-state-gen/BUILD.bazel deleted file mode 100644 index ad00b9db8b5e..000000000000 --- a/tools/genesis-state-gen/BUILD.bazel +++ /dev/null @@ -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", - ], -) diff --git a/tools/genesis-state-gen/main.go b/tools/genesis-state-gen/main.go deleted file mode 100644 index e2f87eeab1e3..000000000000 --- a/tools/genesis-state-gen/main.go +++ /dev/null @@ -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 -}