Compare commits

..

24 Commits

Author SHA1 Message Date
nisdas
1f1c4e2b08 Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into useNewCacheKey 2024-12-17 18:13:26 +08:00
Preston Van Loon
2b25ede641 Update changelog for v5.2.0 release (#14727)
* Update CHANGELOG.md for v5.2.0

* update latest develop
2024-12-17 06:12:02 +00:00
Preston Van Loon
b7de64a340 Check non-nil validator before accessing withdrawal credentials (#14705)
* Check non-nil validator before accessing withdrawal credentials

* Updated changelog
2024-12-16 16:34:01 +00:00
Manu NALEPA
11aa51e033 Display error in "Finished building block" only if error. (#14722) 2024-12-15 20:38:47 +00:00
terence
fa0dc09ce0 Add proper gas limit check through local computation (#14707)
* Add proper gas limit check through local computation

* Potuz's feedback

* Fix new line
2024-12-13 16:02:00 +00:00
Rupam Dey
d93a1b671c process lc finality update only for new finalized checkpoints (#14713)
* add checks for finalized checkpoint

* implement `EmptyExecutionPayloadHeader()` function

* changelog

* fix error message

* revert `process_block.go`

* fix error message

* testing

* Update CHANGELOG.md

Co-authored-by: Radosław Kapka <radoslaw.kapka@gmail.com>

* revert "testing"

---------

Co-authored-by: Radosław Kapka <radoslaw.kapka@gmail.com>
Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2024-12-12 20:39:49 +00:00
Jun Song
1d8ffadd4f chore: add an error field to "Finished building block" (#14696)
* fix: print "Finished building block" only when succeeded

* Add failed log

* Apply preston's review
2024-12-12 17:07:34 +00:00
Nishant Das
ac1717f1e4 Revert "Change Max Payload Size (#14692)" (#14716)
This reverts commit df81fa3e9a.
2024-12-12 15:21:47 +00:00
Dan Park
6e6012b12f Bugfix: Apply eip7549 to slashing pool (#14691)
* Apply eip7549 to slashing pool

* Add CHANGELOG.md

* Update bazel

---------

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
2024-12-11 18:57:21 +00:00
Nishant Das
008f157e17 Update Quic-go to the latest version (#14710)
* Update to v0.48.2

* Changelog
2024-12-11 09:37:54 +00:00
Bastin
7afb8c3c86 move light client rpc helpers tests to core (#14695)
* move rpc helpers tests to core

* remove helpers tests

* fix linter

* deleted extra files

* fix conflicts

---------

Co-authored-by: Radosław Kapka <rkapka@wp.pl>
Co-authored-by: Inspector-Butters <mohamadbastin@gmail.com>
2024-12-10 19:51:29 +00:00
terence
e925d35d55 Fix proposer boost test (#14701) 2024-12-10 18:00:24 +00:00
Nishant Das
6387040613 Merge branch 'develop' into useNewCacheKey 2024-12-10 14:41:38 +08:00
Nishant Das
1c7077e254 Merge branch 'develop' into useNewCacheKey 2024-11-29 11:58:31 +08:00
Nishant Das
9ab7e7d37c Update CHANGELOG.md 2024-11-29 11:57:31 +08:00
Nishant Das
bf80a5430f Merge branch 'develop' into useNewCacheKey 2024-11-27 13:06:03 +08:00
Nishant Das
9aef2c4ee2 Merge branch 'develop' into useNewCacheKey 2024-11-25 17:25:43 +08:00
nisdas
d094118082 Add benchmarks 2024-11-08 17:02:04 +08:00
nisdas
c69599f343 Addressing Review Comments 2024-11-08 16:41:28 +08:00
nisdas
1e0e5e110a Add Changelog 2024-11-08 16:38:26 +08:00
nisdas
8254cb30b4 Merge branch 'develop' of https://github.com/prysmaticlabs/geth-sharding into useNewCacheKey 2024-11-08 16:37:35 +08:00
nisdas
74961eb51f Gosec 2024-10-30 16:50:28 +08:00
nisdas
514f96ec0e Changelog 2024-10-30 13:58:27 +08:00
nisdas
cabe7d34b6 Use New Cache Key 2024-10-30 13:46:38 +08:00
28 changed files with 1235 additions and 753 deletions

View File

@@ -4,7 +4,50 @@ All notable changes to this project will be documented in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
## [Unreleased](https://github.com/prysmaticlabs/prysm/compare/v5.1.2...HEAD)
## [Unreleased](https://github.com/prysmaticlabs/prysm/compare/v5.2.0...HEAD)
### Added
- Added proper gas limit check for header from the builder.
- Added an error field to log `Finished building block`.
- Implemented a new `EmptyExecutionPayloadHeader` function.
- `Finished building block`: Display error only if not nil.
### Changed
- Process light client finality updates only for new finalized epochs instead of doing it for every block.
- Add more efficient method of computing the cache key for unaggregated attestations.
### Deprecated
### Removed
### Fixed
- Added check to prevent nil pointer deference or out of bounds array access when validating the BLSToExecutionChange on an impossibly nil validator.
### Security
## [v5.2.0](https://github.com/prysmaticlabs/prysm/compare/v5.1.2...v5.2.0)
Updating to this release is highly recommended, especially for users running v5.1.1 or v5.1.2.
This release is **mandatory** for all validator clients using mev-boost with a gas limit increase.
Without upgrading to this release, validator clients will default to using local execution blocks
when the gas limit starts to increase.
This release has several fixes and new features. In this release, we have enabled QUIC protocol by
default, which uses port 13000 for `--p2p-quic-port`. This may be a [breaking change](https://github.com/prysmaticlabs/prysm/pull/14688#issuecomment-2516713826)
if you're using port 13000 already. This release has some improvements for raising the gas limit,
but there are [known issues](https://hackmd.io/@ttsao/prysm-gas-limit) with the proposer settings
file provided gas limit not being respected for mev-boost outsourced blocks. Signalling an increase
for the gas limit works perfectly for local block production as of this release. See [pumpthegas.org](https://pumpthegas.org) for more info on raising the gas limit on L1.
Notable features:
- Prysm can reuse blobs from the EL via engine_getBlobsV1, [potentially saving bandwidth](https://hackmd.io/@ttsao/get-blobs-early-results).
- QUIC is enabled by default. This is a UDP based networking protocol with default port 13000.
### Added
@@ -75,8 +118,8 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
- Updated `Blobs` endpoint to return additional metadata fields.
- Made QUIC the default method to connect with peers.
- Check kzg commitments align with blobs and proofs for beacon api end point.
- Increase Max Payload Size in Gossip.
- Revert "Proposer checks gas limit before accepting builder's bid".
- Updated quic-go to v0.48.2 .
### Deprecated
@@ -114,9 +157,10 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
- P2P: Avoid infinite loop when looking for peers in small networks.
- Fixed another rollback bug due to a context deadline.
- Fix checkpoint sync bug on holesky. [pr](https://github.com/prysmaticlabs/prysm/pull/14689)
- Fix proposer boost spec tests being flakey by adjusting start time from 3 to 2s into slot.
- Fix segmentation fault in E2E when light-client feature flag is enabled. [PR](https://github.com/prysmaticlabs/prysm/pull/14699)
- Fix `searchForPeers` infinite loop in small networks.
- Fix slashing pool behavior to enforce MaxAttesterSlashings limit in Electra version.
### Security

View File

@@ -1,6 +1,7 @@
package blockchain
import (
"bytes"
"context"
"fmt"
"time"
@@ -240,6 +241,11 @@ func (s *Service) processLightClientFinalityUpdate(
}
}
// Check if the finalized checkpoint has changed
if finalizedCheckPoint == nil || bytes.Equal(finalizedCheckPoint.GetRoot(), postState.FinalizedCheckpoint().Root) {
return nil
}
update, err := lightclient.NewLightClientFinalityUpdateFromBeaconState(
ctx,
postState.Slot(),

View File

@@ -1,5 +1,5 @@
package blocks
var ProcessBLSToExecutionChange = processBLSToExecutionChange
var ErrInvalidBLSPrefix = errInvalidBLSPrefix
var VerifyBlobCommitmentCount = verifyBlobCommitmentCount

View File

@@ -100,8 +100,11 @@ func ValidateBLSToExecutionChange(st state.ReadOnlyBeaconState, signed *ethpb.Si
if err != nil {
return nil, err
}
if val == nil {
return nil, errors.Wrap(errInvalidWithdrawalCredentials, "validator is nil") // This should not be possible.
}
cred := val.WithdrawalCredentials
if cred[0] != params.BeaconConfig().BLSWithdrawalPrefixByte {
if len(cred) < 2 || cred[0] != params.BeaconConfig().BLSWithdrawalPrefixByte {
return nil, errInvalidBLSPrefix
}

View File

@@ -113,7 +113,42 @@ func TestProcessBLSToExecutionChange(t *testing.T) {
require.NoError(t, err)
require.DeepEqual(t, digest[:], val.WithdrawalCredentials)
})
t.Run("nil validator does not panic", func(t *testing.T) {
priv, err := bls.RandKey()
require.NoError(t, err)
pubkey := priv.PublicKey().Marshal()
message := &ethpb.BLSToExecutionChange{
ToExecutionAddress: []byte{0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13},
ValidatorIndex: 0,
FromBlsPubkey: pubkey,
}
registry := []*ethpb.Validator{
nil,
}
st, err := state_native.InitializeFromProtoPhase0(&ethpb.BeaconState{
Validators: registry,
Fork: &ethpb.Fork{
CurrentVersion: params.BeaconConfig().GenesisForkVersion,
PreviousVersion: params.BeaconConfig().GenesisForkVersion,
},
Slot: params.BeaconConfig().SlotsPerEpoch * 5,
})
require.NoError(t, err)
signature, err := signing.ComputeDomainAndSign(st, time.CurrentEpoch(st), message, params.BeaconConfig().DomainBLSToExecutionChange, priv)
require.NoError(t, err)
signed := &ethpb.SignedBLSToExecutionChange{
Message: message,
Signature: signature,
}
_, err = blocks.ValidateBLSToExecutionChange(st, signed)
// The state should return an empty validator, even when the validator object in the registry is
// nil. This error should return when the withdrawal credentials are invalid or too short.
require.ErrorIs(t, err, blocks.ErrInvalidBLSPrefix)
})
t.Run("non-existent validator", func(t *testing.T) {
priv, err := bls.RandKey()
require.NoError(t, err)

View File

@@ -6,6 +6,7 @@ go_library(
importpath = "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client",
visibility = ["//visibility:public"],
deps = [
"//beacon-chain/execution:go_default_library",
"//beacon-chain/state:go_default_library",
"//config/fieldparams:go_default_library",
"//config/params:go_default_library",
@@ -33,6 +34,7 @@ go_test(
"//config/params:go_default_library",
"//consensus-types:go_default_library",
"//consensus-types/blocks:go_default_library",
"//consensus-types/light-client:go_default_library",
"//consensus-types/primitives:go_default_library",
"//encoding/ssz:go_default_library",
"//proto/engine/v1:go_default_library",

View File

@@ -7,6 +7,7 @@ import (
"reflect"
"github.com/pkg/errors"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/execution"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/state"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params"
@@ -404,18 +405,15 @@ func BlockToLightClientHeader(
var payloadProof [][]byte
if blockEpoch < params.BeaconConfig().CapellaForkEpoch {
payloadHeader = &enginev1.ExecutionPayloadHeaderCapella{
ParentHash: make([]byte, fieldparams.RootLength),
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
StateRoot: make([]byte, fieldparams.RootLength),
ReceiptsRoot: make([]byte, fieldparams.RootLength),
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
PrevRandao: make([]byte, fieldparams.RootLength),
ExtraData: make([]byte, 0),
BaseFeePerGas: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength),
TransactionsRoot: make([]byte, fieldparams.RootLength),
WithdrawalsRoot: make([]byte, fieldparams.RootLength),
var ok bool
p, err := execution.EmptyExecutionPayloadHeader(version.Capella)
if err != nil {
return nil, errors.Wrap(err, "could not get payload header")
}
payloadHeader, ok = p.(*enginev1.ExecutionPayloadHeaderCapella)
if !ok {
return nil, fmt.Errorf("payload header type %T is not %T", p, &enginev1.ExecutionPayloadHeaderCapella{})
}
payloadProof = emptyPayloadProof()
} else {
@@ -472,18 +470,15 @@ func BlockToLightClientHeader(
var payloadProof [][]byte
if blockEpoch < params.BeaconConfig().CapellaForkEpoch {
payloadHeader = &enginev1.ExecutionPayloadHeaderDeneb{
ParentHash: make([]byte, fieldparams.RootLength),
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
StateRoot: make([]byte, fieldparams.RootLength),
ReceiptsRoot: make([]byte, fieldparams.RootLength),
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
PrevRandao: make([]byte, fieldparams.RootLength),
ExtraData: make([]byte, 0),
BaseFeePerGas: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength),
TransactionsRoot: make([]byte, fieldparams.RootLength),
WithdrawalsRoot: make([]byte, fieldparams.RootLength),
var ok bool
p, err := execution.EmptyExecutionPayloadHeader(version.Deneb)
if err != nil {
return nil, errors.Wrap(err, "could not get payload header")
}
payloadHeader, ok = p.(*enginev1.ExecutionPayloadHeaderDeneb)
if !ok {
return nil, fmt.Errorf("payload header type %T is not %T", p, &enginev1.ExecutionPayloadHeaderDeneb{})
}
payloadProof = emptyPayloadProof()
} else {

View File

@@ -2,15 +2,18 @@ package light_client_test
import (
"reflect"
"strings"
"testing"
"github.com/prysmaticlabs/prysm/v5/config/params"
light_client "github.com/prysmaticlabs/prysm/v5/consensus-types/light-client"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/pkg/errors"
lightClient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params"
consensustypes "github.com/prysmaticlabs/prysm/v5/consensus-types"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/ssz"
v11 "github.com/prysmaticlabs/prysm/v5/proto/engine/v1"
pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
@@ -972,3 +975,667 @@ func convertArrayToSlice(arr [4][32]uint8) [][]uint8 {
}
return slice
}
// When the update has relevant sync committee
func createNonEmptySyncCommitteeBranch() [][]byte {
res := make([][]byte, fieldparams.SyncCommitteeBranchDepth)
res[0] = []byte(strings.Repeat("x", 32))
for i := 1; i < len(res); i++ {
res[i] = make([]byte, fieldparams.RootLength)
}
return res
}
// When the update has finality
func createNonEmptyFinalityBranch() [][]byte {
res := make([][]byte, fieldparams.FinalityBranchDepth)
res[0] = []byte(strings.Repeat("x", 32))
for i := 1; i < fieldparams.FinalityBranchDepth; i++ {
res[i] = make([]byte, 32)
}
return res
}
func TestIsBetterUpdate(t *testing.T) {
config := params.BeaconConfig()
st, err := util.NewBeaconStateAltair()
require.NoError(t, err)
t.Run("new has supermajority but old doesn't", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
})
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b11111100, 0b1}, // [0,0,1,1,1,1,1,1]
})
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, true, result)
})
t.Run("old has supermajority but new doesn't", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b11111100, 0b1}, // [0,0,1,1,1,1,1,1]
})
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
})
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, false, result)
})
t.Run("new doesn't have supermajority and newNumActiveParticipants is greater than oldNumActiveParticipants", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
})
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, true, result)
})
t.Run("new doesn't have supermajority and newNumActiveParticipants is lesser than oldNumActiveParticipants", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
})
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, false, result)
})
t.Run("new has relevant sync committee but old doesn't", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
require.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000001,
},
})
require.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
require.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
newUpdate.SetSignatureSlot(1000000)
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, true, result)
})
t.Run("old has relevant sync committee but new doesn't", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000001,
},
})
require.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
require.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
oldUpdate.SetSignatureSlot(1000000)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
require.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, false, result)
})
t.Run("new has finality but old doesn't", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
require.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
require.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, true, result)
})
t.Run("old has finality but new doesn't", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
require.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
require.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, false, result)
})
t.Run("new has finality and sync committee finality both but old doesn't have sync committee finality", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
require.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
require.NoError(t, err)
err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader)
require.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
require.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
newUpdate.SetSignatureSlot(999999)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 999999,
},
})
require.NoError(t, err)
err = newUpdate.SetFinalizedHeader(newFinalizedHeader)
require.NoError(t, err)
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, true, result)
})
t.Run("new has finality but doesn't have sync committee finality and old has sync committee finality", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
require.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
oldUpdate.SetSignatureSlot(999999)
oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 999999,
},
})
require.NoError(t, err)
err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader)
require.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
require.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
require.NoError(t, err)
err = newUpdate.SetFinalizedHeader(newFinalizedHeader)
require.NoError(t, err)
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, false, result)
})
t.Run("new has more active participants than old", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,1,1,1,1,1,0,0]
})
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, true, result)
})
t.Run("new has less active participants than old", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,1,1,1,1,1,0,0]
})
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, false, result)
})
t.Run("new's attested header's slot is lesser than old's attested header's slot", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
require.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
require.NoError(t, err)
err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader)
require.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 999999,
},
})
require.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
require.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
require.NoError(t, err)
err = newUpdate.SetFinalizedHeader(newFinalizedHeader)
require.NoError(t, err)
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, true, result)
})
t.Run("new's attested header's slot is greater than old's attested header's slot", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 999999,
},
})
require.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
require.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
require.NoError(t, err)
err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader)
require.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
require.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
require.NoError(t, err)
err = newUpdate.SetFinalizedHeader(newFinalizedHeader)
require.NoError(t, err)
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, false, result)
})
t.Run("none of the above conditions are met and new signature's slot is less than old signature's slot", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
require.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
require.NoError(t, err)
err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader)
require.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
require.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
newUpdate.SetSignatureSlot(9998)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
require.NoError(t, err)
err = newUpdate.SetFinalizedHeader(newFinalizedHeader)
require.NoError(t, err)
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, true, result)
})
t.Run("none of the above conditions are met and new signature's slot is greater than old signature's slot", func(t *testing.T) {
oldUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
require.NoError(t, err)
newUpdate, err := lightClient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
require.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
require.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
oldUpdate.SetSignatureSlot(9998)
oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
require.NoError(t, err)
err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader)
require.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
require.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
require.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
require.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
require.NoError(t, err)
newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
require.NoError(t, err)
err = newUpdate.SetFinalizedHeader(newFinalizedHeader)
require.NoError(t, err)
result, err := lightClient.IsBetterUpdate(newUpdate, oldUpdate)
require.NoError(t, err)
require.Equal(t, false, result)
})
}

