From 2e49fdb3d22952f47fbead93b344839bfe4fe1e8 Mon Sep 17 00:00:00 2001 From: kasey <489222+kasey@users.noreply.github.com> Date: Tue, 13 Dec 2022 17:13:49 -0600 Subject: [PATCH] Start chain from bellatrix state (#11746) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * WIP trying to start from bellatrix state * env var to control log path with unique paths due to flaky test re-run behavior, logs from a failed test run are overwritten by subsequent retries. This makes it difficult to retrieve logs after the first failed run. It also takes some squinting through output to find the location of the log file in the first place. This flag enables logs to be placed in an arbitrary path. Note that bazel sandboxing generally will force this path to be in the /tmp tree. * WIP - grabbing changes from rm-pre-genesis branch * combine bellatrix state w/ rm-pre-genesis branch * WIP * use encoding/detect for genesis state bytes * WIP more fixes towards start from bellatrix * remove debug wrapping * WIP * multiple bugfixes * fix fork ordering bug and bellatrix genesis blocks * send deposits, spam tx to advance, fix miner alloc * WIP * WIP mess * WIP * Print process ID information for purposes of attaching a debugger * bugs: genesis body_root and deposit index mismatch * fix voting period start, skip altair check * add changes * make it better * rm startup FCU, rm logs * cleanup import grouping&ordering * restore FCU log, get rid of tmp var * rm newline * restore newline * restore wrapped error * rm newline * removing boot node version override this doesn't seem to matter? * add issue number to todo comment * rm commented code * rm vmdebug geth flag * unexport values only used with genesis test pkg and add comments where missing from exported values. * adding comments to special cases for testnets * migrate comments from PR to actual code :) * rm unused test param * mark e2e spawns exempt from gosec warning * Fix DeepSource errors in `proposer_bellatrix.go` (#11739) * Fix DeepSource errors in * Omit receiver name * Address PR comments * Remove unused variable * Fix more DeepSource errors Co-authored-by: Radosław Kapka * Remove `Test_IsExecutionEnabledCapella` (#11752) Co-authored-by: Radosław Kapka * Add REST implementation for Validator's `ProposeBeaconBlock` (#11731) * WIP * WIP * WIP * Add tests * WIP * Add more tests * Address DeepSource errors * Remove unused param * Add more tests * Address PR comments * Address PR comments * Fix formatting * Remove unused parameter * Fix TestLittleEndianBytesToBigInt Co-authored-by: Radosław Kapka * fix validator client (#11755) * fix validator client (cherry picked from commit deb138959a2ffcb89cd2e3eb8304477526f4a168) * Use signed changes in middleware block Co-authored-by: Potuz * API `finalized` metadata field - update protos (#11749) * API `finalized` metadata field - update protos * change nums Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> * log breaks unit tests that don't do full arg setup easiest to just remove it for now * restore prior behavior of phase0 block for altair * update unit tests to account for special case * loosen condition for fork version to match config we don't know which fork version genesis will start from, so we shouldn't force it to be a phase0 genesis. * skip until we can mod configs at runtime * NewGenesisBlockForState computes state root itself * rm noisy log * this log would be noisy in mainnet * fix format specifier, []byte -> string * core.Genesis UnmarshalJson has a value receiver :) * no longer needs to be exported Co-authored-by: Kasey Kirkham Co-authored-by: prestonvanloon Co-authored-by: nisdas Co-authored-by: Patrice Vignola Co-authored-by: Radosław Kapka Co-authored-by: terencechain Co-authored-by: Potuz Co-authored-by: prylabs-bulldozer[bot] <58059840+prylabs-bulldozer[bot]@users.noreply.github.com> --- beacon-chain/blockchain/log.go | 1 + beacon-chain/core/blocks/BUILD.bazel | 7 +- beacon-chain/core/blocks/genesis.go | 68 +++++ beacon-chain/core/transition/BUILD.bazel | 3 + .../core/transition/state-bellatrix.go | 279 ++++++++++++++++++ beacon-chain/db/kv/genesis.go | 27 +- beacon-chain/db/kv/genesis_test.go | 2 +- beacon-chain/execution/rpc_connection.go | 4 +- beacon-chain/execution/service.go | 28 +- beacon-chain/execution/testing/BUILD.bazel | 5 +- beacon-chain/execution/testing/genesis.go | 163 ++++++++++ .../v1alpha1/validator/proposer_eth1data.go | 15 +- .../prysm/v1alpha1/validator/proposer_test.go | 40 ++- config/params/loader_test.go | 2 + config/params/testnet_config_test.go | 2 + config/params/testnet_e2e_config.go | 14 +- network/forks/fork.go | 15 +- network/forks/ordered.go | 8 +- runtime/interop/BUILD.bazel | 7 +- .../generate_genesis_state_bellatrix.go | 62 ++++ .../generate_genesis_state_bellatrix_test.go | 50 ++++ testing/endtoend/components/BUILD.bazel | 8 + testing/endtoend/components/beacon_node.go | 121 +++++++- testing/endtoend/components/eth1/BUILD.bazel | 2 +- testing/endtoend/components/eth1/depositor.go | 10 +- testing/endtoend/components/eth1/helpers.go | 1 - testing/endtoend/components/eth1/miner.go | 89 ++---- testing/endtoend/components/eth1/node.go | 33 ++- .../endtoend/components/eth1/transactions.go | 4 +- .../endtoend/components/lighthouse_beacon.go | 2 +- .../endtoend/components/web3remotesigner.go | 2 +- testing/endtoend/endtoend_test.go | 5 - testing/endtoend/evaluators/BUILD.bazel | 1 + testing/endtoend/evaluators/fork.go | 14 +- testing/endtoend/evaluators/operations.go | 26 +- testing/endtoend/params/BUILD.bazel | 4 +- testing/endtoend/params/params.go | 16 +- .../endtoend/static-files/eth1/BUILD.bazel | 1 - .../endtoend/static-files/eth1/genesis.json | 32 -- testing/util/bellatrix_state.go | 19 +- 40 files changed, 1013 insertions(+), 179 deletions(-) create mode 100644 beacon-chain/core/transition/state-bellatrix.go create mode 100644 beacon-chain/execution/testing/genesis.go create mode 100644 runtime/interop/generate_genesis_state_bellatrix.go create mode 100644 runtime/interop/generate_genesis_state_bellatrix_test.go delete mode 100644 testing/endtoend/static-files/eth1/genesis.json diff --git a/beacon-chain/blockchain/log.go b/beacon-chain/blockchain/log.go index 7e1cfb649..70569d7ee 100644 --- a/beacon-chain/blockchain/log.go +++ b/beacon-chain/blockchain/log.go @@ -87,6 +87,7 @@ func logBlockSyncStatus(block interfaces.BeaconBlock, blockRoot [32]byte, justif "version": version.String(block.Version()), "sinceSlotStartTime": prysmTime.Now().Sub(startTime), "chainServiceProcessedTime": prysmTime.Now().Sub(receivedTime), + "deposits": len(block.Body().Deposits()), }).Debug("Synced new block") } else { log.WithFields(logrus.Fields{ diff --git a/beacon-chain/core/blocks/BUILD.bazel b/beacon-chain/core/blocks/BUILD.bazel index efc50bfcd..f4d6d76bf 100644 --- a/beacon-chain/core/blocks/BUILD.bazel +++ b/beacon-chain/core/blocks/BUILD.bazel @@ -19,12 +19,7 @@ go_library( "withdrawals.go", ], importpath = "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks", - visibility = [ - "//beacon-chain:__subpackages__", - "//testing/spectest:__subpackages__", - "//testing/util:__pkg__", - "//validator:__subpackages__", - ], + visibility = ["//visibility:public"], deps = [ "//beacon-chain/core/helpers:go_default_library", "//beacon-chain/core/signing:go_default_library", diff --git a/beacon-chain/core/blocks/genesis.go b/beacon-chain/core/blocks/genesis.go index 17dda63f2..d6dd3f64b 100644 --- a/beacon-chain/core/blocks/genesis.go +++ b/beacon-chain/core/blocks/genesis.go @@ -3,9 +3,16 @@ package blocks import ( + "context" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/state" fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" "github.com/prysmaticlabs/prysm/v3/config/params" + "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v3/consensus-types/interfaces" "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" + enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1" ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" ) @@ -29,3 +36,64 @@ func NewGenesisBlock(stateRoot []byte) *ethpb.SignedBeaconBlock { } return block } + +var ErrUnrecognizedState = errors.New("uknonwn underlying type for state.BeaconState value") + +func NewGenesisBlockForState(ctx context.Context, st state.BeaconState) (interfaces.SignedBeaconBlock, error) { + root, err := st.HashTreeRoot(ctx) + if err != nil { + return nil, err + } + ps := st.ToProto() + switch ps.(type) { + case *ethpb.BeaconState, *ethpb.BeaconStateAltair: + return blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlock{ + Block: ðpb.BeaconBlock{ + ParentRoot: params.BeaconConfig().ZeroHash[:], + StateRoot: root[:], + Body: ðpb.BeaconBlockBody{ + RandaoReveal: make([]byte, fieldparams.BLSSignatureLength), + Eth1Data: ðpb.Eth1Data{ + DepositRoot: make([]byte, 32), + BlockHash: make([]byte, 32), + }, + Graffiti: make([]byte, 32), + }, + }, + Signature: params.BeaconConfig().EmptySignature[:], + }) + case *ethpb.BeaconStateBellatrix: + return blocks.NewSignedBeaconBlock(ðpb.SignedBeaconBlockBellatrix{ + Block: ðpb.BeaconBlockBellatrix{ + ParentRoot: params.BeaconConfig().ZeroHash[:], + StateRoot: root[:], + Body: ðpb.BeaconBlockBodyBellatrix{ + RandaoReveal: make([]byte, 96), + Eth1Data: ðpb.Eth1Data{ + DepositRoot: make([]byte, 32), + BlockHash: make([]byte, 32), + }, + Graffiti: make([]byte, 32), + SyncAggregate: ðpb.SyncAggregate{ + SyncCommitteeBits: make([]byte, fieldparams.SyncCommitteeLength/8), + SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), + }, + ExecutionPayload: &enginev1.ExecutionPayload{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + Transactions: make([][]byte, 0), + }, + }, + }, + Signature: params.BeaconConfig().EmptySignature[:], + }) + default: + return nil, ErrUnrecognizedState + } +} diff --git a/beacon-chain/core/transition/BUILD.bazel b/beacon-chain/core/transition/BUILD.bazel index a00b22aa0..14c25e831 100644 --- a/beacon-chain/core/transition/BUILD.bazel +++ b/beacon-chain/core/transition/BUILD.bazel @@ -6,6 +6,7 @@ go_library( "log.go", "skip_slot_cache.go", "state.go", + "state-bellatrix.go", "trailing_slot_state_cache.go", "transition.go", "transition_no_verify_sig.go", @@ -36,6 +37,7 @@ go_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", "//consensus-types/interfaces:go_default_library", @@ -45,6 +47,7 @@ go_library( "//encoding/bytesutil:go_default_library", "//math:go_default_library", "//monitoring/tracing:go_default_library", + "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/version:go_default_library", "@com_github_pkg_errors//:go_default_library", diff --git a/beacon-chain/core/transition/state-bellatrix.go b/beacon-chain/core/transition/state-bellatrix.go new file mode 100644 index 000000000..bf6ac6156 --- /dev/null +++ b/beacon-chain/core/transition/state-bellatrix.go @@ -0,0 +1,279 @@ +package transition + +import ( + "context" + + "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/altair" + b "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/state" + state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stateutil" + fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" + "github.com/prysmaticlabs/prysm/v3/config/params" + "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" + enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" +) + +// GenesisBeaconStateBellatrix gets called when MinGenesisActiveValidatorCount count of +// full deposits were made to the deposit contract and the ChainStart log gets emitted. +// +// Spec pseudocode definition: +// +// def initialize_beacon_state_from_eth1(eth1_block_hash: Bytes32, +// eth1_timestamp: uint64, +// deposits: Sequence[Deposit]) -> BeaconState: +// fork = Fork( +// previous_version=GENESIS_FORK_VERSION, +// current_version=GENESIS_FORK_VERSION, +// epoch=GENESIS_EPOCH, +// ) +// state = BeaconState( +// genesis_time=eth1_timestamp + GENESIS_DELAY, +// fork=fork, +// eth1_data=Eth1Data(block_hash=eth1_block_hash, deposit_count=uint64(len(deposits))), +// latest_block_header=BeaconBlockHeader(body_root=hash_tree_root(BeaconBlockBody())), +// randao_mixes=[eth1_block_hash] * EPOCHS_PER_HISTORICAL_VECTOR, # Seed RANDAO with Eth1 entropy +// ) +// +// # Process deposits +// leaves = list(map(lambda deposit: deposit.data, deposits)) +// for index, deposit in enumerate(deposits): +// deposit_data_list = List[DepositData, 2**DEPOSIT_CONTRACT_TREE_DEPTH](*leaves[:index + 1]) +// state.eth1_data.deposit_root = hash_tree_root(deposit_data_list) +// process_deposit(state, deposit) +// +// # Process activations +// for index, validator in enumerate(state.validators): +// balance = state.balances[index] +// validator.effective_balance = min(balance - balance % EFFECTIVE_BALANCE_INCREMENT, MAX_EFFECTIVE_BALANCE) +// if validator.effective_balance == MAX_EFFECTIVE_BALANCE: +// validator.activation_eligibility_epoch = GENESIS_EPOCH +// validator.activation_epoch = GENESIS_EPOCH +// +// # Set genesis validators root for domain separation and chain versioning +// state.genesis_validators_root = hash_tree_root(state.validators) +// +// return state +// +// This method differs from the spec so as to process deposits beforehand instead of the end of the function. +func GenesisBeaconStateBellatrix(ctx context.Context, deposits []*ethpb.Deposit, genesisTime uint64, eth1Data *ethpb.Eth1Data, ep *enginev1.ExecutionPayload) (state.BeaconState, error) { + st, err := EmptyGenesisStateBellatrix() + if err != nil { + return nil, err + } + + // Process initial deposits. + st, err = helpers.UpdateGenesisEth1Data(st, deposits, eth1Data) + if err != nil { + return nil, err + } + + st, err = b.ProcessPreGenesisDeposits(ctx, st, deposits) + if err != nil { + return nil, errors.Wrap(err, "could not process validator deposits") + } + + // After deposits have been processed, overwrite eth1data to what is passed in. This allows us to "pre-mine" validators + // without the deposit root and count mismatching the real deposit contract. + if err := st.SetEth1Data(eth1Data); err != nil { + return nil, err + } + if err := st.SetEth1DepositIndex(eth1Data.DepositCount); err != nil { + return nil, err + } + + return OptimizedGenesisBeaconStateBellatrix(genesisTime, st, st.Eth1Data(), ep) +} + +// OptimizedGenesisBeaconState is used to create a state that has already processed deposits. This is to efficiently +// create a mainnet state at chainstart. +func OptimizedGenesisBeaconStateBellatrix(genesisTime uint64, preState state.BeaconState, eth1Data *ethpb.Eth1Data, ep *enginev1.ExecutionPayload) (state.BeaconState, error) { + if eth1Data == nil { + return nil, errors.New("no eth1data provided for genesis state") + } + + randaoMixes := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) + for i := 0; i < len(randaoMixes); i++ { + h := make([]byte, 32) + copy(h, eth1Data.BlockHash) + randaoMixes[i] = h + } + + zeroHash := params.BeaconConfig().ZeroHash[:] + + activeIndexRoots := make([][]byte, params.BeaconConfig().EpochsPerHistoricalVector) + for i := 0; i < len(activeIndexRoots); i++ { + activeIndexRoots[i] = zeroHash + } + + blockRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(blockRoots); i++ { + blockRoots[i] = zeroHash + } + + stateRoots := make([][]byte, params.BeaconConfig().SlotsPerHistoricalRoot) + for i := 0; i < len(stateRoots); i++ { + stateRoots[i] = zeroHash + } + + slashings := make([]uint64, params.BeaconConfig().EpochsPerSlashingsVector) + + genesisValidatorsRoot, err := stateutil.ValidatorRegistryRoot(preState.Validators()) + if err != nil { + return nil, errors.Wrapf(err, "could not hash tree root genesis validators %v", err) + } + + scores, err := preState.InactivityScores() + if err != nil { + return nil, err + } + scoresMissing := len(preState.Validators()) - len(scores) + if scoresMissing > 0 { + for i := 0; i < scoresMissing; i++ { + scores = append(scores, 0) + } + } + wep, err := blocks.WrappedExecutionPayload(ep) + if err != nil { + return nil, err + } + eph, err := blocks.PayloadToHeader(wep) + if err != nil { + return nil, err + } + st := ðpb.BeaconStateBellatrix{ + // Misc fields. + Slot: 0, + GenesisTime: genesisTime, + GenesisValidatorsRoot: genesisValidatorsRoot[:], + + Fork: ðpb.Fork{ + PreviousVersion: params.BeaconConfig().AltairForkVersion, + CurrentVersion: params.BeaconConfig().BellatrixForkVersion, + Epoch: 0, + }, + + // Validator registry fields. + Validators: preState.Validators(), + Balances: preState.Balances(), + + // Randomness and committees. + RandaoMixes: randaoMixes, + + // Finality. + PreviousJustifiedCheckpoint: ðpb.Checkpoint{ + Epoch: 0, + Root: params.BeaconConfig().ZeroHash[:], + }, + CurrentJustifiedCheckpoint: ðpb.Checkpoint{ + Epoch: 0, + Root: params.BeaconConfig().ZeroHash[:], + }, + JustificationBits: []byte{0}, + FinalizedCheckpoint: ðpb.Checkpoint{ + Epoch: 0, + Root: params.BeaconConfig().ZeroHash[:], + }, + + HistoricalRoots: [][]byte{}, + BlockRoots: blockRoots, + StateRoots: stateRoots, + Slashings: slashings, + + // Eth1 data. + Eth1Data: eth1Data, + Eth1DataVotes: []*ethpb.Eth1Data{}, + Eth1DepositIndex: preState.Eth1DepositIndex(), + LatestExecutionPayloadHeader: eph, + InactivityScores: scores, + } + + bodyRoot, err := (ðpb.BeaconBlockBodyBellatrix{ + RandaoReveal: make([]byte, 96), + Eth1Data: ðpb.Eth1Data{ + DepositRoot: make([]byte, 32), + BlockHash: make([]byte, 32), + }, + Graffiti: make([]byte, 32), + SyncAggregate: ðpb.SyncAggregate{ + SyncCommitteeBits: make([]byte, fieldparams.SyncCommitteeLength/8), + SyncCommitteeSignature: make([]byte, fieldparams.BLSSignatureLength), + }, + ExecutionPayload: &enginev1.ExecutionPayload{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + Transactions: make([][]byte, 0), + }, + }).HashTreeRoot() + if err != nil { + return nil, errors.Wrap(err, "could not hash tree root empty block body") + } + + st.LatestBlockHeader = ðpb.BeaconBlockHeader{ + ParentRoot: zeroHash, + StateRoot: zeroHash, + BodyRoot: bodyRoot[:], + } + + ist, err := state_native.InitializeFromProtoBellatrix(st) + if err != nil { + return nil, err + } + sc, err := altair.NextSyncCommittee(context.Background(), ist) + if err != nil { + return nil, err + } + if err := ist.SetNextSyncCommittee(sc); err != nil { + return nil, err + } + if err := ist.SetCurrentSyncCommittee(sc); err != nil { + return nil, err + } + return ist, nil +} + +// EmptyGenesisState returns an empty beacon state object. +func EmptyGenesisStateBellatrix() (state.BeaconState, error) { + st := ðpb.BeaconStateBellatrix{ + // Misc fields. + Slot: 0, + Fork: ðpb.Fork{ + PreviousVersion: params.BeaconConfig().AltairForkVersion, + CurrentVersion: params.BeaconConfig().BellatrixForkVersion, + Epoch: 0, + }, + // Validator registry fields. + Validators: []*ethpb.Validator{}, + Balances: []uint64{}, + + JustificationBits: []byte{0}, + HistoricalRoots: [][]byte{}, + + // Eth1 data. + Eth1Data: ðpb.Eth1Data{}, + Eth1DataVotes: []*ethpb.Eth1Data{}, + Eth1DepositIndex: 0, + LatestExecutionPayloadHeader: &enginev1.ExecutionPayloadHeader{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + TransactionsRoot: make([]byte, 32), + }, + } + + return state_native.InitializeFromProtoBellatrix(st) +} diff --git a/beacon-chain/db/kv/genesis.go b/beacon-chain/db/kv/genesis.go index c9d70d283..510d69610 100644 --- a/beacon-chain/db/kv/genesis.go +++ b/beacon-chain/db/kv/genesis.go @@ -1,34 +1,25 @@ package kv import ( - "bytes" "context" - "fmt" "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks" dbIface "github.com/prysmaticlabs/prysm/v3/beacon-chain/db/iface" "github.com/prysmaticlabs/prysm/v3/beacon-chain/state" - state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native" - "github.com/prysmaticlabs/prysm/v3/config/params" - consensusblocks "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" + "github.com/prysmaticlabs/prysm/v3/encoding/ssz/detect" ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" ) // SaveGenesisData bootstraps the beaconDB with a given genesis state. func (s *Store) SaveGenesisData(ctx context.Context, genesisState state.BeaconState) error { - stateRoot, err := genesisState.HashTreeRoot(ctx) - if err != nil { - return err - } - genesisBlk := blocks.NewGenesisBlock(stateRoot[:]) - genesisBlkRoot, err := genesisBlk.Block.HashTreeRoot() + wsb, err := blocks.NewGenesisBlockForState(ctx, genesisState) if err != nil { return errors.Wrap(err, "could not get genesis block root") } - wsb, err := consensusblocks.NewSignedBeaconBlock(genesisBlk) + genesisBlkRoot, err := wsb.Block().HashTreeRoot() if err != nil { - return errors.Wrap(err, "could not wrap genesis block") + return errors.Wrap(err, "could not get genesis block root") } if err := s.SaveBlock(ctx, wsb); err != nil { return errors.Wrap(err, "could not save genesis block") @@ -54,11 +45,11 @@ func (s *Store) SaveGenesisData(ctx context.Context, genesisState state.BeaconSt // LoadGenesis loads a genesis state from a ssz-serialized byte slice, if no genesis exists already. func (s *Store) LoadGenesis(ctx context.Context, sb []byte) error { - st := ðpb.BeaconState{} - if err := st.UnmarshalSSZ(sb); err != nil { + vu, err := detect.FromState(sb) + if err != nil { return err } - gs, err := state_native.InitializeFromProtoUnsafePhase0(st) + gs, err := vu.UnmarshalBeaconState(sb) if err != nil { return err } @@ -83,10 +74,6 @@ func (s *Store) LoadGenesis(ctx context.Context, sb []byte) error { return dbIface.ErrExistingGenesisState } - if !bytes.Equal(gs.Fork().CurrentVersion, params.BeaconConfig().GenesisForkVersion) { - return fmt.Errorf("loaded genesis fork version (%#x) does not match config genesis "+ - "fork version (%#x)", gs.Fork().CurrentVersion, params.BeaconConfig().GenesisForkVersion) - } return s.SaveGenesisData(ctx, gs) } diff --git a/beacon-chain/db/kv/genesis_test.go b/beacon-chain/db/kv/genesis_test.go index f4308639c..e954166a7 100644 --- a/beacon-chain/db/kv/genesis_test.go +++ b/beacon-chain/db/kv/genesis_test.go @@ -106,7 +106,7 @@ func TestLoadGenesisFromFile_mismatchedForkVersion(t *testing.T) { // Loading a genesis with the wrong fork version as beacon config should throw an error. db := setupDB(t) - assert.ErrorContains(t, "does not match config genesis fork version", db.LoadGenesis(context.Background(), sb)) + assert.ErrorContains(t, "not found in any known fork choice schedule", db.LoadGenesis(context.Background(), sb)) } func TestEnsureEmbeddedGenesis(t *testing.T) { diff --git a/beacon-chain/execution/rpc_connection.go b/beacon-chain/execution/rpc_connection.go index 250d7e4d4..da8a0e673 100644 --- a/beacon-chain/execution/rpc_connection.go +++ b/beacon-chain/execution/rpc_connection.go @@ -88,13 +88,13 @@ func (s *Service) pollConnectionStatus(ctx context.Context) { // Forces to retry an execution client connection. func (s *Service) retryExecutionClientConnection(ctx context.Context, err error) { - s.runError = err + s.runError = errors.Wrap(err, "retryExecutionClientConnection") s.updateConnectedETH1(false) // Back off for a while before redialing. time.Sleep(backOffPeriod) currClient := s.rpcClient if err := s.setupExecutionClientConnections(ctx, s.cfg.currHttpEndpoint); err != nil { - s.runError = err + s.runError = errors.Wrap(err, "setupExecutionClientConnections") return } // Close previous client, if connection was successful. diff --git a/beacon-chain/execution/service.go b/beacon-chain/execution/service.go index 9043a50b3..06fa05cb0 100644 --- a/beacon-chain/execution/service.go +++ b/beacon-chain/execution/service.go @@ -319,10 +319,15 @@ func (s *Service) followedBlockHeight(ctx context.Context) (uint64, error) { latestBlockTime := uint64(0) if s.latestEth1Data.BlockTime > followTime { latestBlockTime = s.latestEth1Data.BlockTime - followTime + // This should only come into play in testnets - when the chain hasn't advanced past the follow distance, + // we don't want to consider any block before the genesis block. + if s.latestEth1Data.BlockHeight < params.BeaconConfig().Eth1FollowDistance { + latestBlockTime = s.latestEth1Data.BlockTime + } } blk, err := s.BlockByTimestamp(ctx, latestBlockTime) if err != nil { - return 0, err + return 0, errors.Wrapf(err, "BlockByTimestamp=%d", latestBlockTime) } return blk.Number.Uint64(), nil } @@ -467,11 +472,12 @@ func (s *Service) handleETH1FollowDistance() { } if !s.chainStartData.Chainstarted { if err := s.processChainStartFromBlockNum(ctx, big.NewInt(int64(s.latestEth1Data.LastRequestedBlock))); err != nil { - s.runError = err + s.runError = errors.Wrap(err, "processChainStartFromBlockNum") log.Error(err) return } } + // If the last requested block has not changed, // we do not request batched logs as this means there are no new // logs for the powchain service to process. Also it is a potential @@ -481,7 +487,7 @@ func (s *Service) handleETH1FollowDistance() { return } if err := s.requestBatchedHeadersAndLogs(ctx); err != nil { - s.runError = err + s.runError = errors.Wrap(err, "requestBatchedHeadersAndLogs") log.Error(err) return } @@ -511,6 +517,7 @@ func (s *Service) initPOWService() { ctx := s.ctx header, err := s.HeaderByNumber(ctx, nil) if err != nil { + err = errors.Wrap(err, "HeaderByNumber") s.retryExecutionClientConnection(ctx, err) errorLogger(err, "Unable to retrieve latest execution client header") continue @@ -523,6 +530,7 @@ func (s *Service) initPOWService() { s.latestEth1DataLock.Unlock() if err := s.processPastLogs(ctx); err != nil { + err = errors.Wrap(err, "processPastLogs") s.retryExecutionClientConnection(ctx, err) errorLogger( err, @@ -532,6 +540,7 @@ func (s *Service) initPOWService() { } // Cache eth1 headers from our voting period. if err := s.cacheHeadersForEth1DataVote(ctx); err != nil { + err = errors.Wrap(err, "cacheHeadersForEth1DataVote") s.retryExecutionClientConnection(ctx, err) if errors.Is(err, errBlockTimeTooLate) { log.WithError(err).Debug("Unable to cache headers for execution client votes") @@ -550,6 +559,7 @@ func (s *Service) initPOWService() { if genHash != [32]byte{} { genHeader, err := s.HeaderByHash(ctx, genHash) if err != nil { + err = errors.Wrapf(err, "HeaderByHash, hash=%#x", genHash) s.retryExecutionClientConnection(ctx, err) errorLogger(err, "Unable to retrieve proof-of-stake genesis block data") continue @@ -558,6 +568,7 @@ func (s *Service) initPOWService() { } s.chainStartData.GenesisBlock = genBlock if err := s.savePowchainData(ctx); err != nil { + err = errors.Wrap(err, "savePowchainData") s.retryExecutionClientConnection(ctx, err) errorLogger(err, "Unable to save execution client data") continue @@ -641,11 +652,11 @@ func (s *Service) cacheHeadersForEth1DataVote(ctx context.Context) error { // Find the end block to request from. end, err := s.followedBlockHeight(ctx) if err != nil { - return err + return errors.Wrap(err, "followedBlockHeight") } start, err := s.determineEarliestVotingBlock(ctx, end) if err != nil { - return err + return errors.Wrapf(err, "determineEarliestVotingBlock=%d", end) } return s.cacheBlockHeaders(start, end) } @@ -677,7 +688,7 @@ func (s *Service) cacheBlockHeaders(start, end uint64) error { } continue } - return err + return errors.Wrapf(err, "cacheBlockHeaders, start=%d, end=%d", startReq, endReq) } } return nil @@ -696,6 +707,11 @@ func (s *Service) determineEarliestVotingBlock(ctx context.Context, followBlock } return earliestBlk, nil } + // This should only come into play in testnets - when the chain hasn't advanced past the follow distance, + // we don't want to consider any block before the genesis block. + if s.latestEth1Data.BlockHeight < params.BeaconConfig().Eth1FollowDistance { + return 0, nil + } votingTime := slots.VotingPeriodStartTime(genesisTime, currSlot) followBackDist := 2 * params.BeaconConfig().SecondsPerETH1Block * params.BeaconConfig().Eth1FollowDistance if followBackDist > votingTime { diff --git a/beacon-chain/execution/testing/BUILD.bazel b/beacon-chain/execution/testing/BUILD.bazel index ce490c707..b5fbe8e41 100644 --- a/beacon-chain/execution/testing/BUILD.bazel +++ b/beacon-chain/execution/testing/BUILD.bazel @@ -4,13 +4,14 @@ go_library( name = "go_default_library", testonly = True, srcs = [ + "genesis.go", "mock_engine_client.go", "mock_execution_chain.go", "mock_faulty_powchain.go", ], importpath = "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution/testing", visibility = [ - "//beacon-chain:__subpackages__", + "//visibility:public", ], deps = [ "//async/event:go_default_library", @@ -27,7 +28,9 @@ 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/execution/testing/genesis.go b/beacon-chain/execution/testing/genesis.go new file mode 100644 index 000000000..dc52eb2c3 --- /dev/null +++ b/beacon-chain/execution/testing/genesis.go @@ -0,0 +1,163 @@ +package testing + +import ( + "math" + "math/big" + + "github.com/ethereum/go-ethereum/common" + "github.com/ethereum/go-ethereum/common/hexutil" + "github.com/ethereum/go-ethereum/core" + "github.com/ethereum/go-ethereum/params" + clparams "github.com/prysmaticlabs/prysm/v3/config/params" +) + +// defaultMinerAddress is used to send deposits and test transactions in the e2e test. +// This account is given a large initial balance in the genesis block in test setups. +const defaultMinerAddress = "0x878705ba3f8bc32fcf7f4caa1a35e72af65cf766" +const defaultTestChainId int64 = 1337 +const defaultCoinbase = "0x0000000000000000000000000000000000000000" +const defaultDifficulty = "0x20000" +const defaultMixhash = "0x0000000000000000000000000000000000000000000000000000000000000000" +const defaultParenthash = "0x0000000000000000000000000000000000000000000000000000000000000000" +const defaultMinerBalance = "100000000000000000000000000000" + +// DepositContractCode is the compiled deposit contract code, via https://github.com/protolambda/merge-genesis-tools +// This is embedded into genesis so that we can start the chain at a merge block. +// const DepositContractCode = "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100a4578063621fd130146101ba578063c5f2892f14610244575b600080fd5b34801561005057600080fd5b506100906004803603602081101561006757600080fd5b50357fffffffff000000000000000000000000000000000000000000000000000000001661026b565b604080519115158252519081900360200190f35b6101b8600480360360808110156100ba57600080fd5b8101906020810181356401000000008111156100d557600080fd5b8201836020820111156100e757600080fd5b8035906020019184600183028401116401000000008311171561010957600080fd5b91939092909160208101903564010000000081111561012757600080fd5b82018360208201111561013957600080fd5b8035906020019184600183028401116401000000008311171561015b57600080fd5b91939092909160208101903564010000000081111561017957600080fd5b82018360208201111561018b57600080fd5b803590602001918460018302840111640100000000831117156101ad57600080fd5b919350915035610304565b005b3480156101c657600080fd5b506101cf6110b5565b6040805160208082528351818301528351919283929083019185019080838360005b838110156102095781810151838201526020016101f1565b50505050905090810190601f1680156102365780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561025057600080fd5b506102596110c7565b60408051918252519081900360200190f35b60007fffffffff0000000000000000000000000000000000000000000000000000000082167f01ffc9a70000000000000000000000000000000000000000000000000000000014806102fe57507fffffffff0000000000000000000000000000000000000000000000000000000082167f8564090700000000000000000000000000000000000000000000000000000000145b92915050565b6030861461035d576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118056026913960400191505060405180910390fd5b602084146103b6576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252603681526020018061179c6036913960400191505060405180910390fd5b6060821461040f576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260298152602001806118786029913960400191505060405180910390fd5b670de0b6b3a7640000341015610470576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806118526026913960400191505060405180910390fd5b633b9aca003406156104cd576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806117d26033913960400191505060405180910390fd5b633b9aca00340467ffffffffffffffff811115610535576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602781526020018061182b6027913960400191505060405180910390fd5b6060610540826114ba565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a6105756020546114ba565b6040805160a0808252810189905290819060208201908201606083016080840160c085018e8e80828437600083820152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690910187810386528c815260200190508c8c808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe01690920188810386528c5181528c51602091820193918e019250908190849084905b83811015610648578181015183820152602001610630565b50505050905090810190601f1680156106755780820380516001836020036101000a031916815260200191505b5086810383528881526020018989808284376000838201819052601f9091017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0169092018881038452895181528951602091820193918b019250908190849084905b838110156106ef5781810151838201526020016106d7565b50505050905090810190601f16801561071c5780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b604051602001808484808284377fffffffffffffffffffffffffffffffff0000000000000000000000000000000090941691909301908152604080517ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff0818403018152601090920190819052815191955093508392506020850191508083835b602083106107fc57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016107bf565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610859573d6000803e3d6000fd5b5050506040513d602081101561086e57600080fd5b5051905060006002806108846040848a8c6116fe565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108f857805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016108bb565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610955573d6000803e3d6000fd5b5050506040513d602081101561096a57600080fd5b5051600261097b896040818d6116fe565b60405160009060200180848480828437919091019283525050604080518083038152602092830191829052805190945090925082918401908083835b602083106109f457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe090920191602091820191016109b7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610a51573d6000803e3d6000fd5b5050506040513d6020811015610a6657600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610ada57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610a9d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610b37573d6000803e3d6000fd5b5050506040513d6020811015610b4c57600080fd5b50516040805160208101858152929350600092600292839287928f928f92018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610bd957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610b9c565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610c36573d6000803e3d6000fd5b5050506040513d6020811015610c4b57600080fd5b50516040518651600291889160009188916020918201918291908601908083835b60208310610ca957805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610c6c565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610d4e57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610d11565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610dab573d6000803e3d6000fd5b5050506040513d6020811015610dc057600080fd5b5051604080516020818101949094528082019290925280518083038201815260609092019081905281519192909182918401908083835b60208310610e3457805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610df7565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015610e91573d6000803e3d6000fd5b5050506040513d6020811015610ea657600080fd5b50519050858114610f02576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260548152602001806117486054913960600191505060405180910390fd5b60205463ffffffff11610f60576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260218152602001806117276021913960400191505060405180910390fd5b602080546001019081905560005b60208110156110a9578160011660011415610fa0578260008260208110610f9157fe5b0155506110ac95505050505050565b600260008260208110610faf57fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061102557805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101610fe8565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa158015611082573d6000803e3d6000fd5b5050506040513d602081101561109757600080fd5b50519250600282049150600101610f6e565b50fe5b50505050505050565b60606110c26020546114ba565b905090565b6020546000908190815b60208110156112f05781600116600114156111e6576002600082602081106110f557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061116b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161112e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156111c8573d6000803e3d6000fd5b5050506040513d60208110156111dd57600080fd5b505192506112e2565b600283602183602081106111f657fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061126b57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161122e565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa1580156112c8573d6000803e3d6000fd5b5050506040513d60208110156112dd57600080fd5b505192505b6002820491506001016110d1565b506002826112ff6020546114ba565b600060401b6040516020018084815260200183805190602001908083835b6020831061135a57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0909201916020918201910161131d565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790527fffffffffffffffffffffffffffffffffffffffffffffffff000000000000000095909516920191825250604080518083037ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8018152601890920190819052815191955093508392850191508083835b6020831061143f57805182527fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe09092019160209182019101611402565b51815160209384036101000a7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01801990921691161790526040519190930194509192505080830381855afa15801561149c573d6000803e3d6000fd5b5050506040513d60208110156114b157600080fd5b50519250505090565b60408051600880825281830190925260609160208201818036833701905050905060c082901b8060071a60f81b826000815181106114f457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060061a60f81b8260018151811061153757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060051a60f81b8260028151811061157a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060041a60f81b826003815181106115bd57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060031a60f81b8260048151811061160057fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060021a60f81b8260058151811061164357fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060011a60f81b8260068151811061168657fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060001a60f81b826007815181106116c957fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b6000808585111561170d578182fd5b83861115611719578182fd5b505082019391909203915056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a26469706673582212201dd26f37a621703009abf16e77e69c93dc50c79db7f6cc37543e3e0e3decdc9764736f6c634300060b0033" +const DepositContractCode = "0x60806040526004361061003f5760003560e01c806301ffc9a71461004457806322895118146100b6578063621fd130146101e3578063c5f2892f14610273575b600080fd5b34801561005057600080fd5b5061009c6004803603602081101561006757600080fd5b8101908080357bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916906020019092919050505061029e565b604051808215151515815260200191505060405180910390f35b6101e1600480360360808110156100cc57600080fd5b81019080803590602001906401000000008111156100e957600080fd5b8201836020820111156100fb57600080fd5b8035906020019184600183028401116401000000008311171561011d57600080fd5b90919293919293908035906020019064010000000081111561013e57600080fd5b82018360208201111561015057600080fd5b8035906020019184600183028401116401000000008311171561017257600080fd5b90919293919293908035906020019064010000000081111561019357600080fd5b8201836020820111156101a557600080fd5b803590602001918460018302840111640100000000831117156101c757600080fd5b909192939192939080359060200190929190505050610370565b005b3480156101ef57600080fd5b506101f8610fd0565b6040518080602001828103825283818151815260200191508051906020019080838360005b8381101561023857808201518184015260208101905061021d565b50505050905090810190601f1680156102655780820380516001836020036101000a031916815260200191505b509250505060405180910390f35b34801561027f57600080fd5b50610288610fe2565b6040518082815260200191505060405180910390f35b60007f01ffc9a7000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916148061036957507f85640907000000000000000000000000000000000000000000000000000000007bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916827bffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916145b9050919050565b603087879050146103cc576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806116ec6026913960400191505060405180910390fd5b60208585905014610428576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260368152602001806116836036913960400191505060405180910390fd5b60608383905014610484576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602981526020018061175f6029913960400191505060405180910390fd5b670de0b6b3a76400003410156104e5576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260268152602001806117396026913960400191505060405180910390fd5b6000633b9aca0034816104f457fe5b061461054b576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260338152602001806116b96033913960400191505060405180910390fd5b6000633b9aca00348161055a57fe5b04905067ffffffffffffffff80168111156105c0576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004018080602001828103825260278152602001806117126027913960400191505060405180910390fd5b60606105cb82611314565b90507f649bbc62d0e31342afea4e5cd82d4049e7e1ee912fc0889aa790803be39038c589898989858a8a610600602054611314565b60405180806020018060200180602001806020018060200186810386528e8e82818152602001925080828437600081840152601f19601f82011690508083019250505086810385528c8c82818152602001925080828437600081840152601f19601f82011690508083019250505086810384528a818151815260200191508051906020019080838360005b838110156106a657808201518184015260208101905061068b565b50505050905090810190601f1680156106d35780820380516001836020036101000a031916815260200191505b508681038352898982818152602001925080828437600081840152601f19601f820116905080830192505050868103825287818151815260200191508051906020019080838360005b8381101561073757808201518184015260208101905061071c565b50505050905090810190601f1680156107645780820380516001836020036101000a031916815260200191505b509d505050505050505050505050505060405180910390a1600060028a8a600060801b6040516020018084848082843780830192505050826fffffffffffffffffffffffffffffffff19166fffffffffffffffffffffffffffffffff1916815260100193505050506040516020818303038152906040526040518082805190602001908083835b6020831061080e57805182526020820191506020810190506020830392506107eb565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610850573d6000803e3d6000fd5b5050506040513d602081101561086557600080fd5b8101908080519060200190929190505050905060006002808888600090604092610891939291906115da565b6040516020018083838082843780830192505050925050506040516020818303038152906040526040518082805190602001908083835b602083106108eb57805182526020820191506020810190506020830392506108c8565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa15801561092d573d6000803e3d6000fd5b5050506040513d602081101561094257600080fd5b8101908080519060200190929190505050600289896040908092610968939291906115da565b6000801b604051602001808484808284378083019250505082815260200193505050506040516020818303038152906040526040518082805190602001908083835b602083106109cd57805182526020820191506020810190506020830392506109aa565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610a0f573d6000803e3d6000fd5b5050506040513d6020811015610a2457600080fd5b810190808051906020019092919050505060405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610a8e5780518252602082019150602081019050602083039250610a6b565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610ad0573d6000803e3d6000fd5b5050506040513d6020811015610ae557600080fd5b810190808051906020019092919050505090506000600280848c8c604051602001808481526020018383808284378083019250505093505050506040516020818303038152906040526040518082805190602001908083835b60208310610b615780518252602082019150602081019050602083039250610b3e565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610ba3573d6000803e3d6000fd5b5050506040513d6020811015610bb857600080fd5b8101908080519060200190929190505050600286600060401b866040516020018084805190602001908083835b60208310610c085780518252602082019150602081019050602083039250610be5565b6001836020036101000a0380198251168184511680821785525050505050509050018367ffffffffffffffff191667ffffffffffffffff1916815260180182815260200193505050506040516020818303038152906040526040518082805190602001908083835b60208310610c935780518252602082019150602081019050602083039250610c70565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610cd5573d6000803e3d6000fd5b5050506040513d6020811015610cea57600080fd5b810190808051906020019092919050505060405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610d545780518252602082019150602081019050602083039250610d31565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610d96573d6000803e3d6000fd5b5050506040513d6020811015610dab57600080fd5b81019080805190602001909291905050509050858114610e16576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252605481526020018061162f6054913960600191505060405180910390fd5b6001602060020a0360205410610e77576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040180806020018281038252602181526020018061160e6021913960400191505060405180910390fd5b60016020600082825401925050819055506000602054905060008090505b6020811015610fb75760018083161415610ec8578260008260208110610eb757fe5b018190555050505050505050610fc7565b600260008260208110610ed757fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310610f335780518252602082019150602081019050602083039250610f10565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa158015610f75573d6000803e3d6000fd5b5050506040513d6020811015610f8a57600080fd5b8101908080519060200190929190505050925060028281610fa757fe5b0491508080600101915050610e95565b506000610fc057fe5b5050505050505b50505050505050565b6060610fdd602054611314565b905090565b6000806000602054905060008090505b60208110156111d057600180831614156110e05760026000826020811061101557fe5b01548460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b60208310611071578051825260208201915060208101905060208303925061104e565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa1580156110b3573d6000803e3d6000fd5b5050506040513d60208110156110c857600080fd5b810190808051906020019092919050505092506111b6565b600283602183602081106110f057fe5b015460405160200180838152602001828152602001925050506040516020818303038152906040526040518082805190602001908083835b6020831061114b5780518252602082019150602081019050602083039250611128565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa15801561118d573d6000803e3d6000fd5b5050506040513d60208110156111a257600080fd5b810190808051906020019092919050505092505b600282816111c057fe5b0491508080600101915050610ff2565b506002826111df602054611314565b600060401b6040516020018084815260200183805190602001908083835b6020831061122057805182526020820191506020810190506020830392506111fd565b6001836020036101000a0380198251168184511680821785525050505050509050018267ffffffffffffffff191667ffffffffffffffff1916815260180193505050506040516020818303038152906040526040518082805190602001908083835b602083106112a55780518252602082019150602081019050602083039250611282565b6001836020036101000a038019825116818451168082178552505050505050905001915050602060405180830381855afa1580156112e7573d6000803e3d6000fd5b5050506040513d60208110156112fc57600080fd5b81019080805190602001909291905050509250505090565b6060600867ffffffffffffffff8111801561132e57600080fd5b506040519080825280601f01601f1916602001820160405280156113615781602001600182028036833780820191505090505b50905060008260c01b90508060076008811061137957fe5b1a60f81b8260008151811061138a57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806006600881106113c657fe5b1a60f81b826001815181106113d757fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060056008811061141357fe5b1a60f81b8260028151811061142457fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060046008811061146057fe5b1a60f81b8260038151811061147157fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806003600881106114ad57fe5b1a60f81b826004815181106114be57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350806002600881106114fa57fe5b1a60f81b8260058151811061150b57fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060016008811061154757fe5b1a60f81b8260068151811061155857fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a9053508060006008811061159457fe5b1a60f81b826007815181106115a557fe5b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050919050565b600080858511156115ea57600080fd5b838611156115f757600080fd5b600185028301915084860390509450949250505056fe4465706f736974436f6e74726163743a206d65726b6c6520747265652066756c6c4465706f736974436f6e74726163743a207265636f6e7374727563746564204465706f7369744461746120646f6573206e6f74206d6174636820737570706c696564206465706f7369745f646174615f726f6f744465706f736974436f6e74726163743a20696e76616c6964207769746864726177616c5f63726564656e7469616c73206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c7565206e6f74206d756c7469706c65206f6620677765694465706f736974436f6e74726163743a20696e76616c6964207075626b6579206c656e6774684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f20686967684465706f736974436f6e74726163743a206465706f7369742076616c756520746f6f206c6f774465706f736974436f6e74726163743a20696e76616c6964207369676e6174757265206c656e677468a2646970667358221220230afd4b6e3551329e50f1239e08fa3ab7907b77403c4f237d9adf679e8e43cf64736f6c634300060b0033" + +// DefaultDepositContractStorage represents the empty deposit trie used by the deposit contract. +// For details see https://github.com/protolambda/merge-genesis-tools +var DefaultDepositContractStorage = map[string]string{ + "0x0000000000000000000000000000000000000000000000000000000000000022": "0xf5a5fd42d16a20302798ef6ed309979b43003d2320d9f0e8ea9831a92759fb4b", + "0x0000000000000000000000000000000000000000000000000000000000000023": "0xdb56114e00fdd4c1f85c892bf35ac9a89289aaecb1ebd0a96cde606a748b5d71", + "0x0000000000000000000000000000000000000000000000000000000000000024": "0xc78009fdf07fc56a11f122370658a353aaa542ed63e44c4bc15ff4cd105ab33c", + "0x0000000000000000000000000000000000000000000000000000000000000025": "0x536d98837f2dd165a55d5eeae91485954472d56f246df256bf3cae19352a123c", + "0x0000000000000000000000000000000000000000000000000000000000000026": "0x9efde052aa15429fae05bad4d0b1d7c64da64d03d7a1854a588c2cb8430c0d30", + "0x0000000000000000000000000000000000000000000000000000000000000027": "0xd88ddfeed400a8755596b21942c1497e114c302e6118290f91e6772976041fa1", + "0x0000000000000000000000000000000000000000000000000000000000000028": "0x87eb0ddba57e35f6d286673802a4af5975e22506c7cf4c64bb6be5ee11527f2c", + "0x0000000000000000000000000000000000000000000000000000000000000029": "0x26846476fd5fc54a5d43385167c95144f2643f533cc85bb9d16b782f8d7db193", + "0x000000000000000000000000000000000000000000000000000000000000002a": "0x506d86582d252405b840018792cad2bf1259f1ef5aa5f887e13cb2f0094f51e1", + "0x000000000000000000000000000000000000000000000000000000000000002b": "0xffff0ad7e659772f9534c195c815efc4014ef1e1daed4404c06385d11192e92b", + "0x000000000000000000000000000000000000000000000000000000000000002c": "0x6cf04127db05441cd833107a52be852868890e4317e6a02ab47683aa75964220", + "0x000000000000000000000000000000000000000000000000000000000000002d": "0xb7d05f875f140027ef5118a2247bbb84ce8f2f0f1123623085daf7960c329f5f", + "0x000000000000000000000000000000000000000000000000000000000000002e": "0xdf6af5f5bbdb6be9ef8aa618e4bf8073960867171e29676f8b284dea6a08a85e", + "0x000000000000000000000000000000000000000000000000000000000000002f": "0xb58d900f5e182e3c50ef74969ea16c7726c549757cc23523c369587da7293784", + "0x0000000000000000000000000000000000000000000000000000000000000030": "0xd49a7502ffcfb0340b1d7885688500ca308161a7f96b62df9d083b71fcc8f2bb", + "0x0000000000000000000000000000000000000000000000000000000000000031": "0x8fe6b1689256c0d385f42f5bbe2027a22c1996e110ba97c171d3e5948de92beb", + "0x0000000000000000000000000000000000000000000000000000000000000032": "0x8d0d63c39ebade8509e0ae3c9c3876fb5fa112be18f905ecacfecb92057603ab", + "0x0000000000000000000000000000000000000000000000000000000000000033": "0x95eec8b2e541cad4e91de38385f2e046619f54496c2382cb6cacd5b98c26f5a4", + "0x0000000000000000000000000000000000000000000000000000000000000034": "0xf893e908917775b62bff23294dbbe3a1cd8e6cc1c35b4801887b646a6f81f17f", + "0x0000000000000000000000000000000000000000000000000000000000000035": "0xcddba7b592e3133393c16194fac7431abf2f5485ed711db282183c819e08ebaa", + "0x0000000000000000000000000000000000000000000000000000000000000036": "0x8a8d7fe3af8caa085a7639a832001457dfb9128a8061142ad0335629ff23ff9c", + "0x0000000000000000000000000000000000000000000000000000000000000037": "0xfeb3c337d7a51a6fbf00b9e34c52e1c9195c969bd4e7a0bfd51d5c5bed9c1167", + "0x0000000000000000000000000000000000000000000000000000000000000038": "0xe71f0aa83cc32edfbefa9f4d3e0174ca85182eec9f3a09f6a6c0df6377a510d7", + "0x0000000000000000000000000000000000000000000000000000000000000039": "0x31206fa80a50bb6abe29085058f16212212a60eec8f049fecb92d8c8e0a84bc0", + "0x000000000000000000000000000000000000000000000000000000000000003a": "0x21352bfecbeddde993839f614c3dac0a3ee37543f9b412b16199dc158e23b544", + "0x000000000000000000000000000000000000000000000000000000000000003b": "0x619e312724bb6d7c3153ed9de791d764a366b389af13c58bf8a8d90481a46765", + "0x000000000000000000000000000000000000000000000000000000000000003c": "0x7cdd2986268250628d0c10e385c58c6191e6fbe05191bcc04f133f2cea72c1c4", + "0x000000000000000000000000000000000000000000000000000000000000003d": "0x848930bd7ba8cac54661072113fb278869e07bb8587f91392933374d017bcbe1", + "0x000000000000000000000000000000000000000000000000000000000000003e": "0x8869ff2c22b28cc10510d9853292803328be4fb0e80495e8bb8d271f5b889636", + "0x000000000000000000000000000000000000000000000000000000000000003f": "0xb5fe28e79f1b850f8658246ce9b6a1e7b49fc06db7143e8fe0b4f2b0c5523a5c", + "0x0000000000000000000000000000000000000000000000000000000000000040": "0x985e929f70af28d0bdd1a90a808f977f597c7c778c489e98d3bd8910d31ac0f7", +} + +var bigz = big.NewInt(0) +var minerBalance = big.NewInt(0) + +// 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. +// Clique overloads the meaning of the `miner` and `nonce` fields to implement a voting protocol, whereby additional +// signatures can be added to the list (for details see `Repurposing header fields for signing and voting` in EIP-225). +// https://eips.ethereum.org/EIPS/eip-225 +// 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, +// 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 { + cc := ¶ms.ChainConfig{ + ChainID: big.NewInt(defaultTestChainId), + HomesteadBlock: bigz, + DAOForkBlock: bigz, + EIP150Block: bigz, + EIP155Block: bigz, + EIP158Block: bigz, + ByzantiumBlock: bigz, + ConstantinopleBlock: bigz, + PetersburgBlock: bigz, + IstanbulBlock: bigz, + MuirGlacierBlock: bigz, + BerlinBlock: bigz, + LondonBlock: bigz, + ArrowGlacierBlock: bigz, + GrayGlacierBlock: bigz, + MergeNetsplitBlock: bigz, + TerminalTotalDifficulty: bigz, + TerminalTotalDifficultyPassed: false, + } + da := defaultDepositContractAllocation(cfg.DepositContractAddress) + ma := minerAllocation() + return core.Genesis{ + Config: cc, + Nonce: 0, // overridden for authorized signer votes in clique, so we should leave it empty? + Timestamp: genesisTime, + ExtraData: []byte(DefaultCliqueSigner), + GasLimit: math.MaxUint64 >> 1, // shift 1 back from the max, just in case + Difficulty: common.HexToHash(defaultDifficulty).Big(), + Mixhash: common.HexToHash(defaultMixhash), + Coinbase: common.HexToAddress(defaultCoinbase), + Alloc: core.GenesisAlloc{ + da.Address: da.Account, + ma.Address: ma.Account, + }, + ParentHash: common.HexToHash(defaultParenthash), + } +} + +type depositAllocation struct { + Address common.Address + Account core.GenesisAccount +} + +func minerAllocation() depositAllocation { + return depositAllocation{ + Address: common.HexToAddress(defaultMinerAddress), + Account: core.GenesisAccount{ + Balance: minerBalance, + }, + } +} + +func defaultDepositContractAllocation(contractAddress string) depositAllocation { + s := make(map[common.Hash]common.Hash) + for k, v := range DefaultDepositContractStorage { + s[common.HexToHash(k)] = common.HexToHash(v) + } + codeBytes, err := hexutil.Decode(DepositContractCode) + if err != nil { + panic(err) + } + return depositAllocation{ + Address: common.HexToAddress(contractAddress), + Account: core.GenesisAccount{ + Code: codeBytes, + Storage: s, + Balance: bigz, + Nonce: deterministicNonce(0), + }, + } +} + +func deterministicNonce(i uint64) uint64 { + return math.MaxUint64/2 + i +} + +func init() { + err := minerBalance.UnmarshalText([]byte(defaultMinerBalance)) + if err != nil { + panic(err) + } +} diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go index 9caec9744..993fa8c80 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_eth1data.go @@ -45,9 +45,18 @@ func (vs *Server) eth1DataMajorityVote(ctx context.Context, beaconState state.Be } eth1DataNotification = false - eth1FollowDistance := params.BeaconConfig().Eth1FollowDistance - earliestValidTime := votingPeriodStartTime - 2*params.BeaconConfig().SecondsPerETH1Block*eth1FollowDistance - latestValidTime := votingPeriodStartTime - params.BeaconConfig().SecondsPerETH1Block*eth1FollowDistance + genesisTime, _ := vs.Eth1InfoFetcher.GenesisExecutionChainInfo() + followDistanceSeconds := params.BeaconConfig().Eth1FollowDistance * params.BeaconConfig().SecondsPerETH1Block + latestValidTime := votingPeriodStartTime - followDistanceSeconds + earliestValidTime := votingPeriodStartTime - 2*followDistanceSeconds + + // Special case for starting from a pre-mined genesis: the eth1 vote should be genesis until the chain has advanced + // by ETH1_FOLLOW_DISTANCE. The head state should maintain the same ETH1Data until this condition has passed, so + // trust the existing head for the right eth1 vote until we can get a meaningful value from the deposit contract. + if latestValidTime < genesisTime+followDistanceSeconds { + log.WithField("genesisTime", genesisTime).WithField("latestValidTime", latestValidTime).Warn("voting period before genesis + follow distance, using eth1data from head") + return vs.HeadFetcher.HeadETH1Data(), nil + } lastBlockByLatestValidTime, err := vs.Eth1BlockFetcher.BlockByTimestamp(ctx, latestValidTime) if err != nil { diff --git a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go index ad40f57ee..7308ff2c9 100644 --- a/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go +++ b/beacon-chain/rpc/prysm/v1alpha1/validator/proposer_test.go @@ -1103,8 +1103,46 @@ func TestProposer_ValidateDepositTrie(t *testing.T) { } } +func TestProposer_Eth1Data_MajorityVote_SpansGenesis(t *testing.T) { + ctx := context.Background() + // Voting period will span genesis, causing the special case for pre-mined genesis to kick in. + // In other words some part of the valid time range is before genesis, so querying the block cache would fail + // without the special case added to allow this for testnets. + slot := types.Slot(0) + earliestValidTime, latestValidTime := majorityVoteBoundaryTime(slot) + + p := mockExecution.New(). + InsertBlock(50, earliestValidTime, []byte("earliest")). + InsertBlock(100, latestValidTime, []byte("latest")) + + headBlockHash := []byte("headb") + depositCache, err := depositcache.New() + require.NoError(t, err) + ps := &Server{ + ChainStartFetcher: p, + Eth1InfoFetcher: p, + Eth1BlockFetcher: p, + BlockFetcher: p, + DepositFetcher: depositCache, + HeadFetcher: &mock.ChainService{ETH1Data: ðpb.Eth1Data{BlockHash: headBlockHash, DepositCount: 0}}, + } + + beaconState, err := state_native.InitializeFromProtoPhase0(ðpb.BeaconState{ + Slot: slot, + Eth1DataVotes: []*ethpb.Eth1Data{ + {BlockHash: []byte("earliest"), DepositCount: 1}, + }, + }) + require.NoError(t, err) + majorityVoteEth1Data, err := ps.eth1DataMajorityVote(ctx, beaconState) + require.NoError(t, err) + assert.DeepEqual(t, headBlockHash, majorityVoteEth1Data.BlockHash) +} + func TestProposer_Eth1Data_MajorityVote(t *testing.T) { - slot := types.Slot(64) + followDistanceSecs := params.BeaconConfig().Eth1FollowDistance * params.BeaconConfig().SecondsPerETH1Block + followSlots := followDistanceSecs / params.BeaconConfig().SecondsPerSlot + slot := types.Slot(64 + followSlots) earliestValidTime, latestValidTime := majorityVoteBoundaryTime(slot) dc := ethpb.DepositContainer{ diff --git a/config/params/loader_test.go b/config/params/loader_test.go index 1d295cd0e..4ceb25659 100644 --- a/config/params/loader_test.go +++ b/config/params/loader_test.go @@ -23,6 +23,8 @@ import ( var placeholderFields = []string{"UPDATE_TIMEOUT", "EIP4844_FORK_EPOCH", "EIP4844_FORK_VERSION"} func TestLoadConfigFile(t *testing.T) { + // TODO(11750) + t.Skip("needs https://github.com/prysmaticlabs/prysm/issues/11750") // See https://media.githubusercontent.com/media/ethereum/consensus-spec-tests/master/tests/minimal/config/phase0.yaml assertVals := func(name string, fields []string, expected, actual *params.BeaconChainConfig) { // Misc params. diff --git a/config/params/testnet_config_test.go b/config/params/testnet_config_test.go index 2052dd692..4d8d8a651 100644 --- a/config/params/testnet_config_test.go +++ b/config/params/testnet_config_test.go @@ -20,6 +20,8 @@ func testnetConfigFilePath(t *testing.T, network string) string { } func TestE2EConfigParity(t *testing.T) { + // TODO(11750) + t.Skip("needs https://github.com/prysmaticlabs/prysm/issues/11750") params.SetupTestConfigCleanup(t) testDir := bazel.TestTmpDir() yamlDir := filepath.Join(testDir, "config.yaml") diff --git a/config/params/testnet_e2e_config.go b/config/params/testnet_e2e_config.go index 2a8407518..3ab82140d 100644 --- a/config/params/testnet_e2e_config.go +++ b/config/params/testnet_e2e_config.go @@ -1,8 +1,8 @@ package params const ( - altairE2EForkEpoch = 6 - bellatrixE2EForkEpoch = 8 + altairE2EForkEpoch = 0 + bellatrixE2EForkEpoch = 0 ) // E2ETestConfig retrieves the configurations made specifically for E2E testing. @@ -10,6 +10,8 @@ const ( // WARNING: This config is only for testing, it is not meant for use outside of E2E. func E2ETestConfig() *BeaconChainConfig { e2eConfig := MinimalSpecConfig() + e2eConfig.DepositContractAddress = "0x4242424242424242424242424242424242424242" + e2eConfig.Eth1FollowDistance = 8 // Misc. e2eConfig.MinGenesisActiveValidatorCount = 256 @@ -21,7 +23,6 @@ func E2ETestConfig() *BeaconChainConfig { e2eConfig.SlotsPerEpoch = 6 e2eConfig.SqrRootSlotsPerEpoch = 2 e2eConfig.SecondsPerETH1Block = 2 - e2eConfig.Eth1FollowDistance = 8 e2eConfig.EpochsPerEth1VotingPeriod = 2 e2eConfig.ShardCommitteePeriod = 4 e2eConfig.MaxSeedLookahead = 1 @@ -35,7 +36,7 @@ func E2ETestConfig() *BeaconChainConfig { e2eConfig.BellatrixForkEpoch = bellatrixE2EForkEpoch // Terminal Total Difficulty. - e2eConfig.TerminalTotalDifficulty = "616" + e2eConfig.TerminalTotalDifficulty = "0" // Prysm constants. e2eConfig.ConfigName = EndToEndName @@ -50,6 +51,8 @@ func E2ETestConfig() *BeaconChainConfig { func E2EMainnetTestConfig() *BeaconChainConfig { e2eConfig := MainnetConfig().Copy() + e2eConfig.DepositContractAddress = "0x4242424242424242424242424242424242424242" + e2eConfig.Eth1FollowDistance = 8 // Misc. e2eConfig.MinGenesisActiveValidatorCount = 256 @@ -60,7 +63,6 @@ func E2EMainnetTestConfig() *BeaconChainConfig { e2eConfig.SecondsPerSlot = 6 e2eConfig.SqrRootSlotsPerEpoch = 5 e2eConfig.SecondsPerETH1Block = 2 - e2eConfig.Eth1FollowDistance = 8 e2eConfig.ShardCommitteePeriod = 4 // PoW parameters. @@ -72,7 +74,7 @@ func E2EMainnetTestConfig() *BeaconChainConfig { e2eConfig.BellatrixForkEpoch = bellatrixE2EForkEpoch // Terminal Total Difficulty. - e2eConfig.TerminalTotalDifficulty = "616" + e2eConfig.TerminalTotalDifficulty = "0" // Prysm constants. e2eConfig.ConfigName = EndToEndMainnetName diff --git a/network/forks/fork.go b/network/forks/fork.go index f03d0e792..3973fa338 100644 --- a/network/forks/fork.go +++ b/network/forks/fork.go @@ -2,6 +2,7 @@ package forks import ( + "bytes" "math" "sort" "time" @@ -165,7 +166,19 @@ func SortedForkVersions(forkSchedule map[[4]byte]types.Epoch) [][4]byte { i++ } sort.Slice(sortedVersions, func(a, b int) bool { - return forkSchedule[sortedVersions[a]] < forkSchedule[sortedVersions[b]] + // va == "version" a, ie the [4]byte version id + va, vb := sortedVersions[a], sortedVersions[b] + // ea == "epoch" a, ie the types.Epoch corresponding to va + ea, eb := forkSchedule[va], forkSchedule[vb] + // Try to sort by epochs first, which works fine when epochs are all distinct. + // in the case of testnets starting from a given fork, all epochs leading to the fork will be zero. + if ea != eb { + return ea < eb + } + // If the epochs are equal, break the tie with a lexicographic comparison of the fork version bytes. + // eg 2 versions both with a fork epoch of 0, 0x00000000 would come before 0x01000000. + // sort.Slice takes a 'less' func, ie `return a < b`, and when va < vb, bytes.Compare will return -1 + return bytes.Compare(va[:], vb[:]) < 0 }) return sortedVersions } diff --git a/network/forks/ordered.go b/network/forks/ordered.go index 463691388..9a50fcdbb 100644 --- a/network/forks/ordered.go +++ b/network/forks/ordered.go @@ -1,6 +1,7 @@ package forks import ( + "bytes" "sort" "strings" @@ -28,7 +29,12 @@ func (o OrderedSchedule) Len() int { return len(o) } func (o OrderedSchedule) Swap(i, j int) { o[i], o[j] = o[j], o[i] } // Less implements the Less method of sort.Interface -func (o OrderedSchedule) Less(i, j int) bool { return o[i].Epoch < o[j].Epoch } +func (o OrderedSchedule) Less(i, j int) bool { + if o[i].Epoch == o[j].Epoch { + return bytes.Compare(o[i].Version[:], o[j].Version[:]) < 0 + } + return o[i].Epoch < o[j].Epoch +} // VersionForEpoch finds the Version with the highest epoch <= the given epoch func (o OrderedSchedule) VersionForEpoch(epoch types.Epoch) ([fieldparams.VersionLength]byte, error) { diff --git a/runtime/interop/BUILD.bazel b/runtime/interop/BUILD.bazel index 8aedb36da..00ab4ed82 100644 --- a/runtime/interop/BUILD.bazel +++ b/runtime/interop/BUILD.bazel @@ -4,6 +4,7 @@ go_library( name = "go_default_library", srcs = [ "generate_genesis_state.go", + "generate_genesis_state_bellatrix.go", "generate_keys.go", ], importpath = "github.com/prysmaticlabs/prysm/v3/runtime/interop", @@ -18,6 +19,7 @@ go_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", "//time:go_default_library", "@com_github_pkg_errors//:go_default_library", @@ -27,17 +29,20 @@ go_library( go_test( name = "go_default_test", srcs = [ + "generate_genesis_state_bellatrix_test.go", "generate_genesis_state_test.go", "generate_keys_test.go", ], data = [ "keygen_test_vector.yaml", ], + embed = [":go_default_library"], deps = [ - ":go_default_library", "//beacon-chain/core/transition:go_default_library", + "//beacon-chain/state/state-native:go_default_library", "//config/params:go_default_library", "//container/trie:go_default_library", + "//proto/engine/v1:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//testing/assert:go_default_library", "//testing/require:go_default_library", diff --git a/runtime/interop/generate_genesis_state_bellatrix.go b/runtime/interop/generate_genesis_state_bellatrix.go new file mode 100644 index 000000000..23a7fc65f --- /dev/null +++ b/runtime/interop/generate_genesis_state_bellatrix.go @@ -0,0 +1,62 @@ +// Package interop contains deterministic utilities for generating +// genesis states and keys. +package interop + +import ( + "context" + + "github.com/pkg/errors" + coreState "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/transition" + statenative "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native" + "github.com/prysmaticlabs/prysm/v3/config/params" + "github.com/prysmaticlabs/prysm/v3/container/trie" + enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v3/time" +) + +// GenerateGenesisStateBellatrix deterministically given a genesis time and number of validators. +// If a genesis time of 0 is supplied it is set to the current time. +func GenerateGenesisStateBellatrix(ctx context.Context, genesisTime, numValidators uint64, ep *enginev1.ExecutionPayload, ed *ethpb.Eth1Data) (*ethpb.BeaconStateBellatrix, []*ethpb.Deposit, error) { + privKeys, pubKeys, err := DeterministicallyGenerateKeys(0 /*startIndex*/, numValidators) + if err != nil { + return nil, nil, errors.Wrapf(err, "could not deterministically generate keys for %d validators", numValidators) + } + depositDataItems, depositDataRoots, err := DepositDataFromKeys(privKeys, pubKeys) + if err != nil { + return nil, nil, errors.Wrap(err, "could not generate deposit data from keys") + } + return GenerateGenesisStateBellatrixFromDepositData(ctx, genesisTime, depositDataItems, depositDataRoots, ep, ed) +} + +// GenerateGenesisStateBellatrixFromDepositData creates a genesis state given a list of +// deposit data items and their corresponding roots. +func GenerateGenesisStateBellatrixFromDepositData( + ctx context.Context, genesisTime uint64, depositData []*ethpb.Deposit_Data, depositDataRoots [][]byte, ep *enginev1.ExecutionPayload, e1d *ethpb.Eth1Data, +) (*ethpb.BeaconStateBellatrix, []*ethpb.Deposit, error) { + t, err := trie.GenerateTrieFromItems(depositDataRoots, params.BeaconConfig().DepositContractTreeDepth) + if err != nil { + return nil, nil, errors.Wrap(err, "could not generate Merkle trie for deposit proofs") + } + deposits, err := GenerateDepositsFromData(depositData, t) + if err != nil { + return nil, nil, errors.Wrap(err, "could not generate deposits from the deposit data provided") + } + if genesisTime == 0 { + genesisTime = uint64(time.Now().Unix()) + } + beaconState, err := coreState.GenesisBeaconStateBellatrix(ctx, deposits, genesisTime, e1d, ep) + if err != nil { + return nil, nil, errors.Wrap(err, "could not generate genesis state") + } + bsi := beaconState.ToProtoUnsafe() + pbb, ok := bsi.(*ethpb.BeaconStateBellatrix) + if !ok { + return nil, nil, errors.New("unexpected BeaconState version") + } + pbState, err := statenative.ProtobufBeaconStateBellatrix(pbb) + if err != nil { + return nil, nil, err + } + return pbState, deposits, nil +} diff --git a/runtime/interop/generate_genesis_state_bellatrix_test.go b/runtime/interop/generate_genesis_state_bellatrix_test.go new file mode 100644 index 000000000..3aca9e47a --- /dev/null +++ b/runtime/interop/generate_genesis_state_bellatrix_test.go @@ -0,0 +1,50 @@ +package interop + +import ( + "context" + "testing" + + state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native" + "github.com/prysmaticlabs/prysm/v3/config/params" + "github.com/prysmaticlabs/prysm/v3/container/trie" + enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v3/testing/require" +) + +func TestGenerateGenesisStateBellatrix(t *testing.T) { + ep := &enginev1.ExecutionPayload{ + ParentHash: make([]byte, 32), + FeeRecipient: make([]byte, 20), + StateRoot: make([]byte, 32), + ReceiptsRoot: make([]byte, 32), + LogsBloom: make([]byte, 256), + PrevRandao: make([]byte, 32), + BlockNumber: 0, + GasLimit: 0, + GasUsed: 0, + Timestamp: 0, + ExtraData: make([]byte, 32), + BaseFeePerGas: make([]byte, 32), + BlockHash: make([]byte, 32), + Transactions: make([][]byte, 0), + } + e1d := ðpb.Eth1Data{ + DepositRoot: make([]byte, 32), + DepositCount: 0, + BlockHash: make([]byte, 32), + } + g, _, err := GenerateGenesisStateBellatrix(context.Background(), 0, params.BeaconConfig().MinGenesisActiveValidatorCount, ep, e1d) + require.NoError(t, err) + + tr, err := trie.NewTrie(params.BeaconConfig().DepositContractTreeDepth) + require.NoError(t, err) + dr, err := tr.HashTreeRoot() + require.NoError(t, err) + g.Eth1Data.DepositRoot = dr[:] + g.Eth1Data.BlockHash = make([]byte, 32) + st, err := state_native.InitializeFromProtoUnsafeBellatrix(g) + require.NoError(t, err) + _, err = st.MarshalSSZ() + require.NoError(t, err) +} diff --git a/testing/endtoend/components/BUILD.bazel b/testing/endtoend/components/BUILD.bazel index 6e791b4a7..a46113e70 100644 --- a/testing/endtoend/components/BUILD.bazel +++ b/testing/endtoend/components/BUILD.bazel @@ -20,15 +20,23 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v3/testing/endtoend/components", visibility = ["//testing/endtoend:__subpackages__"], deps = [ + "//beacon-chain/core/blocks:go_default_library", + "//beacon-chain/state:go_default_library", + "//beacon-chain/state/state-native:go_default_library", "//cmd:go_default_library", "//cmd/beacon-chain/flags:go_default_library", + "//cmd/beacon-chain/sync/genesis:go_default_library", "//cmd/validator/flags:go_default_library", "//config/features:go_default_library", "//config/fieldparams:go_default_library", "//config/params:go_default_library", "//config/validator/service:go_default_library", + "//container/trie:go_default_library", "//crypto/bls:go_default_library", + "//encoding/bytesutil:go_default_library", "//io/file:go_default_library", + "//proto/engine/v1: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", diff --git a/testing/endtoend/components/beacon_node.go b/testing/endtoend/components/beacon_node.go index 88f09900f..960d3f92c 100644 --- a/testing/endtoend/components/beacon_node.go +++ b/testing/endtoend/components/beacon_node.go @@ -14,10 +14,21 @@ import ( "github.com/bazelbuild/rules_go/go/tools/bazel" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/blocks" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/state" + state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native" cmdshared "github.com/prysmaticlabs/prysm/v3/cmd" "github.com/prysmaticlabs/prysm/v3/cmd/beacon-chain/flags" + "github.com/prysmaticlabs/prysm/v3/cmd/beacon-chain/sync/genesis" "github.com/prysmaticlabs/prysm/v3/config/features" + fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams" "github.com/prysmaticlabs/prysm/v3/config/params" + "github.com/prysmaticlabs/prysm/v3/container/trie" + "github.com/prysmaticlabs/prysm/v3/encoding/bytesutil" + "github.com/prysmaticlabs/prysm/v3/io/file" + enginev1 "github.com/prysmaticlabs/prysm/v3/proto/engine/v1" + ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v3/runtime/interop" "github.com/prysmaticlabs/prysm/v3/testing/endtoend/helpers" e2e "github.com/prysmaticlabs/prysm/v3/testing/endtoend/params" e2etypes "github.com/prysmaticlabs/prysm/v3/testing/endtoend/types" @@ -166,6 +177,108 @@ func NewBeaconNode(config *e2etypes.E2EConfig, index int, enr string) *BeaconNod } } +func (node *BeaconNode) generateGenesis(ctx context.Context) (state.BeaconState, error) { + if e2e.TestParams.Eth1GenesisBlock == nil { + return nil, errors.New("Cannot construct bellatrix block, e2e.TestParams.Eth1GenesisBlock == nil") + } + gb := e2e.TestParams.Eth1GenesisBlock + + // so the DepositRoot in the BeaconState should be set to the HTR of an empty deposit trie. + t, err := trie.NewTrie(params.BeaconConfig().DepositContractTreeDepth) + if err != nil { + return nil, err + } + dr, err := t.HashTreeRoot() + if err != nil { + return nil, err + } + e1d := ðpb.Eth1Data{ + DepositRoot: dr[:], + DepositCount: 0, + BlockHash: gb.Hash().Bytes(), + } + + payload := &enginev1.ExecutionPayload{ + ParentHash: gb.ParentHash().Bytes(), + FeeRecipient: gb.Coinbase().Bytes(), + StateRoot: gb.Root().Bytes(), + ReceiptsRoot: gb.ReceiptHash().Bytes(), + LogsBloom: gb.Bloom().Bytes(), + PrevRandao: params.BeaconConfig().ZeroHash[:], + BlockNumber: gb.NumberU64(), + GasLimit: gb.GasLimit(), + GasUsed: gb.GasUsed(), + Timestamp: gb.Time(), + ExtraData: gb.Extra()[:32], + BaseFeePerGas: bytesutil.PadTo(bytesutil.ReverseByteOrder(gb.BaseFee().Bytes()), fieldparams.RootLength), + BlockHash: gb.Hash().Bytes(), + Transactions: make([][]byte, 0), + } + genesis, _, err := interop.GenerateGenesisStateBellatrix(ctx, e2e.TestParams.CLGenesisTime, params.BeaconConfig().MinGenesisActiveValidatorCount, payload, e1d) + if err != nil { + return nil, err + } + lbhr, err := genesis.LatestBlockHeader.HashTreeRoot() + if err != nil { + return nil, err + } + si, err := state_native.InitializeFromProtoUnsafeBellatrix(genesis) + if err != nil { + return nil, err + } + genb, err := blocks.NewGenesisBlockForState(ctx, si) + if err != nil { + return nil, err + } + gbr, err := genb.Block().HashTreeRoot() + if err != nil { + return nil, err + } + log.WithField("el_block_time", gb.Time()). + WithField("cl_genesis_time", genesis.GenesisTime). + WithField("state_root", fmt.Sprintf("%#x", genb.Block().StateRoot())). + WithField("latest_block_header_root", fmt.Sprintf("%#x", lbhr)). + WithField("latest_block_header_state_root", fmt.Sprintf("%#x", genesis.LatestBlockHeader.StateRoot)). + WithField("latest_block_header_parent_root", fmt.Sprintf("%#x", genesis.LatestBlockHeader.ParentRoot)). + WithField("latest_block_header_body_root", fmt.Sprintf("%#x", genesis.LatestBlockHeader.BodyRoot)). + WithField("derived_block_root", fmt.Sprintf("%#x", gbr)). + WithField("el_block_root", fmt.Sprintf("%#x", genesis.Eth1Data.BlockHash)). + Info("genesis eth1 data") + return si, nil +} + +func (node *BeaconNode) saveGenesis(ctx context.Context) (string, error) { + // The deposit contract starts with an empty trie, we use the BeaconState to "pre-mine" the validator registry, + g, err := node.generateGenesis(ctx) + if err != nil { + return "", err + } + + root, err := g.HashTreeRoot(ctx) + if err != nil { + return "", err + } + lbhr, err := g.LatestBlockHeader().HashTreeRoot() + if err != nil { + return "", err + } + log.WithField("fork_version", g.Fork().CurrentVersion). + WithField("latest_block_header.root", fmt.Sprintf("%#x", lbhr)). + WithField("state_root", fmt.Sprintf("%#x", root)). + Infof("BeaconState info") + + genesisBytes, err := g.MarshalSSZ() + if err != nil { + return "", err + } + genesisDir := path.Join(e2e.TestParams.TestPath, fmt.Sprintf("genesis/%d", node.index)) + if err := file.MkdirAll(genesisDir); err != nil { + return "", err + } + genesisPath := path.Join(genesisDir, "genesis.ssz") + return genesisPath, file.WriteFile(genesisPath, genesisBytes) +} + // Start starts a fresh beacon node, connecting to all passed in beacon nodes. func (node *BeaconNode) Start(ctx context.Context) error { binaryPath, found := bazel.FindBinary("cmd/beacon-chain", "beacon-chain") @@ -191,10 +304,16 @@ func (node *BeaconNode) Start(ctx context.Context) error { jwtPath = path.Join(e2e.TestParams.TestPath, "eth1data/miner/") } jwtPath = path.Join(jwtPath, "geth/jwtsecret") + + genesisPath, err := node.saveGenesis(ctx) + if err != nil { + return err + } args := []string{ + fmt.Sprintf("--%s=%s", genesis.StatePath.Name, genesisPath), fmt.Sprintf("--%s=%s/eth2-beacon-node-%d", cmdshared.DataDirFlag.Name, e2e.TestParams.TestPath, index), fmt.Sprintf("--%s=%s", cmdshared.LogFileName.Name, stdOutFile.Name()), - fmt.Sprintf("--%s=%s", flags.DepositContractFlag.Name, e2e.TestParams.ContractAddress.Hex()), + fmt.Sprintf("--%s=%s", flags.DepositContractFlag.Name, params.BeaconConfig().DepositContractAddress), fmt.Sprintf("--%s=%d", flags.RPCPort.Name, e2e.TestParams.Ports.PrysmBeaconNodeRPCPort+index), fmt.Sprintf("--%s=http://127.0.0.1:%d", flags.ExecutionEngineEndpoint.Name, e2e.TestParams.Ports.Eth1ProxyPort+index), fmt.Sprintf("--%s=%s", flags.ExecutionJWTSecretFlag.Name, jwtPath), diff --git a/testing/endtoend/components/eth1/BUILD.bazel b/testing/endtoend/components/eth1/BUILD.bazel index 687513deb..d5994a296 100644 --- a/testing/endtoend/components/eth1/BUILD.bazel +++ b/testing/endtoend/components/eth1/BUILD.bazel @@ -15,9 +15,9 @@ go_library( importpath = "github.com/prysmaticlabs/prysm/v3/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", - "//contracts/deposit/mock:go_default_library", "//crypto/rand:go_default_library", "//encoding/bytesutil:go_default_library", "//io/file:go_default_library", diff --git a/testing/endtoend/components/eth1/depositor.go b/testing/endtoend/components/eth1/depositor.go index 088aa2014..7e2b4f1f6 100644 --- a/testing/endtoend/components/eth1/depositor.go +++ b/testing/endtoend/components/eth1/depositor.go @@ -10,6 +10,7 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/accounts/keystore" + "github.com/ethereum/go-ethereum/common" gethtypes "github.com/ethereum/go-ethereum/core/types" "github.com/ethereum/go-ethereum/ethclient" "github.com/pkg/errors" @@ -20,6 +21,7 @@ import ( e2e "github.com/prysmaticlabs/prysm/v3/testing/endtoend/params" "github.com/prysmaticlabs/prysm/v3/testing/endtoend/types" "github.com/prysmaticlabs/prysm/v3/testing/util" + log "github.com/sirupsen/logrus" ) var gweiPerEth = big.NewInt(int64(params.BeaconConfig().GweiPerEth)) @@ -143,6 +145,11 @@ type SentDeposit struct { // (using 2 transactions for partial deposits) and then uses WaitForBlocks (which spams the miner node with transactions // to and from its own address) to advance the chain until it has moved forward ETH1_FOLLOW_DISTANCE blocks. func (d *Depositor) SendAndMine(ctx context.Context, offset, nvals int, batch types.DepositBatch, partial bool) error { + balance, err := d.Client.BalanceAt(ctx, d.Key.Address, nil) + if err != nil { + return err + } + log.WithField("balance", balance.String()).WithField("account", d.Key.Address.Hex()).Info("SendAndMine balance check") // This is the "Send" part of the function. Compute deposits for `nvals` validators, // with half of those deposits being split over 2 transactions if the `partial` flag is true, // and throwing away any validators before `offset`. @@ -211,7 +218,8 @@ func (d *Depositor) txops(ctx context.Context) (*bind.TransactOpts, error) { // DepositContract is a special-purpose client for calling the deposit contract. func (d *Depositor) contractDepositor() (*contracts.DepositContract, error) { if d.cd == nil { - contract, err := contracts.NewDepositContract(e2e.TestParams.ContractAddress, d.Client) + addr := common.HexToAddress(params.BeaconConfig().DepositContractAddress) + contract, err := contracts.NewDepositContract(addr, d.Client) if err != nil { return nil, err } diff --git a/testing/endtoend/components/eth1/helpers.go b/testing/endtoend/components/eth1/helpers.go index 740283db1..82e7128b3 100644 --- a/testing/endtoend/components/eth1/helpers.go +++ b/testing/endtoend/components/eth1/helpers.go @@ -20,7 +20,6 @@ const KeystorePassword = "password" const minerPasswordFile = "password.txt" const minerFile = "UTC--2021-12-22T19-14-08.590377700Z--878705ba3f8bc32fcf7f4caa1a35e72af65cf766" -const timeGapPerTX = 100 * time.Millisecond const timeGapPerMiningTX = 250 * time.Millisecond var _ e2etypes.ComponentRunner = (*NodeSet)(nil) diff --git a/testing/endtoend/components/eth1/miner.go b/testing/endtoend/components/eth1/miner.go index dbab7a796..e5b7819b2 100644 --- a/testing/endtoend/components/eth1/miner.go +++ b/testing/endtoend/components/eth1/miner.go @@ -2,23 +2,24 @@ package eth1 import ( "context" + "encoding/json" "fmt" - "math/big" "os" "os/exec" "path" "strings" "syscall" - "time" "github.com/bazelbuild/rules_go/go/tools/bazel" "github.com/ethereum/go-ethereum/accounts/abi/bind" + "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/ethclient" "github.com/ethereum/go-ethereum/rpc" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution/testing" "github.com/prysmaticlabs/prysm/v3/config/params" - contracts "github.com/prysmaticlabs/prysm/v3/contracts/deposit/mock" - io "github.com/prysmaticlabs/prysm/v3/io/file" + contracts "github.com/prysmaticlabs/prysm/v3/contracts/deposit" + "github.com/prysmaticlabs/prysm/v3/io/file" "github.com/prysmaticlabs/prysm/v3/testing/endtoend/helpers" e2e "github.com/prysmaticlabs/prysm/v3/testing/endtoend/params" e2etypes "github.com/prysmaticlabs/prysm/v3/testing/endtoend/types" @@ -86,21 +87,24 @@ func (m *Miner) initAttempt(ctx context.Context, attempt int) (*os.File, error) return nil, errors.New("go-ethereum binary not found") } - staticGenesis, err := e2e.TestParams.Paths.Eth1Runfile("genesis.json") + gethJsonPath := path.Join(path.Dir(binaryPath), "genesis.json") + gen := testing.GethTestnetGenesis(e2e.TestParams.Eth1GenesisTime, params.BeaconConfig()) + log.Infof("eth1 miner genesis timestamp=%d", e2e.TestParams.Eth1GenesisTime) + b, err := json.Marshal(gen) if err != nil { return nil, err } - genesisPath := path.Join(path.Dir(binaryPath), "genesis.json") - if err := io.CopyFile(staticGenesis, genesisPath); err != nil { - return nil, errors.Wrapf(err, "error copying %s to %s", staticGenesis, genesisPath) + if err := file.WriteFile(gethJsonPath, b); err != nil { + return nil, err } - initCmd := exec.CommandContext( - ctx, - binaryPath, - "init", - fmt.Sprintf("--datadir=%s", m.DataDir()), - genesisPath) // #nosec G204 -- Safe + // write the same thing to the logs dir for inspection + gethJsonLogPath := e2e.TestParams.Logfile("genesis.json") + if err := file.WriteFile(gethJsonLogPath, b); err != nil { + return nil, err + } + + initCmd := exec.CommandContext(ctx, binaryPath, "init", fmt.Sprintf("--datadir=%s", m.DataDir()), gethJsonPath) // #nosec G204 -- Safe // redirect stderr to a log file initFile, err := helpers.DeleteAndCreatePath(e2e.TestParams.Logfile("eth1-init_miner.log")) @@ -151,10 +155,10 @@ func (m *Miner) initAttempt(ctx context.Context, attempt int) (*os.File, error) if err != nil { return nil, err } - if err = io.CopyFile(keystorePath, m.DataDir("keystore", minerFile)); err != nil { + if err = file.CopyFile(keystorePath, m.DataDir("keystore", minerFile)); err != nil { return nil, errors.Wrapf(err, "error copying %s to %s", keystorePath, m.DataDir("keystore", minerFile)) } - err = io.WriteFile(pwFile, []byte(KeystorePassword)) + err = file.WriteFile(pwFile, []byte(KeystorePassword)) if err != nil { return nil, err } @@ -170,14 +174,6 @@ func (m *Miner) initAttempt(ctx context.Context, attempt int) (*os.File, error) if err = runCmd.Start(); err != nil { return nil, fmt.Errorf("failed to start eth1 chain: %w", err) } - // check logs for common issues that prevent the EL miner from starting up. - if err = helpers.WaitForTextInFile(minerLog, "Commit new sealing work"); err != nil { - kerr := runCmd.Process.Kill() - if kerr != nil { - log.WithError(kerr).Error("error sending kill to failed miner command process") - } - return nil, fmt.Errorf("mining log not found, this means the eth1 chain had issues starting: %w", err) - } if err = helpers.WaitForTextInFile(minerLog, "Started P2P networking"); err != nil { kerr := runCmd.Process.Kill() if kerr != nil { @@ -220,54 +216,33 @@ func (m *Miner) Start(ctx context.Context) error { return fmt.Errorf("failed to connect to ipc: %w", err) } web3 := ethclient.NewClient(client) - keystorePath, err := e2e.TestParams.Paths.MinerKeyPath() + block, err := web3.BlockByNumber(ctx, nil) if err != nil { return err } - // this is the key for the miner account. miner account balance is pre-mined in genesis.json. - key, err := helpers.KeyFromPath(keystorePath, KeystorePassword) + log.Infof("genesis block timestamp=%d", block.Time()) + eth1BlockHash := block.Hash() + e2e.TestParams.Eth1GenesisBlock = block + log.Infof("miner says genesis block root=%#x", eth1BlockHash) + cAddr := common.HexToAddress(params.BeaconConfig().DepositContractAddress) + code, err := web3.CodeAt(ctx, cAddr, nil) if err != nil { return err } - // Waiting for the blocks to advance by eth1follow to prevent issues reading the chain. - // Note that WaitForBlocks spams transfer transactions (to and from the miner's address) in order to advance. - if err = WaitForBlocks(web3, key, params.BeaconConfig().Eth1FollowDistance); err != nil { - return fmt.Errorf("unable to advance chain: %w", err) - } - - // Time to deploy the contract using the miner's key. - txOpts, err := bind.NewKeyedTransactorWithChainID(key.PrivateKey, big.NewInt(NetworkId)) + log.Infof("contract code size = %d", len(code)) + depositContractCaller, err := contracts.NewDepositContractCaller(cAddr, web3) if err != nil { return err } - nonce, err := web3.PendingNonceAt(ctx, key.Address) + dCount, err := depositContractCaller.GetDepositCount(&bind.CallOpts{}) if err != nil { + log.Error("failed to call get_deposit_count method of deposit contract") return err } - txOpts.Nonce = big.NewInt(0).SetUint64(nonce) - txOpts.Context = ctx - contractAddr, tx, _, err := contracts.DeployDepositContract(txOpts, web3) - if err != nil { - return fmt.Errorf("failed to deploy deposit contract: %w", err) - } - e2e.TestParams.ContractAddress = contractAddr - - // Wait for contract to mine. - for pending := true; pending; _, pending, err = web3.TransactionByHash(ctx, tx.Hash()) { - if err != nil { - return err - } - time.Sleep(timeGapPerTX) - } - - // Advancing the blocks another eth1follow distance to prevent issues reading the chain. - if err = WaitForBlocks(web3, key, params.BeaconConfig().Eth1FollowDistance); err != nil { - return fmt.Errorf("unable to advance chain: %w", err) - } + log.Infof("deposit contract count=%d", dCount) // Mark node as ready. close(m.started) - return m.cmd.Wait() } diff --git a/testing/endtoend/components/eth1/node.go b/testing/endtoend/components/eth1/node.go index ae97015a7..22998ddbf 100644 --- a/testing/endtoend/components/eth1/node.go +++ b/testing/endtoend/components/eth1/node.go @@ -2,6 +2,7 @@ package eth1 import ( "context" + "encoding/json" "fmt" "os" "os/exec" @@ -10,13 +11,15 @@ import ( "strings" "syscall" - log "github.com/sirupsen/logrus" - "github.com/bazelbuild/rules_go/go/tools/bazel" "github.com/pkg/errors" + "github.com/prysmaticlabs/prysm/v3/beacon-chain/execution/testing" + "github.com/prysmaticlabs/prysm/v3/config/params" + "github.com/prysmaticlabs/prysm/v3/io/file" "github.com/prysmaticlabs/prysm/v3/testing/endtoend/helpers" e2e "github.com/prysmaticlabs/prysm/v3/testing/endtoend/params" e2etypes "github.com/prysmaticlabs/prysm/v3/testing/endtoend/types" + log "github.com/sirupsen/logrus" ) // Node represents an ETH1 node. @@ -53,12 +56,26 @@ func (node *Node) Start(ctx context.Context) error { } } - initCmd := exec.CommandContext( - ctx, - binaryPath, - "init", - fmt.Sprintf("--datadir=%s", eth1Path), - binaryPath[:strings.LastIndex(binaryPath, "/")]+"/genesis.json") // #nosec G204 -- Safe + if err := file.MkdirAll(eth1Path); err != nil { + return err + } + gethJsonPath := path.Join(eth1Path, "genesis.json") + + gen := testing.GethTestnetGenesis(e2e.TestParams.Eth1GenesisTime, params.BeaconConfig()) + b, err := json.Marshal(gen) + if err != nil { + return err + } + + if err := file.WriteFile(gethJsonPath, b); err != nil { + return err + } + copyPath := path.Join(e2e.TestParams.LogPath, "eth1-genesis.json") + if err := file.WriteFile(copyPath, b); err != nil { + return err + } + + initCmd := exec.CommandContext(ctx, binaryPath, "init", fmt.Sprintf("--datadir=%s", eth1Path), gethJsonPath) // #nosec G204 -- Safe initFile, err := helpers.DeleteAndCreateFile(e2e.TestParams.LogPath, "eth1-init_"+strconv.Itoa(node.index)+".log") if err != nil { return err diff --git a/testing/endtoend/components/eth1/transactions.go b/testing/endtoend/components/eth1/transactions.go index 99822aaca..bc593524f 100644 --- a/testing/endtoend/components/eth1/transactions.go +++ b/testing/endtoend/components/eth1/transactions.go @@ -70,7 +70,7 @@ func (t *TransactionGenerator) Start(ctx context.Context) error { } f := filler.NewFiller(rnd) // Broadcast Transactions every 3 blocks - txPeriod := time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second + txPeriod := 3 * time.Duration(params.BeaconConfig().SecondsPerSlot) * time.Second ticker := time.NewTicker(txPeriod) gasPrice := big.NewInt(1e11) for { @@ -78,7 +78,7 @@ func (t *TransactionGenerator) Start(ctx context.Context) error { case <-ctx.Done(): return nil case <-ticker.C: - err := SendTransaction(client, mineKey.PrivateKey, f, gasPrice, mineKey.Address.String(), 200, false) + err := SendTransaction(client, mineKey.PrivateKey, f, gasPrice, mineKey.Address.String(), 100, false) if err != nil { return err } diff --git a/testing/endtoend/components/lighthouse_beacon.go b/testing/endtoend/components/lighthouse_beacon.go index f5296eb7b..df317c903 100644 --- a/testing/endtoend/components/lighthouse_beacon.go +++ b/testing/endtoend/components/lighthouse_beacon.go @@ -262,7 +262,7 @@ func (node *LighthouseBeaconNode) createTestnetDir(index int) (string, error) { configPath := filepath.Join(testNetDir, "config.yaml") rawYaml := params.E2EMainnetConfigYaml() // Add in deposit contract in yaml - depContractStr := fmt.Sprintf("\nDEPOSIT_CONTRACT_ADDRESS: %#x", e2e.TestParams.ContractAddress) + depContractStr := fmt.Sprintf("\nDEPOSIT_CONTRACT_ADDRESS: %s", params.BeaconConfig().DepositContractAddress) rawYaml = append(rawYaml, []byte(depContractStr)...) if err := file.MkdirAll(testNetDir); err != nil { diff --git a/testing/endtoend/components/web3remotesigner.go b/testing/endtoend/components/web3remotesigner.go index 65c0e7c07..448339c6f 100644 --- a/testing/endtoend/components/web3remotesigner.go +++ b/testing/endtoend/components/web3remotesigner.go @@ -261,7 +261,7 @@ func (w *Web3RemoteSigner) createTestnetDir() (string, error) { configPath := filepath.Join(testNetDir, "config.yaml") rawYaml := params.E2ETestConfigYaml() // Add in deposit contract in yaml - depContractStr := fmt.Sprintf("\nDEPOSIT_CONTRACT_ADDRESS: %#x", e2e.TestParams.ContractAddress) + depContractStr := fmt.Sprintf("\nDEPOSIT_CONTRACT_ADDRESS: %s", params.BeaconConfig().DepositContractAddress) rawYaml = append(rawYaml, []byte(depContractStr)...) if err := file.MkdirAll(testNetDir); err != nil { diff --git a/testing/endtoend/endtoend_test.go b/testing/endtoend/endtoend_test.go index 046dcaae1..ecfd8b688 100644 --- a/testing/endtoend/endtoend_test.go +++ b/testing/endtoend/endtoend_test.go @@ -84,8 +84,6 @@ func (r *testRunner) runBase(runEvents []runEvent) { if err := helpers.ComponentsStarted(r.comHandler.ctx, []e2etypes.ComponentRunner{miner}); err != nil { return errors.Wrap(err, "eth1Miner component never started - cannot send deposits") } - // refactored send and mine goes here - minGenesisActiveCount := int(params.BeaconConfig().MinGenesisActiveValidatorCount) keyPath, err := e2e.TestParams.Paths.MinerKeyPath() if err != nil { return errors.Wrap(err, "error getting miner key file from bazel static files") @@ -99,9 +97,6 @@ func (r *testRunner) runBase(runEvents []runEvent) { return errors.Wrap(err, "failed to initialize a client to connect to the miner EL node") } r.depositor = ð1.Depositor{Key: key, Client: client, NetworkId: big.NewInt(eth1.NetworkId)} - if err := r.depositor.SendAndMine(r.comHandler.ctx, 0, minGenesisActiveCount, e2etypes.GenesisDepositBatch, true); err != nil { - return errors.Wrap(err, "failed to send and mine deposits") - } if err := r.depositor.Start(r.comHandler.ctx); err != nil { return errors.Wrap(err, "depositor.Start failed") } diff --git a/testing/endtoend/evaluators/BUILD.bazel b/testing/endtoend/evaluators/BUILD.bazel index baa92d4a0..ace2076d8 100644 --- a/testing/endtoend/evaluators/BUILD.bazel +++ b/testing/endtoend/evaluators/BUILD.bazel @@ -40,6 +40,7 @@ go_library( "//proto/eth/v2:go_default_library", "//proto/prysm/v1alpha1:go_default_library", "//runtime/interop:go_default_library", + "//runtime/version:go_default_library", "//testing/endtoend/components:go_default_library", "//testing/endtoend/helpers:go_default_library", "//testing/endtoend/params:go_default_library", diff --git a/testing/endtoend/evaluators/fork.go b/testing/endtoend/evaluators/fork.go index 65b8fc937..8df1f5bf0 100644 --- a/testing/endtoend/evaluators/fork.go +++ b/testing/endtoend/evaluators/fork.go @@ -6,7 +6,9 @@ import ( "github.com/pkg/errors" "github.com/prysmaticlabs/prysm/v3/consensus-types/blocks" + ptypes "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives" ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1" + "github.com/prysmaticlabs/prysm/v3/runtime/version" "github.com/prysmaticlabs/prysm/v3/testing/endtoend/helpers" "github.com/prysmaticlabs/prysm/v3/testing/endtoend/policies" "github.com/prysmaticlabs/prysm/v3/testing/endtoend/types" @@ -15,11 +17,19 @@ import ( ) var streamDeadline = 1 * time.Minute +var startingFork = version.Bellatrix // AltairForkTransition ensures that the Altair hard fork has occurred successfully. var AltairForkTransition = types.Evaluator{ - Name: "altair_fork_transition_%d", - Policy: policies.OnEpoch(helpers.AltairE2EForkEpoch), + Name: "altair_fork_transition_%d", + Policy: func(e ptypes.Epoch) bool { + altair := policies.OnEpoch(helpers.AltairE2EForkEpoch) + // TODO (11750): modify policies to take an end to end config + if startingFork == version.Phase0 { + return altair(e) + } + return false + }, Evaluation: altairForkOccurs, } diff --git a/testing/endtoend/evaluators/operations.go b/testing/endtoend/evaluators/operations.go index dab561b3f..7dc7ea6f1 100644 --- a/testing/endtoend/evaluators/operations.go +++ b/testing/endtoend/evaluators/operations.go @@ -34,7 +34,7 @@ var churnLimit = 4 var depositValCount = e2e.DepositCount // Deposits should be processed in twice the length of the epochs per eth1 voting period. -var depositsInBlockStart = types.Epoch(math.Floor(float64(params.E2ETestConfig().EpochsPerEth1VotingPeriod) * 2)) +var depositsInBlockStart = params.E2ETestConfig().EpochsPerEth1VotingPeriod * 2 // deposits included + finalization + MaxSeedLookahead for activation. var depositActivationStartEpoch = depositsInBlockStart + 2 + params.E2ETestConfig().MaxSeedLookahead @@ -120,15 +120,7 @@ func processesDepositsInBlocks(ec e2etypes.EvaluationContext, conns ...*grpc.Cli return errors.Wrap(err, "failed to convert api response type to SignedBeaconBlock interface") } b := sb.Block() - slot := b.Slot() - eth1Data := b.Body().Eth1Data() deposits := b.Body().Deposits() - fmt.Printf( - "Slot: %d with %d deposits, Eth1 block %#x with %d deposits\n", - slot, - len(deposits), - eth1Data.BlockHash, eth1Data.DepositCount, - ) for _, d := range deposits { k := bytesutil.ToBytes48(d.Data.PublicKey) v := observed[k] @@ -155,7 +147,12 @@ func verifyGraffitiInBlocks(_ e2etypes.EvaluationContext, conns ...*grpc.ClientC if err != nil { return errors.Wrap(err, "failed to get chain head") } - req := ðpb.ListBlocksRequest{QueryFilter: ðpb.ListBlocksRequest_Epoch{Epoch: chainHead.HeadEpoch.Sub(1)}} + begin := chainHead.HeadEpoch + // Prevent underflow when this runs at epoch 0. + if begin > 0 { + begin = begin.Sub(1) + } + req := ðpb.ListBlocksRequest{QueryFilter: ðpb.ListBlocksRequest_Epoch{Epoch: begin}} blks, err := client.ListBeaconBlocks(context.Background(), req) if err != nil { return errors.Wrap(err, "failed to get blocks from beacon-chain") @@ -393,12 +390,18 @@ func validatorsVoteWithTheMajority(_ e2etypes.EvaluationContext, conns ...*grpc. return errors.Wrap(err, "failed to get chain head") } - req := ðpb.ListBlocksRequest{QueryFilter: ðpb.ListBlocksRequest_Epoch{Epoch: chainHead.HeadEpoch.Sub(1)}} + begin := chainHead.HeadEpoch + // Prevent underflow when this runs at epoch 0. + if begin > 0 { + begin = begin.Sub(1) + } + req := ðpb.ListBlocksRequest{QueryFilter: ðpb.ListBlocksRequest_Epoch{Epoch: begin}} blks, err := client.ListBeaconBlocks(context.Background(), req) if err != nil { return errors.Wrap(err, "failed to get blocks from beacon-chain") } + slotsPerVotingPeriod := params.E2ETestConfig().SlotsPerEpoch.Mul(uint64(params.E2ETestConfig().EpochsPerEth1VotingPeriod)) for _, blk := range blks.BlockContainers { var slot types.Slot var vote []byte @@ -422,7 +425,6 @@ func validatorsVoteWithTheMajority(_ e2etypes.EvaluationContext, conns ...*grpc. default: return errors.New("block neither phase0,altair or bellatrix") } - slotsPerVotingPeriod := params.E2ETestConfig().SlotsPerEpoch.Mul(uint64(params.E2ETestConfig().EpochsPerEth1VotingPeriod)) // We treat epoch 1 differently from other epoch for two reasons: // - this evaluator is not executed for epoch 0 so we have to calculate the first slot differently diff --git a/testing/endtoend/params/BUILD.bazel b/testing/endtoend/params/BUILD.bazel index 656b05398..d5187d32a 100644 --- a/testing/endtoend/params/BUILD.bazel +++ b/testing/endtoend/params/BUILD.bazel @@ -8,10 +8,10 @@ go_library( "params.go", ], importpath = "github.com/prysmaticlabs/prysm/v3/testing/endtoend/params", - visibility = ["//testing/endtoend:__subpackages__"], + visibility = ["//visibility:public"], deps = [ "//io/file:go_default_library", - "@com_github_ethereum_go_ethereum//common:go_default_library", + "@com_github_ethereum_go_ethereum//core/types:go_default_library", "@io_bazel_rules_go//go/tools/bazel:go_default_library", ], ) diff --git a/testing/endtoend/params/params.go b/testing/endtoend/params/params.go index e487a7f26..2b2aa2a74 100644 --- a/testing/endtoend/params/params.go +++ b/testing/endtoend/params/params.go @@ -14,8 +14,9 @@ import ( "testing" "time" + "github.com/ethereum/go-ethereum/core/types" + "github.com/bazelbuild/rules_go/go/tools/bazel" - "github.com/ethereum/go-ethereum/common" "github.com/prysmaticlabs/prysm/v3/io/file" ) @@ -26,9 +27,12 @@ type params struct { TestShardIndex int BeaconNodeCount int LighthouseBeaconNodeCount int - ContractAddress common.Address Ports *ports Paths *paths + Eth1GenesisBlock *types.Block + StartTime time.Time + CLGenesisTime uint64 + Eth1GenesisTime uint64 } type ports struct { @@ -149,6 +153,8 @@ const ( ValidatorMetricsPort = ValidatorGatewayPort + portSpan JaegerTracingPort = 9150 + + StartupBufferSecs = 5 ) func logDir() string { @@ -198,12 +204,15 @@ func Init(t *testing.T, beaconNodeCount int) error { return err } + genTime := uint64(time.Now().Unix()) + StartupBufferSecs TestParams = ¶ms{ TestPath: filepath.Join(testPath, fmt.Sprintf("shard-%d", testShardIndex)), LogPath: logPath, TestShardIndex: testShardIndex, BeaconNodeCount: beaconNodeCount, Ports: testPorts, + CLGenesisTime: genTime, + Eth1GenesisTime: genTime, } return nil } @@ -247,6 +256,7 @@ func InitMultiClient(t *testing.T, beaconNodeCount int, lighthouseNodeCount int) return err } + genTime := uint64(time.Now().Unix()) + StartupBufferSecs TestParams = ¶ms{ TestPath: filepath.Join(testPath, fmt.Sprintf("shard-%d", testShardIndex)), LogPath: logPath, @@ -254,6 +264,8 @@ func InitMultiClient(t *testing.T, beaconNodeCount int, lighthouseNodeCount int) BeaconNodeCount: beaconNodeCount, LighthouseBeaconNodeCount: lighthouseNodeCount, Ports: testPorts, + CLGenesisTime: genTime, + Eth1GenesisTime: genTime, } return nil } diff --git a/testing/endtoend/static-files/eth1/BUILD.bazel b/testing/endtoend/static-files/eth1/BUILD.bazel index 68a4d35fd..9ee952809 100644 --- a/testing/endtoend/static-files/eth1/BUILD.bazel +++ b/testing/endtoend/static-files/eth1/BUILD.bazel @@ -2,7 +2,6 @@ filegroup( name = "eth1data", srcs = [ "UTC--2021-12-22T19-14-08.590377700Z--878705ba3f8bc32fcf7f4caa1a35e72af65cf766", - "genesis.json", ], visibility = ["//testing/endtoend:__subpackages__"], ) diff --git a/testing/endtoend/static-files/eth1/genesis.json b/testing/endtoend/static-files/eth1/genesis.json deleted file mode 100644 index bb4a020b9..000000000 --- a/testing/endtoend/static-files/eth1/genesis.json +++ /dev/null @@ -1,32 +0,0 @@ -{ - "config": { - "chainId": 1337, - "homesteadBlock": 0, - "eip150Block": 0, - "eip155Block": 0, - "eip158Block": 0, - "byzantiumBlock": 0, - "constantinopleBlock": 0, - "petersburgBlock": 0, - "istanbulBlock": 0, - "berlinBlock": 0, - "londonBlock": 0, - "mergeForkBlock": 308, - "terminalTotalDifficulty": 616, - "clique": { - "period": 2, - "epoch": 30000 - } - }, - "alloc": { - "0x878705ba3f8bc32fcf7f4caa1a35e72af65cf766": {"balance": "100000000000000000000000000000"} - }, - "coinbase" : "0x0000000000000000000000000000000000000000", - "difficulty": "1", - "extradata": "0x0000000000000000000000000000000000000000000000000000000000000000878705ba3f8bc32fcf7f4caa1a35e72af65cf7660000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", - "gasLimit" : "0xffffff", - "nonce" : "0x0000000000000042", - "mixhash" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "parentHash" : "0x0000000000000000000000000000000000000000000000000000000000000000", - "timestamp" : "0x00" -} \ No newline at end of file diff --git a/testing/util/bellatrix_state.go b/testing/util/bellatrix_state.go index dd5a35f6f..f7cb9bb69 100644 --- a/testing/util/bellatrix_state.go +++ b/testing/util/bellatrix_state.go @@ -134,6 +134,12 @@ func buildGenesisBeaconStateBellatrix(genesisTime uint64, preState state.BeaconS if err != nil { return nil, err } + scoresMissing := len(preState.Validators()) - len(scores) + if scoresMissing > 0 { + for i := 0; i < scoresMissing; i++ { + scores = append(scores, 0) + } + } st := ðpb.BeaconStateBellatrix{ // Misc fields. Slot: 0, @@ -240,5 +246,16 @@ func buildGenesisBeaconStateBellatrix(genesisTime uint64, preState state.BeaconS TransactionsRoot: make([]byte, 32), } - return state_native.InitializeFromProtoBellatrix(st) + bs, err := state_native.InitializeFromProtoBellatrix(st) + if err != nil { + return nil, err + } + is, err := bs.InactivityScores() + if err != nil { + return nil, err + } + if bs.NumValidators() != len(is) { + return nil, errors.New("inactivity score mismatch with num vals") + } + return bs, nil }