mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 21:38:05 -05:00
Deneb spectests release v1.4.0-beta.2-hotfix (#12959)
* Update and use max per epoch churn limit * Update spec tests * Fix e2e test * deneb fork epoch condition * Fix lint and better casting * fix ordering * fix check * gaz * Fix more tests * Apply proposer boost to first block in equivocation * Increase timeout * Don't increase timeout, it's not the reason * implement deneb forkchoice spectests expose ReceiveBlob from the blockchain package * spin_off_helper * remove minimal tests * Terence's review * Add process register test for Deneb * Terence's suggestion Co-authored-by: terencechain <terence@prysmaticlabs.com> * fix forkchoice minimal * fix minimal sha * general sha * different repos * different repos --------- Co-authored-by: terence tsao <terence@prysmaticlabs.com> Co-authored-by: nisdas <nishdas93@gmail.com>
This commit is contained in:
18
WORKSPACE
18
WORKSPACE
@@ -247,7 +247,9 @@ filegroup(
|
||||
url = "https://github.com/ethereum/EIPs/archive/5480440fe51742ed23342b68cf106cefd427e39d.tar.gz",
|
||||
)
|
||||
|
||||
consensus_spec_version = "v1.4.0-beta.1"
|
||||
consensus_spec_test_version = "v1.4.0-beta.2-hotfix"
|
||||
|
||||
consensus_spec_version = "v1.4.0-beta.2"
|
||||
|
||||
bls_test_version = "v0.1.1"
|
||||
|
||||
@@ -263,8 +265,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "24399b60ce3fbeb2311952d213dc3731b6dcb0f8881b016c283de5b518d2bbba",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_version,
|
||||
sha256 = "99770a001189f66204a4ef79161c8002bcbbcbd8236f1c6479bd5b83a3c68d42",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/general.tar.gz" % consensus_spec_test_version,
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -279,8 +281,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "8e656ee48d2e2ebc9cf9baedb81f27925bc625b3e3fbb2883444a08758a5884a",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_version,
|
||||
sha256 = "56763f6492ee137108271007d62feef60d8e3f1698e53dee4bc4b07e55f7326b",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/minimal.tar.gz" % consensus_spec_test_version,
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -295,8 +297,8 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "8bd137da6cc57a25383bfac5bc37e31265098145278bd8002b88e24c8b4718b9",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_version,
|
||||
sha256 = "bc1cac1a991cdc7426efea14385dcf215df85ed3f0572b824ad6a1d7ca0c89ad",
|
||||
url = "https://github.com/ethereum/consensus-spec-tests/releases/download/%s/mainnet.tar.gz" % consensus_spec_test_version,
|
||||
)
|
||||
|
||||
http_archive(
|
||||
@@ -310,7 +312,7 @@ filegroup(
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
""",
|
||||
sha256 = "2bc1edb6e4a4f86c00317c04618a90b0ca29ee1eba833d0a64dd67fdd83fdbe3",
|
||||
sha256 = "c5898001aaab2a5bb38a39ff9d17a52f1f9befcc26e63752cbf556040f0c884e",
|
||||
strip_prefix = "consensus-specs-" + consensus_spec_version[1:],
|
||||
url = "https://github.com/ethereum/consensus-specs/archive/refs/tags/%s.tar.gz" % consensus_spec_version,
|
||||
)
|
||||
|
||||
@@ -1,7 +1,23 @@
|
||||
package blockchain
|
||||
|
||||
import (
|
||||
"context"
|
||||
|
||||
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||
)
|
||||
|
||||
// SendNewBlobEvent sends a message to the BlobNotifier channel that the blob
|
||||
// for the blocroot `root` is ready in the database
|
||||
func (s *Service) SendNewBlobEvent(root [32]byte, index uint64) {
|
||||
func (s *Service) sendNewBlobEvent(root [32]byte, index uint64) {
|
||||
s.blobNotifiers.forRoot(root) <- index
|
||||
}
|
||||
|
||||
// ReceiveBlob saves the blob to database and sends the new event
|
||||
func (s *Service) ReceiveBlob(ctx context.Context, b *ethpb.BlobSidecar) error {
|
||||
if err := s.cfg.BeaconDB.SaveBlobSidecar(ctx, []*ethpb.BlobSidecar{b}); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.sendNewBlobEvent([32]byte(b.BlockRoot), b.Index)
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package blockchain
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"time"
|
||||
|
||||
"github.com/pkg/errors"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/feed"
|
||||
@@ -21,7 +22,6 @@ import (
|
||||
ethpb "github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1"
|
||||
"github.com/prysmaticlabs/prysm/v4/proto/prysm/v1alpha1/attestation"
|
||||
"github.com/prysmaticlabs/prysm/v4/runtime/version"
|
||||
"github.com/prysmaticlabs/prysm/v4/time"
|
||||
"github.com/prysmaticlabs/prysm/v4/time/slots"
|
||||
"go.opencensus.io/trace"
|
||||
"golang.org/x/sync/errgroup"
|
||||
@@ -42,7 +42,7 @@ type BlockReceiver interface {
|
||||
// BlobReceiver interface defines the methods of chain service for receiving new
|
||||
// blobs
|
||||
type BlobReceiver interface {
|
||||
SendNewBlobEvent([32]byte, uint64)
|
||||
ReceiveBlob(context.Context, *ethpb.BlobSidecar) error
|
||||
}
|
||||
|
||||
// SlashingReceiver interface defines the methods of chain service for receiving validated slashing over the wire.
|
||||
|
||||
@@ -606,10 +606,12 @@ func (s *ChainService) UnrealizedJustifiedPayloadBlockHash() [32]byte {
|
||||
return [32]byte{}
|
||||
}
|
||||
|
||||
// SendNewBlobEvent mocks the same method in the chain service
|
||||
func (*ChainService) SendNewBlobEvent(_ [32]byte, _ uint64) {}
|
||||
|
||||
// BlockBeingSynced mocks the same method in the chain service
|
||||
func (c *ChainService) BlockBeingSynced(root [32]byte) bool {
|
||||
return root == c.SyncingRoot
|
||||
}
|
||||
|
||||
// ReceiveBlob implements the same method in the chain service
|
||||
func (*ChainService) ReceiveBlob(_ context.Context, _ *ethpb.BlobSidecar) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -142,6 +142,13 @@ func ProcessRegistryUpdates(ctx context.Context, state state.BeaconState) (state
|
||||
return nil, errors.Wrap(err, "could not get churn limit")
|
||||
}
|
||||
|
||||
if state.Version() >= version.Deneb {
|
||||
// Cap churn limit to max per epoch churn limit. New in EIP7514.
|
||||
if churnLimit > params.BeaconConfig().MaxPerEpochActivationChurnLimit {
|
||||
churnLimit = params.BeaconConfig().MaxPerEpochActivationChurnLimit
|
||||
}
|
||||
}
|
||||
|
||||
// Prevent churn limit cause index out of bound.
|
||||
if churnLimit < limit {
|
||||
limit = churnLimit
|
||||
|
||||
@@ -338,6 +338,42 @@ func TestProcessRegistryUpdates_EligibleToActivate(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessRegistryUpdates_EligibleToActivate_Cancun(t *testing.T) {
|
||||
base := ðpb.BeaconStateDeneb{
|
||||
Slot: 5 * params.BeaconConfig().SlotsPerEpoch,
|
||||
FinalizedCheckpoint: ðpb.Checkpoint{Epoch: 6, Root: make([]byte, fieldparams.RootLength)},
|
||||
}
|
||||
cfg := params.BeaconConfig()
|
||||
cfg.MinPerEpochChurnLimit = 10
|
||||
cfg.ChurnLimitQuotient = 1
|
||||
params.OverrideBeaconConfig(cfg)
|
||||
|
||||
for i := uint64(0); i < 10; i++ {
|
||||
base.Validators = append(base.Validators, ðpb.Validator{
|
||||
ActivationEligibilityEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
EffectiveBalance: params.BeaconConfig().MaxEffectiveBalance,
|
||||
ActivationEpoch: params.BeaconConfig().FarFutureEpoch,
|
||||
})
|
||||
}
|
||||
beaconState, err := state_native.InitializeFromProtoDeneb(base)
|
||||
require.NoError(t, err)
|
||||
currentEpoch := time.CurrentEpoch(beaconState)
|
||||
newState, err := epoch.ProcessRegistryUpdates(context.Background(), beaconState)
|
||||
require.NoError(t, err)
|
||||
for i, validator := range newState.Validators() {
|
||||
assert.Equal(t, currentEpoch+1, validator.ActivationEligibilityEpoch, "Could not update registry %d, unexpected activation eligibility epoch", i)
|
||||
// Note: In Deneb, only validators indices before `MaxPerEpochActivationChurnLimit` should be activated.
|
||||
if uint64(i) < params.BeaconConfig().MaxPerEpochActivationChurnLimit && validator.ActivationEpoch != helpers.ActivationExitEpoch(currentEpoch) {
|
||||
t.Errorf("Could not update registry %d, validators failed to activate: wanted activation epoch %d, got %d",
|
||||
i, helpers.ActivationExitEpoch(currentEpoch), validator.ActivationEpoch)
|
||||
}
|
||||
if uint64(i) >= params.BeaconConfig().MaxPerEpochActivationChurnLimit && validator.ActivationEpoch != params.BeaconConfig().FarFutureEpoch {
|
||||
t.Errorf("Could not update registry %d, validators should not have been activated, wanted activation epoch: %d, got %d",
|
||||
i, params.BeaconConfig().FarFutureEpoch, validator.ActivationEpoch)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func TestProcessRegistryUpdates_ActivationCompletes(t *testing.T) {
|
||||
base := ðpb.BeaconState{
|
||||
Slot: 5 * params.BeaconConfig().SlotsPerEpoch,
|
||||
|
||||
@@ -49,6 +49,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
slot := primitives.Slot(1)
|
||||
driftGenesisTime(f, slot, 0)
|
||||
newRoot := indexToHash(1)
|
||||
f.store.proposerBoostRoot = [32]byte{}
|
||||
state, blkRoot, err := prepareForkchoiceState(
|
||||
ctx,
|
||||
slot,
|
||||
@@ -74,6 +75,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
slot = primitives.Slot(2)
|
||||
driftGenesisTime(f, slot, 0)
|
||||
newRoot = indexToHash(2)
|
||||
f.store.proposerBoostRoot = [32]byte{}
|
||||
state, blkRoot, err = prepareForkchoiceState(
|
||||
ctx,
|
||||
slot,
|
||||
@@ -101,6 +103,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
slot = primitives.Slot(3)
|
||||
driftGenesisTime(f, slot, 0)
|
||||
newRoot = indexToHash(3)
|
||||
f.store.proposerBoostRoot = [32]byte{}
|
||||
state, blkRoot, err = prepareForkchoiceState(
|
||||
ctx,
|
||||
slot,
|
||||
@@ -129,6 +132,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
slot = primitives.Slot(4)
|
||||
driftGenesisTime(f, slot, 0)
|
||||
newRoot = indexToHash(4)
|
||||
f.store.proposerBoostRoot = [32]byte{}
|
||||
state, blkRoot, err = prepareForkchoiceState(
|
||||
ctx,
|
||||
slot,
|
||||
@@ -335,6 +339,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
cSlot := primitives.Slot(2)
|
||||
driftGenesisTime(f, cSlot, 0)
|
||||
c := indexToHash(2)
|
||||
f.store.proposerBoostRoot = [32]byte{}
|
||||
state, blkRoot, err := prepareForkchoiceState(
|
||||
ctx,
|
||||
cSlot,
|
||||
@@ -354,6 +359,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
|
||||
bSlot := primitives.Slot(1)
|
||||
b := indexToHash(1)
|
||||
f.store.proposerBoostRoot = [32]byte{}
|
||||
state, blkRoot, err = prepareForkchoiceState(
|
||||
ctx,
|
||||
bSlot,
|
||||
@@ -378,6 +384,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
// A block D, building on B, is received at slot N+3. It should not be able to win without boosting.
|
||||
dSlot := primitives.Slot(3)
|
||||
d := indexToHash(3)
|
||||
f.store.proposerBoostRoot = [32]byte{}
|
||||
state, blkRoot, err = prepareForkchoiceState(
|
||||
ctx,
|
||||
dSlot,
|
||||
@@ -398,6 +405,7 @@ func TestForkChoice_BoostProposerRoot_PreventsExAnteAttack(t *testing.T) {
|
||||
// If the same block arrives with boosting then it becomes head:
|
||||
driftGenesisTime(f, dSlot, 0)
|
||||
d2 := indexToHash(30)
|
||||
f.store.proposerBoostRoot = [32]byte{}
|
||||
state, blkRoot, err = prepareForkchoiceState(
|
||||
ctx,
|
||||
dSlot,
|
||||
|
||||
@@ -109,7 +109,8 @@ func (s *Store) insert(ctx context.Context,
|
||||
secondsIntoSlot := (timeNow - s.genesisTime) % params.BeaconConfig().SecondsPerSlot
|
||||
currentSlot := slots.CurrentSlot(s.genesisTime)
|
||||
boostThreshold := params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().IntervalsPerSlot
|
||||
if currentSlot == slot && secondsIntoSlot < boostThreshold {
|
||||
isFirstBlock := s.proposerBoostRoot == [32]byte{}
|
||||
if currentSlot == slot && secondsIntoSlot < boostThreshold && isFirstBlock {
|
||||
s.proposerBoostRoot = root
|
||||
}
|
||||
|
||||
|
||||
@@ -141,7 +141,7 @@ func TestGetSpec(t *testing.T) {
|
||||
resp, err := server.GetSpec(context.Background(), &emptypb.Empty{})
|
||||
require.NoError(t, err)
|
||||
|
||||
assert.Equal(t, 111, len(resp.Data))
|
||||
assert.Equal(t, 112, len(resp.Data))
|
||||
for k, v := range resp.Data {
|
||||
switch k {
|
||||
case "CONFIG_NAME":
|
||||
@@ -380,6 +380,8 @@ func TestGetSpec(t *testing.T) {
|
||||
assert.Equal(t, "20", v)
|
||||
case "REORG_PARENT_WEIGHT_THRESHOLD":
|
||||
assert.Equal(t, "160", v)
|
||||
case "MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT":
|
||||
assert.Equal(t, "8", v)
|
||||
case "SAFE_SLOTS_TO_IMPORT_OPTIMISTICALLY":
|
||||
default:
|
||||
t.Errorf("Incorrect key: %s", k)
|
||||
|
||||
@@ -18,12 +18,10 @@ func (s *Service) blobSubscriber(ctx context.Context, msg proto.Message) error {
|
||||
|
||||
s.setSeenBlobIndex(b.Message.Blob, b.Message.Index)
|
||||
|
||||
if err := s.cfg.beaconDB.SaveBlobSidecar(ctx, []*eth.BlobSidecar{b.Message}); err != nil {
|
||||
if err := s.cfg.chain.ReceiveBlob(ctx, b.Message); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
s.cfg.chain.SendNewBlobEvent([32]byte(b.Message.BlockRoot), b.Message.Index)
|
||||
|
||||
s.cfg.operationNotifier.OperationFeed().Send(&feed.Event{
|
||||
Type: opfeed.BlobSidecarReceived,
|
||||
Data: &opfeed.BlobSidecarReceivedData{
|
||||
|
||||
@@ -213,7 +213,7 @@ type BeaconChainConfig struct {
|
||||
|
||||
// Mev-boost circuit breaker
|
||||
MaxBuilderConsecutiveMissedSlots primitives.Slot // MaxBuilderConsecutiveMissedSlots defines the number of consecutive skip slot to fallback from using relay/builder to local execution engine for block construction.
|
||||
MaxBuilderEpochMissedSlots primitives.Slot // MaxBuilderEpochMissedSlots is defines the number of total skip slot (per epoch rolling windows) to fallback from using relay/builder to local execution engine for block construction.
|
||||
MaxBuilderEpochMissedSlots primitives.Slot // MaxBuilderEpochMissedSlots is defining the number of total skip slot (per epoch rolling windows) to fallback from using relay/builder to local execution engine for block construction.
|
||||
LocalBlockValueBoost uint64 // LocalBlockValueBoost is the value boost for local block construction. This is used to prioritize local block construction over relay/builder block construction.
|
||||
|
||||
// Execution engine timeout value
|
||||
@@ -221,6 +221,9 @@ type BeaconChainConfig struct {
|
||||
|
||||
// Subnet value
|
||||
BlobsidecarSubnetCount uint64 `yaml:"BLOB_SIDECAR_SUBNET_COUNT"` // BlobsidecarSubnetCount is the number of blobsidecar subnets used in the gossipsub protocol.
|
||||
|
||||
// Values introduced in Deneb hard fork
|
||||
MaxPerEpochActivationChurnLimit uint64 `yaml:"MAX_PER_EPOCH_ACTIVATION_CHURN_LIMIT" spec:"true"` // MaxPerEpochActivationChurnLimit is the maximum amount of churn allotted for validator activation.
|
||||
}
|
||||
|
||||
// InitializeForkSchedule initializes the schedules forks baked into the config.
|
||||
|
||||
@@ -47,8 +47,10 @@ var placeholderFields = []string{
|
||||
"SUBNETS_PER_NODE",
|
||||
"TTFB_TIMEOUT",
|
||||
"UPDATE_TIMEOUT",
|
||||
"WHISK_EPOCHS_PER_SHUFFLING_PHASE",
|
||||
"WHISK_FORK_EPOCH",
|
||||
"WHISK_FORK_VERSION",
|
||||
"WHISK_PROPOSER_SELECTION_GAP",
|
||||
}
|
||||
|
||||
func TestPlaceholderFieldsDistinctSorted(t *testing.T) {
|
||||
|
||||
@@ -270,6 +270,8 @@ var mainnetBeaconConfig = &BeaconChainConfig{
|
||||
|
||||
// Subnet value
|
||||
BlobsidecarSubnetCount: 6,
|
||||
|
||||
MaxPerEpochActivationChurnLimit: 8,
|
||||
}
|
||||
|
||||
// MainnetTestConfig provides a version of the mainnet config that has a different name
|
||||
|
||||
@@ -13,7 +13,8 @@ func MinimalSpecConfig() *BeaconChainConfig {
|
||||
minimalConfig.MaxCommitteesPerSlot = 4
|
||||
minimalConfig.TargetCommitteeSize = 4
|
||||
minimalConfig.MaxValidatorsPerCommittee = 2048
|
||||
minimalConfig.MinPerEpochChurnLimit = 4
|
||||
minimalConfig.MinPerEpochChurnLimit = 2 // Changed in EIP7514
|
||||
minimalConfig.MaxPerEpochActivationChurnLimit = 4 // New in EIP7514
|
||||
minimalConfig.ChurnLimitQuotient = 32
|
||||
minimalConfig.ShuffleRoundCount = 10
|
||||
minimalConfig.MinGenesisActiveValidatorCount = 64
|
||||
|
||||
4
config/params/testdata/e2e_config.yaml
vendored
4
config/params/testdata/e2e_config.yaml
vendored
@@ -68,8 +68,8 @@ INACTIVITY_SCORE_BIAS: 4
|
||||
INACTIVITY_SCORE_RECOVERY_RATE: 16
|
||||
# 2**4 * 10**9 (= 16,000,000,000) Gwei
|
||||
EJECTION_BALANCE: 16000000000
|
||||
# 2**2 (= 4)
|
||||
MIN_PER_EPOCH_CHURN_LIMIT: 4
|
||||
# 2**1 (= 2)
|
||||
MIN_PER_EPOCH_CHURN_LIMIT: 2
|
||||
# [customized] scale queue churn at much lower validator counts for testing
|
||||
CHURN_LIMIT_QUOTIENT: 65536
|
||||
|
||||
|
||||
@@ -96,6 +96,9 @@ func E2EMainnetTestConfig() *BeaconChainConfig {
|
||||
e2eConfig.CapellaForkVersion = []byte{3, 0, 0, 254}
|
||||
e2eConfig.DenebForkVersion = []byte{4, 0, 0, 254}
|
||||
|
||||
// Deneb changes.
|
||||
e2eConfig.MinPerEpochChurnLimit = 2
|
||||
|
||||
e2eConfig.InitializeForkSchedule()
|
||||
return e2eConfig
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: 07349f3ccd696e6980796cf0b8dc149b14d1791dce8dbc553e506af598c11ebb
|
||||
// Hash: 8807216586301e9517cb647c4514f4ef73f2c52b106aa5cf7706ce504fcdf511
|
||||
package v1
|
||||
|
||||
import (
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: eaf49253855a8c44a53cb851548885777d203c0cdcd3249906ea5f9a7b6e93c6
|
||||
// Hash: c5b73fa04173f2f7ff57471820227c1c57ed2cf64771a033a8dd7661476b1534
|
||||
package eth
|
||||
|
||||
import (
|
||||
|
||||
@@ -67,4 +67,4 @@ message SignedBlindedBlobSidecar {
|
||||
message BlobIdentifier {
|
||||
bytes block_root = 1 [(ethereum.eth.ext.ssz_size) = "32"];
|
||||
uint64 index = 2;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Code generated by fastssz. DO NOT EDIT.
|
||||
// Hash: 5d81458f3b159025d0b0af981efc97e49e33f9a0e91711f2045924512ddf8f68
|
||||
// Hash: 437628ba689fb27f524848c027086209535727cf259e162754f174e54b3940cc
|
||||
package eth
|
||||
|
||||
import (
|
||||
|
||||
@@ -29,8 +29,6 @@ import (
|
||||
"google.golang.org/protobuf/types/known/emptypb"
|
||||
)
|
||||
|
||||
// churnLimit is normally 4 unless the validator set is extremely large.
|
||||
var churnLimit = 4
|
||||
var depositValCount = e2e.DepositCount
|
||||
var numOfExits = 2
|
||||
|
||||
@@ -39,7 +37,7 @@ var depositsInBlockStart = params.E2ETestConfig().EpochsPerEth1VotingPeriod * 2
|
||||
|
||||
// deposits included + finalization + MaxSeedLookahead for activation.
|
||||
var depositActivationStartEpoch = depositsInBlockStart + 2 + params.E2ETestConfig().MaxSeedLookahead
|
||||
var depositEndEpoch = depositActivationStartEpoch + primitives.Epoch(math.Ceil(float64(depositValCount)/float64(churnLimit)))
|
||||
var depositEndEpoch = depositActivationStartEpoch + primitives.Epoch(math.Ceil(float64(depositValCount)/float64(params.BeaconConfig().MinPerEpochChurnLimit)))
|
||||
var exitSubmissionEpoch = primitives.Epoch(7)
|
||||
|
||||
// ProcessesDepositsInBlocks ensures the expected amount of deposits are accepted into blocks.
|
||||
@@ -249,8 +247,8 @@ func activatesDepositedValidators(ec *e2etypes.EvaluationContext, conns ...*grpc
|
||||
return fmt.Errorf("missing %d validators for post-genesis deposits", len(expected))
|
||||
}
|
||||
|
||||
if deposits != churnLimit {
|
||||
return fmt.Errorf("expected %d deposits to be processed in epoch %d, received %d", churnLimit, epoch, deposits)
|
||||
if uint64(deposits) != params.BeaconConfig().MinPerEpochChurnLimit {
|
||||
return fmt.Errorf("expected %d deposits to be processed in epoch %d, received %d", params.BeaconConfig().MinPerEpochChurnLimit, epoch, deposits)
|
||||
}
|
||||
|
||||
if lowBalance > 0 {
|
||||
|
||||
@@ -26,9 +26,9 @@ type KZGTestData struct {
|
||||
|
||||
func TestVerifyBlobKZGProofBatch(t *testing.T) {
|
||||
require.NoError(t, kzgPrysm.Start())
|
||||
testFolders, testFolderPath := utils.TestFolders(t, "general", "deneb", "kzg/verify_blob_kzg_proof_batch/small")
|
||||
testFolders, testFolderPath := utils.TestFolders(t, "general", "deneb", "kzg/verify_blob_kzg_proof_batch/kzg-mainnet")
|
||||
if len(testFolders) == 0 {
|
||||
t.Fatalf("No test folders found for %s/%s/%s", "general", "deneb", "kzg/verify_blob_kzg_proof_batch/small")
|
||||
t.Fatalf("No test folders found for %s/%s/%s", "general", "deneb", "kzg/verify_blob_kzg_proof_batch/kzg-mainnet")
|
||||
}
|
||||
for _, folder := range testFolders {
|
||||
t.Run(folder.Name(), func(t *testing.T) {
|
||||
|
||||
@@ -19,9 +19,9 @@ func TestAggregate(t *testing.T) {
|
||||
}
|
||||
|
||||
func testAggregate(t *testing.T) {
|
||||
testFolders, testFolderPath := utils.TestFolders(t, "general", "phase0", "bls/aggregate/small")
|
||||
testFolders, testFolderPath := utils.TestFolders(t, "general", "phase0", "bls/aggregate/bls")
|
||||
if len(testFolders) == 0 {
|
||||
t.Fatalf("No test folders found for %s/%s/%s", "general", "phase0", "bls/aggregate/small")
|
||||
t.Fatalf("No test folders found for %s/%s/%s", "general", "phase0", "bls/aggregate/bls")
|
||||
}
|
||||
for _, folder := range testFolders {
|
||||
t.Run(folder.Name(), func(t *testing.T) {
|
||||
|
||||
@@ -20,9 +20,9 @@ func TestAggregateVerify(t *testing.T) {
|
||||
}
|
||||
|
||||
func testAggregateVerify(t *testing.T) {
|
||||
testFolders, testFolderPath := utils.TestFolders(t, "general", "phase0", "bls/aggregate_verify/small")
|
||||
testFolders, testFolderPath := utils.TestFolders(t, "general", "phase0", "bls/aggregate_verify/bls")
|
||||
if len(testFolders) == 0 {
|
||||
t.Fatalf("No test folders found for %s/%s/%s", "general", "phase0", "bls/aggregate_verify/small")
|
||||
t.Fatalf("No test folders found for %s/%s/%s", "general", "phase0", "bls/aggregate_verify/bls")
|
||||
}
|
||||
for i, folder := range testFolders {
|
||||
t.Run(folder.Name(), func(t *testing.T) {
|
||||
|
||||
@@ -20,9 +20,9 @@ func TestFastAggregateVerify(t *testing.T) {
|
||||
}
|
||||
|
||||
func testFastAggregateVerify(t *testing.T) {
|
||||
testFolders, testFolderPath := utils.TestFolders(t, "general", "phase0", "bls/fast_aggregate_verify/small")
|
||||
testFolders, testFolderPath := utils.TestFolders(t, "general", "phase0", "bls/fast_aggregate_verify/bls")
|
||||
if len(testFolders) == 0 {
|
||||
t.Fatalf("No test folders found for %s/%s/%s", "general", "phase0", "bls/fast_aggregate_verify/small")
|
||||
t.Fatalf("No test folders found for %s/%s/%s", "general", "phase0", "bls/fast_aggregate_verify/bls")
|
||||
}
|
||||
for i, folder := range testFolders {
|
||||
t.Run(folder.Name(), func(t *testing.T) {
|
||||
|
||||
@@ -20,9 +20,9 @@ func TestSign(t *testing.T) {
|
||||
}
|
||||
|
||||
func testSign(t *testing.T) {
|
||||
testFolders, testFolderPath := utils.TestFolders(t, "general", "phase0", "bls/sign/small")
|
||||
testFolders, testFolderPath := utils.TestFolders(t, "general", "phase0", "bls/sign/bls")
|
||||
if len(testFolders) == 0 {
|
||||
t.Fatalf("No test folders found for %s/%s/%s", "general", "phase0", "bls/sign/small")
|
||||
t.Fatalf("No test folders found for %s/%s/%s", "general", "phase0", "bls/sign/bls")
|
||||
}
|
||||
for i, folder := range testFolders {
|
||||
t.Run(folder.Name(), func(t *testing.T) {
|
||||
|
||||
@@ -19,9 +19,9 @@ func TestVerify(t *testing.T) {
|
||||
}
|
||||
|
||||
func testVerify(t *testing.T) {
|
||||
testFolders, testFolderPath := utils.TestFolders(t, "general", "phase0", "bls/verify/small")
|
||||
testFolders, testFolderPath := utils.TestFolders(t, "general", "phase0", "bls/verify/bls")
|
||||
if len(testFolders) == 0 {
|
||||
t.Fatalf("No test folders found for %s/%s/%s", "general", "phase0", "bls/verify/small")
|
||||
t.Fatalf("No test folders found for %s/%s/%s", "general", "phase0", "bls/verify/bls")
|
||||
}
|
||||
for i, folder := range testFolders {
|
||||
t.Run(folder.Name(), func(t *testing.T) {
|
||||
|
||||
@@ -8,5 +8,6 @@ import (
|
||||
)
|
||||
|
||||
func TestMinimal_Deneb_Forkchoice(t *testing.T) {
|
||||
t.Skip("blocked by go-kzg-4844 minimal trusted setup")
|
||||
forkchoice.Run(t, "minimal", version.Deneb)
|
||||
}
|
||||
|
||||
@@ -13,6 +13,7 @@ go_library(
|
||||
visibility = ["//testing/spectest:__subpackages__"],
|
||||
deps = [
|
||||
"//beacon-chain/blockchain:go_default_library",
|
||||
"//beacon-chain/blockchain/kzg:go_default_library",
|
||||
"//beacon-chain/blockchain/testing:go_default_library",
|
||||
"//beacon-chain/cache:go_default_library",
|
||||
"//beacon-chain/cache/depositcache:go_default_library",
|
||||
|
||||
@@ -88,13 +88,17 @@ func (bb *Builder) block(t testing.TB, b interfaces.ReadOnlySignedBeaconBlock) [
|
||||
// InvalidBlock receives the invalid block and notifies forkchoice.
|
||||
func (bb *Builder) InvalidBlock(t testing.TB, b interfaces.ReadOnlySignedBeaconBlock) {
|
||||
r := bb.block(t, b)
|
||||
require.Equal(t, true, bb.service.ReceiveBlock(context.TODO(), b, r) != nil)
|
||||
ctx, cancel := context.WithTimeout(context.TODO(), time.Duration(params.BeaconConfig().SecondsPerSlot)*time.Second)
|
||||
defer cancel()
|
||||
require.Equal(t, true, bb.service.ReceiveBlock(ctx, b, r) != nil)
|
||||
}
|
||||
|
||||
// ValidBlock receives the valid block and notifies forkchoice.
|
||||
func (bb *Builder) ValidBlock(t testing.TB, b interfaces.ReadOnlySignedBeaconBlock) {
|
||||
r := bb.block(t, b)
|
||||
require.NoError(t, bb.service.ReceiveBlock(context.TODO(), b, r))
|
||||
ctx, cancel := context.WithTimeout(context.TODO(), time.Duration(params.BeaconConfig().SecondsPerSlot)*time.Second)
|
||||
defer cancel()
|
||||
require.NoError(t, bb.service.ReceiveBlock(ctx, b, r))
|
||||
}
|
||||
|
||||
// PoWBlock receives the block and notifies a mocked execution engine.
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
package forkchoice
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
"os"
|
||||
"path"
|
||||
"testing"
|
||||
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
"github.com/golang/snappy"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/core/transition"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/state"
|
||||
@@ -90,12 +93,12 @@ func runTest(t *testing.T, config string, fork int, basePath string) {
|
||||
if step.Tick != nil {
|
||||
builder.Tick(t, int64(*step.Tick))
|
||||
}
|
||||
var beaconBlock interfaces.ReadOnlySignedBeaconBlock
|
||||
if step.Block != nil {
|
||||
blockFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), fmt.Sprint(*step.Block, ".ssz_snappy"))
|
||||
require.NoError(t, err)
|
||||
blockSSZ, err := snappy.Decode(nil /* dst */, blockFile)
|
||||
require.NoError(t, err)
|
||||
var beaconBlock interfaces.ReadOnlySignedBeaconBlock
|
||||
switch fork {
|
||||
case version.Phase0:
|
||||
beaconBlock = unmarshalSignedPhase0Block(t, blockSSZ)
|
||||
@@ -110,6 +113,9 @@ func runTest(t *testing.T, config string, fork int, basePath string) {
|
||||
default:
|
||||
t.Fatalf("unknown fork version: %v", fork)
|
||||
}
|
||||
}
|
||||
runBlobStep(t, step.Blobs, beaconBlock, fork, folder, testsFolderPath, step.Proofs, builder)
|
||||
if beaconBlock != nil {
|
||||
if step.Valid != nil && !*step.Valid {
|
||||
builder.InvalidBlock(t, beaconBlock)
|
||||
} else {
|
||||
@@ -272,3 +278,57 @@ func unmarshalSignedDenebBlock(t *testing.T, raw []byte) interfaces.SignedBeacon
|
||||
require.NoError(t, err)
|
||||
return blk
|
||||
}
|
||||
|
||||
func runBlobStep(t *testing.T,
|
||||
blobs *string,
|
||||
beaconBlock interfaces.ReadOnlySignedBeaconBlock,
|
||||
fork int,
|
||||
folder os.DirEntry,
|
||||
testsFolderPath string,
|
||||
proofs []*string,
|
||||
builder *Builder,
|
||||
) {
|
||||
if blobs != nil && *blobs != "null" {
|
||||
require.NotNil(t, beaconBlock)
|
||||
require.Equal(t, true, fork >= version.Deneb)
|
||||
|
||||
block := beaconBlock.Block()
|
||||
root, err := block.HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
parentRoot := block.ParentRoot()
|
||||
kzgs, err := block.Body().BlobKzgCommitments()
|
||||
require.NoError(t, err)
|
||||
|
||||
blobsFile, err := util.BazelFileBytes(testsFolderPath, folder.Name(), fmt.Sprint(*blobs, ".ssz_snappy"))
|
||||
require.NoError(t, err)
|
||||
blobsSSZ, err := snappy.Decode(nil /* dst */, blobsFile)
|
||||
require.NoError(t, err)
|
||||
for index := uint64(0); index*fieldparams.BlobLength < uint64(len(blobsSSZ)); index++ {
|
||||
var proof []byte
|
||||
if index < uint64(len(proofs)) {
|
||||
proofPTR := proofs[index]
|
||||
require.NotNil(t, proofPTR)
|
||||
proof, err = hexutil.Decode(*proofPTR)
|
||||
require.NoError(t, err)
|
||||
}
|
||||
|
||||
var kzg []byte
|
||||
if uint64(len(kzgs)) < index {
|
||||
kzg = kzgs[index]
|
||||
}
|
||||
blob := [fieldparams.BlobLength]byte{}
|
||||
copy(blob[:], blobsSSZ[index*fieldparams.BlobLength:])
|
||||
sidecar := ðpb.BlobSidecar{
|
||||
BlockRoot: root[:],
|
||||
Index: index,
|
||||
Slot: block.Slot(),
|
||||
BlockParentRoot: parentRoot[:],
|
||||
ProposerIndex: block.ProposerIndex(),
|
||||
Blob: blob[:],
|
||||
KzgCommitment: kzg,
|
||||
KzgProof: proof,
|
||||
}
|
||||
require.NoError(t, builder.service.ReceiveBlob(context.Background(), sidecar))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,6 +9,7 @@ import (
|
||||
"github.com/ethereum/go-ethereum/common/hexutil"
|
||||
gethtypes "github.com/ethereum/go-ethereum/core/types"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/kzg"
|
||||
mock "github.com/prysmaticlabs/prysm/v4/beacon-chain/blockchain/testing"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/cache"
|
||||
"github.com/prysmaticlabs/prysm/v4/beacon-chain/cache/depositcache"
|
||||
@@ -33,8 +34,8 @@ func startChainService(t testing.TB,
|
||||
block interfaces.ReadOnlySignedBeaconBlock,
|
||||
engineMock *engineMock,
|
||||
) *blockchain.Service {
|
||||
db := testDB.SetupDB(t)
|
||||
ctx := context.Background()
|
||||
db := testDB.SetupDB(t)
|
||||
require.NoError(t, db.SaveBlock(ctx, block))
|
||||
r, err := block.Block().HashTreeRoot()
|
||||
require.NoError(t, err)
|
||||
@@ -71,6 +72,8 @@ func startChainService(t testing.TB,
|
||||
)
|
||||
service, err := blockchain.NewService(context.Background(), opts...)
|
||||
require.NoError(t, err)
|
||||
// force start kzg context here until Deneb fork epoch is decided
|
||||
require.NoError(t, kzg.Start())
|
||||
require.NoError(t, service.StartFromSavedState(st))
|
||||
return service
|
||||
}
|
||||
|
||||
@@ -3,6 +3,8 @@ package forkchoice
|
||||
type Step struct {
|
||||
Tick *int `json:"tick"`
|
||||
Block *string `json:"block"`
|
||||
Blobs *string `json:"blobs"`
|
||||
Proofs []*string `json:"proofs"`
|
||||
Valid *bool `json:"valid"`
|
||||
Attestation *string `json:"attestation"`
|
||||
AttesterSlashing *string `json:"attester_slashing"`
|
||||
|
||||
Reference in New Issue
Block a user