E2E from Phase0 or Bellatrix (#11802)

* e2e using dynamic configs; runtime bellatrix setup

* starts from phase0 but fee recipient eval fails

* lower TTD to cross before bellatrix epoch in e2e

* fix debug printf

* fix it

* dynamic ttd and more robust fee_recipient eval

* let multiplication set ttd=0 if bellatrix epoch=0

* refactoring fee recipient test after cognit errors

* lint

* appease deepsource

* deep sourcin

* gazelle

* missed a usage of this when refactoring

Co-authored-by: Kasey Kirkham <kasey@users.noreply.github.com>
Co-authored-by: nisdas <nishdas93@gmail.com>
This commit is contained in:
kasey 2022-12-20 22:43:29 -06:00 committed by GitHub
parent e43152102e
commit d916827fb9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
31 changed files with 534 additions and 297 deletions

View File

@ -43,6 +43,7 @@ go_library(
"//consensus-types/blocks:go_default_library",
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//container/trie:go_default_library",
"//crypto/bls:go_default_library",
"//crypto/hash:go_default_library",
"//encoding/bytesutil:go_default_library",

View File

@ -10,6 +10,7 @@ import (
state_native "github.com/prysmaticlabs/prysm/v3/beacon-chain/state/state-native"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/state/stateutil"
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/container/trie"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
)
@ -75,6 +76,43 @@ func GenesisBeaconState(ctx context.Context, deposits []*ethpb.Deposit, genesisT
return OptimizedGenesisBeaconState(genesisTime, st, st.Eth1Data())
}
// PreminedGenesisBeaconState works almost exactly like GenesisBeaconState, except that it assumes that genesis deposits
// are not represented in the deposit contract and are only found in the genesis state validator registry. In order
// to ensure the deposit root and count match the empty deposit contract deployed in a testnet genesis block, the root
// of an empty deposit trie is computed and used as Eth1Data.deposit_root, and the deposit count is set to 0.
func PreminedGenesisBeaconState(ctx context.Context, deposits []*ethpb.Deposit, genesisTime uint64, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) {
st, err := EmptyGenesisState()
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")
}
t, err := trie.NewTrie(params.BeaconConfig().DepositContractTreeDepth)
if err != nil {
return nil, err
}
dr, err := t.HashTreeRoot()
if err != nil {
return nil, err
}
if err := st.SetEth1Data(&ethpb.Eth1Data{DepositRoot: dr[:], BlockHash: eth1Data.BlockHash}); err != nil {
return nil, err
}
if err := st.SetEth1DepositIndex(0); err != nil {
return nil, err
}
return OptimizedGenesisBeaconState(genesisTime, st, st.Eth1Data())
}
// OptimizedGenesisBeaconState is used to create a state that has already processed deposits. This is to efficiently
// create a mainnet state at chainstart.
func OptimizedGenesisBeaconState(genesisTime uint64, preState state.BeaconState, eth1Data *ethpb.Eth1Data) (state.BeaconState, error) {

View File

@ -718,6 +718,9 @@ func (s *Service) determineEarliestVotingBlock(ctx context.Context, followBlock
return 0, errors.Errorf("invalid genesis time provided. %d > %d", followBackDist, votingTime)
}
earliestValidTime := votingTime - followBackDist
if earliestValidTime < genesisTime {
return 0, nil
}
hdr, err := s.BlockByTimestamp(ctx, earliestValidTime)
if err != nil {
return 0, err

View File

@ -1,6 +1,7 @@
package testing
import (
"fmt"
"math"
"math/big"
@ -16,7 +17,7 @@ import (
const defaultMinerAddress = "0x878705ba3f8bc32fcf7f4caa1a35e72af65cf766"
const defaultTestChainId int64 = 1337
const defaultCoinbase = "0x0000000000000000000000000000000000000000"
const defaultDifficulty = "0x20000"
const defaultDifficulty = "1"
const defaultMixhash = "0x0000000000000000000000000000000000000000000000000000000000000000"
const defaultParenthash = "0x0000000000000000000000000000000000000000000000000000000000000000"
const defaultMinerBalance = "100000000000000000000000000000"
@ -78,6 +79,10 @@ const DefaultCliqueSigner = "0x0000000000000000000000000000000000000000000000000
// 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 {
ttd, ok := big.NewInt(0).SetString(clparams.BeaconConfig().TerminalTotalDifficulty, 10)
if !ok {
panic(fmt.Sprintf("unable to parse TerminalTotalDifficulty as an integer = %s", clparams.BeaconConfig().TerminalTotalDifficulty))
}
cc := &params.ChainConfig{
ChainID: big.NewInt(defaultTestChainId),
HomesteadBlock: bigz,
@ -95,16 +100,24 @@ func GethTestnetGenesis(genesisTime uint64, cfg *clparams.BeaconChainConfig) cor
ArrowGlacierBlock: bigz,
GrayGlacierBlock: bigz,
MergeNetsplitBlock: bigz,
TerminalTotalDifficulty: bigz,
TerminalTotalDifficulty: ttd,
TerminalTotalDifficultyPassed: false,
Clique: &params.CliqueConfig{
Period: cfg.SecondsPerETH1Block,
Epoch: 20000,
},
}
da := defaultDepositContractAllocation(cfg.DepositContractAddress)
ma := minerAllocation()
extra, err := hexutil.Decode(DefaultCliqueSigner)
if err != nil {
panic(fmt.Sprintf("unable to decode DefaultCliqueSigner, with error %v", err.Error()))
}
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),
ExtraData: extra,
GasLimit: math.MaxUint64 >> 1, // shift 1 back from the max, just in case
Difficulty: common.HexToHash(defaultDifficulty).Big(),
Mixhash: common.HexToHash(defaultMixhash),

View File

@ -10,7 +10,6 @@ import (
type Flags struct {
// Configuration related flags.
MinimalConfig bool // MinimalConfig as defined in the spec.
E2EConfig bool // E2EConfig made specifically for testing, do not use except in E2E.
MaxRPCPageSize int // MaxRPCPageSize is used for a cap of page sizes in RPC requests.
}

View File

@ -25,11 +25,7 @@ func isMinimal(lines []string) bool {
return false
}
func UnmarshalConfigFile(path string, conf *BeaconChainConfig) (*BeaconChainConfig, error) {
yamlFile, err := os.ReadFile(path) // #nosec G304
if err != nil {
return nil, errors.Wrap(err, "Failed to read chain config file.")
}
func UnmarshalConfig(yamlFile []byte, conf *BeaconChainConfig) (*BeaconChainConfig, error) {
// To track if config name is defined inside config file.
hasConfigName := false
// Convert 0x hex inputs to fixed bytes arrays
@ -72,6 +68,14 @@ func UnmarshalConfigFile(path string, conf *BeaconChainConfig) (*BeaconChainConf
return conf, nil
}
func UnmarshalConfigFile(path string, conf *BeaconChainConfig) (*BeaconChainConfig, error) {
yamlFile, err := os.ReadFile(path) // #nosec G304
if err != nil {
return nil, errors.Wrap(err, "Failed to read chain config file.")
}
return UnmarshalConfig(yamlFile, conf)
}
// LoadChainConfigFile load, convert hex values into valid param yaml format,
// unmarshal , and apply beacon chain config file.
func LoadChainConfigFile(path string, conf *BeaconChainConfig) error {
@ -201,6 +205,7 @@ func ConfigToYaml(cfg *BeaconChainConfig) []byte {
fmt.Sprintf("TERMINAL_TOTAL_DIFFICULTY: %s", cfg.TerminalTotalDifficulty),
fmt.Sprintf("TERMINAL_BLOCK_HASH: %#x", cfg.TerminalBlockHash),
fmt.Sprintf("TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: %d", cfg.TerminalBlockHashActivationEpoch),
fmt.Sprintf("DEPOSIT_CONTRACT_ADDRESS: %s", cfg.DepositContractAddress),
}
yamlFile := []byte(strings.Join(lines, "\n"))

View File

@ -22,99 +22,115 @@ import (
// These are variables that we don't use in Prysm. (i.e. future hardfork, light client... etc)
var placeholderFields = []string{"UPDATE_TIMEOUT", "EIP4844_FORK_EPOCH", "EIP4844_FORK_VERSION"}
func assertEqualConfigs(t *testing.T, name string, fields []string, expected, actual *params.BeaconChainConfig) {
// Misc params.
assert.Equal(t, expected.MaxCommitteesPerSlot, actual.MaxCommitteesPerSlot, "%s: MaxCommitteesPerSlot", name)
assert.Equal(t, expected.TargetCommitteeSize, actual.TargetCommitteeSize, "%s: TargetCommitteeSize", name)
assert.Equal(t, expected.MaxValidatorsPerCommittee, actual.MaxValidatorsPerCommittee, "%s: MaxValidatorsPerCommittee", name)
assert.Equal(t, expected.MinPerEpochChurnLimit, actual.MinPerEpochChurnLimit, "%s: MinPerEpochChurnLimit", name)
assert.Equal(t, expected.ChurnLimitQuotient, actual.ChurnLimitQuotient, "%s: ChurnLimitQuotient", name)
assert.Equal(t, expected.ShuffleRoundCount, actual.ShuffleRoundCount, "%s: ShuffleRoundCount", name)
assert.Equal(t, expected.MinGenesisActiveValidatorCount, actual.MinGenesisActiveValidatorCount, "%s: MinGenesisActiveValidatorCount", name)
assert.Equal(t, expected.MinGenesisTime, actual.MinGenesisTime, "%s: MinGenesisTime", name)
assert.Equal(t, expected.HysteresisQuotient, actual.HysteresisQuotient, "%s: HysteresisQuotient", name)
assert.Equal(t, expected.HysteresisDownwardMultiplier, actual.HysteresisDownwardMultiplier, "%s: HysteresisDownwardMultiplier", name)
assert.Equal(t, expected.HysteresisUpwardMultiplier, actual.HysteresisUpwardMultiplier, "%s: HysteresisUpwardMultiplier", name)
// Fork Choice params.
assert.Equal(t, expected.SafeSlotsToUpdateJustified, actual.SafeSlotsToUpdateJustified, "%s: SafeSlotsToUpdateJustified", name)
// Validator params.
assert.Equal(t, expected.Eth1FollowDistance, actual.Eth1FollowDistance, "%s: Eth1FollowDistance", name)
assert.Equal(t, expected.TargetAggregatorsPerCommittee, actual.TargetAggregatorsPerCommittee, "%s: TargetAggregatorsPerCommittee", name)
assert.Equal(t, expected.RandomSubnetsPerValidator, actual.RandomSubnetsPerValidator, "%s: RandomSubnetsPerValidator", name)
assert.Equal(t, expected.EpochsPerRandomSubnetSubscription, actual.EpochsPerRandomSubnetSubscription, "%s: EpochsPerRandomSubnetSubscription", name)
assert.Equal(t, expected.SecondsPerETH1Block, actual.SecondsPerETH1Block, "%s: SecondsPerETH1Block", name)
// Deposit contract.
assert.Equal(t, expected.DepositChainID, actual.DepositChainID, "%s: DepositChainID", name)
assert.Equal(t, expected.DepositNetworkID, actual.DepositNetworkID, "%s: DepositNetworkID", name)
assert.Equal(t, expected.DepositContractAddress, actual.DepositContractAddress, "%s: DepositContractAddress", name)
// Gwei values.
assert.Equal(t, expected.MinDepositAmount, actual.MinDepositAmount, "%s: MinDepositAmount", name)
assert.Equal(t, expected.MaxEffectiveBalance, actual.MaxEffectiveBalance, "%s: MaxEffectiveBalance", name)
assert.Equal(t, expected.EjectionBalance, actual.EjectionBalance, "%s: EjectionBalance", name)
assert.Equal(t, expected.EffectiveBalanceIncrement, actual.EffectiveBalanceIncrement, "%s: EffectiveBalanceIncrement", name)
// Initial values.
assert.DeepEqual(t, expected.GenesisForkVersion, actual.GenesisForkVersion, "%s: GenesisForkVersion", name)
assert.DeepEqual(t, expected.BLSWithdrawalPrefixByte, actual.BLSWithdrawalPrefixByte, "%s: BLSWithdrawalPrefixByte", name)
assert.DeepEqual(t, expected.ETH1AddressWithdrawalPrefixByte, actual.ETH1AddressWithdrawalPrefixByte, "%s: ETH1AddressWithdrawalPrefixByte", name)
// Time parameters.
assert.Equal(t, expected.GenesisDelay, actual.GenesisDelay, "%s: GenesisDelay", name)
assert.Equal(t, expected.SecondsPerSlot, actual.SecondsPerSlot, "%s: SecondsPerSlot", name)
assert.Equal(t, expected.MinAttestationInclusionDelay, actual.MinAttestationInclusionDelay, "%s: MinAttestationInclusionDelay", name)
assert.Equal(t, expected.SlotsPerEpoch, actual.SlotsPerEpoch, "%s: SlotsPerEpoch", name)
assert.Equal(t, expected.MinSeedLookahead, actual.MinSeedLookahead, "%s: MinSeedLookahead", name)
assert.Equal(t, expected.MaxSeedLookahead, actual.MaxSeedLookahead, "%s: MaxSeedLookahead", name)
assert.Equal(t, expected.EpochsPerEth1VotingPeriod, actual.EpochsPerEth1VotingPeriod, "%s: EpochsPerEth1VotingPeriod", name)
assert.Equal(t, expected.SlotsPerHistoricalRoot, actual.SlotsPerHistoricalRoot, "%s: SlotsPerHistoricalRoot", name)
assert.Equal(t, expected.MinValidatorWithdrawabilityDelay, actual.MinValidatorWithdrawabilityDelay, "%s: MinValidatorWithdrawabilityDelay", name)
assert.Equal(t, expected.ShardCommitteePeriod, actual.ShardCommitteePeriod, "%s: ShardCommitteePeriod", name)
assert.Equal(t, expected.MinEpochsToInactivityPenalty, actual.MinEpochsToInactivityPenalty, "%s: MinEpochsToInactivityPenalty", name)
// State vector lengths.
assert.Equal(t, expected.EpochsPerHistoricalVector, actual.EpochsPerHistoricalVector, "%s: EpochsPerHistoricalVector", name)
assert.Equal(t, expected.EpochsPerSlashingsVector, actual.EpochsPerSlashingsVector, "%s: EpochsPerSlashingsVector", name)
assert.Equal(t, expected.HistoricalRootsLimit, actual.HistoricalRootsLimit, "%s: HistoricalRootsLimit", name)
assert.Equal(t, expected.ValidatorRegistryLimit, actual.ValidatorRegistryLimit, "%s: ValidatorRegistryLimit", name)
// Reward and penalty quotients.
assert.Equal(t, expected.BaseRewardFactor, actual.BaseRewardFactor, "%s: BaseRewardFactor", name)
assert.Equal(t, expected.WhistleBlowerRewardQuotient, actual.WhistleBlowerRewardQuotient, "%s: WhistleBlowerRewardQuotient", name)
assert.Equal(t, expected.ProposerRewardQuotient, actual.ProposerRewardQuotient, "%s: ProposerRewardQuotient", name)
assert.Equal(t, expected.InactivityPenaltyQuotient, actual.InactivityPenaltyQuotient, "%s: InactivityPenaltyQuotient", name)
assert.Equal(t, expected.InactivityPenaltyQuotientAltair, actual.InactivityPenaltyQuotientAltair, "%s: InactivityPenaltyQuotientAltair", name)
assert.Equal(t, expected.MinSlashingPenaltyQuotient, actual.MinSlashingPenaltyQuotient, "%s: MinSlashingPenaltyQuotient", name)
assert.Equal(t, expected.MinSlashingPenaltyQuotientAltair, actual.MinSlashingPenaltyQuotientAltair, "%s: MinSlashingPenaltyQuotientAltair", name)
assert.Equal(t, expected.ProportionalSlashingMultiplier, actual.ProportionalSlashingMultiplier, "%s: ProportionalSlashingMultiplier", name)
assert.Equal(t, expected.ProportionalSlashingMultiplierAltair, actual.ProportionalSlashingMultiplierAltair, "%s: ProportionalSlashingMultiplierAltair", name)
// Max operations per block.
assert.Equal(t, expected.MaxProposerSlashings, actual.MaxProposerSlashings, "%s: MaxProposerSlashings", name)
assert.Equal(t, expected.MaxAttesterSlashings, actual.MaxAttesterSlashings, "%s: MaxAttesterSlashings", name)
assert.Equal(t, expected.MaxAttestations, actual.MaxAttestations, "%s: MaxAttestations", name)
assert.Equal(t, expected.MaxDeposits, actual.MaxDeposits, "%s: MaxDeposits", name)
assert.Equal(t, expected.MaxVoluntaryExits, actual.MaxVoluntaryExits, "%s: MaxVoluntaryExits", name)
// Signature domains.
assert.Equal(t, expected.DomainBeaconProposer, actual.DomainBeaconProposer, "%s: DomainBeaconProposer", name)
assert.Equal(t, expected.DomainBeaconAttester, actual.DomainBeaconAttester, "%s: DomainBeaconAttester", name)
assert.Equal(t, expected.DomainRandao, actual.DomainRandao, "%s: DomainRandao", name)
assert.Equal(t, expected.DomainDeposit, actual.DomainDeposit, "%s: DomainDeposit", name)
assert.Equal(t, expected.DomainVoluntaryExit, actual.DomainVoluntaryExit, "%s: DomainVoluntaryExit", name)
assert.Equal(t, expected.DomainSelectionProof, actual.DomainSelectionProof, "%s: DomainSelectionProof", name)
assert.Equal(t, expected.DomainAggregateAndProof, actual.DomainAggregateAndProof, "%s: DomainAggregateAndProof", name)
assert.Equal(t, expected.TerminalTotalDifficulty, actual.TerminalTotalDifficulty, "%s: DomainAggregateAndProof", name)
assert.Equal(t, expected.AltairForkEpoch, actual.AltairForkEpoch, "%s: DomainAggregateAndProof", name)
assert.Equal(t, expected.BellatrixForkEpoch, actual.BellatrixForkEpoch, "%s: DomainAggregateAndProof", name)
assert.Equal(t, expected.SqrRootSlotsPerEpoch, actual.SqrRootSlotsPerEpoch, "%s: DomainAggregateAndProof", name)
assert.DeepEqual(t, expected.GenesisForkVersion, actual.GenesisForkVersion, "%s: DomainAggregateAndProof", name)
assert.DeepEqual(t, expected.AltairForkVersion, actual.AltairForkVersion, "%s: DomainAggregateAndProof", name)
assert.DeepEqual(t, expected.BellatrixForkVersion, actual.BellatrixForkVersion, "%s: DomainAggregateAndProof", name)
assertYamlFieldsMatch(t, name, fields, expected, actual)
}
func TestModifiedE2E(t *testing.T) {
c := params.E2ETestConfig().Copy()
c.DepositContractAddress = "0x4242424242424242424242424242424242424242"
c.TerminalTotalDifficulty = "0"
c.AltairForkEpoch = 0
c.BellatrixForkEpoch = 0
y := params.ConfigToYaml(c)
cfg, err := params.UnmarshalConfig(y, nil)
require.NoError(t, err)
assertEqualConfigs(t, "modified-e2e", []string{}, c, cfg)
}
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.
assert.Equal(t, expected.MaxCommitteesPerSlot, actual.MaxCommitteesPerSlot, "%s: MaxCommitteesPerSlot", name)
assert.Equal(t, expected.TargetCommitteeSize, actual.TargetCommitteeSize, "%s: TargetCommitteeSize", name)
assert.Equal(t, expected.MaxValidatorsPerCommittee, actual.MaxValidatorsPerCommittee, "%s: MaxValidatorsPerCommittee", name)
assert.Equal(t, expected.MinPerEpochChurnLimit, actual.MinPerEpochChurnLimit, "%s: MinPerEpochChurnLimit", name)
assert.Equal(t, expected.ChurnLimitQuotient, actual.ChurnLimitQuotient, "%s: ChurnLimitQuotient", name)
assert.Equal(t, expected.ShuffleRoundCount, actual.ShuffleRoundCount, "%s: ShuffleRoundCount", name)
assert.Equal(t, expected.MinGenesisActiveValidatorCount, actual.MinGenesisActiveValidatorCount, "%s: MinGenesisActiveValidatorCount", name)
assert.Equal(t, expected.MinGenesisTime, actual.MinGenesisTime, "%s: MinGenesisTime", name)
assert.Equal(t, expected.HysteresisQuotient, actual.HysteresisQuotient, "%s: HysteresisQuotient", name)
assert.Equal(t, expected.HysteresisDownwardMultiplier, actual.HysteresisDownwardMultiplier, "%s: HysteresisDownwardMultiplier", name)
assert.Equal(t, expected.HysteresisUpwardMultiplier, actual.HysteresisUpwardMultiplier, "%s: HysteresisUpwardMultiplier", name)
// Fork Choice params.
assert.Equal(t, expected.SafeSlotsToUpdateJustified, actual.SafeSlotsToUpdateJustified, "%s: SafeSlotsToUpdateJustified", name)
// Validator params.
assert.Equal(t, expected.Eth1FollowDistance, actual.Eth1FollowDistance, "%s: Eth1FollowDistance", name)
assert.Equal(t, expected.TargetAggregatorsPerCommittee, actual.TargetAggregatorsPerCommittee, "%s: TargetAggregatorsPerCommittee", name)
assert.Equal(t, expected.RandomSubnetsPerValidator, actual.RandomSubnetsPerValidator, "%s: RandomSubnetsPerValidator", name)
assert.Equal(t, expected.EpochsPerRandomSubnetSubscription, actual.EpochsPerRandomSubnetSubscription, "%s: EpochsPerRandomSubnetSubscription", name)
assert.Equal(t, expected.SecondsPerETH1Block, actual.SecondsPerETH1Block, "%s: SecondsPerETH1Block", name)
// Deposit contract.
assert.Equal(t, expected.DepositChainID, actual.DepositChainID, "%s: DepositChainID", name)
assert.Equal(t, expected.DepositNetworkID, actual.DepositNetworkID, "%s: DepositNetworkID", name)
assert.Equal(t, expected.DepositContractAddress, actual.DepositContractAddress, "%s: DepositContractAddress", name)
// Gwei values.
assert.Equal(t, expected.MinDepositAmount, actual.MinDepositAmount, "%s: MinDepositAmount", name)
assert.Equal(t, expected.MaxEffectiveBalance, actual.MaxEffectiveBalance, "%s: MaxEffectiveBalance", name)
assert.Equal(t, expected.EjectionBalance, actual.EjectionBalance, "%s: EjectionBalance", name)
assert.Equal(t, expected.EffectiveBalanceIncrement, actual.EffectiveBalanceIncrement, "%s: EffectiveBalanceIncrement", name)
// Initial values.
assert.DeepEqual(t, expected.GenesisForkVersion, actual.GenesisForkVersion, "%s: GenesisForkVersion", name)
assert.DeepEqual(t, expected.BLSWithdrawalPrefixByte, actual.BLSWithdrawalPrefixByte, "%s: BLSWithdrawalPrefixByte", name)
assert.DeepEqual(t, expected.ETH1AddressWithdrawalPrefixByte, actual.ETH1AddressWithdrawalPrefixByte, "%s: ETH1AddressWithdrawalPrefixByte", name)
// Time parameters.
assert.Equal(t, expected.GenesisDelay, actual.GenesisDelay, "%s: GenesisDelay", name)
assert.Equal(t, expected.SecondsPerSlot, actual.SecondsPerSlot, "%s: SecondsPerSlot", name)
assert.Equal(t, expected.MinAttestationInclusionDelay, actual.MinAttestationInclusionDelay, "%s: MinAttestationInclusionDelay", name)
assert.Equal(t, expected.SlotsPerEpoch, actual.SlotsPerEpoch, "%s: SlotsPerEpoch", name)
assert.Equal(t, expected.MinSeedLookahead, actual.MinSeedLookahead, "%s: MinSeedLookahead", name)
assert.Equal(t, expected.MaxSeedLookahead, actual.MaxSeedLookahead, "%s: MaxSeedLookahead", name)
assert.Equal(t, expected.EpochsPerEth1VotingPeriod, actual.EpochsPerEth1VotingPeriod, "%s: EpochsPerEth1VotingPeriod", name)
assert.Equal(t, expected.SlotsPerHistoricalRoot, actual.SlotsPerHistoricalRoot, "%s: SlotsPerHistoricalRoot", name)
assert.Equal(t, expected.MinValidatorWithdrawabilityDelay, actual.MinValidatorWithdrawabilityDelay, "%s: MinValidatorWithdrawabilityDelay", name)
assert.Equal(t, expected.ShardCommitteePeriod, actual.ShardCommitteePeriod, "%s: ShardCommitteePeriod", name)
assert.Equal(t, expected.MinEpochsToInactivityPenalty, actual.MinEpochsToInactivityPenalty, "%s: MinEpochsToInactivityPenalty", name)
// State vector lengths.
assert.Equal(t, expected.EpochsPerHistoricalVector, actual.EpochsPerHistoricalVector, "%s: EpochsPerHistoricalVector", name)
assert.Equal(t, expected.EpochsPerSlashingsVector, actual.EpochsPerSlashingsVector, "%s: EpochsPerSlashingsVector", name)
assert.Equal(t, expected.HistoricalRootsLimit, actual.HistoricalRootsLimit, "%s: HistoricalRootsLimit", name)
assert.Equal(t, expected.ValidatorRegistryLimit, actual.ValidatorRegistryLimit, "%s: ValidatorRegistryLimit", name)
// Reward and penalty quotients.
assert.Equal(t, expected.BaseRewardFactor, actual.BaseRewardFactor, "%s: BaseRewardFactor", name)
assert.Equal(t, expected.WhistleBlowerRewardQuotient, actual.WhistleBlowerRewardQuotient, "%s: WhistleBlowerRewardQuotient", name)
assert.Equal(t, expected.ProposerRewardQuotient, actual.ProposerRewardQuotient, "%s: ProposerRewardQuotient", name)
assert.Equal(t, expected.InactivityPenaltyQuotient, actual.InactivityPenaltyQuotient, "%s: InactivityPenaltyQuotient", name)
assert.Equal(t, expected.InactivityPenaltyQuotientAltair, actual.InactivityPenaltyQuotientAltair, "%s: InactivityPenaltyQuotientAltair", name)
assert.Equal(t, expected.MinSlashingPenaltyQuotient, actual.MinSlashingPenaltyQuotient, "%s: MinSlashingPenaltyQuotient", name)
assert.Equal(t, expected.MinSlashingPenaltyQuotientAltair, actual.MinSlashingPenaltyQuotientAltair, "%s: MinSlashingPenaltyQuotientAltair", name)
assert.Equal(t, expected.ProportionalSlashingMultiplier, actual.ProportionalSlashingMultiplier, "%s: ProportionalSlashingMultiplier", name)
assert.Equal(t, expected.ProportionalSlashingMultiplierAltair, actual.ProportionalSlashingMultiplierAltair, "%s: ProportionalSlashingMultiplierAltair", name)
// Max operations per block.
assert.Equal(t, expected.MaxProposerSlashings, actual.MaxProposerSlashings, "%s: MaxProposerSlashings", name)
assert.Equal(t, expected.MaxAttesterSlashings, actual.MaxAttesterSlashings, "%s: MaxAttesterSlashings", name)
assert.Equal(t, expected.MaxAttestations, actual.MaxAttestations, "%s: MaxAttestations", name)
assert.Equal(t, expected.MaxDeposits, actual.MaxDeposits, "%s: MaxDeposits", name)
assert.Equal(t, expected.MaxVoluntaryExits, actual.MaxVoluntaryExits, "%s: MaxVoluntaryExits", name)
// Signature domains.
assert.Equal(t, expected.DomainBeaconProposer, actual.DomainBeaconProposer, "%s: DomainBeaconProposer", name)
assert.Equal(t, expected.DomainBeaconAttester, actual.DomainBeaconAttester, "%s: DomainBeaconAttester", name)
assert.Equal(t, expected.DomainRandao, actual.DomainRandao, "%s: DomainRandao", name)
assert.Equal(t, expected.DomainDeposit, actual.DomainDeposit, "%s: DomainDeposit", name)
assert.Equal(t, expected.DomainVoluntaryExit, actual.DomainVoluntaryExit, "%s: DomainVoluntaryExit", name)
assert.Equal(t, expected.DomainSelectionProof, actual.DomainSelectionProof, "%s: DomainSelectionProof", name)
assert.Equal(t, expected.DomainAggregateAndProof, actual.DomainAggregateAndProof, "%s: DomainAggregateAndProof", name)
assertYamlFieldsMatch(t, name, fields, expected, actual)
}
t.Run("mainnet", func(t *testing.T) {
mn := params.MainnetConfig().Copy()
mainnetPresetsFiles := presetsFilePath(t, "mainnet")
@ -130,7 +146,7 @@ func TestLoadConfigFile(t *testing.T) {
mnf, err := params.UnmarshalConfigFile(mainnetConfigFile, nil)
require.NoError(t, err)
fields := fieldsFromYamls(t, append(mainnetPresetsFiles, mainnetConfigFile))
assertVals("mainnet", fields, mn, mnf)
assertEqualConfigs(t, "mainnet", fields, mn, mnf)
})
t.Run("minimal", func(t *testing.T) {
@ -148,7 +164,7 @@ func TestLoadConfigFile(t *testing.T) {
minf, err := params.UnmarshalConfigFile(minimalConfigFile, nil)
require.NoError(t, err)
fields := fieldsFromYamls(t, append(minimalPresetsFiles, minimalConfigFile))
assertVals("minimal", fields, min, minf)
assertEqualConfigs(t, "minimal", fields, min, minf)
})
t.Run("e2e", func(t *testing.T) {
@ -158,7 +174,7 @@ func TestLoadConfigFile(t *testing.T) {
e2ef, err := params.UnmarshalConfigFile(configFile, nil)
require.NoError(t, err)
fields := fieldsFromYamls(t, []string{configFile})
assertVals("e2e", fields, e2e, e2ef)
assertEqualConfigs(t, "e2e", fields, e2e, e2ef)
})
}

View File

@ -7,8 +7,8 @@ PRESET_BASE: 'minimal'
# Transition
# ---------------------------------------------------------------
# TBD, 2**256-2**10 is a placeholder, e2e is 616
TERMINAL_TOTAL_DIFFICULTY: 616
# TBD, 2**256-2**10 is a placeholder, e2e is 480
TERMINAL_TOTAL_DIFFICULTY: 480
# By default, don't use these params
#TERMINAL_BLOCK_HASH: 0x0000000000000000000000000000000000000000000000000000000000000000
#TERMINAL_BLOCK_HASH_ACTIVATION_EPOCH: 18446744073709551615
@ -83,7 +83,7 @@ PROPOSER_SCORE_BOOST: 40
DEPOSIT_CHAIN_ID: 1337 # Override for e2e tests
DEPOSIT_NETWORK_ID: 1337 # Override for e2e tests
# Configured on a per testnet basis
DEPOSIT_CONTRACT_ADDRESS: 0x1234567890123456789012345678901234567890
DEPOSIT_CONTRACT_ADDRESS: 0x4242424242424242424242424242424242424242
# Updated penalty values
# ---------------------------------------------------------------

View File

@ -20,14 +20,12 @@ 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")
testCfg := params.E2EMainnetTestConfig()
yamlObj := params.E2EMainnetConfigYaml()
yamlObj := params.ConfigToYaml(params.E2EMainnetTestConfig())
assert.NoError(t, file.WriteFile(yamlDir, yamlObj))
require.NoError(t, params.LoadChainConfigFile(yamlDir, params.MainnetConfig().Copy()))

View File

@ -1,8 +1,8 @@
package params
const (
altairE2EForkEpoch = 0
bellatrixE2EForkEpoch = 0
altairE2EForkEpoch = 6
bellatrixE2EForkEpoch = 8
)
// E2ETestConfig retrieves the configurations made specifically for E2E testing.
@ -36,7 +36,7 @@ func E2ETestConfig() *BeaconChainConfig {
e2eConfig.BellatrixForkEpoch = bellatrixE2EForkEpoch
// Terminal Total Difficulty.
e2eConfig.TerminalTotalDifficulty = "0"
e2eConfig.TerminalTotalDifficulty = "480"
// Prysm constants.
e2eConfig.ConfigName = EndToEndName
@ -74,7 +74,7 @@ func E2EMainnetTestConfig() *BeaconChainConfig {
e2eConfig.BellatrixForkEpoch = bellatrixE2EForkEpoch
// Terminal Total Difficulty.
e2eConfig.TerminalTotalDifficulty = "0"
e2eConfig.TerminalTotalDifficulty = "480"
// Prysm constants.
e2eConfig.ConfigName = EndToEndMainnetName
@ -86,13 +86,3 @@ func E2EMainnetTestConfig() *BeaconChainConfig {
e2eConfig.InitializeForkSchedule()
return e2eConfig
}
// E2EMainnetConfigYaml returns the e2e config in yaml format.
func E2EMainnetConfigYaml() []byte {
return ConfigToYaml(E2EMainnetTestConfig())
}
// E2ETestConfigYaml returns the e2e config in yaml format.
func E2ETestConfigYaml() []byte {
return ConfigToYaml(E2ETestConfig())
}

View File

@ -6,6 +6,7 @@ go_library(
"generate_genesis_state.go",
"generate_genesis_state_bellatrix.go",
"generate_keys.go",
"premined_genesis_state.go",
],
importpath = "github.com/prysmaticlabs/prysm/v3/runtime/interop",
visibility = ["//visibility:public"],

View File

@ -0,0 +1,63 @@
package interop
import (
"context"
"time"
"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"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
)
// GeneratePreminedGenesisState 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 GeneratePreminedGenesisState(ctx context.Context, genesisTime, numValidators uint64, e1d *ethpb.Eth1Data) (*ethpb.BeaconState, []*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 GeneratePreminedGenesisStateFromDepositData(ctx, genesisTime, depositDataItems, depositDataRoots, e1d)
}
// GeneratePreminedGenesisStateFromDepositData creates a genesis state given a list of
// deposit data items and their corresponding roots.
func GeneratePreminedGenesisStateFromDepositData(
ctx context.Context, genesisTime uint64, depositData []*ethpb.Deposit_Data, depositDataRoots [][]byte, e1d *ethpb.Eth1Data,
) (*ethpb.BeaconState, []*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")
}
root, err := t.HashTreeRoot()
if err != nil {
return nil, nil, errors.Wrap(err, "could not hash tree root of deposit trie")
}
if genesisTime == 0 {
genesisTime = uint64(time.Now().Unix())
}
beaconState, err := coreState.PreminedGenesisBeaconState(ctx, deposits, genesisTime, &ethpb.Eth1Data{
DepositRoot: root[:],
DepositCount: uint64(len(deposits)),
BlockHash: e1d.BlockHash,
})
if err != nil {
return nil, nil, errors.Wrap(err, "could not generate genesis state")
}
pbState, err := statenative.ProtobufBeaconStatePhase0(beaconState.ToProtoUnsafe())
if err != nil {
return nil, nil, err
}
return pbState, deposits, nil
}

View File

@ -37,10 +37,6 @@ var (
// VerifyTosAcceptedOrPrompt check if Tos was accepted before or asks to accept.
func VerifyTosAcceptedOrPrompt(ctx *cli.Context) error {
if ctx.Bool(cmd.E2EConfigFlag.Name) {
return nil
}
if file.FileExists(filepath.Join(ctx.String(cmd.DataDirFlag.Name), acceptTosFilename)) {
return nil
}

View File

@ -42,6 +42,7 @@ test_suite(
)
common_deps = [
"//runtime/version:go_default_library",
"//api/client/beacon:go_default_library",
"//beacon-chain/blockchain/testing:go_default_library",
"//beacon-chain/core/transition:go_default_library",

View File

@ -20,7 +20,6 @@ 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",
@ -38,12 +37,14 @@ go_library(
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/interop:go_default_library",
"//runtime/version:go_default_library",
"//testing/endtoend/helpers:go_default_library",
"//testing/endtoend/params:go_default_library",
"//testing/endtoend/types:go_default_library",
"//validator/keymanager:go_default_library",
"@com_github_ethereum_go_ethereum//common:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",
"@com_github_ethereum_go_ethereum//core/types:go_default_library",
"@com_github_google_uuid//:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_sirupsen_logrus//:go_default_library",

View File

@ -13,8 +13,8 @@ import (
"syscall"
"github.com/bazelbuild/rules_go/go/tools/bazel"
"github.com/ethereum/go-ethereum/core/types"
"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"
@ -29,6 +29,7 @@ import (
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/runtime/version"
"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"
@ -182,7 +183,6 @@ func (node *BeaconNode) generateGenesis(ctx context.Context) (state.BeaconState,
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 {
@ -197,54 +197,15 @@ func (node *BeaconNode) generateGenesis(ctx context.Context) (state.BeaconState,
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),
v := e2etypes.GenesisFork()
switch v {
case version.Bellatrix:
return generateGenesisBellatrix(ctx, gb, e1d)
case version.Phase0:
return generateGenesisPhase0(ctx, e1d)
default:
return nil, fmt.Errorf("unsupported genesis fork version %s", version.String(v))
}
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) {
@ -279,6 +240,17 @@ func (node *BeaconNode) saveGenesis(ctx context.Context) (string, error) {
return genesisPath, file.WriteFile(genesisPath, genesisBytes)
}
func (node *BeaconNode) saveConfig() (string, error) {
cfg := params.BeaconConfig().Copy()
cfgBytes := params.ConfigToYaml(cfg)
cfgDir := path.Join(e2e.TestParams.TestPath, fmt.Sprintf("config/%d", node.index))
if err := file.MkdirAll(cfgDir); err != nil {
return "", err
}
cfgPath := path.Join(cfgDir, "beacon-config.yaml")
return cfgPath, file.WriteFile(cfgPath, cfgBytes)
}
// 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")
@ -309,6 +281,10 @@ func (node *BeaconNode) Start(ctx context.Context) error {
if err != nil {
return err
}
cfgPath, err := node.saveConfig()
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),
@ -329,8 +305,8 @@ func (node *BeaconNode) Start(ctx context.Context) error {
fmt.Sprintf("--%s=%s", cmdshared.BootstrapNode.Name, enr),
fmt.Sprintf("--%s=%s", cmdshared.VerbosityFlag.Name, "debug"),
fmt.Sprintf("--%s=%d", flags.BlockBatchLimitBurstFactor.Name, 8),
fmt.Sprintf("--%s=%s", cmdshared.ChainConfigFileFlag.Name, cfgPath),
"--" + cmdshared.ForceClearDB.Name,
"--" + cmdshared.E2EConfigFlag.Name,
"--" + cmdshared.AcceptTosFlag.Name,
"--" + flags.EnableDebugRPCEndpoints.Name,
}
@ -413,3 +389,35 @@ func (node *BeaconNode) Stop() error {
func (node *BeaconNode) UnderlyingProcess() *os.Process {
return node.cmd.Process
}
func generateGenesisPhase0(ctx context.Context, e1d *ethpb.Eth1Data) (state.BeaconState, error) {
g, _, err := interop.GeneratePreminedGenesisState(ctx, e2e.TestParams.CLGenesisTime, params.BeaconConfig().MinGenesisActiveValidatorCount, e1d)
if err != nil {
return nil, err
}
return state_native.InitializeFromProtoUnsafePhase0(g)
}
func generateGenesisBellatrix(ctx context.Context, gb *types.Block, e1d *ethpb.Eth1Data) (state.BeaconState, error) {
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),
}
g, _, err := interop.GenerateGenesisStateBellatrix(ctx, e2e.TestParams.CLGenesisTime, params.BeaconConfig().MinGenesisActiveValidatorCount, payload, e1d)
if err != nil {
return nil, err
}
return state_native.InitializeFromProtoUnsafeBellatrix(g)
}

View File

@ -260,7 +260,7 @@ func (node *LighthouseBeaconNode) Stop() error {
func (node *LighthouseBeaconNode) createTestnetDir(index int) (string, error) {
testNetDir := e2e.TestParams.TestPath + fmt.Sprintf("/lighthouse-testnet-%d", index)
configPath := filepath.Join(testNetDir, "config.yaml")
rawYaml := params.E2EMainnetConfigYaml()
rawYaml := params.ConfigToYaml(params.BeaconConfig())
// Add in deposit contract in yaml
depContractStr := fmt.Sprintf("\nDEPOSIT_CONTRACT_ADDRESS: %s", params.BeaconConfig().DepositContractAddress)
rawYaml = append(rawYaml, []byte(depContractStr)...)

View File

@ -164,6 +164,17 @@ func NewValidatorNode(config *e2etypes.E2EConfig, validatorNum, index, offset in
}
}
func (node *ValidatorNode) saveConfig() (string, error) {
cfg := params.BeaconConfig().Copy()
cfgBytes := params.ConfigToYaml(cfg)
cfgDir := path.Join(e2e.TestParams.TestPath, fmt.Sprintf("config/%d", node.index))
if err := file.MkdirAll(cfgDir); err != nil {
return "", err
}
cfgPath := path.Join(cfgDir, "validator-config.yaml")
return cfgPath, file.WriteFile(cfgPath, cfgBytes)
}
// Start starts a validator client.
func (v *ValidatorNode) Start(ctx context.Context) error {
validatorHexPubKeys := make([]string, 0)
@ -206,6 +217,10 @@ func (v *ValidatorNode) Start(ctx context.Context) error {
if err != nil {
return err
}
cfgPath, err := v.saveConfig()
if err != nil {
return err
}
args := []string{
fmt.Sprintf("--%s=%s/eth2-val-%d", cmdshared.DataDirFlag.Name, e2e.TestParams.TestPath, index),
fmt.Sprintf("--%s=%s", cmdshared.LogFileName.Name, file.Name()),
@ -217,8 +232,8 @@ func (v *ValidatorNode) Start(ctx context.Context) error {
fmt.Sprintf("--%s=%s", flags.GrpcHeadersFlag.Name, "dummy=value,foo=bar"), // Sending random headers shouldn't break anything.
fmt.Sprintf("--%s=%s", cmdshared.VerbosityFlag.Name, "debug"),
fmt.Sprintf("--%s=%s", flags.ProposerSettingsFlag.Name, proposerSettingsPathPath),
fmt.Sprintf("--%s=%s", cmdshared.ChainConfigFileFlag.Name, cfgPath),
"--" + cmdshared.ForceClearDB.Name,
"--" + cmdshared.E2EConfigFlag.Name,
"--" + cmdshared.AcceptTosFlag.Name,
}
@ -314,40 +329,26 @@ func (v *ValidatorNode) UnderlyingProcess() *os.Process {
return v.cmd.Process
}
func createProposerSettingsPath(pubkeys []string, validatorIndex int) (string, error) {
testNetDir := e2e.TestParams.TestPath + fmt.Sprintf("/proposer-settings/validator_%d", validatorIndex)
func createProposerSettingsPath(pubkeys []string, nodeIdx int) (string, error) {
testNetDir := e2e.TestParams.TestPath + fmt.Sprintf("/proposer-settings/validator_%d", nodeIdx)
configPath := filepath.Join(testNetDir, "config.json")
if len(pubkeys) == 0 {
return "", errors.New("number of validators must be greater than 0")
}
var proposerSettingsPayload validator_service_config.ProposerSettingsPayload
if len(pubkeys) == 1 {
proposerSettingsPayload = validator_service_config.ProposerSettingsPayload{
DefaultConfig: &validator_service_config.ProposerOptionPayload{
FeeRecipient: DefaultFeeRecipientAddress,
},
}
} else {
config := make(map[string]*validator_service_config.ProposerOptionPayload)
config := make(map[string]*validator_service_config.ProposerOptionPayload)
for i, pubkey := range pubkeys {
// Create an account
byteval, err := hexutil.Decode(pubkey)
if err != nil {
return "", err
}
deterministicFeeRecipient := common.HexToAddress(hexutil.Encode(byteval[:fieldparams.FeeRecipientLength])).Hex()
config[pubkeys[i]] = &validator_service_config.ProposerOptionPayload{
FeeRecipient: deterministicFeeRecipient,
}
}
proposerSettingsPayload = validator_service_config.ProposerSettingsPayload{
ProposerConfig: config,
DefaultConfig: &validator_service_config.ProposerOptionPayload{
FeeRecipient: DefaultFeeRecipientAddress,
},
for i, pubkey := range pubkeys {
config[pubkeys[i]] = &validator_service_config.ProposerOptionPayload{
FeeRecipient: FeeRecipientFromPubkey(pubkey),
}
}
proposerSettingsPayload = validator_service_config.ProposerSettingsPayload{
ProposerConfig: config,
DefaultConfig: &validator_service_config.ProposerOptionPayload{
FeeRecipient: DefaultFeeRecipientAddress,
},
}
jsonBytes, err := json.Marshal(proposerSettingsPayload)
if err != nil {
return "", err
@ -360,3 +361,10 @@ func createProposerSettingsPath(pubkeys []string, validatorIndex int) (string, e
}
return configPath, nil
}
// FeeRecipientFromPubkey slices, from the beginning of the hex-encoded pubkey string, the 2 character 0x preamble
// plus enough hex chars to fill out the fee_recipient byte value.
func FeeRecipientFromPubkey(key string) string {
// pubkey[:(2+fieldparams.FeeRecipientLength*2)] slicing 2 (for the 0x preamble) + 2 hex chars for each byte
return common.HexToAddress(key[:(2 + fieldparams.FeeRecipientLength*2)]).Hex()
}

View File

@ -70,7 +70,7 @@ func (w *Web3RemoteSigner) Start(ctx context.Context) error {
return err
}
testDir, err := w.createTestnetDir()
testDir, err := createTestnetDir()
if err != nil {
return err
}
@ -256,10 +256,14 @@ func writeKeystoreKeys(ctx context.Context, keystorePath string, numKeys uint64)
return nil
}
func (w *Web3RemoteSigner) createTestnetDir() (string, error) {
func (w *Web3RemoteSigner) UnderlyingProcess() *os.Process {
return w.cmd.Process
}
func createTestnetDir() (string, error) {
testNetDir := e2e.TestParams.TestPath + "/web3signer-testnet"
configPath := filepath.Join(testNetDir, "config.yaml")
rawYaml := params.E2ETestConfigYaml()
rawYaml := params.ConfigToYaml(params.BeaconConfig())
// Add in deposit contract in yaml
depContractStr := fmt.Sprintf("\nDEPOSIT_CONTRACT_ADDRESS: %s", params.BeaconConfig().DepositContractAddress)
rawYaml = append(rawYaml, []byte(depContractStr)...)
@ -273,7 +277,3 @@ func (w *Web3RemoteSigner) createTestnetDir() (string, error) {
return configPath, nil
}
func (w *Web3RemoteSigner) UnderlyingProcess() *os.Process {
return w.cmd.Process
}

View File

@ -14,9 +14,9 @@ import (
"github.com/prysmaticlabs/prysm/v3/testing/require"
)
func e2eMinimal(t *testing.T, cfgo ...types.E2EConfigOpt) *testRunner {
func e2eMinimal(t *testing.T, v int, cfgo ...types.E2EConfigOpt) *testRunner {
params.SetupTestConfigCleanup(t)
params.OverrideBeaconConfig(params.E2ETestConfig().Copy())
require.NoError(t, params.SetActive(types.StartAt(v, params.E2ETestConfig())))
require.NoError(t, e2eParams.Init(t, e2eParams.StandardBeaconCount))
// Run for 12 epochs if not in long-running to confirm long-running has no issues.
@ -87,9 +87,9 @@ func e2eMinimal(t *testing.T, cfgo ...types.E2EConfigOpt) *testRunner {
return newTestRunner(t, testConfig)
}
func e2eMainnet(t *testing.T, usePrysmSh, useMultiClient bool, cfgo ...types.E2EConfigOpt) *testRunner {
func e2eMainnet(t *testing.T, usePrysmSh, useMultiClient bool, cfg *params.BeaconChainConfig, cfgo ...types.E2EConfigOpt) *testRunner {
params.SetupTestConfigCleanup(t)
params.OverrideBeaconConfig(params.E2EMainnetTestConfig())
require.NoError(t, params.SetActive(cfg))
if useMultiClient {
require.NoError(t, e2eParams.InitMultiClient(t, e2eParams.StandardBeaconCount, e2eParams.StandardLighthouseNodeCount))
} else {
@ -153,6 +153,7 @@ func e2eMainnet(t *testing.T, usePrysmSh, useMultiClient bool, cfgo ...types.E2E
for _, o := range cfgo {
o(testConfig)
}
// In the event we use the cross-client e2e option, we add in an additional
// evaluator for multiclient runs to verify the beacon api conformance.
if testConfig.UseValidatorCrossClient {

View File

@ -31,7 +31,6 @@ go_library(
"//consensus-types/interfaces:go_default_library",
"//consensus-types/primitives:go_default_library",
"//container/slice:go_default_library",
"//crypto/bls:go_default_library",
"//encoding/bytesutil:go_default_library",
"//math:go_default_library",
"//network/forks:go_default_library",

View File

@ -1,6 +1,7 @@
package evaluators
import (
"bytes"
"context"
"fmt"
@ -9,9 +10,7 @@ import (
"github.com/ethereum/go-ethereum/ethclient"
"github.com/ethereum/go-ethereum/rpc"
"github.com/pkg/errors"
fieldparams "github.com/prysmaticlabs/prysm/v3/config/fieldparams"
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/crypto/bls"
ethpb "github.com/prysmaticlabs/prysm/v3/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v3/runtime/interop"
"github.com/prysmaticlabs/prysm/v3/testing/endtoend/components"
@ -19,6 +18,7 @@ import (
e2e "github.com/prysmaticlabs/prysm/v3/testing/endtoend/params"
"github.com/prysmaticlabs/prysm/v3/testing/endtoend/policies"
"github.com/prysmaticlabs/prysm/v3/testing/endtoend/types"
log "github.com/sirupsen/logrus"
"google.golang.org/grpc"
"google.golang.org/protobuf/types/known/emptypb"
)
@ -29,6 +29,39 @@ var FeeRecipientIsPresent = types.Evaluator{
Evaluation: feeRecipientIsPresent,
}
func lhKeyMap() (map[string]bool, error) {
if e2e.TestParams.LighthouseBeaconNodeCount == 0 {
return nil, nil
}
pry, lh := e2e.TestParams.BeaconNodeCount, e2e.TestParams.LighthouseBeaconNodeCount
valPerNode := int(params.BeaconConfig().MinGenesisActiveValidatorCount) / (pry + lh)
lhOff := valPerNode * pry
_, keys, err := interop.DeterministicallyGenerateKeys(uint64(lhOff), uint64(valPerNode*lh))
if err != nil {
return nil, err
}
km := make(map[string]bool)
for _, k := range keys {
km[hexutil.Encode(k.Marshal())] = true
}
return km, nil
}
func valKeyMap() (map[string]bool, error) {
nvals := params.BeaconConfig().MinGenesisActiveValidatorCount
// matches validator start in validator component + validators used for deposits
_, pubs, err := interop.DeterministicallyGenerateKeys(0, nvals+e2e.DepositCount)
if err != nil {
return nil, err
}
km := make(map[string]bool)
for _, k := range pubs {
km[hexutil.Encode(k.Marshal())] = true
}
return km, nil
}
func feeRecipientIsPresent(_ types.EvaluationContext, conns ...*grpc.ClientConn) error {
conn := conns[0]
client := ethpb.NewBeaconChainClient(conn)
@ -47,97 +80,98 @@ func feeRecipientIsPresent(_ types.EvaluationContext, conns ...*grpc.ClientConn)
return err
}
defer rpcclient.Close()
web3 := ethclient.NewClient(rpcclient)
ctx := context.Background()
validatorNum := int(params.BeaconConfig().MinGenesisActiveValidatorCount)
_, pubs, err := interop.DeterministicallyGenerateKeys(uint64(0), uint64(validatorNum+int(e2e.DepositCount))) // matches validator start in validator component + validators used for deposits
valkeys, err := valKeyMap()
if err != nil {
return err
}
lighthouseKeys := []bls.PublicKey{}
if e2e.TestParams.LighthouseBeaconNodeCount != 0 {
totalNodecount := e2e.TestParams.BeaconNodeCount + e2e.TestParams.LighthouseBeaconNodeCount
valPerNode := validatorNum / totalNodecount
lighthouseOffset := valPerNode * e2e.TestParams.BeaconNodeCount
_, lighthouseKeys, err = interop.DeterministicallyGenerateKeys(uint64(lighthouseOffset), uint64(valPerNode*e2e.TestParams.LighthouseBeaconNodeCount))
if err != nil {
return err
}
lhkeys, err := lhKeyMap()
if err != nil {
return err
}
for _, ctr := range blks.BlockContainers {
if fr := ctr.GetBellatrixBlock(); fr != nil {
var account common.Address
fr := ctr.GetBellatrixBlock().Block.Body.ExecutionPayload.FeeRecipient
if len(fr) != 0 && hexutil.Encode(fr) != params.BeaconConfig().EthBurnAddressHex {
account = common.BytesToAddress(fr)
} else {
if ctr.GetBellatrixBlock() != nil {
bb := ctr.GetBellatrixBlock().Block
payload := bb.Body.ExecutionPayload
// If the beacon chain has transitioned to Bellatrix, but the EL hasn't hit TTD, we could see a few slots
// of blocks with empty payloads.
if bytes.Equal(payload.BlockHash, make([]byte, 32)) {
continue
}
if len(payload.FeeRecipient) == 0 || hexutil.Encode(payload.FeeRecipient) == params.BeaconConfig().EthBurnAddressHex {
log.WithField("proposer_index", bb.ProposerIndex).WithField("slot", bb.Slot).Error("fee recipient eval bug")
return errors.New("fee recipient is not set")
}
validatorRequest := &ethpb.GetValidatorRequest{
fr := common.BytesToAddress(payload.FeeRecipient)
gvr := &ethpb.GetValidatorRequest{
QueryFilter: &ethpb.GetValidatorRequest_Index{
Index: ctr.GetBellatrixBlock().Block.ProposerIndex,
},
}
validator, err := client.GetValidator(context.Background(), validatorRequest)
validator, err := client.GetValidator(context.Background(), gvr)
if err != nil {
return errors.Wrap(err, "failed to get validators")
}
publickey := validator.GetPublicKey()
isDeterministicKey := false
isLighthouseKey := false
pk := hexutil.Encode(validator.GetPublicKey())
// If lighthouse keys are present, we skip the check.
for _, pub := range lighthouseKeys {
if hexutil.Encode(publickey) == hexutil.Encode(pub.Marshal()) {
isLighthouseKey = true
break
}
}
if isLighthouseKey {
if _, ok := lhkeys[pk]; ok {
// Don't check lighthouse keys.
continue
}
for _, pub := range pubs {
if hexutil.Encode(publickey) == hexutil.Encode(pub.Marshal()) {
isDeterministicKey = true
break
}
}
// calculate deterministic fee recipient using first 20 bytes of public key
deterministicFeeRecipient := common.HexToAddress(hexutil.Encode(publickey[:fieldparams.FeeRecipientLength])).Hex()
if isDeterministicKey && deterministicFeeRecipient != account.Hex() {
return fmt.Errorf("publickey %s, fee recipient %s does not match the proposer settings fee recipient %s",
hexutil.Encode(publickey), account.Hex(), deterministicFeeRecipient)
}
if !isDeterministicKey && components.DefaultFeeRecipientAddress != account.Hex() {
return fmt.Errorf("publickey %s, fee recipient %s does not match the default fee recipient %s",
hexutil.Encode(publickey), account.Hex(), components.DefaultFeeRecipientAddress)
}
currentBlock, err := web3.BlockByHash(ctx, common.BytesToHash(ctr.GetBellatrixBlock().GetBlock().GetBody().GetExecutionPayload().BlockHash))
if err != nil {
return err
// In e2e we generate deterministic keys by validator index, and then use a slice of their public key bytes
// as the fee recipient, so that this will also be deterministic, so this test can statelessly verify it.
// These should be the only keys we see.
// Otherwise something has changed in e2e and this test needs to be updated.
_, knownKey := valkeys[pk]
if !knownKey {
log.WithField("pubkey", pk).
WithField("slot", bb.Slot).
WithField("proposer_index", bb.ProposerIndex).
WithField("fee_recipient", fr.Hex()).
Warn("unknown key observed, not a deterministically generated key")
return errors.New("unknown key observed, not a deterministically generated key")
}
accountBalance, err := web3.BalanceAt(ctx, account, currentBlock.Number())
if err != nil {
return err
if components.FeeRecipientFromPubkey(pk) != fr.Hex() {
return fmt.Errorf("publickey %s, fee recipient %s does not match the proposer settings fee recipient %s",
pk, fr.Hex(), components.FeeRecipientFromPubkey(pk))
}
previousBlock, err := web3.BlockByHash(ctx, common.BytesToHash(ctr.GetBellatrixBlock().GetBlock().GetBody().GetExecutionPayload().ParentHash))
if err != nil {
if err := checkRecipientBalance(rpcclient, common.BytesToHash(payload.BlockHash), common.BytesToHash(payload.ParentHash), fr); err != nil {
return err
}
prevAccountBalance, err := web3.BalanceAt(ctx, account, previousBlock.Number())
if err != nil {
return err
}
if currentBlock.GasUsed() > 0 && accountBalance.Uint64() <= prevAccountBalance.Uint64() {
return errors.Errorf("account balance didn't change after applying fee recipient for account: %s", account.Hex())
}
}
}
return nil
}
func checkRecipientBalance(c *rpc.Client, block, parent common.Hash, account common.Address) error {
web3 := ethclient.NewClient(c)
ctx := context.Background()
b, err := web3.BlockByHash(ctx, block)
if err != nil {
return err
}
bal, err := web3.BalanceAt(ctx, account, b.Number())
if err != nil {
return err
}
pBlock, err := web3.BlockByHash(ctx, parent)
if err != nil {
return err
}
pBal, err := web3.BalanceAt(ctx, account, pBlock.Number())
if err != nil {
return err
}
if b.GasUsed() > 0 && bal.Uint64() <= pBal.Uint64() {
return errors.Errorf("account balance didn't change after applying fee recipient for account: %s", account.Hex())
}
return nil
}

View File

@ -7,8 +7,6 @@ import (
"math"
"strings"
log "github.com/sirupsen/logrus"
"github.com/pkg/errors"
corehelpers "github.com/prysmaticlabs/prysm/v3/beacon-chain/core/helpers"
"github.com/prysmaticlabs/prysm/v3/beacon-chain/core/signing"
@ -256,7 +254,6 @@ func getAllValidators(c ethpb.BeaconChainClient) ([]*ethpb.Validator, error) {
vals = append(vals, v.Validator)
}
pageToken = validators.NextPageToken
log.WithField("len", len(vals)).WithField("pageToken", pageToken).Info("getAllValidators")
}
return vals, nil
}
@ -425,6 +422,7 @@ func validatorsVoteWithTheMajority(_ e2etypes.EvaluationContext, conns ...*grpc.
default:
return errors.New("block neither phase0,altair or bellatrix")
}
seenVotes[slot] = vote
// 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
@ -445,6 +443,14 @@ func validatorsVoteWithTheMajority(_ e2etypes.EvaluationContext, conns ...*grpc.
}
if !bytes.Equal(vote, expectedEth1DataVote) {
for i := types.Slot(0); i < slot; i++ {
v, ok := seenVotes[i]
if ok {
fmt.Printf("vote at slot=%d = %#x\n", i, v)
} else {
fmt.Printf("did not see slot=%d\n", i)
}
}
return fmt.Errorf("incorrect eth1data vote for slot %d; expected: %#x vs voted: %#x",
slot, expectedEth1DataVote, vote)
}
@ -452,4 +458,5 @@ func validatorsVoteWithTheMajority(_ e2etypes.EvaluationContext, conns ...*grpc.
return nil
}
var seenVotes = make(map[types.Slot][]byte)
var expectedEth1DataVote []byte

1
testing/endtoend/fork.go Normal file
View File

@ -0,0 +1 @@
package endtoend

View File

@ -2,9 +2,14 @@ package endtoend
import (
"testing"
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/testing/endtoend/types"
)
// Run mainnet e2e config with the current release validator against latest beacon node.
func TestEndToEnd_MainnetConfig_ValidatorAtCurrentRelease(t *testing.T) {
e2eMainnet(t, true, false).run()
r := e2eMainnet(t, true, false, types.StartAt(version.Phase0, params.E2EMainnetTestConfig()))
r.run()
}

View File

@ -3,15 +3,16 @@ package endtoend
import (
"testing"
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/testing/endtoend/types"
)
func TestEndToEnd_MainnetConfig_MultiClient(t *testing.T) {
e2eMainnet(t, false /*usePrysmSh*/, true /*useMultiClient*/, types.WithValidatorCrossClient()).run()
e2eMainnet(t, false, true, params.E2EMainnetTestConfig().Copy(), types.WithValidatorCrossClient()).run()
}
func TestEndToEnd_MultiScenarioRun_Multiclient(t *testing.T) {
runner := e2eMainnet(t, false /*usePrysmSh*/, true /*useMultiClient*/, types.WithEpochs(22))
runner := e2eMainnet(t, false, true, params.E2EMainnetTestConfig().Copy(), types.WithEpochs(22))
runner.config.Evaluators = scenarioEvalsMulti()
runner.config.EvalInterceptor = runner.multiScenarioMulticlient
runner.scenarioRunner()

View File

@ -3,9 +3,11 @@ package endtoend
import (
"testing"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/testing/endtoend/types"
)
func TestEndToEnd_MinimalConfig(t *testing.T) {
e2eMinimal(t, types.WithCheckpointSync()).run()
r := e2eMinimal(t, version.Phase0, types.WithCheckpointSync())
r.run()
}

View File

@ -3,11 +3,12 @@ package endtoend
import (
"testing"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"github.com/prysmaticlabs/prysm/v3/testing/endtoend/types"
)
func TestEndToEnd_MultiScenarioRun(t *testing.T) {
runner := e2eMinimal(t, types.WithEpochs(22))
runner := e2eMinimal(t, version.Phase0, types.WithEpochs(22))
runner.config.Evaluators = scenarioEvals()
runner.config.EvalInterceptor = runner.multiScenario
@ -15,16 +16,16 @@ func TestEndToEnd_MultiScenarioRun(t *testing.T) {
}
func TestEndToEnd_MinimalConfig_Web3Signer(t *testing.T) {
e2eMinimal(t, types.WithRemoteSigner()).run()
e2eMinimal(t, version.Phase0, types.WithRemoteSigner()).run()
}
func TestEndToEnd_MinimalConfig_ValidatorRESTApi(t *testing.T) {
e2eMinimal(t, types.WithCheckpointSync(), types.WithValidatorRESTApi()).run()
e2eMinimal(t, version.Phase0, types.WithCheckpointSync(), types.WithValidatorRESTApi()).run()
}
func TestEndToEnd_ScenarioRun_EEOffline(t *testing.T) {
t.Skip("TODO(#10242) Prysm is current unable to handle an offline e2e")
runner := e2eMinimal(t)
runner := e2eMinimal(t, version.Phase0)
runner.config.Evaluators = scenarioEvals()
runner.config.EvalInterceptor = runner.eeOffline

View File

@ -5,12 +5,15 @@ go_library(
testonly = True,
srcs = [
"empty.go",
"fork.go",
"types.go",
],
importpath = "github.com/prysmaticlabs/prysm/v3/testing/endtoend/types",
visibility = ["//testing/endtoend:__subpackages__"],
deps = [
"//config/params:go_default_library",
"//consensus-types/primitives:go_default_library",
"//runtime/version:go_default_library",
"@org_golang_google_grpc//:go_default_library",
],
)

View File

@ -0,0 +1,26 @@
package types
import (
"fmt"
"github.com/prysmaticlabs/prysm/v3/config/params"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
)
func StartAt(v int, c *params.BeaconChainConfig) *params.BeaconChainConfig {
c = c.Copy()
if v >= version.Altair {
c.AltairForkEpoch = 0
}
if v >= version.Bellatrix {
c.BellatrixForkEpoch = 0
}
if v >= version.Capella {
c.CapellaForkEpoch = 0
}
// Time TTD to line up roughly with the bellatrix fork epoch.
// E2E sets EL block production rate equal to SecondsPerETH1Block to keep the math simple.
ttd := uint64(c.BellatrixForkEpoch) * uint64(c.SlotsPerEpoch) * c.SecondsPerSlot
c.TerminalTotalDifficulty = fmt.Sprintf("%d", ttd)
return c
}

View File

@ -6,7 +6,9 @@ import (
"context"
"os"
"github.com/prysmaticlabs/prysm/v3/config/params"
types "github.com/prysmaticlabs/prysm/v3/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v3/runtime/version"
"google.golang.org/grpc"
)
@ -65,6 +67,20 @@ type E2EConfig struct {
ExtraEpochs uint64
}
func GenesisFork() int {
cfg := params.BeaconConfig()
if cfg.CapellaForkEpoch == 0 {
return version.Capella
}
if cfg.BellatrixForkEpoch == 0 {
return version.Bellatrix
}
if cfg.AltairForkEpoch == 0 {
return version.Altair
}
return version.Phase0
}
// Evaluator defines the structure of the evaluators used to
// conduct the current beacon state during the E2E.
type Evaluator struct {