Skip to content
This repository was archived by the owner on Oct 25, 2024. It is now read-only.

Commit 507f9fc

Browse files
dvushavalonche
authored andcommitted
add miner blocklist (#21)
1 parent 5173924 commit 507f9fc

File tree

3 files changed

+141
-8
lines changed

3 files changed

+141
-8
lines changed

cmd/utils/flags.go

+17
Original file line numberDiff line numberDiff line change
@@ -578,6 +578,12 @@ var (
578578
Value: "0x870e2734DdBe2Fba9864f33f3420d59Bc641f2be",
579579
Category: flags.MinerCategory,
580580
}
581+
MinerBlocklistFileFlag = &cli.StringFlag{
582+
Name: "miner.blocklist",
583+
Usage: "flashbots - Path to JSON file with list of blocked addresses. Miner will ignore txs that touch mentioned addresses.",
584+
Value: "",
585+
Category: flags.MinerCategory,
586+
}
581587

582588
// Account settings
583589
UnlockedAccountFlag = &cli.StringFlag{
@@ -1759,6 +1765,17 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
17591765
}
17601766
}
17611767
log.Info("Trusted relays set as", "addresses", cfg.TrustedRelays)
1768+
1769+
if ctx.IsSet(MinerBlocklistFileFlag.Name) {
1770+
bytes, err := os.ReadFile(ctx.String(MinerBlocklistFileFlag.Name))
1771+
if err != nil {
1772+
Fatalf("Failed to read blocklist file: %s", err)
1773+
}
1774+
1775+
if err := json.Unmarshal(bytes, &cfg.Blocklist); err != nil {
1776+
Fatalf("Failed to parse blocklist: %s", err)
1777+
}
1778+
}
17621779
}
17631780