View File

@@ -849,6 +849,53 @@ func EmptyExecutionPayload(v int) (proto.Message, error) {
}
}
func EmptyExecutionPayloadHeader(v int) (proto.Message, error) {
switch v {
case version.Bellatrix:
return &pb.ExecutionPayloadHeader{
ParentHash: make([]byte, fieldparams.RootLength),
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
StateRoot: make([]byte, fieldparams.RootLength),
ReceiptsRoot: make([]byte, fieldparams.RootLength),
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
PrevRandao: make([]byte, fieldparams.RootLength),
ExtraData: make([]byte, 0),
BaseFeePerGas: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength),
}, nil
case version.Capella:
return &pb.ExecutionPayloadHeaderCapella{
ParentHash: make([]byte, fieldparams.RootLength),
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
StateRoot: make([]byte, fieldparams.RootLength),
ReceiptsRoot: make([]byte, fieldparams.RootLength),
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
PrevRandao: make([]byte, fieldparams.RootLength),
ExtraData: make([]byte, 0),
BaseFeePerGas: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength),
TransactionsRoot: make([]byte, fieldparams.RootLength),
WithdrawalsRoot: make([]byte, fieldparams.RootLength),
}, nil
case version.Deneb, version.Electra:
return &pb.ExecutionPayloadHeaderDeneb{
ParentHash: make([]byte, fieldparams.RootLength),
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
StateRoot: make([]byte, fieldparams.RootLength),
ReceiptsRoot: make([]byte, fieldparams.RootLength),
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
PrevRandao: make([]byte, fieldparams.RootLength),
ExtraData: make([]byte, 0),
BaseFeePerGas: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength),
TransactionsRoot: make([]byte, fieldparams.RootLength),
WithdrawalsRoot: make([]byte, fieldparams.RootLength),
}, nil
default:
return nil, errors.Wrapf(ErrUnsupportedVersion, "version=%s", version.String(v))
}
}
func toBlockNumArg(number *big.Int) string {
if number == nil {
return "latest"

View File

@@ -25,6 +25,7 @@ go_library(
"//container/slice:go_default_library",
"//monitoring/tracing/trace:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"@com_github_pkg_errors//:go_default_library",
"@com_github_prometheus_client_golang//prometheus:go_default_library",
"@com_github_prometheus_client_golang//prometheus/promauto:go_default_library",

View File

@@ -15,6 +15,7 @@ import (
"github.com/prysmaticlabs/prysm/v5/container/slice"
"github.com/prysmaticlabs/prysm/v5/monitoring/tracing/trace"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/runtime/version"
"github.com/trailofbits/go-mutexasserts"
)
@@ -43,6 +44,11 @@ func (p *Pool) PendingAttesterSlashings(ctx context.Context, state state.ReadOnl
// Allocate pending slice with a capacity of maxAttesterSlashings or len(p.pendingAttesterSlashing)) depending on the request.
maxSlashings := params.BeaconConfig().MaxAttesterSlashings
// EIP-7549: Beginning from Electra, the max attester slashings is reduced to 1.
if state.Version() >= version.Electra {
maxSlashings = params.BeaconConfig().MaxAttesterSlashingsElectra
}
if noLimit {
maxSlashings = uint64(len(p.pendingAttesterSlashing))
}

View File

@@ -516,6 +516,70 @@ func TestPool_PendingAttesterSlashings(t *testing.T) {
}
}
func TestPool_PendingAttesterSlashings_AfterElectra(t *testing.T) {
type fields struct {
pending []*PendingAttesterSlashing
all bool
}
params.SetupTestConfigCleanup(t)
beaconState, privKeys := util.DeterministicGenesisStateElectra(t, 64)
pendingSlashings := make([]*PendingAttesterSlashing, 20)
slashings := make([]ethpb.AttSlashing, 20)
for i := 0; i < len(pendingSlashings); i++ {
sl, err := util.GenerateAttesterSlashingForValidator(beaconState, privKeys[i], primitives.ValidatorIndex(i))
require.NoError(t, err)
pendingSlashings[i] = &PendingAttesterSlashing{
attesterSlashing: sl,
validatorToSlash: primitives.ValidatorIndex(i),
}
slashings[i] = sl
}
tests := []struct {
name string
fields fields
want []ethpb.AttSlashing
}{
{
name: "Empty list",
fields: fields{
pending: []*PendingAttesterSlashing{},
},
want: []ethpb.AttSlashing{},
},
{
name: "All pending",
fields: fields{
pending: pendingSlashings,
all: true,
},
want: slashings,
},
{
name: "All eligible",
fields: fields{
pending: pendingSlashings,
},
want: slashings[0:1],
},
{
name: "Multiple indices",
fields: fields{
pending: pendingSlashings[3:6],
},
want: slashings[3:4],
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
p := &Pool{
pendingAttesterSlashing: tt.fields.pending,
}
assert.DeepEqual(t, tt.want, p.PendingAttesterSlashings(context.Background(), beaconState, tt.fields.all))
})
}
}
func TestPool_PendingAttesterSlashings_Slashed(t *testing.T) {
type fields struct {
pending []*PendingAttesterSlashing

View File

@@ -18,7 +18,6 @@ var _ NetworkEncoding = (*SszNetworkEncoder)(nil)
// MaxGossipSize allowed for gossip messages.
var MaxGossipSize = params.BeaconConfig().GossipMaxSize // 10 Mib.
var MaxChunkSize = params.BeaconConfig().MaxChunkSize // 10 Mib.
var MaxUncompressedPayloadSize = 2 * MaxGossipSize // 20 Mib.
// This pool defines the sync pool for our buffered snappy writers, so that they
// can be constantly reused.
@@ -44,8 +43,8 @@ func (_ SszNetworkEncoder) EncodeGossip(w io.Writer, msg fastssz.Marshaler) (int
if err != nil {
return 0, err
}
if uint64(len(b)) > MaxUncompressedPayloadSize {
return 0, errors.Errorf("gossip message exceeds max gossip size: %d bytes > %d bytes", len(b), MaxUncompressedPayloadSize)
if uint64(len(b)) > MaxGossipSize {
return 0, errors.Errorf("gossip message exceeds max gossip size: %d bytes > %d bytes", len(b), MaxGossipSize)
}
b = snappy.Encode(nil /*dst*/, b)
return w.Write(b)
@@ -82,7 +81,7 @@ func doDecode(b []byte, to fastssz.Unmarshaler) error {
// DecodeGossip decodes the bytes to the protobuf gossip message provided.
func (_ SszNetworkEncoder) DecodeGossip(b []byte, to fastssz.Unmarshaler) error {
b, err := DecodeSnappy(b, MaxUncompressedPayloadSize)
b, err := DecodeSnappy(b, MaxGossipSize)
if err != nil {
return err
}

View File

@@ -555,7 +555,7 @@ func TestSszNetworkEncoder_FailsSnappyLength(t *testing.T) {
e := &encoder.SszNetworkEncoder{}
att := &ethpb.Fork{}
data := make([]byte, 32)
binary.PutUvarint(data, encoder.MaxUncompressedPayloadSize+32)
binary.PutUvarint(data, encoder.MaxGossipSize+32)
err := e.DecodeGossip(data, att)
require.ErrorContains(t, "snappy message exceeds max size", err)
}

View File

@@ -54,7 +54,6 @@ go_test(
"//proto/engine/v1:go_default_library",
"//proto/prysm/v1alpha1:go_default_library",
"//runtime/version:go_default_library",
"//testing/assert:go_default_library",
"//testing/require:go_default_library",
"//testing/util:go_default_library",
"@com_github_ethereum_go_ethereum//common/hexutil:go_default_library",

View File

@@ -1,680 +1 @@
package lightclient
import (
"strings"
"testing"
lightclient "github.com/prysmaticlabs/prysm/v5/beacon-chain/core/light-client"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params"
light_client "github.com/prysmaticlabs/prysm/v5/consensus-types/light-client"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
pb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
"github.com/prysmaticlabs/prysm/v5/testing/assert"
"github.com/prysmaticlabs/prysm/v5/testing/require"
"github.com/prysmaticlabs/prysm/v5/testing/util"
)
// When the update has relevant sync committee
func createNonEmptySyncCommitteeBranch() [][]byte {
res := make([][]byte, fieldparams.SyncCommitteeBranchDepth)
res[0] = []byte(strings.Repeat("x", 32))
for i := 1; i < len(res); i++ {
res[i] = make([]byte, fieldparams.RootLength)
}
return res
}
// When the update has finality
func createNonEmptyFinalityBranch() [][]byte {
res := make([][]byte, fieldparams.FinalityBranchDepth)
res[0] = []byte(strings.Repeat("x", 32))
for i := 1; i < fieldparams.FinalityBranchDepth; i++ {
res[i] = make([]byte, 32)
}
return res
}
func TestIsBetterUpdate(t *testing.T) {
config := params.BeaconConfig()
st, err := util.NewBeaconStateAltair()
require.NoError(t, err)
t.Run("new has supermajority but old doesn't", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
})
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b11111100, 0b1}, // [0,0,1,1,1,1,1,1]
})
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, true, result)
})
t.Run("old has supermajority but new doesn't", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b11111100, 0b1}, // [0,0,1,1,1,1,1,1]
})
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
})
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, false, result)
})
t.Run("new doesn't have supermajority and newNumActiveParticipants is greater than oldNumActiveParticipants", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
})
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, true, result)
})
t.Run("new doesn't have supermajority and newNumActiveParticipants is lesser than oldNumActiveParticipants", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
})
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, false, result)
})
t.Run("new has relevant sync committee but old doesn't", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
assert.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000001,
},
})
assert.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
assert.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
newUpdate.SetSignatureSlot(1000000)
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, true, result)
})
t.Run("old has relevant sync committee but new doesn't", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000001,
},
})
assert.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
assert.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
oldUpdate.SetSignatureSlot(1000000)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
assert.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, false, result)
})
t.Run("new has finality but old doesn't", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
assert.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
assert.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, true, result)
})
t.Run("old has finality but new doesn't", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
assert.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
assert.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, false, result)
})
t.Run("new has finality and sync committee finality both but old doesn't have sync committee finality", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
assert.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
assert.NoError(t, err)
err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader)
assert.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,0,1,1,1,1,1,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
assert.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
newUpdate.SetSignatureSlot(999999)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 999999,
},
})
assert.NoError(t, err)
err = newUpdate.SetFinalizedHeader(newFinalizedHeader)
assert.NoError(t, err)
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, true, result)
})
t.Run("new has finality but doesn't have sync committee finality and old has sync committee finality", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
assert.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
oldUpdate.SetSignatureSlot(999999)
oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 999999,
},
})
assert.NoError(t, err)
err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader)
assert.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
assert.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
assert.NoError(t, err)
err = newUpdate.SetFinalizedHeader(newFinalizedHeader)
assert.NoError(t, err)
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, false, result)
})
t.Run("new has more active participants than old", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,1,1,1,1,1,0,0]
})
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, true, result)
})
t.Run("new has less active participants than old", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b01111100, 0b1}, // [0,1,1,1,1,1,0,0]
})
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, false, result)
})
t.Run("new's attested header's slot is lesser than old's attested header's slot", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
assert.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
assert.NoError(t, err)
err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader)
assert.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 999999,
},
})
assert.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
assert.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
assert.NoError(t, err)
err = newUpdate.SetFinalizedHeader(newFinalizedHeader)
assert.NoError(t, err)
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, true, result)
})
t.Run("new's attested header's slot is greater than old's attested header's slot", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 999999,
},
})
assert.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
assert.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
assert.NoError(t, err)
err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader)
assert.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
assert.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
assert.NoError(t, err)
err = newUpdate.SetFinalizedHeader(newFinalizedHeader)
assert.NoError(t, err)
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, false, result)
})
t.Run("none of the above conditions are met and new signature's slot is less than old signature's slot", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
assert.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
oldUpdate.SetSignatureSlot(9999)
oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
assert.NoError(t, err)
err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader)
assert.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
assert.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
newUpdate.SetSignatureSlot(9998)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
assert.NoError(t, err)
err = newUpdate.SetFinalizedHeader(newFinalizedHeader)
assert.NoError(t, err)
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, true, result)
})
t.Run("none of the above conditions are met and new signature's slot is greater than old signature's slot", func(t *testing.T) {
oldUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(1), st)
assert.NoError(t, err)
newUpdate, err := lightclient.CreateDefaultLightClientUpdate(primitives.Slot(config.AltairForkEpoch*primitives.Epoch(config.SlotsPerEpoch)).Add(2), st)
assert.NoError(t, err)
oldUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
oldAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = oldUpdate.SetAttestedHeader(oldAttestedHeader)
assert.NoError(t, err)
err = oldUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
err = oldUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
oldUpdate.SetSignatureSlot(9998)
oldFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
assert.NoError(t, err)
err = oldUpdate.SetFinalizedHeader(oldFinalizedHeader)
assert.NoError(t, err)
newUpdate.SetSyncAggregate(&pb.SyncAggregate{
SyncCommitteeBits: []byte{0b00111100, 0b1}, // [0,0,1,1,1,1,0,0]
})
newAttestedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 1000000,
},
})
assert.NoError(t, err)
err = newUpdate.SetAttestedHeader(newAttestedHeader)
assert.NoError(t, err)
err = newUpdate.SetNextSyncCommitteeBranch(createNonEmptySyncCommitteeBranch())
assert.NoError(t, err)
newUpdate.SetSignatureSlot(9999)
err = newUpdate.SetFinalityBranch(createNonEmptyFinalityBranch())
assert.NoError(t, err)
newFinalizedHeader, err := light_client.NewWrappedHeader(&pb.LightClientHeaderAltair{
Beacon: &pb.BeaconBlockHeader{
Slot: 9999,
},
})
assert.NoError(t, err)
err = newUpdate.SetFinalizedHeader(newFinalizedHeader)
assert.NoError(t, err)
result, err := lightclient.IsBetterUpdate(newUpdate, oldUpdate)
assert.NoError(t, err)
assert.Equal(t, false, result)
})
}

