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:
Potuz
2023-09-28 18:05:23 -03:00
committed by GitHub
parent a7361cd5ab
commit b4e72f1e19
33 changed files with 200 additions and 48 deletions

View File

@@ -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,
)

View File

@@ -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
}

View File

@@ -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.

View File

@@ -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
}

View File

@@ -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

View File

@@ -338,6 +338,42 @@ func TestProcessRegistryUpdates_EligibleToActivate(t *testing.T) {
}
}
func TestProcessRegistryUpdates_EligibleToActivate_Cancun(t *testing.T) {
base := &ethpb.BeaconStateDeneb{
Slot: 5 * params.BeaconConfig().SlotsPerEpoch,
FinalizedCheckpoint: &ethpb.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, &ethpb.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 := &ethpb.BeaconState{
Slot: 5 * params.BeaconConfig().SlotsPerEpoch,

View File

@@ -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,

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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{

View File

@@ -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.

View File

@@ -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) {

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -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
}

View File

@@ -1,5 +1,5 @@
// Code generated by fastssz. DO NOT EDIT.
// Hash: 07349f3ccd696e6980796cf0b8dc149b14d1791dce8dbc553e506af598c11ebb
// Hash: 8807216586301e9517cb647c4514f4ef73f2c52b106aa5cf7706ce504fcdf511
package v1
import (

View File

@@ -1,5 +1,5 @@
// Code generated by fastssz. DO NOT EDIT.
// Hash: eaf49253855a8c44a53cb851548885777d203c0cdcd3249906ea5f9a7b6e93c6
// Hash: c5b73fa04173f2f7ff57471820227c1c57ed2cf64771a033a8dd7661476b1534
package eth
import (

View File

@@ -67,4 +67,4 @@ message SignedBlindedBlobSidecar {
message BlobIdentifier {
bytes block_root = 1 [(ethereum.eth.ext.ssz_size) = "32"];
uint64 index = 2;
}
}

View File

@@ -1,5 +1,5 @@
// Code generated by fastssz. DO NOT EDIT.
// Hash: 5d81458f3b159025d0b0af981efc97e49e33f9a0e91711f2045924512ddf8f68
// Hash: 437628ba689fb27f524848c027086209535727cf259e162754f174e54b3940cc
package eth
import (

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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)
}

View File

@@ -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",

View File

@@ -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.

View File

@@ -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 := &ethpb.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))
}
}
}

View File

@@ -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
}

View File

@@ -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"`