Skip to content

Commit

Permalink
refactor: rely on builder api to provide gaslimit
Browse files Browse the repository at this point in the history
  • Loading branch information
prestwich committed Sep 6, 2023
1 parent d7f4c28 commit 61c42ec
Show file tree
Hide file tree
Showing 6 changed files with 59 additions and 32 deletions.
19 changes: 12 additions & 7 deletions common/types.go
Original file line number Diff line number Diff line change
Expand Up @@ -133,15 +133,15 @@ func NewEthNetworkDetails(networkName string) (ret *EthNetworkDetails, err error
func (e *EthNetworkDetails) String() string {
return fmt.Sprintf(
`EthNetworkDetails{
Name: %s,
GenesisForkVersionHex: %s,
Name: %s,
GenesisForkVersionHex: %s,
GenesisValidatorsRootHex: %s,
BellatrixForkVersionHex: %s,
CapellaForkVersionHex: %s,
BellatrixForkVersionHex: %s,
CapellaForkVersionHex: %s,
DenebForkVersionHex: %s,
DomainBuilder: %x,
DomainBeaconProposerBellatrix: %x,
DomainBeaconProposerCapella: %x,
DomainBuilder: %x,
DomainBeaconProposerBellatrix: %x,
DomainBeaconProposerCapella: %x,
DomainBeaconProposerDeneb: %x
}`,
e.Name,
Expand Down Expand Up @@ -1070,3 +1070,8 @@ func (s *SubmitBlockRequestV2Optimistic) SizeSSZ() (size int) {

return
}

type BuilderBlockValidationResponseV2 struct {
NewGasLimit uint64 `json:"new_gas_limit,string"`
NewBlockHash phase0.Hash32 `json:"new_block_hash"`
}
2 changes: 1 addition & 1 deletion database/database.go
Original file line number Diff line number Diff line change
Expand Up @@ -241,7 +241,7 @@ func (s *DatabaseService) SaveBuilderBlockSubmission(payload *common.BuilderSubm
}

func (s *DatabaseService) GetBlockSubmissionEntry(slot uint64, proposerPubkey, blockHash string) (entry *BuilderBlockSubmissionEntry, err error) {
query := `SELECT id, inserted_at, received_at, eligible_at, execution_payload_id, sim_success, sim_error, signature, slot, parent_hash, block_hash, builder_pubkey, proposer_pubkey, proposer_fee_recipient, gas_used, gas_limit, num_tx, value, epoch, block_number, decode_duration, prechecks_duration, simulation_duration, redis_update_duration, total_duration, optimistic_submission
query := `SELECT id, inserted_at, received_at, eligible_at, execution_payload_id, sim_success, sim_error, signature, slot, parent_hash, block_hash, builder_pubkey, proposer_pubkey, proposer_fee_recipient, gas_used, gas_limit, num_tx, value, epoch, block_number, decode_duration, prechecks_duration, simulation_duration, redis_update_duration, total_duration, optimistic_submission
FROM ` + vars.TableBuilderBlockSubmission + `
WHERE slot=$1 AND proposer_pubkey=$2 AND block_hash=$3
ORDER BY builder_pubkey ASC
Expand Down
15 changes: 9 additions & 6 deletions services/api/blocksim_ratelimiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ var (
)

type IBlockSimRateLimiter interface {
Send(context context.Context, payload *common.BuilderBlockValidationRequest, isHighPrio, fastTrack bool) (error, error)
Send(context context.Context, payload *common.BuilderBlockValidationRequest, isHighPrio, fastTrack bool) (*common.BuilderBlockValidationResponseV2, error, error)
CurrentCounter() int64
}

Expand All @@ -50,7 +50,7 @@ func NewBlockSimulationRateLimiter(blockSimURL string) *BlockSimulationRateLimit
}
}

func (b *BlockSimulationRateLimiter) Send(context context.Context, payload *common.BuilderBlockValidationRequest, isHighPrio, fastTrack bool) (requestErr, validationErr error) {
func (b *BlockSimulationRateLimiter) Send(context context.Context, payload *common.BuilderBlockValidationRequest, isHighPrio, fastTrack bool) (resp *common.BuilderBlockValidationResponseV2, requestErr, validationErr error) {
b.cv.L.Lock()
cnt := atomic.AddInt64(&b.counter, 1)
if maxConcurrentBlocks > 0 && cnt > maxConcurrentBlocks {
Expand All @@ -66,12 +66,12 @@ func (b *BlockSimulationRateLimiter) Send(context context.Context, payload *comm
}()

if err := context.Err(); err != nil {
return fmt.Errorf("%w, %w", ErrRequestClosed, err), nil
return nil, fmt.Errorf("%w, %w", ErrRequestClosed, err), nil
}

var simReq *jsonrpc.JSONRPCRequest
if payload.Capella == nil {
return ErrNoCapellaPayload, nil
return nil, ErrNoCapellaPayload, nil
}
// TODO: add deneb support.

Expand All @@ -87,8 +87,11 @@ func (b *BlockSimulationRateLimiter) Send(context context.Context, payload *comm

// Create and fire off JSON-RPC request
simReq = jsonrpc.NewJSONRPCRequest("1", "flashbots_validateBuilderSubmissionV2", payload)
_, requestErr, validationErr = SendJSONRPCRequest(&b.client, *simReq, b.blockSimURL, headers)
return requestErr, validationErr
rawResp, requestErr, validationErr := SendJSONRPCRequest(&b.client, *simReq, b.blockSimURL, headers)

json.Unmarshal(rawResp.Result, resp)

return resp, requestErr, validationErr
}

// CurrentCounter returns the number of waiting and active requests
Expand Down
7 changes: 5 additions & 2 deletions services/api/mock_blocksim_ratelimiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,14 @@ import (
)

type MockBlockSimulationRateLimiter struct {
overrides common.BuilderBlockValidationResponseV2
simulationError error
}

func (m *MockBlockSimulationRateLimiter) Send(context context.Context, payload *common.BuilderBlockValidationRequest, isHighPrio, fastTrack bool) (error, error) {
return nil, m.simulationError
func (m *MockBlockSimulationRateLimiter) Send(context context.Context, payload *common.BuilderBlockValidationRequest, isHighPrio, fastTrack bool) (
*common.BuilderBlockValidationResponseV2, error, error,
) {
return &m.overrides, nil, m.simulationError
}

func (m *MockBlockSimulationRateLimiter) CurrentCounter() int64 {
Expand Down
2 changes: 1 addition & 1 deletion services/api/optimistic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -180,7 +180,7 @@ func TestSimulateBlock(t *testing.T) {
backend.relay.blockSimRateLimiter = &MockBlockSimulationRateLimiter{
simulationError: tc.simulationError,
}
_, simErr := backend.relay.simulateBlock(context.Background(), blockSimOptions{
_, _, simErr := backend.relay.simulateBlock(context.Background(), blockSimOptions{
isHighPrio: true,
log: backend.relay.log,
builder: &blockBuilderCacheEntry{
Expand Down
46 changes: 31 additions & 15 deletions services/api/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -550,9 +550,10 @@ func (api *RelayAPI) startValidatorRegistrationDBProcessor() {
}

// simulateBlock sends a request for a block simulation to blockSimRateLimiter.
func (api *RelayAPI) simulateBlock(ctx context.Context, opts blockSimOptions) (requestErr, validationErr error) {
func (api *RelayAPI) simulateBlock(ctx context.Context, opts blockSimOptions) (overrides *common.BuilderBlockValidationResponseV2, requestErr, validationErr error) {
t := time.Now()
requestErr, validationErr = api.blockSimRateLimiter.Send(ctx, opts.req, opts.isHighPrio, opts.fastTrack)
overrides, requestErr, validationErr = api.blockSimRateLimiter.Send(ctx, opts.req, opts.isHighPrio, opts.fastTrack)

log := opts.log.WithFields(logrus.Fields{
"durationMs": time.Since(t).Milliseconds(),
"numWaiting": api.blockSimRateLimiter.CurrentCounter(),
Expand All @@ -563,18 +564,18 @@ func (api *RelayAPI) simulateBlock(ctx context.Context, opts blockSimOptions) (r
ignoreError := validationErr.Error() == ErrBlockAlreadyKnown || validationErr.Error() == ErrBlockRequiresReorg || strings.Contains(validationErr.Error(), ErrMissingTrieNode)
if ignoreError {
log.WithError(validationErr).Warn("block validation failed with ignorable error")
return nil, nil
return nil, nil, nil
}
}
log.WithError(validationErr).Warn("block validation failed")
return nil, validationErr
return nil, nil, validationErr
}
if requestErr != nil {
log.WithError(requestErr).Warn("block validation failed: request error")
return requestErr, nil
return nil, requestErr, nil
}
log.Info("block validation successful")
return nil, nil
return overrides, nil, nil
}

func (api *RelayAPI) demoteBuilder(pubkey string, req *common.BuilderSubmitBlockRequest, simError error) {
Expand Down Expand Up @@ -620,7 +621,13 @@ func (api *RelayAPI) processOptimisticBlock(opts blockSimOptions, simResultC cha
// it for logging, it is not atomic to avoid the performance impact.
"optBlocksInFlight": api.optimisticBlocksInFlight,
}).Infof("simulating optimistic block with hash: %v", opts.req.BuilderSubmitBlockRequest.BlockHash())
reqErr, simErr := api.simulateBlock(ctx, opts)
overrides, reqErr, simErr := api.simulateBlock(ctx, opts)

overrideGasValues(
opts.req,
overrides,
)

simResultC <- &blockSimResult{reqErr == nil, true, reqErr, simErr}
if reqErr != nil || simErr != nil {
// Mark builder as non-optimistic.
Expand Down Expand Up @@ -1785,13 +1792,6 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque
}
}

// Refuse blocks outside the specified gas limit
if payload.Capella.ExecutionPayload.GasLimit > RelayActualGasLimit {
return
}
// Overwrite the builder's gasLimit with the relay-set fictitious limit
payload.Capella.ExecutionPayload.GasLimit = RelayFictitiousGasLimit

nextTime = time.Now().UTC()
pf.Decode = uint64(nextTime.Sub(prevTime).Microseconds())
prevTime = nextTime
Expand Down Expand Up @@ -1964,7 +1964,13 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque
go api.processOptimisticBlock(opts, simResultC)
} else {
// Simulate block (synchronously).
requestErr, validationErr := api.simulateBlock(context.Background(), opts) // success/error logging happens inside
overrides, requestErr, validationErr := api.simulateBlock(context.Background(), opts) // success/error logging happens inside

overrideGasValues(
opts.req,
overrides,
)

simResultC <- &blockSimResult{requestErr == nil, false, requestErr, validationErr}
validationDurationMs := time.Since(timeBeforeValidation).Milliseconds()
log = log.WithFields(logrus.Fields{
Expand Down Expand Up @@ -2375,3 +2381,13 @@ func (api *RelayAPI) handleReadyz(w http.ResponseWriter, req *http.Request) {
api.RespondMsg(w, http.StatusServiceUnavailable, "not ready")
}
}

func overrideGasValues(
req *common.BuilderBlockValidationRequest,
overrides *common.BuilderBlockValidationResponseV2,
) {
if overrides != nil {
req.Capella.ExecutionPayload.BlockHash = overrides.NewBlockHash
req.Capella.ExecutionPayload.GasLimit = overrides.NewGasLimit
}
}

0 comments on commit 61c42ec

Please sign in to comment.