diff --git a/builder/service.go b/builder/service.go index b49a0edf29..447ad7301f 100644 --- a/builder/service.go +++ b/builder/service.go @@ -156,14 +156,7 @@ func Register(stack *node.Node, backend *eth.Ethereum, cfg *Config) error { var validator *blockvalidation.BlockValidationAPI if cfg.DryRun { - var accessVerifier *blockvalidation.AccessVerifier - if cfg.ValidationBlocklist != "" { - accessVerifier, err = blockvalidation.NewAccessVerifierFromFile(cfg.ValidationBlocklist) - if err != nil { - return fmt.Errorf("failed to load validation blocklist %w", err) - } - } - validator = blockvalidation.NewBlockValidationAPI(backend, accessVerifier) + validator = blockvalidation.NewBlockValidationAPI(backend) } // TODO: move to proper flags diff --git a/cmd/geth/config.go b/cmd/geth/config.go index 1327e90a69..3273986838 100644 --- a/cmd/geth/config.go +++ b/cmd/geth/config.go @@ -173,12 +173,7 @@ func makeFullNode(ctx *cli.Context) (*node.Node, ethapi.Backend) { // Configure log filter RPC API. filterSystem := utils.RegisterFilterAPI(stack, backend, &cfg.Eth) - bvConfig := blockvalidationapi.BlockValidationConfig{} - if ctx.IsSet(utils.BuilderBlockValidationBlacklistSourceFilePath.Name) { - bvConfig.BlacklistSourceFilePath = ctx.String(utils.BuilderBlockValidationBlacklistSourceFilePath.Name) - } - - if err := blockvalidationapi.Register(stack, eth, bvConfig); err != nil { + if err := blockvalidationapi.Register(stack, eth); err != nil { utils.Fatalf("Failed to register the Block Validation API: %v", err) } diff --git a/core/blockchain.go b/core/blockchain.go index e3461bd964..1ccfe05c91 100644 --- a/core/blockchain.go +++ b/core/blockchain.go @@ -2502,6 +2502,8 @@ func (bc *BlockChain) ValidatePayload(block *types.Block, feeRecipient common.Ad // and dangling prefetcher, without defering each and holding on live refs. defer statedb.StopPrefetcher() + balanceBefore := statedb.GetBalance(feeRecipient) + receipts, _, usedGas, err := bc.processor.Process(block, statedb, vmConfig) if err != nil { return err @@ -2515,6 +2517,17 @@ func (bc *BlockChain) ValidatePayload(block *types.Block, feeRecipient common.Ad return err } + // First just check the balance delta to see if it matches. + balanceAfter := statedb.GetBalance(feeRecipient) + feeRecipientDiff := new(big.Int).Sub(balanceAfter, balanceBefore) + + // If diff is sufficiently large, just return success. + if feeRecipientDiff.Cmp(expectedProfit) >= 0 { + return nil + } + log.Warn(fmt.Sprintf("fee recipient diff %s is less than expected %s. checking for last transaction", feeRecipientDiff.String(), expectedProfit.String())) + + // Flashbots logic for last transaction checks. if len(receipts) == 0 { return errors.New("no proposer payment receipt") } diff --git a/eth/block-validation/api.go b/eth/block-validation/api.go index 0fecfeb0b3..f15f209424 100644 --- a/eth/block-validation/api.go +++ b/eth/block-validation/api.go @@ -4,17 +4,13 @@ import ( "encoding/json" "errors" "fmt" - "math/big" - "os" capellaapi "github.com/attestantio/go-builder-client/api/capella" "github.com/attestantio/go-eth2-client/spec/phase0" "github.com/ethereum/go-ethereum/beacon/engine" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/core/vm" "github.com/ethereum/go-ethereum/eth" - "github.com/ethereum/go-ethereum/eth/tracers/logger" "github.com/ethereum/go-ethereum/log" "github.com/ethereum/go-ethereum/node" "github.com/ethereum/go-ethereum/rpc" @@ -23,50 +19,6 @@ import ( boostTypes "github.com/flashbots/go-boost-utils/types" ) -type BlacklistedAddresses []common.Address - -type AccessVerifier struct { - blacklistedAddresses map[common.Address]struct{} -} - -func (a *AccessVerifier) verifyTraces(tracer *logger.AccessListTracer) error { - log.Trace("x", "tracer.AccessList()", tracer.AccessList()) - for _, accessTuple := range tracer.AccessList() { - // TODO: should we ignore common.Address{}? - if _, found := a.blacklistedAddresses[accessTuple.Address]; found { - log.Info("bundle accesses blacklisted address", "address", accessTuple.Address) - return fmt.Errorf("blacklisted address %s in execution trace", accessTuple.Address.String()) - } - } - - return nil -} - -func (a *AccessVerifier) isBlacklisted(addr common.Address) error { - if _, present := a.blacklistedAddresses[addr]; present { - return fmt.Errorf("transaction from blacklisted address %s", addr.String()) - } - return nil -} - -func (a *AccessVerifier) verifyTransactions(signer types.Signer, txs types.Transactions) error { - for _, tx := range txs { - from, err := signer.Sender(tx) - if err == nil { - if _, present := a.blacklistedAddresses[from]; present { - return fmt.Errorf("transaction from blacklisted address %s", from.String()) - } - } - to := tx.To() - if to != nil { - if _, present := a.blacklistedAddresses[*to]; present { - return fmt.Errorf("transaction to blacklisted address %s", to.String()) - } - } - } - return nil -} - func verifyWithdrawals(withdrawals types.Withdrawals, expectedWithdrawalsRoot common.Hash, isShanghai bool) error { if !isShanghai { // Reject payload attributes with withdrawals before shanghai @@ -83,62 +35,26 @@ func verifyWithdrawals(withdrawals types.Withdrawals, expectedWithdrawalsRoot co return nil } -func NewAccessVerifierFromFile(path string) (*AccessVerifier, error) { - bytes, err := os.ReadFile(path) - if err != nil { - return nil, err - } - - var ba BlacklistedAddresses - if err := json.Unmarshal(bytes, &ba); err != nil { - return nil, err - } - - blacklistedAddresses := make(map[common.Address]struct{}, len(ba)) - for _, address := range ba { - blacklistedAddresses[address] = struct{}{} - } - - return &AccessVerifier{ - blacklistedAddresses: blacklistedAddresses, - }, nil -} - -type BlockValidationConfig struct { - BlacklistSourceFilePath string -} - // Register adds catalyst APIs to the full node. -func Register(stack *node.Node, backend *eth.Ethereum, cfg BlockValidationConfig) error { - var accessVerifier *AccessVerifier - if cfg.BlacklistSourceFilePath != "" { - var err error - accessVerifier, err = NewAccessVerifierFromFile(cfg.BlacklistSourceFilePath) - if err != nil { - return err - } - } - +func Register(stack *node.Node, backend *eth.Ethereum) error { stack.RegisterAPIs([]rpc.API{ { Namespace: "flashbots", - Service: NewBlockValidationAPI(backend, accessVerifier), + Service: NewBlockValidationAPI(backend), }, }) return nil } type BlockValidationAPI struct { - eth *eth.Ethereum - accessVerifier *AccessVerifier + eth *eth.Ethereum } // NewConsensusAPI creates a new consensus api for the given backend. // The underlying blockchain needs to have a valid terminal total difficulty set. -func NewBlockValidationAPI(eth *eth.Ethereum, accessVerifier *AccessVerifier) *BlockValidationAPI { +func NewBlockValidationAPI(eth *eth.Ethereum) *BlockValidationAPI { return &BlockValidationAPI{ - eth: eth, - accessVerifier: accessVerifier, + eth: eth, } } @@ -179,37 +95,12 @@ func (api *BlockValidationAPI) ValidateBuilderSubmissionV1(params *BuilderBlockV feeRecipient := common.BytesToAddress(params.Message.ProposerFeeRecipient[:]) expectedProfit := params.Message.Value.BigInt() - var vmconfig vm.Config - var tracer *logger.AccessListTracer = nil - if api.accessVerifier != nil { - if err := api.accessVerifier.isBlacklisted(block.Coinbase()); err != nil { - return err - } - if err := api.accessVerifier.isBlacklisted(feeRecipient); err != nil { - return err - } - if err := api.accessVerifier.verifyTransactions(types.LatestSigner(api.eth.BlockChain().Config()), block.Transactions()); err != nil { - return err - } - isPostMerge := true // the call is PoS-native - timestamp := params.BuilderSubmitBlockRequest.ExecutionPayload.Timestamp - precompiles := vm.ActivePrecompiles(api.eth.APIBackend.ChainConfig().Rules(new(big.Int).SetUint64(params.ExecutionPayload.BlockNumber), isPostMerge, timestamp)) - tracer = logger.NewAccessListTracer(nil, common.Address{}, common.Address{}, precompiles) - vmconfig = vm.Config{Tracer: tracer, Debug: true} - } - - err = api.eth.BlockChain().ValidatePayload(block, feeRecipient, expectedProfit, params.RegisteredGasLimit, vmconfig) + err = api.eth.BlockChain().ValidatePayload(block, feeRecipient, expectedProfit, params.RegisteredGasLimit, *api.eth.BlockChain().GetVMConfig()) if err != nil { log.Error("invalid payload", "hash", payload.BlockHash.String(), "number", payload.BlockNumber, "parentHash", payload.ParentHash.String(), "err", err) return err } - if api.accessVerifier != nil && tracer != nil { - if err := api.accessVerifier.verifyTraces(tracer); err != nil { - return err - } - } - log.Info("validated block", "hash", block.Hash(), "number", block.NumberU64(), "parentHash", block.ParentHash()) return nil } @@ -278,36 +169,12 @@ func (api *BlockValidationAPI) ValidateBuilderSubmissionV2(params *BuilderBlockV feeRecipient := common.BytesToAddress(params.Message.ProposerFeeRecipient[:]) expectedProfit := params.Message.Value.ToBig() - var vmconfig vm.Config - var tracer *logger.AccessListTracer = nil - if api.accessVerifier != nil { - if err := api.accessVerifier.isBlacklisted(block.Coinbase()); err != nil { - return err - } - if err := api.accessVerifier.isBlacklisted(feeRecipient); err != nil { - return err - } - if err := api.accessVerifier.verifyTransactions(types.LatestSigner(api.eth.BlockChain().Config()), block.Transactions()); err != nil { - return err - } - isPostMerge := true // the call is PoS-native - precompiles := vm.ActivePrecompiles(api.eth.APIBackend.ChainConfig().Rules(new(big.Int).SetUint64(params.ExecutionPayload.BlockNumber), isPostMerge, params.ExecutionPayload.Timestamp)) - tracer = logger.NewAccessListTracer(nil, common.Address{}, common.Address{}, precompiles) - vmconfig = vm.Config{Tracer: tracer, Debug: true} - } - - err = api.eth.BlockChain().ValidatePayload(block, feeRecipient, expectedProfit, params.RegisteredGasLimit, vmconfig) + err = api.eth.BlockChain().ValidatePayload(block, feeRecipient, expectedProfit, params.RegisteredGasLimit, *api.eth.BlockChain().GetVMConfig()) if err != nil { log.Error("invalid payload", "hash", payload.BlockHash.String(), "number", payload.BlockNumber, "parentHash", payload.ParentHash.String(), "err", err) return err } - if api.accessVerifier != nil && tracer != nil { - if err := api.accessVerifier.verifyTraces(tracer); err != nil { - return err - } - } - log.Info("validated block", "hash", block.Hash(), "number", block.NumberU64(), "parentHash", block.ParentHash()) return nil }