View File

@@ -99,14 +99,18 @@ func (vs *Server) GetBeaconBlock(ctx context.Context, req *ethpb.BlockRequest) (
}
resp, err := vs.BuildBlockParallel(ctx, sBlk, head, req.SkipMevBoost, builderBoostFactor)
log.WithFields(logrus.Fields{
log := log.WithFields(logrus.Fields{
"slot": req.Slot,
"sinceSlotStartTime": time.Since(t),
"validator": sBlk.Block().ProposerIndex(),
}).Info("Finished building block")
})
if err != nil {
log.WithError(err).Error("Finished building block")
return nil, errors.Wrap(err, "could not build block in parallel")
}
log.Info("Finished building block")
return resp, nil
}
@@ -236,7 +240,12 @@ func (vs *Server) BuildBlockParallel(ctx context.Context, sBlk interfaces.Signed
// There's no reason to try to get a builder bid if local override is true.
var builderBid builderapi.Bid
if !(local.OverrideBuilder || skipMevBoost) {
builderBid, err = vs.getBuilderPayloadAndBlobs(ctx, sBlk.Block().Slot(), sBlk.Block().ProposerIndex())
latestHeader, err := head.LatestExecutionPayloadHeader()
if err != nil {
return nil, status.Errorf(codes.Internal, "Could not get latest execution payload header: %v", err)
}
parentGasLimit := latestHeader.GasLimit()
builderBid, err = vs.getBuilderPayloadAndBlobs(ctx, sBlk.Block().Slot(), sBlk.Block().ProposerIndex(), parentGasLimit)
if err != nil {
builderGetPayloadMissCount.Inc()
log.WithError(err).Error("Could not get builder payload")

View File

@@ -51,6 +51,7 @@ var emptyTransactionsRoot = [32]byte{127, 254, 36, 30, 166, 1, 135, 253, 176, 24
// blockBuilderTimeout is the maximum amount of time allowed for a block builder to respond to a
// block request. This value is known as `BUILDER_PROPOSAL_DELAY_TOLERANCE` in builder spec.
const blockBuilderTimeout = 1 * time.Second
const gasLimitAdjustmentFactor = 1024
// Sets the execution data for the block. Execution data can come from local EL client or remote builder depends on validator registration and circuit breaker conditions.
func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, local *blocks.GetPayloadResponse, bid builder.Bid, builderBoostFactor primitives.Gwei) (primitives.Wei, *enginev1.BlobsBundle, error) {
@@ -170,7 +171,11 @@ func setExecutionData(ctx context.Context, blk interfaces.SignedBeaconBlock, loc
// This function retrieves the payload header and kzg commitments given the slot number and the validator index.
// It's a no-op if the latest head block is not versioned bellatrix.
func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitives.Slot, idx primitives.ValidatorIndex) (builder.Bid, error) {
func (vs *Server) getPayloadHeaderFromBuilder(
ctx context.Context,
slot primitives.Slot,
idx primitives.ValidatorIndex,
parentGasLimit uint64) (builder.Bid, error) {
ctx, span := trace.StartSpan(ctx, "ProposerServer.getPayloadHeaderFromBuilder")
defer span.End()
@@ -243,6 +248,16 @@ func (vs *Server) getPayloadHeaderFromBuilder(ctx context.Context, slot primitiv
return nil, fmt.Errorf("incorrect parent hash %#x != %#x", header.ParentHash(), h.BlockHash())
}
reg, err := vs.BlockBuilder.RegistrationByValidatorID(ctx, idx)
if err != nil {
log.WithError(err).Warn("Proposer: failed to get registration by validator ID, could not check gas limit")
} else {
gasLimit := expectedGasLimit(parentGasLimit, reg.GasLimit)
if gasLimit != header.GasLimit() {
return nil, fmt.Errorf("incorrect header gas limit %d != %d", gasLimit, header.GasLimit())
}
}
t, err := slots.ToTime(uint64(vs.TimeFetcher.GenesisTime().Unix()), slot)
if err != nil {
return nil, err
@@ -393,3 +408,32 @@ func setExecution(blk interfaces.SignedBeaconBlock, execution interfaces.Executi
return nil
}
// Calculates expected gas limit based on parent gas limit and target gas limit.
// Spec code:
//
// def expected_gas_limit(parent_gas_limit, target_gas_limit, adjustment_factor):
// max_gas_limit_difference = (parent_gas_limit // adjustment_factor) - 1
// if target_gas_limit > parent_gas_limit:
// gas_diff = target_gas_limit - parent_gas_limit
// return parent_gas_limit + min(gas_diff, max_gas_limit_difference)
// else:
// gas_diff = parent_gas_limit - target_gas_limit
// return parent_gas_limit - min(gas_diff, max_gas_limit_difference)
func expectedGasLimit(parentGasLimit, proposerGasLimit uint64) uint64 {
maxGasLimitDiff := uint64(0)
if parentGasLimit > gasLimitAdjustmentFactor {
maxGasLimitDiff = parentGasLimit/gasLimitAdjustmentFactor - 1
}
if proposerGasLimit > parentGasLimit {
if proposerGasLimit-parentGasLimit > maxGasLimitDiff {
return parentGasLimit + maxGasLimitDiff
}
return proposerGasLimit
}
if parentGasLimit-proposerGasLimit > maxGasLimitDiff {
return parentGasLimit - maxGasLimitDiff
}
return proposerGasLimit
}

View File

@@ -94,14 +94,14 @@ func TestServer_setExecutionData(t *testing.T) {
ForkchoiceFetcher: &blockchainTest.ChainService{},
TrackedValidatorsCache: cache.NewTrackedValidatorsCache(),
}
gasLimit := uint64(30000000)
t.Run("No builder configured. Use local block", func(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella())
require.NoError(t, err)
b := blk.Block()
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit)
require.NoError(t, err)
require.IsNil(t, builderBid)
_, bundle, err := setExecutionData(context.Background(), blk, res, builderBid, defaultBuilderBoostFactor)
@@ -115,7 +115,11 @@ func TestServer_setExecutionData(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockCapella())
require.NoError(t, err)
require.NoError(t, vs.BeaconDB.SaveRegistrationsByValidatorIDs(ctx, []primitives.ValidatorIndex{blk.Block().ProposerIndex()},
[]*ethpb.ValidatorRegistrationV1{{FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), Timestamp: uint64(time.Now().Unix()), Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
[]*ethpb.ValidatorRegistrationV1{{
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
Timestamp: uint64(time.Now().Unix()),
GasLimit: gasLimit,
Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
ti, err := slots.ToTime(uint64(time.Now().Unix()), 0)
require.NoError(t, err)
sk, err := bls.RandKey()
@@ -135,6 +139,7 @@ func TestServer_setExecutionData(t *testing.T) {
BlockHash: make([]byte, fieldparams.RootLength),
TransactionsRoot: bytesutil.PadTo([]byte{1}, fieldparams.RootLength),
WithdrawalsRoot: make([]byte, fieldparams.RootLength),
GasLimit: gasLimit,
},
Pubkey: sk.PublicKey().Marshal(),
Value: bytesutil.PadTo([]byte{1}, 32),
@@ -164,7 +169,7 @@ func TestServer_setExecutionData(t *testing.T) {
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit)
require.NoError(t, err)
_, err = builderBid.Header()
require.NoError(t, err)
@@ -184,7 +189,11 @@ func TestServer_setExecutionData(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockCapella())
require.NoError(t, err)
require.NoError(t, vs.BeaconDB.SaveRegistrationsByValidatorIDs(ctx, []primitives.ValidatorIndex{blk.Block().ProposerIndex()},
[]*ethpb.ValidatorRegistrationV1{{FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), Timestamp: uint64(time.Now().Unix()), Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
[]*ethpb.ValidatorRegistrationV1{{
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
Timestamp: uint64(time.Now().Unix()),
GasLimit: gasLimit,
Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
ti, err := slots.ToTime(uint64(time.Now().Unix()), 0)
require.NoError(t, err)
sk, err := bls.RandKey()
@@ -207,6 +216,7 @@ func TestServer_setExecutionData(t *testing.T) {
BlockHash: make([]byte, fieldparams.RootLength),
TransactionsRoot: bytesutil.PadTo([]byte{1}, fieldparams.RootLength),
WithdrawalsRoot: wr[:],
GasLimit: gasLimit,
},
Pubkey: sk.PublicKey().Marshal(),
Value: bytesutil.PadTo(builderValue, 32),
@@ -236,7 +246,7 @@ func TestServer_setExecutionData(t *testing.T) {
b := blk.Block()
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit)
require.NoError(t, err)
_, err = builderBid.Header()
require.NoError(t, err)
@@ -256,7 +266,11 @@ func TestServer_setExecutionData(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockCapella())
require.NoError(t, err)
require.NoError(t, vs.BeaconDB.SaveRegistrationsByValidatorIDs(ctx, []primitives.ValidatorIndex{blk.Block().ProposerIndex()},
[]*ethpb.ValidatorRegistrationV1{{FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), Timestamp: uint64(time.Now().Unix()), Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
[]*ethpb.ValidatorRegistrationV1{{
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
Timestamp: uint64(time.Now().Unix()),
GasLimit: gasLimit,
Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
ti, err := slots.ToTime(uint64(time.Now().Unix()), 0)
require.NoError(t, err)
sk, err := bls.RandKey()
@@ -278,6 +292,7 @@ func TestServer_setExecutionData(t *testing.T) {
Timestamp: uint64(ti.Unix()),
BlockNumber: 2,
WithdrawalsRoot: wr[:],
GasLimit: gasLimit,
},
Pubkey: sk.PublicKey().Marshal(),
Value: bytesutil.PadTo(builderValue, 32),
@@ -307,7 +322,7 @@ func TestServer_setExecutionData(t *testing.T) {
b := blk.Block()
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit)
require.NoError(t, err)
_, err = builderBid.Header()
require.NoError(t, err)
@@ -327,7 +342,11 @@ func TestServer_setExecutionData(t *testing.T) {
blk, err := blocks.NewSignedBeaconBlock(util.NewBlindedBeaconBlockCapella())
require.NoError(t, err)
require.NoError(t, vs.BeaconDB.SaveRegistrationsByValidatorIDs(ctx, []primitives.ValidatorIndex{blk.Block().ProposerIndex()},
[]*ethpb.ValidatorRegistrationV1{{FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), Timestamp: uint64(time.Now().Unix()), Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
[]*ethpb.ValidatorRegistrationV1{{
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
Timestamp: uint64(time.Now().Unix()),
GasLimit: gasLimit,
Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
ti, err := slots.ToTime(uint64(time.Now().Unix()), 0)
require.NoError(t, err)
sk, err := bls.RandKey()
@@ -349,6 +368,7 @@ func TestServer_setExecutionData(t *testing.T) {
Timestamp: uint64(ti.Unix()),
BlockNumber: 2,
WithdrawalsRoot: wr[:],
GasLimit: gasLimit,
},
Pubkey: sk.PublicKey().Marshal(),
Value: bytesutil.PadTo(builderValue, 32),
@@ -378,7 +398,7 @@ func TestServer_setExecutionData(t *testing.T) {
b := blk.Block()
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit)
require.NoError(t, err)
_, err = builderBid.Header()
require.NoError(t, err)
@@ -404,7 +424,7 @@ func TestServer_setExecutionData(t *testing.T) {
b := blk.Block()
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit)
require.NoError(t, err)
_, err = builderBid.Header()
require.NoError(t, err)
@@ -436,7 +456,7 @@ func TestServer_setExecutionData(t *testing.T) {
b := blk.Block()
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit)
require.NoError(t, err)
_, err = builderBid.Header()
require.NoError(t, err)
@@ -471,7 +491,7 @@ func TestServer_setExecutionData(t *testing.T) {
b := blk.Block()
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit)
require.NoError(t, err)
builderKzgCommitments, err := builderBid.BlobKzgCommitments()
if builderBid.Version() >= version.Deneb {
@@ -503,7 +523,7 @@ func TestServer_setExecutionData(t *testing.T) {
b := blk.Block()
res, err := vs.getLocalPayload(ctx, b, capellaTransitionState)
require.NoError(t, err)
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, b.Slot(), b.ProposerIndex(), gasLimit)
require.ErrorIs(t, consensus_types.ErrNilObjectWrapped, err) // Builder returns fault. Use local block
require.IsNil(t, builderBid)
_, bundle, err := setExecutionData(context.Background(), blk, res, nil, defaultBuilderBoostFactor)
@@ -578,6 +598,7 @@ func TestServer_setExecutionData(t *testing.T) {
WithdrawalsRoot: wr[:],
BlobGasUsed: 123,
ExcessBlobGas: 456,
GasLimit: gasLimit,
},
Pubkey: sk.PublicKey().Marshal(),
Value: bytesutil.PadTo(builderValue, 32),
@@ -599,7 +620,11 @@ func TestServer_setExecutionData(t *testing.T) {
Cfg: &builderTest.Config{BeaconDB: beaconDB},
}
require.NoError(t, beaconDB.SaveRegistrationsByValidatorIDs(ctx, []primitives.ValidatorIndex{blk.Block().ProposerIndex()},
[]*ethpb.ValidatorRegistrationV1{{FeeRecipient: make([]byte, fieldparams.FeeRecipientLength), Timestamp: uint64(time.Now().Unix()), Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
[]*ethpb.ValidatorRegistrationV1{{
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
Timestamp: uint64(time.Now().Unix()),
GasLimit: gasLimit,
Pubkey: make([]byte, fieldparams.BLSPubkeyLength)}}))
wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockDeneb())
require.NoError(t, err)
@@ -619,7 +644,7 @@ func TestServer_setExecutionData(t *testing.T) {
require.NoError(t, err)
blk.SetSlot(primitives.Slot(params.BeaconConfig().DenebForkEpoch) * params.BeaconConfig().SlotsPerEpoch)
require.NoError(t, err)
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, blk.Block().Slot(), blk.Block().ProposerIndex())
builderBid, err := vs.getBuilderPayloadAndBlobs(ctx, blk.Block().Slot(), blk.Block().ProposerIndex(), gasLimit)
require.NoError(t, err)
builderPayload, err := builderBid.Header()
require.NoError(t, err)
@@ -660,6 +685,8 @@ func TestServer_getPayloadHeader(t *testing.T) {
sk, err := bls.RandKey()
require.NoError(t, err)
gasLimit := uint64(30000000)
bid := &ethpb.BuilderBid{
Header: &v1.ExecutionPayloadHeader{
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
@@ -672,6 +699,7 @@ func TestServer_getPayloadHeader(t *testing.T) {
TransactionsRoot: bytesutil.PadTo([]byte{1}, fieldparams.RootLength),
ParentHash: params.BeaconConfig().ZeroHash[:],
Timestamp: uint64(ti.Unix()),
GasLimit: gasLimit,
},
Pubkey: sk.PublicKey().Marshal(),
Value: bytesutil.PadTo([]byte{1, 2, 3}, 32),
@@ -709,6 +737,7 @@ func TestServer_getPayloadHeader(t *testing.T) {
ParentHash: params.BeaconConfig().ZeroHash[:],
Timestamp: uint64(tiCapella.Unix()),
WithdrawalsRoot: wr[:],
GasLimit: gasLimit,
},
Pubkey: sk.PublicKey().Marshal(),
Value: bytesutil.PadTo([]byte{1, 2, 3}, 32),
@@ -720,7 +749,29 @@ func TestServer_getPayloadHeader(t *testing.T) {
Signature: sk.Sign(srCapella[:]).Marshal(),
}
require.NoError(t, err)
incorrectGasLimitBid := &ethpb.BuilderBid{
Header: &v1.ExecutionPayloadHeader{
FeeRecipient: make([]byte, fieldparams.FeeRecipientLength),
StateRoot: make([]byte, fieldparams.RootLength),
ReceiptsRoot: make([]byte, fieldparams.RootLength),
LogsBloom: make([]byte, fieldparams.LogsBloomLength),
PrevRandao: make([]byte, fieldparams.RootLength),
BaseFeePerGas: make([]byte, fieldparams.RootLength),
BlockHash: make([]byte, fieldparams.RootLength),
TransactionsRoot: bytesutil.PadTo([]byte{1}, fieldparams.RootLength),
ParentHash: params.BeaconConfig().ZeroHash[:],
Timestamp: uint64(tiCapella.Unix()),
GasLimit: 31000000,
},
Pubkey: sk.PublicKey().Marshal(),
Value: bytesutil.PadTo([]byte{1, 2, 3}, 32),
}
signedIncorrectGasLimitBid :=
&ethpb.SignedBuilderBid{
Message: incorrectGasLimitBid,
Signature: sk.Sign(srCapella[:]).Marshal(),
}
tests := []struct {
name string
head interfaces.ReadOnlySignedBeaconBlock
@@ -847,15 +898,39 @@ func TestServer_getPayloadHeader(t *testing.T) {
},
returnedHeaderCapella: bidCapella.Header,
},
{
name: "incorrect gas limit",
mock: &builderTest.MockBuilderService{
Bid: signedIncorrectGasLimitBid,
},
fetcher: &blockchainTest.ChainService{
Block: func() interfaces.ReadOnlySignedBeaconBlock {
wb, err := blocks.NewSignedBeaconBlock(util.NewBeaconBlockBellatrix())
require.NoError(t, err)
wb.SetSlot(primitives.Slot(params.BeaconConfig().BellatrixForkEpoch) * params.BeaconConfig().SlotsPerEpoch)
return wb
}(),
},
err: "incorrect header gas limit 30000000 != 31000000",
},
}
for _, tc := range tests {
t.Run(tc.name, func(t *testing.T) {
vs := &Server{BlockBuilder: tc.mock, HeadFetcher: tc.fetcher, TimeFetcher: &blockchainTest.ChainService{
vs := &Server{BeaconDB: dbTest.SetupDB(t), BlockBuilder: tc.mock, HeadFetcher: tc.fetcher, TimeFetcher: &blockchainTest.ChainService{
Genesis: genesis,
}}
regCache := cache.NewRegistrationCache()
regCache.UpdateIndexToRegisteredMap(context.Background(), map[primitives.ValidatorIndex]*ethpb.ValidatorRegistrationV1{
0: {
GasLimit: gasLimit,
FeeRecipient: make([]byte, 20),
Pubkey: make([]byte, 48),
},
})
tc.mock.RegistrationCache = regCache
hb, err := vs.HeadFetcher.HeadBlock(context.Background())
require.NoError(t, err)
bid, err := vs.getPayloadHeaderFromBuilder(context.Background(), hb.Block().Slot(), 0)
bid, err := vs.getPayloadHeaderFromBuilder(context.Background(), hb.Block().Slot(), 0, 30000000)
if tc.err != "" {
require.ErrorContains(t, tc.err, err)
} else {
@@ -971,3 +1046,87 @@ func TestEmptyTransactionsRoot(t *testing.T) {
require.NoError(t, err)
require.DeepEqual(t, r, emptyTransactionsRoot)
}
func Test_expectedGasLimit(t *testing.T) {
type args struct {
parentGasLimit uint64
targetGasLimit uint64
}
tests := []struct {
name string
args args
want uint64
}{
{
name: "Increase within limit",
args: args{
parentGasLimit: 15000000,
targetGasLimit: 15000100,
},
want: 15000100,
},
{
name: "Increase exceeding limit",
args: args{
parentGasLimit: 15000000,
targetGasLimit: 16000000,
},
want: 15014647, // maxGasLimitDiff = (15000000 / 1024) - 1 = 1464
},
{
name: "Decrease within limit",
args: args{
parentGasLimit: 15000000,
targetGasLimit: 14999990,
},
want: 14999990,
},
{
name: "Decrease exceeding limit",
args: args{
parentGasLimit: 15000000,
targetGasLimit: 14000000,
},
want: 14985353, // maxGasLimitDiff = (15000000 / 1024) - 1 = 1464
},
{
name: "Target equals parent",
args: args{
parentGasLimit: 15000000,
targetGasLimit: 15000000,
},
want: 15000000, // No change
},
{
name: "Very small parent gas limit",
args: args{
parentGasLimit: 1025,
targetGasLimit: 2000,
},
want: 1025 + ((1025 / 1024) - 1),
},
{
name: "Target far below parent but limited",
args: args{
parentGasLimit: 20000000,
targetGasLimit: 10000000,
},
want: 19980470, // maxGasLimitDiff = (20000000 / 1024) - 1
},
{
name: "Parent gas limit under flows",
args: args{
parentGasLimit: 1023,
targetGasLimit: 30000000,
},
want: 1023,
},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := expectedGasLimit(tt.args.parentGasLimit, tt.args.targetGasLimit); got != tt.want {
t.Errorf("expectedGasLimit() = %v, want %v", got, tt.want)
}
})
}
}

View File

@@ -239,7 +239,8 @@ func (vs *Server) getTerminalBlockHashIfExists(ctx context.Context, transitionTi
func (vs *Server) getBuilderPayloadAndBlobs(ctx context.Context,
slot primitives.Slot,
vIdx primitives.ValidatorIndex) (builder.Bid, error) {
vIdx primitives.ValidatorIndex,
parentGasLimit uint64) (builder.Bid, error) {
ctx, span := trace.StartSpan(ctx, "ProposerServer.getBuilderPayloadAndBlobs")
defer span.End()
@@ -255,7 +256,7 @@ func (vs *Server) getBuilderPayloadAndBlobs(ctx context.Context,
return nil, nil
}
return vs.getPayloadHeaderFromBuilder(ctx, slot, vIdx)
return vs.getPayloadHeaderFromBuilder(ctx, slot, vIdx, parentGasLimit)
}
var errActivationNotReached = errors.New("activation epoch not reached")

View File

@@ -149,6 +149,7 @@ go_test(
size = "small",
srcs = [
"batch_verifier_test.go",
"benchmark_test.go",
"blobs_test.go",
"block_batcher_test.go",
"broadcast_bls_changes_test.go",
@@ -268,3 +269,20 @@ go_test(
"@org_golang_google_protobuf//proto:go_default_library",
],
)
go_test(
name = "go_benchmark_test",
size = "medium",
srcs = ["benchmark_test.go"],
args = [
"-test.bench=.",
"-test.benchmem",
"-test.v",
],
embed = [":go_default_library"],
local = True,
tags = [
"benchmark",
"no-cache",
],
)

View File

@@ -0,0 +1,25 @@
package sync
import (
"testing"
"github.com/prysmaticlabs/prysm/v5/consensus-types/primitives"
"github.com/prysmaticlabs/prysm/v5/encoding/bytesutil"
)
func BenchmarkCacheKeyImplementations(b *testing.B) {
b.Run("Old Cache Key Implementation", func(b *testing.B) {
for i := 0; i < b.N; i++ {
b := append(bytesutil.Bytes32(uint64(i)), bytesutil.Bytes32(uint64(i+10))...)
b = append(b, bytesutil.SafeCopyBytes([]byte("random"))...)
_ = string(b)
}
})
b.Run("New Cache Key Implementation", func(b *testing.B) {
for i := 0; i < b.N; i++ {
_ = seenAttCacheKey(primitives.Slot(i), primitives.CommitteeIndex(i+10), []byte("random"))
}
})
}

View File

@@ -2,6 +2,7 @@ package sync
import (
"context"
"encoding/binary"
"fmt"
"reflect"
"strings"
@@ -305,9 +306,7 @@ func (s *Service) validateBitLength(
func (s *Service) hasSeenCommitteeIndicesSlot(slot primitives.Slot, committeeID primitives.CommitteeIndex, aggregateBits []byte) bool {
s.seenUnAggregatedAttestationLock.RLock()
defer s.seenUnAggregatedAttestationLock.RUnlock()
b := append(bytesutil.Bytes32(uint64(slot)), bytesutil.Bytes32(uint64(committeeID))...)
b = append(b, aggregateBits...)
_, seen := s.seenUnAggregatedAttestationCache.Get(string(b))
_, seen := s.seenUnAggregatedAttestationCache.Get(seenAttCacheKey(slot, committeeID, aggregateBits))
return seen
}
@@ -315,9 +314,7 @@ func (s *Service) hasSeenCommitteeIndicesSlot(slot primitives.Slot, committeeID
func (s *Service) setSeenCommitteeIndicesSlot(slot primitives.Slot, committeeID primitives.CommitteeIndex, aggregateBits []byte) {
s.seenUnAggregatedAttestationLock.Lock()
defer s.seenUnAggregatedAttestationLock.Unlock()
b := append(bytesutil.Bytes32(uint64(slot)), bytesutil.Bytes32(uint64(committeeID))...)
b = append(b, bytesutil.SafeCopyBytes(aggregateBits)...)
s.seenUnAggregatedAttestationCache.Add(string(b), true)
s.seenUnAggregatedAttestationCache.Add(seenAttCacheKey(slot, committeeID, aggregateBits), true)
}
// hasBlockAndState returns true if the beacon node knows about a block and associated state in the
@@ -327,3 +324,15 @@ func (s *Service) hasBlockAndState(ctx context.Context, blockRoot [32]byte) bool
hasState := hasStateSummary || s.cfg.beaconDB.HasState(ctx, blockRoot)
return hasState && s.cfg.chain.HasBlock(ctx, blockRoot)
}
// Amount of bytes required to store a uint64 value.
const uint64ByteLength = 8
func seenAttCacheKey(slot primitives.Slot, committeeID primitives.CommitteeIndex, aggregationBits []byte) string {
totalLen := uint64ByteLength + uint64ByteLength + len(aggregationBits)
key := make([]byte, totalLen)
binary.LittleEndian.PutUint64(key[:8], uint64(slot))
binary.LittleEndian.PutUint64(key[8:16], uint64(committeeID))
copy(key[16:], aggregationBits)
return bytesutil.UnsafeCastToString(key)
}

View File

@@ -327,3 +327,11 @@ func TestService_setSeenCommitteeIndicesSlot(t *testing.T) {
require.Equal(t, false, s.hasSeenCommitteeIndicesSlot(0, 2, b1))
require.Equal(t, true, s.hasSeenCommitteeIndicesSlot(1, 2, b1))
}
func TestAttestationCacheKey(t *testing.T) {
stringKey := seenAttCacheKey(1, 1024, []byte("aggregation"))
wantedKey := append(bytesutil.Bytes8(1), bytesutil.Bytes8(1024)...)
wantedKey = append(wantedKey, []byte("aggregation")...)
require.Equal(t, string(wantedKey), stringKey)
}

View File

@@ -2824,8 +2824,8 @@ def prysm_deps():
"gazelle:exclude tools.go",
],
importpath = "github.com/quic-go/quic-go",
sum = "h1:2TCyvBrMu1Z25rvIAlnp2dPT4lgh/uTqLqiXVpp5AeU=",
version = "v0.48.0",
sum = "h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=",
version = "v0.48.2",
)
go_repository(
name = "com_github_quic_go_webtransport_go",

2
go.mod
View File

@@ -233,7 +233,7 @@ require (
github.com/prometheus/common v0.55.0 // indirect
github.com/prometheus/procfs v0.15.1 // indirect
github.com/quic-go/qpack v0.5.1 // indirect
github.com/quic-go/quic-go v0.48.0 // indirect
github.com/quic-go/quic-go v0.48.2 // indirect
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 // indirect
github.com/raulk/go-watchdog v1.3.0 // indirect
github.com/rivo/uniseg v0.4.4 // indirect

4
go.sum
View File

@@ -907,8 +907,8 @@ github.com/prysmaticlabs/protoc-gen-go-cast v0.0.0-20230228205207-28762a7b9294 h
github.com/prysmaticlabs/protoc-gen-go-cast v0.0.0-20230228205207-28762a7b9294/go.mod h1:ZVEbRdnMkGhp/pu35zq4SXxtvUwWK0J1MATtekZpH2Y=
github.com/quic-go/qpack v0.5.1 h1:giqksBPnT/HDtZ6VhtFKgoLOWmlyo9Ei6u9PqzIMbhI=
github.com/quic-go/qpack v0.5.1/go.mod h1:+PC4XFrEskIVkcLzpEkbLqq1uCoxPhQuvK5rH1ZgaEg=
github.com/quic-go/quic-go v0.48.0 h1:2TCyvBrMu1Z25rvIAlnp2dPT4lgh/uTqLqiXVpp5AeU=
github.com/quic-go/quic-go v0.48.0/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
github.com/quic-go/quic-go v0.48.2 h1:wsKXZPeGWpMpCGSWqOcqpW2wZYic/8T3aqiOID0/KWE=
github.com/quic-go/quic-go v0.48.2/go.mod h1:yBgs3rWBOADpga7F+jJsb6Ybg1LSYiQvwWlLX+/6HMs=
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66 h1:4WFk6u3sOT6pLa1kQ50ZVdm8BQFgJNA117cepZxtLIg=
github.com/quic-go/webtransport-go v0.8.1-0.20241018022711-4ac2c9250e66/go.mod h1:Vp72IJajgeOL6ddqrAhmp7IM9zbTcgkQxD/YdxrVwMw=
github.com/r3labs/sse/v2 v2.10.0 h1:hFEkLLFY4LDifoHdiCN/LlGBAdVJYsANaLqNYa1l/v0=

View File

@@ -6,6 +6,7 @@ import (
"fmt"
"os"
"path"
"slices"
"strings"
"testing"
@@ -16,6 +17,7 @@ import (
state_native "github.com/prysmaticlabs/prysm/v5/beacon-chain/state/state-native"
"github.com/prysmaticlabs/prysm/v5/beacon-chain/verification"
fieldparams "github.com/prysmaticlabs/prysm/v5/config/fieldparams"
"github.com/prysmaticlabs/prysm/v5/config/params"
"github.com/prysmaticlabs/prysm/v5/consensus-types/blocks"
"github.com/prysmaticlabs/prysm/v5/consensus-types/interfaces"
ethpb "github.com/prysmaticlabs/prysm/v5/proto/prysm/v1alpha1"
@@ -25,6 +27,13 @@ import (
"github.com/prysmaticlabs/prysm/v5/testing/util"
)
// These are proposer boost spec tests that assume the clock starts 3 seconds into the slot.
// Example: Tick is 51, which corresponds to 3 seconds into slot 4.
var proposerBoostTests3s = []string{
"proposer_boost_is_first_block",
"proposer_boost",
}
func init() {
transition.SkipSlotCache.Disable()
}
@@ -97,7 +106,18 @@ func runTest(t *testing.T, config string, fork int, basePath string) { // nolint
for _, step := range steps {
if step.Tick != nil {
builder.Tick(t, int64(*step.Tick))
tick := int64(*step.Tick)
// If the test is for proposer boost starting 3 seconds into the slot and the tick aligns with this,
// we provide an additional second buffer. Instead of starting 3 seconds into the slot, we start 2 seconds in to avoid missing the proposer boost.
// A 1-second buffer has proven insufficient during parallel spec test runs, as the likelihood of missing the proposer boost increases significantly,
// often extending to 4 seconds. Starting 2 seconds into the slot ensures close to a 100% pass rate.
if slices.Contains(proposerBoostTests3s, folder.Name()) {
deadline := params.BeaconConfig().SecondsPerSlot / params.BeaconConfig().IntervalsPerSlot
if uint64(tick)%params.BeaconConfig().SecondsPerSlot == deadline-1 {
tick--
}
}
builder.Tick(t, tick)
}
var beaconBlock interfaces.ReadOnlySignedBeaconBlock
if step.Block != nil {