From 8c74033e51b0aa94c381870162a73f4523571c2d Mon Sep 17 00:00:00 2001 From: James Date: Tue, 5 Sep 2023 17:54:59 -0700 Subject: [PATCH 1/7] feature: boost proposer and builder profits --- services/api/service.go | 28 +++++++++++++++++++--------- services/api/service_test.go | 3 +-- 2 files changed, 20 insertions(+), 11 deletions(-) diff --git a/services/api/service.go b/services/api/service.go index 41908b29..9c94510e 100644 --- a/services/api/service.go +++ b/services/api/service.go @@ -41,9 +41,11 @@ import ( ) const ( - ErrBlockAlreadyKnown = "simulation failed: block already known" - ErrBlockRequiresReorg = "simulation failed: block requires a reorg" - ErrMissingTrieNode = "missing trie node" + RelayActualGasLimit = 30_000_000 + RelayFictitiousGasLimit = 1_000_000_000 + ErrBlockAlreadyKnown = "simulation failed: block already known" + ErrBlockRequiresReorg = "simulation failed: block requires a reorg" + ErrMissingTrieNode = "missing trie node" ) var ( @@ -752,6 +754,11 @@ func (api *RelayAPI) updateProposerDuties(headSlot uint64) { return } + // Instruct builders treat 30mm as the gas limit + for _, duty := range duties { + duty.Entry.Message.GasLimit = RelayActualGasLimit + } + // Prepare raw bytes for HTTP response respBytes, err := json.Marshal(duties) if err != nil { @@ -1484,23 +1491,23 @@ func (api *RelayAPI) handleBuilderGetValidators(w http.ResponseWriter, req *http } } -func (api *RelayAPI) checkSubmissionFeeRecipient(w http.ResponseWriter, log *logrus.Entry, payload *common.BuilderSubmitBlockRequest) (uint64, bool) { +func (api *RelayAPI) checkSubmissionFeeRecipient(w http.ResponseWriter, log *logrus.Entry, payload *common.BuilderSubmitBlockRequest) bool { api.proposerDutiesLock.RLock() slotDuty := api.proposerDutiesMap[payload.Slot()] api.proposerDutiesLock.RUnlock() if slotDuty == nil { log.Warn("could not find slot duty") api.RespondError(w, http.StatusBadRequest, "could not find slot duty") - return 0, false + return false } else if !strings.EqualFold(slotDuty.Entry.Message.FeeRecipient.String(), payload.ProposerFeeRecipient()) { log.WithFields(logrus.Fields{ "expectedFeeRecipient": slotDuty.Entry.Message.FeeRecipient.String(), "actualFeeRecipient": payload.ProposerFeeRecipient(), }).Info("fee recipient does not match") api.RespondError(w, http.StatusBadRequest, "fee recipient does not match") - return 0, false + return false } - return slotDuty.Entry.Message.GasLimit, true + return true } func (api *RelayAPI) checkSubmissionPayloadAttrs(w http.ResponseWriter, log *logrus.Entry, payload *common.BuilderSubmitBlockRequest) bool { @@ -1778,6 +1785,9 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque } } + // 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 @@ -1817,7 +1827,7 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque "timestampAfterChecks1": time.Now().UTC().UnixMilli(), }) - gasLimit, ok := api.checkSubmissionFeeRecipient(w, log, payload) + ok = api.checkSubmissionFeeRecipient(w, log, payload) if !ok { return } @@ -1940,7 +1950,7 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque builder: builderEntry, req: &common.BuilderBlockValidationRequest{ BuilderSubmitBlockRequest: *payload, - RegisteredGasLimit: gasLimit, + RegisteredGasLimit: RelayFictitiousGasLimit, }, } // With sufficient collateral, process the block optimistically. diff --git a/services/api/service_test.go b/services/api/service_test.go index 1f5f13ef..8ddb4517 100644 --- a/services/api/service_test.go +++ b/services/api/service_test.go @@ -578,8 +578,7 @@ func TestCheckSubmissionFeeRecipient(t *testing.T) { w := httptest.NewRecorder() logger := logrus.New() log := logrus.NewEntry(logger) - gasLimit, ok := backend.relay.checkSubmissionFeeRecipient(w, log, tc.payload) - require.Equal(t, tc.expectGasLimit, gasLimit) + ok := backend.relay.checkSubmissionFeeRecipient(w, log, tc.payload) require.Equal(t, tc.expectOk, ok) }) } From 04932cf7482dc4784f469ff871e4eb5dc9511068 Mon Sep 17 00:00:00 2001 From: James Date: Tue, 5 Sep 2023 20:11:33 -0700 Subject: [PATCH 2/7] fix: reject blocks that exceed the actual limit --- services/api/service.go | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/services/api/service.go b/services/api/service.go index 9c94510e..08b3e55d 100644 --- a/services/api/service.go +++ b/services/api/service.go @@ -1785,6 +1785,10 @@ 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 From d7f4c2847633bb53f1232d3bf1922dc313b38b1f Mon Sep 17 00:00:00 2001 From: James Date: Tue, 5 Sep 2023 22:44:29 -0700 Subject: [PATCH 3/7] refactor: change the fictitious limit to 100mm --- services/api/service.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/services/api/service.go b/services/api/service.go index 08b3e55d..d74d8698 100644 --- a/services/api/service.go +++ b/services/api/service.go @@ -42,7 +42,7 @@ import ( const ( RelayActualGasLimit = 30_000_000 - RelayFictitiousGasLimit = 1_000_000_000 + RelayFictitiousGasLimit = 100_000_000 ErrBlockAlreadyKnown = "simulation failed: block already known" ErrBlockRequiresReorg = "simulation failed: block requires a reorg" ErrMissingTrieNode = "missing trie node" From 61c42ec6c5bd7cf7d169b1fd06b94a4f496f4cfc Mon Sep 17 00:00:00 2001 From: James Date: Wed, 6 Sep 2023 10:39:17 -0700 Subject: [PATCH 4/7] refactor: rely on builder api to provide gaslimit --- common/types.go | 19 ++++++---- database/database.go | 2 +- services/api/blocksim_ratelimiter.go | 15 +++++--- services/api/mock_blocksim_ratelimiter.go | 7 +++- services/api/optimistic_test.go | 2 +- services/api/service.go | 46 +++++++++++++++-------- 6 files changed, 59 insertions(+), 32 deletions(-) diff --git a/common/types.go b/common/types.go index bc909676..46513d80 100644 --- a/common/types.go +++ b/common/types.go @@ -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, @@ -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"` +} diff --git a/database/database.go b/database/database.go index 939161a2..4aa5003c 100644 --- a/database/database.go +++ b/database/database.go @@ -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 diff --git a/services/api/blocksim_ratelimiter.go b/services/api/blocksim_ratelimiter.go index 74fdbb8a..e99a812f 100644 --- a/services/api/blocksim_ratelimiter.go +++ b/services/api/blocksim_ratelimiter.go @@ -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 } @@ -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 { @@ -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. @@ -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 diff --git a/services/api/mock_blocksim_ratelimiter.go b/services/api/mock_blocksim_ratelimiter.go index 1d180e56..76c07b36 100644 --- a/services/api/mock_blocksim_ratelimiter.go +++ b/services/api/mock_blocksim_ratelimiter.go @@ -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 { diff --git a/services/api/optimistic_test.go b/services/api/optimistic_test.go index b0f6e491..fb76b25a 100644 --- a/services/api/optimistic_test.go +++ b/services/api/optimistic_test.go @@ -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{ diff --git a/services/api/service.go b/services/api/service.go index d74d8698..6d2d34c1 100644 --- a/services/api/service.go +++ b/services/api/service.go @@ -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(), @@ -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) { @@ -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. @@ -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 @@ -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{ @@ -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 + } +} From 40e5c920dda850a038bb407e3fd5c8434ca95839 Mon Sep 17 00:00:00 2001 From: James Date: Wed, 6 Sep 2023 15:24:31 -0700 Subject: [PATCH 5/7] fix: add overrides to sim result --- services/api/service.go | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) diff --git a/services/api/service.go b/services/api/service.go index 6d2d34c1..c3ca17c2 100644 --- a/services/api/service.go +++ b/services/api/service.go @@ -162,6 +162,7 @@ type blockSimResult struct { optimisticSubmission bool requestErr error validationErr error + overrides *common.BuilderBlockValidationResponseV2 } // RelayAPI represents a single Relay instance @@ -624,11 +625,11 @@ func (api *RelayAPI) processOptimisticBlock(opts blockSimOptions, simResultC cha overrides, reqErr, simErr := api.simulateBlock(ctx, opts) overrideGasValues( - opts.req, + &opts.req.BuilderSubmitBlockRequest, overrides, ) - simResultC <- &blockSimResult{reqErr == nil, true, reqErr, simErr} + simResultC <- &blockSimResult{reqErr == nil, true, reqErr, simErr, overrides} if reqErr != nil || simErr != nil { // Mark builder as non-optimistic. opts.builder.status.IsOptimistic = false @@ -1644,7 +1645,7 @@ func (api *RelayAPI) checkFloorBidValue(opts bidFloorOpts) (*big.Int, *logrus.En isBidBelowFloor := floorBidValue != nil && opts.payload.Value().Cmp(floorBidValue) == -1 isBidAtOrBelowFloor := floorBidValue != nil && opts.payload.Value().Cmp(floorBidValue) < 1 if opts.cancellationsEnabled && isBidBelowFloor { // with cancellations: if below floor -> delete previous bid - opts.simResultC <- &blockSimResult{false, false, nil, nil} + opts.simResultC <- &blockSimResult{false, false, nil, nil, nil} opts.log.Info("submission below floor bid value, with cancellation") err := api.redis.DelBuilderBid(context.Background(), opts.tx, opts.payload.Slot(), opts.payload.ParentHash(), opts.payload.ProposerPubkey(), opts.payload.BuilderPubkey().String()) if err != nil { @@ -1655,7 +1656,7 @@ func (api *RelayAPI) checkFloorBidValue(opts bidFloorOpts) (*big.Int, *logrus.En api.Respond(opts.w, http.StatusAccepted, "accepted bid below floor, skipped validation") return nil, nil, false } else if !opts.cancellationsEnabled && isBidAtOrBelowFloor { // without cancellations: if at or below floor -> ignore - opts.simResultC <- &blockSimResult{false, false, nil, nil} + opts.simResultC <- &blockSimResult{false, false, nil, nil, nil} opts.log.Info("submission at or below floor bid value, without cancellation") api.RespondMsg(opts.w, http.StatusAccepted, "accepted bid below floor, skipped validation") return nil, nil, false @@ -1901,7 +1902,12 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque case simResult = <-simResultC: case <-time.After(10 * time.Second): log.Warn("timed out waiting for simulation result") - simResult = &blockSimResult{false, false, nil, nil} + simResult = &blockSimResult{false, false, nil, nil, nil} + } + + if simResult.overrides != nil { + // override the gas values with the ones from the simulation + overrideGasValues(payload, simResult.overrides) } submissionEntry, err := api.db.SaveBuilderBlockSubmission(payload, simResult.requestErr, simResult.validationErr, receivedAt, eligibleAt, simResult.wasSimulated, savePayloadToDatabase, pf, simResult.optimisticSubmission) @@ -1967,11 +1973,11 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque overrides, requestErr, validationErr := api.simulateBlock(context.Background(), opts) // success/error logging happens inside overrideGasValues( - opts.req, + &opts.req.BuilderSubmitBlockRequest, overrides, ) - simResultC <- &blockSimResult{requestErr == nil, false, requestErr, validationErr} + simResultC <- &blockSimResult{requestErr == nil, false, requestErr, validationErr, overrides} validationDurationMs := time.Since(timeBeforeValidation).Milliseconds() log = log.WithFields(logrus.Fields{ "timestampAfterValidation": time.Now().UTC().UnixMilli(), @@ -2383,7 +2389,7 @@ func (api *RelayAPI) handleReadyz(w http.ResponseWriter, req *http.Request) { } func overrideGasValues( - req *common.BuilderBlockValidationRequest, + req *common.BuilderSubmitBlockRequest, overrides *common.BuilderBlockValidationResponseV2, ) { if overrides != nil { From 66a565da0e773febd00e1ebdfa120bb12e7ed50c Mon Sep 17 00:00:00 2001 From: James Date: Wed, 6 Sep 2023 16:05:57 -0700 Subject: [PATCH 6/7] refactor: move check inside function --- services/api/service.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/services/api/service.go b/services/api/service.go index c3ca17c2..68467504 100644 --- a/services/api/service.go +++ b/services/api/service.go @@ -1905,10 +1905,8 @@ func (api *RelayAPI) handleSubmitNewBlock(w http.ResponseWriter, req *http.Reque simResult = &blockSimResult{false, false, nil, nil, nil} } - if simResult.overrides != nil { - // override the gas values with the ones from the simulation - overrideGasValues(payload, simResult.overrides) - } + // override the gas values with the ones from the simulation + overrideGasValues(payload, simResult.overrides) submissionEntry, err := api.db.SaveBuilderBlockSubmission(payload, simResult.requestErr, simResult.validationErr, receivedAt, eligibleAt, simResult.wasSimulated, savePayloadToDatabase, pf, simResult.optimisticSubmission) if err != nil { @@ -2392,7 +2390,7 @@ func overrideGasValues( req *common.BuilderSubmitBlockRequest, overrides *common.BuilderBlockValidationResponseV2, ) { - if overrides != nil { + if overrides != nil && req != nil { req.Capella.ExecutionPayload.BlockHash = overrides.NewBlockHash req.Capella.ExecutionPayload.GasLimit = overrides.NewGasLimit } From 03c1961ab7178df521d8bce619dd50dcff05a1f2 Mon Sep 17 00:00:00 2001 From: James Date: Mon, 11 Sep 2023 08:45:38 -0700 Subject: [PATCH 7/7] fix: error check unmarshalling --- common/types.go | 3 +++ services/api/blocksim_ratelimiter.go | 5 ++++- services/api/service.go | 3 ++- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/common/types.go b/common/types.go index 46513d80..e9f440c3 100644 --- a/common/types.go +++ b/common/types.go @@ -1071,6 +1071,9 @@ func (s *SubmitBlockRequestV2Optimistic) SizeSSZ() (size int) { return } +// BuilderBlockValidationResponseV2 is the expected response from the builder +// node simulation requests. It contains the modified gas limit and the new +// block hash. type BuilderBlockValidationResponseV2 struct { NewGasLimit uint64 `json:"new_gas_limit,string"` NewBlockHash phase0.Hash32 `json:"new_block_hash"` diff --git a/services/api/blocksim_ratelimiter.go b/services/api/blocksim_ratelimiter.go index e99a812f..e269ce8d 100644 --- a/services/api/blocksim_ratelimiter.go +++ b/services/api/blocksim_ratelimiter.go @@ -89,7 +89,10 @@ func (b *BlockSimulationRateLimiter) Send(context context.Context, payload *comm simReq = jsonrpc.NewJSONRPCRequest("1", "flashbots_validateBuilderSubmissionV2", payload) rawResp, requestErr, validationErr := SendJSONRPCRequest(&b.client, *simReq, b.blockSimURL, headers) - json.Unmarshal(rawResp.Result, resp) + err := json.Unmarshal(rawResp.Result, resp) + if err != nil { + return nil, err, nil + } return resp, requestErr, validationErr } diff --git a/services/api/service.go b/services/api/service.go index 68467504..db55b73e 100644 --- a/services/api/service.go +++ b/services/api/service.go @@ -762,7 +762,8 @@ func (api *RelayAPI) updateProposerDuties(headSlot uint64) { return } - // Instruct builders treat 30mm as the gas limit + // Changes the response to indicate that the target gas limit is + // RelayActualGasLimit, not the proposer-specified value. for _, duty := range duties { duty.Entry.Message.GasLimit = RelayActualGasLimit }