diff --git a/builder/service.go b/builder/service.go index 7cd777ded5..55f4300c67 100644 --- a/builder/service.go +++ b/builder/service.go @@ -206,7 +206,7 @@ func Register(stack *node.Node, backend *eth.Ethereum, cfg *Config) error { } var validator *blockvalidation.BlockValidationAPI - if cfg.DryRun || !cfg.DryRun { + if cfg.DryRun { var accessVerifier *blockvalidation.AccessVerifier if cfg.ValidationBlocklist != "" { accessVerifier, err = blockvalidation.NewAccessVerifierFromFile(cfg.ValidationBlocklist) diff --git a/builder/utils.go b/builder/utils.go index 0871ce73a6..284285cf4e 100644 --- a/builder/utils.go +++ b/builder/utils.go @@ -7,20 +7,12 @@ import ( "encoding/json" "errors" "fmt" - "github.com/ethereum/go-ethereum/log" "io" "net/http" ) var errHTTPErrorResponse = errors.New("HTTP error response") -type JSONRPCResponse struct { - ID interface{} `json:"id"` - Result json.RawMessage `json:"result,omitempty"` - Error json.RawMessage `json:"error,omitempty"` - Version string `json:"jsonrpc"` -} - // SendSSZRequest is a request to send SSZ data to a remote relay. func SendSSZRequest(ctx context.Context, client http.Client, method, url string, payload []byte, useGzip bool) (code int, err error) { var req *http.Request @@ -63,21 +55,11 @@ func SendSSZRequest(ctx context.Context, client http.Client, method, url string, } defer resp.Body.Close() - bodyBytes, err := io.ReadAll(resp.Body) - if err != nil { - return resp.StatusCode, fmt.Errorf("could not read error response body for status code %d: %w", resp.StatusCode, err) - } - - res := new(JSONRPCResponse) - if err := json.Unmarshal(bodyBytes, &res); err != nil { - return resp.StatusCode, fmt.Errorf("could not unmarshal error response body for status code %d: %w", resp.StatusCode, err) - } - - if res.Error != nil { - log.Info("Error response", "code", resp.StatusCode, "message", string(res.Error)) - } - if resp.StatusCode > 299 { + bodyBytes, err := io.ReadAll(resp.Body) + if err != nil { + return resp.StatusCode, fmt.Errorf("could not read error response body for status code %d: %w", resp.StatusCode, err) + } return resp.StatusCode, fmt.Errorf("HTTP error response: %d / %s", resp.StatusCode, string(bodyBytes)) } return resp.StatusCode, nil diff --git a/miner/algo_common.go b/miner/algo_common.go index f3e49cfc31..14d8f21331 100644 --- a/miner/algo_common.go +++ b/miner/algo_common.go @@ -170,6 +170,41 @@ func NewBuildBlockFunc( } } +func ValidateGasPriceAndProfit(algoConf algorithmConfig, actualPrice, expectedPrice *big.Int, tolerablePriceDifferencePercent int, + actualProfit, expectedProfit *big.Int) error { + // allow tolerablePriceDifferencePercent % divergence + expectedPriceMultiple := new(big.Int).Mul(expectedPrice, big.NewInt(100-int64(tolerablePriceDifferencePercent))) + actualPriceMultiple := new(big.Int).Mul(actualPrice, common.Big100) + + var errLowProfit *lowProfitError = nil + if expectedPriceMultiple.Cmp(actualPriceMultiple) > 0 { + errLowProfit = &lowProfitError{ + ExpectedEffectiveGasPrice: expectedPrice, + ActualEffectiveGasPrice: actualPrice, + } + } + + if algoConf.EnforceProfit { + // We want to make expected profit smaller to allow for some leeway in cases where the actual profit is + // lower due to transaction ordering + expectedProfitMultiple := common.PercentOf(expectedProfit, algoConf.ProfitThresholdPercent) + actualProfitMultiple := new(big.Int).Mul(actualProfit, common.Big100) + + if expectedProfitMultiple.Cmp(actualProfitMultiple) > 0 { + if errLowProfit == nil { + errLowProfit = new(lowProfitError) + } + errLowProfit.ExpectedProfit = expectedProfit + errLowProfit.ActualProfit = actualProfit + } + } + + if errLowProfit != nil { // staticcheck linter complains if we don't check for nil here + return errLowProfit + } + return nil +} + func checkInterrupt(i *int32) bool { return i != nil && atomic.LoadInt32(i) != commitInterruptNone } diff --git a/miner/env_changes.go b/miner/env_changes.go index d7798998a1..053ac8b538 100644 --- a/miner/env_changes.go +++ b/miner/env_changes.go @@ -156,7 +156,6 @@ func (c *envChanges) commitBundle(bundle *types.SimulatedBundle, chData chainDat if err := c.env.state.MultiTxSnapshotCommit(); err != nil { panic(fmt.Sprintf("err: %v, receipt: %v", err, receipt)) } - } //switch err { //case nil: @@ -252,22 +251,28 @@ func (c *envChanges) commitBundle(bundle *types.SimulatedBundle, chData chainDat bundleProfit = new(big.Int).Sub(c.env.state.GetBalance(c.env.coinbase), coinbaseBefore) gasUsed = c.usedGas - gasUsedBefore - simEffGP = new(big.Int).Set(bundle.MevGasPrice) - effGP *big.Int + // EGP = Effective Gas Price (Profit / GasUsed) + simulatedEGP = new(big.Int).Set(bundle.MevGasPrice) + actualEGP *big.Int + tolerablePriceDifferencePercent = 1 + + simulatedBundleProfit = new(big.Int).Set(bundle.TotalEth) + actualBundleProfit = new(big.Int).Set(bundleProfit) ) + if gasUsed == 0 { - effGP = new(big.Int).SetUint64(0) + actualEGP = big.NewInt(0) } else { - effGP = new(big.Int).Div(bundleProfit, new(big.Int).SetUint64(gasUsed)) + actualEGP = new(big.Int).Div(bundleProfit, big.NewInt(int64(gasUsed))) } - // allow >-1% divergence - effGP.Mul(effGP, common.Big100) - simEffGP.Mul(simEffGP, big.NewInt(99)) - if simEffGP.Cmp(effGP) > 0 { - log.Trace("Bundle underpays after inclusion", "bundle", bundle.OriginalBundle.Hash) + err := ValidateGasPriceAndProfit(algoConf, + actualEGP, simulatedEGP, tolerablePriceDifferencePercent, + actualBundleProfit, simulatedBundleProfit, + ) + if err != nil { c.rollback(gasUsedBefore, gasPoolBefore, profitBefore, txsBefore, receiptsBefore) - return errors.New("bundle underpays") + return err } c.profit.Add(profitBefore, bundleProfit) diff --git a/miner/environment_diff.go b/miner/environment_diff.go index 238a47b774..daefffa1e6 100644 --- a/miner/environment_diff.go +++ b/miner/environment_diff.go @@ -195,45 +195,29 @@ func (envDiff *environmentDiff) commitBundle(bundle *types.SimulatedBundle, chDa coinbaseBalanceDelta := new(big.Int).Sub(coinbaseBalanceAfter, coinbaseBalanceBefore) tmpEnvDiff.newProfit.Add(profitBefore, coinbaseBalanceDelta) - bundleProfit := coinbaseBalanceDelta + var ( + bundleProfit = coinbaseBalanceDelta + // EGP = Effective Gas Price (Profit / GasUsed) + simulatedEGP = new(big.Int).Set(bundle.MevGasPrice) + actualEGP *big.Int + tolerablePriceDifferencePercent = 1 + + simulatedBundleProfit = new(big.Int).Set(bundle.TotalEth) + actualBundleProfit = new(big.Int).Set(bundleProfit) + ) - var bundleActualEffGP *big.Int if gasUsed == 0 { - bundleActualEffGP = big.NewInt(0) + actualEGP = big.NewInt(0) } else { - bundleActualEffGP = bundleProfit.Div(bundleProfit, big.NewInt(int64(gasUsed))) - } - bundleSimEffGP := new(big.Int).Set(bundle.MevGasPrice) - - // allow >-1% divergence - actualEGP := new(big.Int).Mul(bundleActualEffGP, common.Big100) // bundle actual effective gas price * 100 - simulatedEGP := new(big.Int).Mul(bundleSimEffGP, big.NewInt(99)) // bundle simulated effective gas price * 99 - - if simulatedEGP.Cmp(actualEGP) > 0 { - log.Trace("Bundle underpays after inclusion", "bundle", bundle.OriginalBundle.Hash) - return &lowProfitError{ - ExpectedEffectiveGasPrice: bundleSimEffGP, - ActualEffectiveGasPrice: bundleActualEffGP, - } + actualEGP = new(big.Int).Div(bundleProfit, big.NewInt(int64(gasUsed))) } - if algoConf.EnforceProfit { - // if profit is enforced between simulation and actual commit, only allow ProfitThresholdPercent divergence - simulatedBundleProfit := new(big.Int).Set(bundle.TotalEth) - actualBundleProfit := new(big.Int).Mul(bundleActualEffGP, big.NewInt(int64(gasUsed))) - - // We want to make simulated profit smaller to allow for some leeway in cases where the actual profit is - // lower due to transaction ordering - simulatedProfitMultiple := common.PercentOf(simulatedBundleProfit, algoConf.ProfitThresholdPercent) - actualProfitMultiple := new(big.Int).Mul(actualBundleProfit, common.Big100) - - if simulatedProfitMultiple.Cmp(actualProfitMultiple) > 0 { - log.Trace("Lower bundle profit found after inclusion", "bundle", bundle.OriginalBundle.Hash) - return &lowProfitError{ - ExpectedProfit: simulatedBundleProfit, - ActualProfit: actualBundleProfit, - } - } + err := ValidateGasPriceAndProfit(algoConf, + actualEGP, simulatedEGP, tolerablePriceDifferencePercent, + actualBundleProfit, simulatedBundleProfit, + ) + if err != nil { + return err } *envDiff = *tmpEnvDiff