Skip to content

Commit fc07ef8

Browse files
bogatyygreg7mdp
authored andcommitted
Flashbots changes v0.3 to v0.4
1 parent bd1a953 commit fc07ef8

File tree

13 files changed

+243
-28
lines changed

13 files changed

+243
-28
lines changed

README.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ See [here](https://docs.flashbots.net) for Flashbots documentation.
2020

2121
| Version | Spec |
2222
| ------- | ------------------------------------------------------------------------------------------- |
23+
| v0.4 | [MEV-Geth Spec v0.4](https://docs.flashbots.net/flashbots-auction/miners/mev-geth-spec/v04) |
2324
| v0.3 | [MEV-Geth Spec v0.3](https://docs.flashbots.net/flashbots-auction/miners/mev-geth-spec/v03) |
2425
| v0.2 | [MEV-Geth Spec v0.2](https://docs.flashbots.net/flashbots-auction/miners/mev-geth-spec/v02) |
2526
| v0.1 | [MEV-Geth Spec v0.1](https://docs.flashbots.net/flashbots-auction/miners/mev-geth-spec/v01) |

cmd/geth/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ var (
125125
utils.MinerExtraDataFlag,
126126
utils.MinerRecommitIntervalFlag,
127127
utils.MinerNoVerifyFlag,
128-
utils.MinerMaxMergedBundles,
128+
utils.MinerMaxMergedBundlesFlag,
129+
utils.MinerTrustedRelaysFlag,
129130
utils.NATFlag,
130131
utils.NoDiscoverFlag,
131132
utils.DiscoveryV5Flag,

cmd/geth/usage.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -187,7 +187,8 @@ var AppHelpFlagGroups = []flags.FlagGroup{
187187
utils.MinerExtraDataFlag,
188188
utils.MinerRecommitIntervalFlag,
189189
utils.MinerNoVerifyFlag,
190-
utils.MinerMaxMergedBundles,
190+
utils.MinerMaxMergedBundlesFlag,
191+
utils.MinerTrustedRelaysFlag,
191192
},
192193
},
193194
{

cmd/utils/flags.go

Lines changed: 26 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -460,11 +460,16 @@ var (
460460
Usage: "Time interval to recreate the block being mined",
461461
Value: ethconfig.Defaults.Miner.Recommit,
462462
}
463-
MinerMaxMergedBundles = cli.IntFlag{
463+
MinerMaxMergedBundlesFlag = cli.IntFlag{
464464
Name: "miner.maxmergedbundles",
465465
Usage: "flashbots - The maximum amount of bundles to merge. The miner will run this many workers in parallel to calculate if the full block is more profitable with these additional bundles.",
466466
Value: 3,
467467
}
468+
MinerTrustedRelaysFlag = cli.StringFlag{
469+
Name: "miner.trustedrelays",
470+
Usage: "flashbots - The Ethereum addresses of trusted relays for signature verification. The miner will accept signed bundles and other tasks from the relay, being reasonably certain about DDoS safety.",
471+
Value: "0x870e2734DdBe2Fba9864f33f3420d59Bc641f2be",
472+
}
468473
MinerNoVerifyFlag = cli.BoolFlag{
469474
Name: "miner.noverify",
470475
Usage: "Disable remote sealing verification",
@@ -1338,6 +1343,15 @@ func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
13381343
if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
13391344
cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
13401345
}
1346+
1347+
addresses := strings.Split(ctx.GlobalString(MinerTrustedRelaysFlag.Name), ",")
1348+
for _, address := range addresses {
1349+
if trimmed := strings.TrimSpace(address); !common.IsHexAddress(trimmed) {
1350+
Fatalf("Invalid account in --miner.trustedrelays: %s", trimmed)
1351+
} else {
1352+
cfg.TrustedRelays = append(cfg.TrustedRelays, common.HexToAddress(trimmed))
1353+
}
1354+
}
13411355
}
13421356

13431357
func setEthash(ctx *cli.Context, cfg *ethconfig.Config) {
@@ -1391,7 +1405,17 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
13911405
log.Warn("The generic --miner.gastarget flag is deprecated and will be removed in the future!")
13921406
}
13931407

1394-
cfg.MaxMergedBundles = ctx.GlobalInt(MinerMaxMergedBundles.Name)
1408+
cfg.MaxMergedBundles = ctx.GlobalInt(MinerMaxMergedBundlesFlag.Name)
1409+
1410+
addresses := strings.Split(ctx.GlobalString(MinerTrustedRelaysFlag.Name), ",")
1411+
for _, address := range addresses {
1412+
if trimmed := strings.TrimSpace(address); !common.IsHexAddress(trimmed) {
1413+
Fatalf("Invalid account in --miner.trustedrelays: %s", trimmed)
1414+
} else {
1415+
cfg.TrustedRelays = append(cfg.TrustedRelays, common.HexToAddress(trimmed))
1416+
}
1417+
}
1418+
log.Info("Trusted relays set as", "addresses", cfg.TrustedRelays)
13951419
}
13961420

13971421
func setWhitelist(ctx *cli.Context, cfg *ethconfig.Config) {

core/tx_pool.go

Lines changed: 56 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -165,6 +165,8 @@ type TxPoolConfig struct {
165165
GlobalQueue uint64 // Maximum number of non-executable transaction slots for all accounts
166166

167167
Lifetime time.Duration // Maximum amount of time non-executable transaction are queued
168+
169+
TrustedRelays []common.Address // Trusted relay addresses. Duplicated from the miner config.
168170
}
169171

170172
// DefaultTxPoolConfig contains the default configurations for the transaction
@@ -251,12 +253,13 @@ type TxPool struct {
251253
locals *accountSet // Set of local transaction to exempt from eviction rules
252254
journal *txJournal // Journal of local transaction to back up to disk
253255

254-
pending map[common.Address]*txList // All currently processable transactions
255-
queue map[common.Address]*txList // Queued but non-processable transactions
256-
beats map[common.Address]time.Time // Last heartbeat from each known account
257-
mevBundles []types.MevBundle
258-
all *txLookup // All transactions to allow lookups
259-
priced *txPricedList // All transactions sorted by price
256+
pending map[common.Address]*txList // All currently processable transactions
257+
queue map[common.Address]*txList // Queued but non-processable transactions
258+
beats map[common.Address]time.Time // Last heartbeat from each known account
259+
mevBundles []types.MevBundle
260+
megabundles map[common.Address]types.MevBundle // One megabundle per each trusted relay
261+
all *txLookup // All transactions to allow lookups
262+
priced *txPricedList // All transactions sorted by price
260263

261264
chainHeadCh chan ChainHeadEvent
262265
chainHeadSub event.Subscription
@@ -290,6 +293,7 @@ func NewTxPool(config TxPoolConfig, chainconfig *params.ChainConfig, chain block
290293
pending: make(map[common.Address]*txList),
291294
queue: make(map[common.Address]*txList),
292295
beats: make(map[common.Address]time.Time),
296+
megabundles: make(map[common.Address]types.MevBundle),
293297
all: newTxLookup(),
294298
chainHeadCh: make(chan ChainHeadEvent, chainHeadChanSize),
295299
reqResetCh: make(chan *txpoolResetRequest),
@@ -611,6 +615,52 @@ func (pool *TxPool) AddMevBundle(txs types.Transactions, blockNumber *big.Int, m
611615
return nil
612616
}
613617

618+
// AddMegaBundle adds a megabundle to the pool. Assumes the relay signature has been verified already.
619+
func (pool *TxPool) AddMegabundle(relayAddr common.Address, txs types.Transactions, blockNumber *big.Int, minTimestamp, maxTimestamp uint64, revertingTxHashes []common.Hash) error {
620+
pool.mu.Lock()
621+
defer pool.mu.Unlock()
622+
623+
fromTrustedRelay := false
624+
for _, trustedAddr := range pool.config.TrustedRelays {
625+
if relayAddr == trustedAddr {
626+
fromTrustedRelay = true
627+
}
628+
}
629+
if !fromTrustedRelay {
630+
return errors.New("megabundle from non-trusted address")
631+
}
632+
633+
pool.megabundles[relayAddr] = types.MevBundle{
634+
Txs: txs,
635+
BlockNumber: blockNumber,
636+
MinTimestamp: minTimestamp,
637+
MaxTimestamp: maxTimestamp,
638+
RevertingTxHashes: revertingTxHashes,
639+
}
640+
return nil
641+
}
642+
643+
// GetMegabundle returns the latest megabundle submitted by a given relay.
644+
func (pool *TxPool) GetMegabundle(relayAddr common.Address, blockNumber *big.Int, blockTimestamp uint64) (types.MevBundle, error) {
645+
pool.mu.Lock()
646+
defer pool.mu.Unlock()
647+
648+
megabundle, ok := pool.megabundles[relayAddr]
649+
if !ok {
650+
return types.MevBundle{}, errors.New("No megabundle found")
651+
}
652+
if megabundle.BlockNumber.Cmp(blockNumber) != 0 {
653+
return types.MevBundle{}, errors.New("Megabundle does not fit blockNumber constraints")
654+
}
655+
if megabundle.MinTimestamp != 0 && megabundle.MinTimestamp > blockTimestamp {
656+
return types.MevBundle{}, errors.New("Megabundle does not fit minTimestamp constraints")
657+
}
658+
if megabundle.MaxTimestamp != 0 && megabundle.MaxTimestamp < blockTimestamp {
659+
return types.MevBundle{}, errors.New("Megabundle does not fit maxTimestamp constraints")
660+
}
661+
return megabundle, nil
662+
}
663+
614664
// Locals retrieves the accounts currently considered local by the pool.
615665
func (pool *TxPool) Locals() []common.Address {
616666
pool.mu.Lock()

eth/api_backend.go

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -243,6 +243,10 @@ func (b *EthAPIBackend) SendBundle(ctx context.Context, txs types.Transactions,
243243
return b.eth.txPool.AddMevBundle(txs, big.NewInt(blockNumber.Int64()), minTimestamp, maxTimestamp, revertingTxHashes)
244244
}
245245

246+
func (b *EthAPIBackend) SendMegabundle(ctx context.Context, txs types.Transactions, blockNumber rpc.BlockNumber, minTimestamp uint64, maxTimestamp uint64, revertingTxHashes []common.Hash, relayAddr common.Address) error {
247+
return b.eth.txPool.AddMegabundle(relayAddr, txs, big.NewInt(blockNumber.Int64()), minTimestamp, maxTimestamp, revertingTxHashes)
248+
}
249+
246250
func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
247251
pending := b.eth.txPool.Pending(false)
248252
var txs types.Transactions

internal/ethapi/api.go

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2085,7 +2085,7 @@ func NewPrivateTxBundleAPI(b Backend) *PrivateTxBundleAPI {
20852085
return &PrivateTxBundleAPI{b}
20862086
}
20872087

2088-
// SendBundleArgs represents the arguments for a call.
2088+
// SendBundleArgs represents the arguments for a SendBundle call.
20892089
type SendBundleArgs struct {
20902090
Txs []hexutil.Bytes `json:"txs"`
20912091
BlockNumber rpc.BlockNumber `json:"blockNumber"`
@@ -2094,6 +2094,25 @@ type SendBundleArgs struct {
20942094
RevertingTxHashes []common.Hash `json:"revertingTxHashes"`
20952095
}
20962096

2097+
// SendMegabundleArgs represents the arguments for a SendMegabundle call.
2098+
type SendMegabundleArgs struct {
2099+
Txs []hexutil.Bytes `json:"txs"`
2100+
BlockNumber uint64 `json:"blockNumber"`
2101+
MinTimestamp *uint64 `json:"minTimestamp"`
2102+
MaxTimestamp *uint64 `json:"maxTimestamp"`
2103+
RevertingTxHashes []common.Hash `json:"revertingTxHashes"`
2104+
RelaySignature hexutil.Bytes `json:"relaySignature"`
2105+
}
2106+
2107+
// UnsignedMegabundle is used for serialization and subsequent digital signing.
2108+
type UnsignedMegabundle struct {
2109+
Txs []hexutil.Bytes
2110+
BlockNumber uint64
2111+
MinTimestamp uint64
2112+
MaxTimestamp uint64
2113+
RevertingTxHashes []common.Hash
2114+
}
2115+
20972116
// SendBundle will add the signed transaction to the transaction pool.
20982117
// The sender is responsible for signing the transaction and using the correct nonce and ensuring validity
20992118
func (s *PrivateTxBundleAPI) SendBundle(ctx context.Context, args SendBundleArgs) error {
@@ -2123,3 +2142,58 @@ func (s *PrivateTxBundleAPI) SendBundle(ctx context.Context, args SendBundleArgs
21232142

21242143
return s.b.SendBundle(ctx, txs, args.BlockNumber, minTimestamp, maxTimestamp, args.RevertingTxHashes)
21252144
}
2145+
2146+
// Recovers the Ethereum address of the trusted relay that signed the megabundle.
2147+
func RecoverRelayAddress(args SendMegabundleArgs) (common.Address, error) {
2148+
megabundle := UnsignedMegabundle{Txs: args.Txs, BlockNumber: args.BlockNumber, RevertingTxHashes: args.RevertingTxHashes}
2149+
if args.MinTimestamp != nil {
2150+
megabundle.MinTimestamp = *args.MinTimestamp
2151+
} else {
2152+
megabundle.MinTimestamp = 0
2153+
}
2154+
if args.MaxTimestamp != nil {
2155+
megabundle.MaxTimestamp = *args.MaxTimestamp
2156+
} else {
2157+
megabundle.MaxTimestamp = 0
2158+
}
2159+
rlpEncoding, _ := rlp.EncodeToBytes(megabundle)
2160+
signature := args.RelaySignature
2161+
signature[64] -= 27 // account for Ethereum V
2162+
recoveredPubkey, err := crypto.SigToPub(accounts.TextHash(rlpEncoding), args.RelaySignature)
2163+
if err != nil {
2164+
return common.Address{}, err
2165+
}
2166+
return crypto.PubkeyToAddress(*recoveredPubkey), nil
2167+
}
2168+
2169+
// SendMegabundle will add the signed megabundle to one of the workers for evaluation.
2170+
func (s *PrivateTxBundleAPI) SendMegabundle(ctx context.Context, args SendMegabundleArgs) error {
2171+
log.Info("Received a Megabundle request", "signature", args.RelaySignature)
2172+
var txs types.Transactions
2173+
if len(args.Txs) == 0 {
2174+
return errors.New("megabundle missing txs")
2175+
}
2176+
if args.BlockNumber == 0 {
2177+
return errors.New("megabundle missing blockNumber")
2178+
}
2179+
for _, encodedTx := range args.Txs {
2180+
tx := new(types.Transaction)
2181+
if err := tx.UnmarshalBinary(encodedTx); err != nil {
2182+
return err
2183+
}
2184+
txs = append(txs, tx)
2185+
}
2186+
var minTimestamp, maxTimestamp uint64
2187+
if args.MinTimestamp != nil {
2188+
minTimestamp = *args.MinTimestamp
2189+
}
2190+
if args.MaxTimestamp != nil {
2191+
maxTimestamp = *args.MaxTimestamp
2192+
}
2193+
relayAddr, err := RecoverRelayAddress(args)
2194+
log.Info("Megabundle", "relayAddr", relayAddr, "err", err)
2195+
if err != nil {
2196+
return err
2197+
}
2198+
return s.b.SendMegabundle(ctx, txs, rpc.BlockNumber(args.BlockNumber), minTimestamp, maxTimestamp, args.RevertingTxHashes, relayAddr)
2199+
}

internal/ethapi/backend.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,7 @@ type Backend interface {
7575
// Transaction pool API
7676
SendTx(ctx context.Context, signedTx *types.Transaction) error
7777
SendBundle(ctx context.Context, txs types.Transactions, blockNumber rpc.BlockNumber, minTimestamp uint64, maxTimestamp uint64, revertingTxHashes []common.Hash) error
78+
SendMegabundle(ctx context.Context, txs types.Transactions, blockNumber rpc.BlockNumber, minTimestamp uint64, maxTimestamp uint64, revertingTxHashes []common.Hash, relayAddr common.Address) error
7879
GetTransaction(ctx context.Context, txHash common.Hash) (*types.Transaction, common.Hash, uint64, uint64, error)
7980
GetPoolTransactions() (types.Transactions, error)
8081
GetPoolTransaction(txHash common.Hash) *types.Transaction

internal/web3ext/web3ext.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -581,6 +581,11 @@ web3._extend({
581581
call: 'eth_sendBundle',
582582
params: 1
583583
}),
584+
new web3._extend.Method({
585+
name: 'sendMegabundle',
586+
call: 'eth_sendMegabundle',
587+
params: 1
588+
}),
584589
],
585590
properties: [
586591
new web3._extend.Property({

les/api_backend.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -198,10 +198,15 @@ func (b *LesApiBackend) SendTx(ctx context.Context, signedTx *types.Transaction)
198198
func (b *LesApiBackend) RemoveTx(txHash common.Hash) {
199199
b.eth.txPool.RemoveTx(txHash)
200200
}
201+
201202
func (b *LesApiBackend) SendBundle(ctx context.Context, txs types.Transactions, blockNumber rpc.BlockNumber, minTimestamp uint64, maxTimestamp uint64, revertingTxHashes []common.Hash) error {
202203
return b.eth.txPool.AddMevBundle(txs, big.NewInt(blockNumber.Int64()), minTimestamp, maxTimestamp, revertingTxHashes)
203204
}
204205

206+
func (b *LesApiBackend) SendMegabundle(ctx context.Context, txs types.Transactions, blockNumber rpc.BlockNumber, minTimestamp uint64, maxTimestamp uint64, revertingTxHashes []common.Hash, relayAddr common.Address) error {
207+
return nil
208+
}
209+
205210
func (b *LesApiBackend) GetPoolTransactions() (types.Transactions, error) {
206211
return b.eth.txPool.GetTransactions()
207212
}

0 commit comments

Comments
 (0)