Skip to content

Commit

Permalink
Add proper gas limit check through local computation
Browse files Browse the repository at this point in the history
  • Loading branch information
terencechain committed Dec 10, 2024
1 parent 63bc965 commit a5bdd56
Show file tree
Hide file tree
Showing 5 changed files with 222 additions and 23 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

### Changed

Expand Down
7 changes: 6 additions & 1 deletion beacon-chain/rpc/prysm/v1alpha1/validator/proposer.go
Original file line number Diff line number Diff line change
Expand Up @@ -236,7 +236,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")
Expand Down
43 changes: 42 additions & 1 deletion beacon-chain/rpc/prysm/v1alpha1/validator/proposer_bellatrix.go
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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()

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -393,3 +408,29 @@ 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, targetGasLimit uint64) uint64 {
maxGasLimitDiff := parentGasLimit/gasLimitAdjustmentFactor - 1
if targetGasLimit > parentGasLimit {
if targetGasLimit-parentGasLimit > maxGasLimitDiff {
return parentGasLimit + maxGasLimitDiff
}
return targetGasLimit
} else {
if parentGasLimit-targetGasLimit > maxGasLimitDiff {
return parentGasLimit - maxGasLimitDiff
}
return targetGasLimit
}
}
Loading

0 comments on commit a5bdd56

Please sign in to comment.