Add proper gas limit check through local computation (#14707)

* Add proper gas limit check through local computation

* Potuz's feedback

* Fix new line
This commit is contained in:
terence
2024-12-13 08:02:00 -08:00
committed by GitHub
parent d93a1b671c
commit fa0dc09ce0
5 changed files with 233 additions and 23 deletions

View File

@@ -33,6 +33,7 @@ The format is based on Keep a Changelog, and this project adheres to Semantic Ve
- Added a Prometheus error counter metric for SSE requests.
- Save light client updates and bootstraps in DB.
- Added more comprehensive tests for `BlockToLightClientHeader`. [PR](https://github.com/prysmaticlabs/prysm/pull/14699)
- Added proper gas limit check for header from the builder.
- Added an error field to log `Finished building block`.
- Implemented a new `EmptyExecutionPayloadHeader` function.

View File

@@ -237,7 +237,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")