diff --git a/beacon-chain/execution/testing/BUILD.bazel b/beacon-chain/execution/testing/BUILD.bazel index 0dff59719c..ca7c21152c 100644 --- a/beacon-chain/execution/testing/BUILD.bazel +++ b/beacon-chain/execution/testing/BUILD.bazel @@ -4,7 +4,6 @@ go_library( name = "go_default_library", testonly = True, srcs = [ - "genesis.go", "mock_engine_client.go", "mock_execution_chain.go", "mock_faulty_powchain.go", @@ -30,9 +29,7 @@ go_library( "@com_github_ethereum_go_ethereum//accounts/abi/bind/backends:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_ethereum_go_ethereum//core:go_default_library", "@com_github_ethereum_go_ethereum//core/types:go_default_library", - "@com_github_ethereum_go_ethereum//params:go_default_library", "@com_github_ethereum_go_ethereum//rpc:go_default_library", "@com_github_holiman_uint256//:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/state/stateutil/BUILD.bazel b/beacon-chain/state/stateutil/BUILD.bazel index 7e71c6cbac..f9847d6f98 100644 --- a/beacon-chain/state/stateutil/BUILD.bazel +++ b/beacon-chain/state/stateutil/BUILD.bazel @@ -20,17 +20,7 @@ go_library( "validator_root.go", ], importpath = "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/stateutil", - visibility = [ - "//beacon-chain:__subpackages__", - "//proto/migration:__subpackages__", - "//proto/prysm/v1alpha1:__subpackages__", - "//proto/testing:__subpackages__", - "//slasher:__subpackages__", - "//testing:__subpackages__", - "//tools/blocktree:__pkg__", - "//tools/pcli:__pkg__", - "//validator/client:__pkg__", - ], + visibility = ["//visibility:public"], deps = [ "//beacon-chain/core/transition/stateutils:go_default_library", "//config/fieldparams:go_default_library", diff --git a/cmd/prysmctl/testnet/BUILD.bazel b/cmd/prysmctl/testnet/BUILD.bazel index 1e9a00646c..cabfd32226 100644 --- a/cmd/prysmctl/testnet/BUILD.bazel +++ b/cmd/prysmctl/testnet/BUILD.bazel @@ -9,11 +9,7 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v4/cmd/prysmctl/testnet", visibility = ["//visibility:public"], deps = [ - "//beacon-chain/core/altair:go_default_library", - "//beacon-chain/core/capella:go_default_library", - "//beacon-chain/core/execution:go_default_library", "//beacon-chain/state:go_default_library", - "//beacon-chain/state/state-native:go_default_library", "//cmd/flags:go_default_library", "//config/params:go_default_library", "//container/trie:go_default_library", @@ -21,6 +17,7 @@ go_library( "//proto/prysm/v1alpha1:go_default_library", "//runtime/interop:go_default_library", "//runtime/version:go_default_library", + "@com_github_ethereum_go_ethereum//core:go_default_library", "@com_github_ethereum_go_ethereum//ethclient:go_default_library", "@com_github_ethereum_go_ethereum//rpc:go_default_library", "@com_github_ghodss_yaml//:go_default_library", diff --git a/cmd/prysmctl/testnet/generate_genesis.go b/cmd/prysmctl/testnet/generate_genesis.go index cc530d5665..0e4a158be3 100644 --- a/cmd/prysmctl/testnet/generate_genesis.go +++ b/cmd/prysmctl/testnet/generate_genesis.go @@ -5,20 +5,17 @@ import ( "encoding/hex" "encoding/json" "fmt" - "io" "math/big" "os" "strings" + "time" + "github.com/ethereum/go-ethereum/core" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rpc" "github.com/ghodss/yaml" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/altair" - "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/capella" - "github.com/prysmaticlabs/prysm/v4/beacon-chain/core/execution" "github.com/prysmaticlabs/prysm/v4/beacon-chain/state" - state_native "github.com/prysmaticlabs/prysm/v4/beacon-chain/state/state-native" "github.com/prysmaticlabs/prysm/v4/cmd/flags" "github.com/prysmaticlabs/prysm/v4/config/params" "github.com/prysmaticlabs/prysm/v4/container/trie" @@ -32,17 +29,19 @@ import ( var ( generateGenesisStateFlags = struct { - DepositJsonFile string - ChainConfigFile string - ConfigName string - NumValidators uint64 - GenesisTime uint64 - OutputSSZ string - OutputJSON string - OutputYaml string - ForkName string - OverrideEth1Data bool - ExecutionEndpoint string + DepositJsonFile string + ChainConfigFile string + ConfigName string + NumValidators uint64 + GenesisTime uint64 + OutputSSZ string + OutputJSON string + OutputYaml string + ForkName string + OverrideEth1Data bool + ExecutionEndpoint string + GethGenesisJsonIn string + GethGenesisJsonOut string }{} log = logrus.WithField("prefix", "genesis") outputSSZFlag = &cli.StringFlag{ @@ -106,6 +105,16 @@ var ( Usage: "Overrides Eth1Data with values from execution client. If unset, defaults to false", Value: false, }, + &cli.StringFlag{ + Name: "geth-genesis-json-in", + Destination: &generateGenesisStateFlags.GethGenesisJsonIn, + Usage: "Path to a \"genesis.json\" file, containing a json representation of Geth's core.Genesis", + }, + &cli.StringFlag{ + Name: "geth-genesis-json-out", + Destination: &generateGenesisStateFlags.GethGenesisJsonOut, + Usage: "Path to write generated \"genesis.json\" file, containing a json representation of Geth's core.Genesis", + }, &cli.StringFlag{ Name: "execution-endpoint", Destination: &generateGenesisStateFlags.ExecutionEndpoint, @@ -146,9 +155,6 @@ type depositDataJSON struct { } 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 @@ -164,14 +170,10 @@ func cliActionGenerateGenesisState(cliCtx *cli.Context) error { if err := setGlobalParams(); err != nil { return fmt.Errorf("could not set config params: %v", err) } - genesisState, err := generateGenesis(cliCtx.Context) + st, err := generateGenesis(cliCtx.Context) if err != nil { return fmt.Errorf("could not generate genesis state: %v", err) } - st, err := upgradeStateToForkName(cliCtx.Context, genesisState, generateGenesisStateFlags.ForkName) - if err != nil { - return err - } if outputJson != "" { if err := writeToOutputFile(outputJson, st, json.Marshal); err != nil { @@ -202,42 +204,6 @@ func cliActionGenerateGenesisState(cliCtx *cli.Context) error { return nil } -func upgradeStateToForkName(ctx context.Context, pbst *ethpb.BeaconState, name string) (state.BeaconState, error) { - st, err := state_native.InitializeFromProtoUnsafePhase0(pbst) - if err != nil { - return nil, err - } - if name == "" || name == "phase0" { - return st, nil - } - - st, err = altair.UpgradeToAltair(ctx, st) - if err != nil { - return nil, err - } - if name == "altair" { - return st, nil - } - - st, err = execution.UpgradeToBellatrix(st) - if err != nil { - return nil, err - } - if name == "bellatrix" { - return st, nil - } - - st, err = capella.UpgradeToCapella(st) - if err != nil { - return nil, err - } - if name == "capella" { - return st, nil - } - - return nil, fmt.Errorf("unrecognized fork name '%s'", name) -} - func setGlobalParams() error { chainConfigFile := generateGenesisStateFlags.ChainConfigFile if chainConfigFile != "" { @@ -251,43 +217,71 @@ func setGlobalParams() error { return params.SetActive(cfg.Copy()) } -func generateGenesis(ctx context.Context) (genesisState *ethpb.BeaconState, err error) { - genesisTime := generateGenesisStateFlags.GenesisTime - numValidators := generateGenesisStateFlags.NumValidators - depositJsonFile := generateGenesisStateFlags.DepositJsonFile - overrideEth1Data := generateGenesisStateFlags.OverrideEth1Data - if depositJsonFile != "" { - expanded, err := file.ExpandPath(depositJsonFile) +func generateGenesis(ctx context.Context) (state.BeaconState, error) { + f := &generateGenesisStateFlags + if f.GenesisTime == 0 { + f.GenesisTime = uint64(time.Now().Unix()) + log.Info("No genesis time specified, defaulting to now()") + } + + v, err := version.FromString(f.ForkName) + if err != nil { + return nil, err + } + opts := make([]interop.PremineGenesisOpt, 0) + nv := f.NumValidators + if f.DepositJsonFile != "" { + expanded, err := file.ExpandPath(f.DepositJsonFile) if err != nil { return nil, err } - inputJSON, err := os.Open(expanded) // #nosec G304 + log.Printf("reading deposits from JSON at %s", expanded) + b, err := os.ReadFile(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) - genesisState, err = genesisStateFromJSONValidators(ctx, inputJSON, genesisTime) + roots, dds, err := depositEntriesFromJSON(b) if err != nil { return nil, err } + opts = append(opts, interop.WithDepositData(dds, roots)) + } else if nv == 0 { + return nil, fmt.Errorf( + "expected --num-validators > 0 or --deposit-json-file to have been provided", + ) + } + + gen := &core.Genesis{} + if f.GethGenesisJsonIn != "" { + gbytes, err := os.ReadFile(f.GethGenesisJsonIn) // #nosec G304 + if err != nil { + return nil, errors.Wrapf(err, "failed to read %s", f.GethGenesisJsonIn) + } + if err := json.Unmarshal(gbytes, gen); err != nil { + return nil, err + } } else { - 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) + gen = interop.GethTestnetGenesis(f.GenesisTime, params.BeaconConfig()) + } + if f.GethGenesisJsonOut != "" { + gbytes, err := json.MarshalIndent(gen, "", "\t") if err != nil { return nil, err } + if err := os.WriteFile(f.GethGenesisJsonOut, gbytes, os.ModePerm); err != nil { + return nil, errors.Wrapf(err, "failed to write %s", f.GethGenesisJsonOut) + } } - if overrideEth1Data { + + gb := gen.ToBlock() + + // TODO: expose the PregenesisCreds option with a cli flag - for now defaulting to no withdrawal credentials at genesis + genesisState, err := interop.NewPreminedGenesis(ctx, f.GenesisTime, nv, 0, v, gb, opts...) + if err != nil { + return nil, err + } + + if f.OverrideEth1Data { log.Print("Overriding Eth1Data with data from execution client") conn, err := rpc.Dial(generateGenesisStateFlags.ExecutionEndpoint) if err != nil { @@ -309,67 +303,63 @@ func generateGenesis(ctx context.Context) (genesisState *ethpb.BeaconState, err if err != nil { return nil, errors.Wrap(err, "could not get hash tree root") } - genesisState.Eth1Data = ðpb.Eth1Data{ + e1d := ðpb.Eth1Data{ DepositRoot: depositRoot[:], DepositCount: 0, BlockHash: header.Hash().Bytes(), } - genesisState.Eth1DepositIndex = 0 + if err := genesisState.SetEth1Data(e1d); err != nil { + return nil, err + } + if err := genesisState.SetEth1DepositIndex(0); 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 - } +func depositEntriesFromJSON(enc []byte) ([][]byte, []*ethpb.Deposit_Data, error) { var depositJSON []*depositDataJSON if err := json.Unmarshal(enc, &depositJSON); err != nil { - return nil, err + return nil, nil, err } - depositDataList := make([]*ethpb.Deposit_Data, len(depositJSON)) - depositDataRoots := make([][]byte, len(depositJSON)) + dds := make([]*ethpb.Deposit_Data, len(depositJSON)) + roots := make([][]byte, len(depositJSON)) for i, val := range depositJSON { - data, dataRootBytes, err := depositJSONToDepositData(val) + root, data, err := depositJSONToDepositData(val) if err != nil { - return nil, err + return nil, nil, err } - depositDataList[i] = data - depositDataRoots[i] = dataRootBytes + dds[i] = data + roots[i] = root } - beaconState, _, err := interop.GenerateGenesisStateFromDepositData(ctx, genesisTime, depositDataList, depositDataRoots) - if err != nil { - return nil, err - } - return beaconState, nil + return roots, dds, nil } -func depositJSONToDepositData(input *depositDataJSON) (depositData *ethpb.Deposit_Data, dataRoot []byte, err error) { - pubKeyBytes, err := hex.DecodeString(strings.TrimPrefix(input.PubKey, "0x")) +func depositJSONToDepositData(input *depositDataJSON) ([]byte, *ethpb.Deposit_Data, error) { + root, err := hex.DecodeString(strings.TrimPrefix(input.DepositDataRoot, "0x")) if err != nil { - return + return nil, nil, err } - withdrawalbytes, err := hex.DecodeString(strings.TrimPrefix(input.WithdrawalCredentials, "0x")) + pk, err := hex.DecodeString(strings.TrimPrefix(input.PubKey, "0x")) if err != nil { - return + return nil, nil, err } - signatureBytes, err := hex.DecodeString(strings.TrimPrefix(input.Signature, "0x")) + creds, err := hex.DecodeString(strings.TrimPrefix(input.WithdrawalCredentials, "0x")) if err != nil { - return + return nil, nil, err } - dataRootBytes, err := hex.DecodeString(strings.TrimPrefix(input.DepositDataRoot, "0x")) + sig, err := hex.DecodeString(strings.TrimPrefix(input.Signature, "0x")) if err != nil { - return + return nil, nil, err } - depositData = ðpb.Deposit_Data{ - PublicKey: pubKeyBytes, - WithdrawalCredentials: withdrawalbytes, + return root, ðpb.Deposit_Data{ + PublicKey: pk, + WithdrawalCredentials: creds, Amount: input.Amount, - Signature: signatureBytes, - } - dataRoot = dataRootBytes - return + Signature: sig, + }, nil } func writeToOutputFile( diff --git a/cmd/prysmctl/testnet/generate_genesis_test.go b/cmd/prysmctl/testnet/generate_genesis_test.go index 4e3cf4a79c..4768f162e2 100644 --- a/cmd/prysmctl/testnet/generate_genesis_test.go +++ b/cmd/prysmctl/testnet/generate_genesis_test.go @@ -1,8 +1,6 @@ package testnet import ( - "bytes" - "context" "encoding/json" "fmt" "testing" @@ -18,13 +16,10 @@ 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( - ctx, bytes.NewReader(jsonInput), 0, /* genesis time defaults to time.Now() */ - ) + _, dds, err := depositEntriesFromJSON(jsonInput) require.NoError(t, err) - for i, val := range genesisState.Validators { - assert.DeepEqual(t, fmt.Sprintf("%#x", val.PublicKey), jsonData[i].PubKey) + for i := range dds { + assert.DeepEqual(t, fmt.Sprintf("%#x", dds[i].PublicKey), jsonData[i].PubKey) } } diff --git a/runtime/interop/BUILD.bazel b/runtime/interop/BUILD.bazel index a21396c316..b240cba3fe 100644 --- a/runtime/interop/BUILD.bazel +++ b/runtime/interop/BUILD.bazel @@ -6,23 +6,39 @@ go_library( "generate_genesis_state.go", "generate_genesis_state_bellatrix.go", "generate_keys.go", + "genesis.go", + "premine-state.go", "premined_genesis_state.go", ], importpath = "github.com/prysmaticlabs/prysm/v4/runtime/interop", visibility = ["//visibility:public"], deps = [ "//async:go_default_library", + "//beacon-chain/core/altair:go_default_library", + "//beacon-chain/core/blocks:go_default_library", + "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/signing:go_default_library", "//beacon-chain/core/transition:go_default_library", + "//beacon-chain/state:go_default_library", "//beacon-chain/state/state-native:go_default_library", + "//beacon-chain/state/stateutil:go_default_library", + "//config/fieldparams:go_default_library", "//config/params:go_default_library", + "//consensus-types/blocks:go_default_library", "//container/trie:go_default_library", "//crypto/bls:go_default_library", "//crypto/hash:go_default_library", "//encoding/bytesutil:go_default_library", "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/version:go_default_library", "//time:go_default_library", + "//time/slots:go_default_library", + "@com_github_ethereum_go_ethereum//common:go_default_library", + "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", + "@com_github_ethereum_go_ethereum//core:go_default_library", + "@com_github_ethereum_go_ethereum//core/types:go_default_library", + "@com_github_ethereum_go_ethereum//params:go_default_library", "@com_github_pkg_errors//:go_default_library", ], ) diff --git a/beacon-chain/execution/testing/genesis.go b/runtime/interop/genesis.go similarity index 99% rename from beacon-chain/execution/testing/genesis.go rename to runtime/interop/genesis.go index 1e0af1259a..dcd76a3fd9 100644 --- a/beacon-chain/execution/testing/genesis.go +++ b/runtime/interop/genesis.go @@ -1,4 +1,4 @@ -package testing +package interop import ( "fmt" @@ -67,6 +67,7 @@ var DefaultDepositContractStorage = map[string]string{ var bigz = big.NewInt(0) var minerBalance = big.NewInt(0) +// DefaultCliqueSigner is the testnet miner (clique signer) address encoded in the special way EIP-225 requires. // EIP-225 assigns a special meaning to the `extra-data` field in the block header for clique chains. // In a clique chain, this field contains one secp256k1 "miner" signature. This allows other nodes to // verify that the block was signed by an authorized signer, in place of the typical PoW verification. @@ -76,10 +77,10 @@ var minerBalance = big.NewInt(0) // The following value is for the key used by the e2e test "miner" node. const DefaultCliqueSigner = "0x0000000000000000000000000000000000000000000000000000000000000000878705ba3f8bc32fcf7f4caa1a35e72af65cf7660000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" -// DefaultTestnetGenesis creates a genesis.json for eth1 clients with a set of defaults suitable for ephemeral testnets, +// GethTestnetGenesis creates a genesis.json for eth1 clients with a set of defaults suitable for ephemeral testnets, // like in an e2e test. The parameters are minimal but the full value is returned unmarshaled so that it can be // customized as desired. -func GethTestnetGenesis(genesisTime uint64, cfg *clparams.BeaconChainConfig) core.Genesis { +func GethTestnetGenesis(genesisTime uint64, cfg *clparams.BeaconChainConfig) *core.Genesis { ttd, ok := big.NewInt(0).SetString(clparams.BeaconConfig().TerminalTotalDifficulty, 10) if !ok { panic(fmt.Sprintf("unable to parse TerminalTotalDifficulty as an integer = %s", clparams.BeaconConfig().TerminalTotalDifficulty)) @@ -124,7 +125,7 @@ func GethTestnetGenesis(genesisTime uint64, cfg *clparams.BeaconChainConfig) cor if err != nil { panic(fmt.Sprintf("unable to decode DefaultCliqueSigner, with error %v", err.Error())) } - return core.Genesis{ + return &core.Genesis{ Config: cc, Nonce: 0, // overridden for authorized signer votes in clique, so we should leave it empty? Timestamp: genesisTime, diff --git a/testing/util/premine-state.go b/runtime/interop/premine-state.go similarity index 83% rename from testing/util/premine-state.go rename to runtime/interop/premine-state.go index d276ee53eb..62117b68ec 100644 --- a/testing/util/premine-state.go +++ b/runtime/interop/premine-state.go @@ -1,4 +1,4 @@ -package util +package interop import ( "context" @@ -19,32 +19,52 @@ import ( "github.com/prysmaticlabs/prysm/v4/encoding/bytesutil" enginev1 "github.com/prysmaticlabs/prysm/v4/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1" - "github.com/prysmaticlabs/prysm/v4/runtime/interop" "github.com/prysmaticlabs/prysm/v4/runtime/version" ) -var errUnsupportedVersion = errors.New("schema version not supported by premineGenesisConfig") +var errUnsupportedVersion = errors.New("schema version not supported by PremineGenesisConfig") -type premineGenesisConfig struct { +type PremineGenesisConfig struct { GenesisTime uint64 NVals uint64 PregenesisCreds uint64 Version int // as in "github.com/prysmaticlabs/prysm/v4/runtime/version" GB *types.Block // geth genesis block + depositEntries *depositEntries +} + +type depositEntries struct { + dds []*ethpb.Deposit_Data + roots [][]byte +} + +type PremineGenesisOpt func(*PremineGenesisConfig) + +func WithDepositData(dds []*ethpb.Deposit_Data, roots [][]byte) PremineGenesisOpt { + return func(cfg *PremineGenesisConfig) { + cfg.depositEntries = &depositEntries{ + dds: dds, + roots: roots, + } + } } // NewPreminedGenesis creates a genesis BeaconState at the given fork version, suitable for using as an e2e genesis. -func NewPreminedGenesis(ctx context.Context, t, nvals, pCreds uint64, version int, gb *types.Block) (state.BeaconState, error) { - return (&premineGenesisConfig{ +func NewPreminedGenesis(ctx context.Context, t, nvals, pCreds uint64, version int, gb *types.Block, opts ...PremineGenesisOpt) (state.BeaconState, error) { + cfg := &PremineGenesisConfig{ GenesisTime: t, NVals: nvals, PregenesisCreds: pCreds, Version: version, GB: gb, - }).prepare(ctx) + } + for _, o := range opts { + o(cfg) + } + return cfg.prepare(ctx) } -func (s *premineGenesisConfig) prepare(ctx context.Context) (state.BeaconState, error) { +func (s *PremineGenesisConfig) prepare(ctx context.Context) (state.BeaconState, error) { switch s.Version { case version.Phase0, version.Altair, version.Bellatrix: default: @@ -65,7 +85,7 @@ func (s *premineGenesisConfig) prepare(ctx context.Context) (state.BeaconState, return st, nil } -func (s *premineGenesisConfig) empty() (state.BeaconState, error) { +func (s *PremineGenesisConfig) empty() (state.BeaconState, error) { var e state.BeaconState var err error switch s.Version { @@ -129,7 +149,7 @@ func (s *premineGenesisConfig) empty() (state.BeaconState, error) { return e.Copy(), nil } -func (s *premineGenesisConfig) processDeposits(ctx context.Context, g state.BeaconState) error { +func (s *PremineGenesisConfig) processDeposits(ctx context.Context, g state.BeaconState) error { deposits, err := s.deposits() if err != nil { return err @@ -147,35 +167,42 @@ func (s *premineGenesisConfig) processDeposits(ctx context.Context, g state.Beac return nil } -func (s *premineGenesisConfig) deposits() ([]*ethpb.Deposit, error) { - prv, pub, err := s.keys() - if err != nil { - return nil, err +func (s *PremineGenesisConfig) deposits() ([]*ethpb.Deposit, error) { + if s.depositEntries == nil { + prv, pub, err := s.keys() + if err != nil { + return nil, err + } + dds, roots, err := DepositDataFromKeysWithExecCreds(prv, pub, s.PregenesisCreds) + if err != nil { + return nil, errors.Wrap(err, "could not generate deposit data from keys") + } + s.depositEntries = &depositEntries{ + dds: dds, + roots: roots, + } } - items, roots, err := interop.DepositDataFromKeysWithExecCreds(prv, pub, s.PregenesisCreds) - if err != nil { - return nil, errors.Wrap(err, "could not generate deposit data from keys") - } - t, err := trie.GenerateTrieFromItems(roots, params.BeaconConfig().DepositContractTreeDepth) + + t, err := trie.GenerateTrieFromItems(s.depositEntries.roots, params.BeaconConfig().DepositContractTreeDepth) if err != nil { return nil, errors.Wrap(err, "could not generate Merkle trie for deposit proofs") } - deposits, err := interop.GenerateDepositsFromData(items, t) + deposits, err := GenerateDepositsFromData(s.depositEntries.dds, t) if err != nil { return nil, errors.Wrap(err, "could not generate deposits from the deposit data provided") } return deposits, nil } -func (s *premineGenesisConfig) keys() ([]bls.SecretKey, []bls.PublicKey, error) { - prv, pub, err := interop.DeterministicallyGenerateKeys(0, s.NVals) +func (s *PremineGenesisConfig) keys() ([]bls.SecretKey, []bls.PublicKey, error) { + prv, pub, err := DeterministicallyGenerateKeys(0, s.NVals) if err != nil { return nil, nil, errors.Wrapf(err, "could not deterministically generate keys for %d validators", s.NVals) } return prv, pub, nil } -func (s *premineGenesisConfig) setEth1Data(g state.BeaconState) error { +func (s *PremineGenesisConfig) setEth1Data(g state.BeaconState) error { if err := g.SetEth1DepositIndex(0); err != nil { return err } @@ -194,7 +221,7 @@ func emptyDepositRoot() ([32]byte, error) { return t.HashTreeRoot() } -func (s *premineGenesisConfig) populate(g state.BeaconState) error { +func (s *PremineGenesisConfig) populate(g state.BeaconState) error { if err := g.SetGenesisTime(s.GenesisTime); err != nil { return err } @@ -235,7 +262,7 @@ func (s *premineGenesisConfig) populate(g state.BeaconState) error { return s.setEth1Data(g) } -func (s *premineGenesisConfig) setGenesisValidatorsRoot(g state.BeaconState) error { +func (s *PremineGenesisConfig) setGenesisValidatorsRoot(g state.BeaconState) error { vroot, err := stateutil.ValidatorRegistryRoot(g.Validators()) if err != nil { return err @@ -243,7 +270,7 @@ func (s *premineGenesisConfig) setGenesisValidatorsRoot(g state.BeaconState) err return g.SetGenesisValidatorsRoot(vroot[:]) } -func (s *premineGenesisConfig) setFork(g state.BeaconState) error { +func (s *PremineGenesisConfig) setFork(g state.BeaconState) error { var pv, cv []byte switch s.Version { case version.Phase0: @@ -263,7 +290,7 @@ func (s *premineGenesisConfig) setFork(g state.BeaconState) error { return g.SetFork(fork) } -func (s *premineGenesisConfig) setInactivityScores(g state.BeaconState) error { +func (s *PremineGenesisConfig) setInactivityScores(g state.BeaconState) error { if s.Version < version.Altair { return nil } @@ -281,7 +308,7 @@ func (s *premineGenesisConfig) setInactivityScores(g state.BeaconState) error { return g.SetInactivityScores(scores) } -func (s *premineGenesisConfig) setSyncCommittees(g state.BeaconState) error { +func (s *PremineGenesisConfig) setSyncCommittees(g state.BeaconState) error { if s.Version < version.Altair { return nil } @@ -299,7 +326,7 @@ type rooter interface { HashTreeRoot() ([32]byte, error) } -func (s *premineGenesisConfig) setLatestBlockHeader(g state.BeaconState) error { +func (s *PremineGenesisConfig) setLatestBlockHeader(g state.BeaconState) error { var body rooter switch s.Version { case version.Phase0: @@ -364,7 +391,7 @@ func (s *premineGenesisConfig) setLatestBlockHeader(g state.BeaconState) error { return g.SetLatestBlockHeader(lbh) } -func (s *premineGenesisConfig) setExecutionPayload(g state.BeaconState) error { +func (s *PremineGenesisConfig) setExecutionPayload(g state.BeaconState) error { if s.Version < version.Bellatrix { return nil } diff --git a/runtime/version/BUILD.bazel b/runtime/version/BUILD.bazel index 157ccc2b55..011819aa08 100644 --- a/runtime/version/BUILD.bazel +++ b/runtime/version/BUILD.bazel @@ -16,6 +16,7 @@ go_library( "gitTag": "{STABLE_GIT_TAG}", }, deps = [ + "@com_github_pkg_errors//:go_default_library", "@com_github_prometheus_client_golang//prometheus:go_default_library", "@com_github_prometheus_client_golang//prometheus/promauto:go_default_library", ], diff --git a/runtime/version/fork.go b/runtime/version/fork.go index 6d4e0d7abd..5385dfc9b3 100644 --- a/runtime/version/fork.go +++ b/runtime/version/fork.go @@ -1,5 +1,7 @@ package version +import "github.com/pkg/errors" + const ( Phase0 = iota Altair @@ -7,22 +9,50 @@ const ( Capella ) +var versionToString = map[int]string{ + Phase0: "phase0", + Altair: "altair", + Bellatrix: "bellatrix", + Capella: "capella", +} + +// stringToVersion and allVersions are populated in init() +var stringToVersion = map[string]int{} +var allVersions = []int{} + +// ErrUnrecognizedVersionName means a string does not match the list of canonical version names. +var ErrUnrecognizedVersionName = errors.New("version name doesn't map to a known value in the enum") + +// FromString translates a canonical version name to the version number. +func FromString(name string) (int, error) { + v, ok := stringToVersion[name] + if !ok { + return 0, errors.Wrap(ErrUnrecognizedVersionName, name) + } + return v, nil +} + +// String returns the canonical string form of a version. +// Unrecognized versions won't generate an error and are represented by the string "unknown version". func String(version int) string { - switch version { - case Phase0: - return "phase0" - case Altair: - return "altair" - case Bellatrix: - return "bellatrix" - case Capella: - return "capella" - default: + name, ok := versionToString[version] + if !ok { return "unknown version" } + return name } // All returns a list of all known fork versions. func All() []int { - return []int{Phase0, Altair, Bellatrix, Capella} + return allVersions +} + +func init() { + allVersions = make([]int, len(versionToString)) + i := 0 + for v, s := range versionToString { + allVersions[i] = v + stringToVersion[s] = v + i++ + } } diff --git a/testing/endtoend/components/BUILD.bazel b/testing/endtoend/components/BUILD.bazel index 6d71d8bafa..a778d9e9fb 100644 --- a/testing/endtoend/components/BUILD.bazel +++ b/testing/endtoend/components/BUILD.bazel @@ -35,7 +35,6 @@ go_library( "//testing/endtoend/helpers:go_default_library", "//testing/endtoend/params:go_default_library", "//testing/endtoend/types:go_default_library", - "//testing/util:go_default_library", "//validator/keymanager:go_default_library", "@com_github_ethereum_go_ethereum//common:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", diff --git a/testing/endtoend/components/beacon_node.go b/testing/endtoend/components/beacon_node.go index c390b012b8..a14dc22cf2 100644 --- a/testing/endtoend/components/beacon_node.go +++ b/testing/endtoend/components/beacon_node.go @@ -21,10 +21,10 @@ import ( "github.com/prysmaticlabs/prysm/v4/config/features" "github.com/prysmaticlabs/prysm/v4/config/params" "github.com/prysmaticlabs/prysm/v4/io/file" + "github.com/prysmaticlabs/prysm/v4/runtime/interop" "github.com/prysmaticlabs/prysm/v4/testing/endtoend/helpers" e2e "github.com/prysmaticlabs/prysm/v4/testing/endtoend/params" e2etypes "github.com/prysmaticlabs/prysm/v4/testing/endtoend/types" - "github.com/prysmaticlabs/prysm/v4/testing/util" ) var _ e2etypes.ComponentRunner = (*BeaconNode)(nil) @@ -353,5 +353,5 @@ func generateGenesis(ctx context.Context) (state.BeaconState, error) { pcreds := e2e.TestParams.NumberOfExecutionCreds nvals := params.BeaconConfig().MinGenesisActiveValidatorCount version := e2etypes.GenesisFork() - return util.NewPreminedGenesis(ctx, t, nvals, pcreds, version, gb) + return interop.NewPreminedGenesis(ctx, t, nvals, pcreds, version, gb) } diff --git a/testing/endtoend/components/eth1/BUILD.bazel b/testing/endtoend/components/eth1/BUILD.bazel index baad417e1b..14c88d96d3 100644 --- a/testing/endtoend/components/eth1/BUILD.bazel +++ b/testing/endtoend/components/eth1/BUILD.bazel @@ -15,13 +15,13 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v4/testing/endtoend/components/eth1", visibility = ["//testing/endtoend:__subpackages__"], deps = [ - "//beacon-chain/execution/testing:go_default_library", "//config/params:go_default_library", "//contracts/deposit:go_default_library", "//crypto/rand:go_default_library", "//encoding/bytesutil:go_default_library", "//io/file:go_default_library", "//proto/prysm/v1alpha1:go_default_library", + "//runtime/interop:go_default_library", "//testing/endtoend/helpers:go_default_library", "//testing/endtoend/params:go_default_library", "//testing/endtoend/types:go_default_library", diff --git a/testing/endtoend/components/eth1/miner.go b/testing/endtoend/components/eth1/miner.go index ac3d50da5f..c8a393d575 100644 --- a/testing/endtoend/components/eth1/miner.go +++ b/testing/endtoend/components/eth1/miner.go @@ -16,10 +16,10 @@ import ( "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v4/beacon-chain/execution/testing" "github.com/prysmaticlabs/prysm/v4/config/params" contracts "github.com/prysmaticlabs/prysm/v4/contracts/deposit" "github.com/prysmaticlabs/prysm/v4/io/file" + "github.com/prysmaticlabs/prysm/v4/runtime/interop" "github.com/prysmaticlabs/prysm/v4/testing/endtoend/helpers" e2e "github.com/prysmaticlabs/prysm/v4/testing/endtoend/params" e2etypes "github.com/prysmaticlabs/prysm/v4/testing/endtoend/types" @@ -88,7 +88,7 @@ func (m *Miner) initAttempt(ctx context.Context, attempt int) (*os.File, error) } gethJsonPath := path.Join(path.Dir(binaryPath), "genesis.json") - gen := testing.GethTestnetGenesis(e2e.TestParams.Eth1GenesisTime, params.BeaconConfig()) + gen := interop.GethTestnetGenesis(e2e.TestParams.Eth1GenesisTime, params.BeaconConfig()) log.Infof("eth1 miner genesis timestamp=%d", e2e.TestParams.Eth1GenesisTime) b, err := json.Marshal(gen) if err != nil { diff --git a/testing/endtoend/components/eth1/node.go b/testing/endtoend/components/eth1/node.go index 7412a9009a..8f856372af 100644 --- a/testing/endtoend/components/eth1/node.go +++ b/testing/endtoend/components/eth1/node.go @@ -13,9 +13,9 @@ import ( "github.com/bazelbuild/rules_go/go/tools/bazel" "github.com/pkg/errors" - "github.com/prysmaticlabs/prysm/v4/beacon-chain/execution/testing" "github.com/prysmaticlabs/prysm/v4/config/params" "github.com/prysmaticlabs/prysm/v4/io/file" + "github.com/prysmaticlabs/prysm/v4/runtime/interop" "github.com/prysmaticlabs/prysm/v4/testing/endtoend/helpers" e2e "github.com/prysmaticlabs/prysm/v4/testing/endtoend/params" e2etypes "github.com/prysmaticlabs/prysm/v4/testing/endtoend/types" @@ -61,7 +61,7 @@ func (node *Node) Start(ctx context.Context) error { } gethJsonPath := path.Join(eth1Path, "genesis.json") - gen := testing.GethTestnetGenesis(e2e.TestParams.Eth1GenesisTime, params.BeaconConfig()) + gen := interop.GethTestnetGenesis(e2e.TestParams.Eth1GenesisTime, params.BeaconConfig()) b, err := json.Marshal(gen) if err != nil { return err diff --git a/testing/util/BUILD.bazel b/testing/util/BUILD.bazel index 71c27c181b..685a33517b 100644 --- a/testing/util/BUILD.bazel +++ b/testing/util/BUILD.bazel @@ -15,7 +15,6 @@ go_library( "deposits.go", "helpers.go", "merge.go", - "premine-state.go", "state.go", "sync_aggregate.go", "sync_committee.go", @@ -55,7 +54,6 @@ go_library( "//testing/require:go_default_library", "//time/slots:go_default_library", "@com_github_ethereum_go_ethereum//common/hexutil:go_default_library", - "@com_github_ethereum_go_ethereum//core/types:go_default_library", "@com_github_pkg_errors//:go_default_library", "@com_github_prysmaticlabs_go_bitfield//:go_default_library", "@com_github_sirupsen_logrus//:go_default_library",