mirror of
https://github.com/OffchainLabs/prysm.git
synced 2026-01-09 21:38:05 -05:00
Compare commits
19 Commits
v5.2.0
...
useNewCach
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1f1c4e2b08 | ||
|
|
2b25ede641 | ||
|
|
b7de64a340 | ||
|
|
11aa51e033 | ||
|
|
fa0dc09ce0 | ||
|
|
d93a1b671c | ||
|
|
1d8ffadd4f | ||
|
|
6387040613 | ||
|
|
1c7077e254 | ||
|
|
9ab7e7d37c | ||
|
|
bf80a5430f | ||
|
|
9aef2c4ee2 | ||
|
|
d094118082 | ||
|
|
c69599f343 | ||
|
|
1e0e5e110a | ||
|
|
8254cb30b4 | ||
|
|
74961eb51f | ||
|
|
514f96ec0e | ||
|
|
cabe7d34b6 |
45
CHANGELOG.md
45
CHANGELOG.md
@@ -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
|
||||
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
package blocks
|
||||
|
||||
var ProcessBLSToExecutionChange = processBLSToExecutionChange
|
||||
|
||||
var ErrInvalidBLSPrefix = errInvalidBLSPrefix
|
||||
var VerifyBlobCommitmentCount = verifyBlobCommitmentCount
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
|
||||
@@ -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 := ðpb.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(ðpb.BeaconState{
|
||||
Validators: registry,
|
||||
Fork: ðpb.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 := ðpb.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)
|
||||
|
||||
@@ -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",
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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
|
||||
}
|
||||
|
||||
@@ -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 := ðpb.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 := ðpb.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 :=
|
||||
ðpb.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)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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")
|
||||
|
||||
@@ -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",
|
||||
],
|
||||
)
|
||||
|
||||
25
beacon-chain/sync/benchmark_test.go
Normal file
25
beacon-chain/sync/benchmark_test.go
Normal 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"))
|
||||
}
|
||||
})
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user