17641781
func setRequiredBlocks(ctx *cli.Context, cfg *ethconfig.Config) {
+69
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
// Copyright 2022 flashbots
2+
// This file is part of the go-ethereum library.
3+
//
4+
// The go-ethereum library is free software: you can redistribute it and/or modify
5+
// it under the terms of the GNU Lesser General Public License as published by
6+
// the Free Software Foundation, either version 3 of the License, or
7+
// (at your option) any later version.
8+
//
9+
// The go-ethereum library is distributed in the hope that it will be useful,
10+
// but WITHOUT ANY WARRANTY; without even the implied warranty of
11+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12+
// GNU Lesser General Public License for more details.
13+
//
14+
// You should have received a copy of the GNU Lesser General Public License
15+
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
16+
17+
package logger
18+
19+
import (
20+
"github.com/ethereum/go-ethereum/common"
21+
"github.com/ethereum/go-ethereum/core/vm"
22+
"math/big"
23+
"time"
24+
)
25+
26+
type AccountTouchTracer struct {
27+
touched map[common.Address]struct{}
28+
}
29+
30+
// NewAccountTouchTracer creates new AccountTouchTracer
31+
// that collect all addresses touched in the given tx
32+
// including tx sender and tx.to from the top level call
33+
func NewAccountTouchTracer() *AccountTouchTracer {
34+
return &AccountTouchTracer{
35+
touched: map[common.Address]struct{}{},
36+
}
37+
}
38+
39+
func (t *AccountTouchTracer) TouchedAddresses() []common.Address {
40+
result := make([]common.Address, 0, len(t.touched))
41+
42+
for address := range t.touched {
43+
result = append(result, address)
44+
}
45+
return result
46+
}
47+
48+
func (t *AccountTouchTracer) CaptureTxStart(uint64) {}
49+
50+
func (t *AccountTouchTracer) CaptureTxEnd(uint64) {}
51+
52+
func (t *AccountTouchTracer) CaptureStart(_ *vm.EVM, from common.Address, to common.Address, _ bool, _ []byte, _ uint64, _ *big.Int) {
53+
t.touched[from] = struct{}{}
54+
t.touched[to] = struct{}{}
55+
}
56+
57+
func (t *AccountTouchTracer) CaptureEnd([]byte, uint64, time.Duration, error) {}
58+
59+
func (t *AccountTouchTracer) CaptureEnter(_ vm.OpCode, _ common.Address, to common.Address, _ []byte, _ uint64, _ *big.Int) {
60+
t.touched[to] = struct{}{}
61+
}
62+
63+
func (t *AccountTouchTracer) CaptureExit([]byte, uint64, error) {}
64+
65+
func (t *AccountTouchTracer) CaptureState(uint64, vm.OpCode, uint64, uint64, *vm.ScopeContext, []byte, int, error) {
66+
}
67+
68+
func (t *AccountTouchTracer) CaptureFault(uint64, vm.OpCode, uint64, uint64, *vm.ScopeContext, int, error) {
69+
}

miner/worker.go

+55-8
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,7 @@ import (
3737
"github.com/ethereum/go-ethereum/core/state"
3838
"github.com/ethereum/go-ethereum/core/types"
3939
"github.com/ethereum/go-ethereum/crypto"
40+
"github.com/ethereum/go-ethereum/eth/tracers/logger"
4041
"github.com/ethereum/go-ethereum/event"
4142
"github.com/ethereum/go-ethereum/log"
4243
"github.com/ethereum/go-ethereum/params"
@@ -210,6 +211,7 @@ type worker struct {
210211
engine consensus.Engine
211212
eth Backend
212213
chain *core.BlockChain
214+
blockList map[common.Address]struct{}
213215

214216
// Feeds
215217
pendingLogsFeed event.Feed
@@ -330,6 +332,11 @@ func newWorker(config *Config, chainConfig *params.ChainConfig, engine consensus
330332
}()
331333
}
332334

335+
blockList := make(map[common.Address]struct{})
336+
for _, address := range config.Blocklist {
337+
blockList[address] = struct{}{}
338+
}
339+
333340
worker := &worker{
334341
config: config,
335342
chainConfig: chainConfig,
@@ -957,22 +964,47 @@ func (w *worker) updateSnapshot(env *environment) {
957964
}
958965

959966
func (w *worker) commitTransaction(env *environment, tx *types.Transaction) ([]*types.Log, error) {
960-
var (
961-
snap = env.state.Snapshot()
962-
gp = env.gasPool.Gas()
963-
)
967+
gasPool := *env.gasPool
968+
envGasUsed := env.header.GasUsed
969+
var stateDB *state.StateDB
970+
if len(w.blockList) != 0 {
971+
stateDB = env.state.Copy()
972+
} else {
973+
stateDB = env.state
974+
}
975+
976+
snapshot := stateDB.Snapshot()
964977

965978
gasPrice, err := tx.EffectiveGasTip(env.header.BaseFee)
966979
if err != nil {
967980
return nil, err
968981
}
969982

970-
receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, env.gasPool, env.state, env.header, tx, &env.header.GasUsed, *w.chain.GetVMConfig())
983+
var tracer *logger.AccountTouchTracer
984+
config := *w.chain.GetVMConfig()
985+
if len(w.blockList) != 0 {
986+
tracer = logger.NewAccountTouchTracer()
987+
config.Tracer = tracer
988+
config.Debug = true
989+
}
990+
991+
receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, &gasPool, stateDB, env.header, tx, &envGasUsed, config)
971992
if err != nil {
972-
env.state.RevertToSnapshot(snap)
973-
env.gasPool.SetGas(gp)
993+
stateDB.RevertToSnapshot(snapshot)
974994
return nil, err
975995
}
996+
if len(w.blockList) != 0 {
997+
for _, address := range tracer.TouchedAddresses() {
998+
if _, in := w.blockList[address]; in {
999+
return nil, errBlocklistViolation
1000+
}
1001+
}
1002+
}
1003+
1004+
*env.gasPool = gasPool
1005+
env.header.GasUsed = envGasUsed
1006+
env.state = stateDB
1007+
9761008
env.txs = append(env.txs, tx)
9771009
env.receipts = append(env.receipts, receipt)
9781010

@@ -1395,6 +1427,7 @@ func (w *worker) generateWork(params *generateParams) (*types.Block, *big.Int, e
13951427
log.Warn("Block building is interrupted", "allowance", common.PrettyDuration(w.newpayloadTimeout))
13961428
}
13971429
blockBundles = mergedBundles
1430+
log.Info("Filled block with transactions", "time", time.Since(start), "gas used", work.header.GasUsed)
13981431
}
13991432
block, err := w.engine.FinalizeAndAssemble(w.chain, work.header, work.state, work.txs, work.unclelist(), work.receipts, params.withdrawals)
14001433
if err != nil {
@@ -1674,13 +1707,27 @@ func (w *worker) computeBundleGas(env *environment, bundle types.MevBundle, stat
16741707
state.Prepare(tx.Hash(), i+currentTxCount)
16751708
coinbaseBalanceBefore := state.GetBalance(env.coinbase)
16761709

1677-
receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, gasPool, state, env.header, tx, &tempGasUsed, *w.chain.GetVMConfig())
1710+
config := *w.chain.GetVMConfig()
1711+
var tracer *logger.AccountTouchTracer
1712+
if len(w.blockList) != 0 {
1713+
tracer = logger.NewAccountTouchTracer()
1714+
config.Tracer = tracer
1715+
config.Debug = true
1716+
}
1717+
receipt, err := core.ApplyTransaction(w.chainConfig, w.chain, &env.coinbase, gasPool, state, env.header, tx, &tempGasUsed, config)
16781718
if err != nil {
16791719
return simulatedBundle{}, err
16801720
}
16811721
if receipt.Status == types.ReceiptStatusFailed && !containsHash(bundle.RevertingTxHashes, receipt.TxHash) {
16821722
return simulatedBundle{}, errors.New("failed tx")
16831723
}
1724+
if len(w.blockList) != 0 {
1725+
for _, address := range tracer.TouchedAddresses() {
1726+
if _, in := w.blockList[address]; in {
1727+
return simulatedBundle{}, errBlocklistViolation
1728+
}
1729+
}
1730+
}
16841731

16851732
totalGasUsed += receipt.GasUsed
16861733

0 commit comments

Comments
 (0)