Skip to content
This repository was archived by the owner on Sep 6, 2022. It is now read-only.

Commit eb321d8

Browse files
bogatyyRuteri
authored andcommitted
Flashbots changes v0.3 to v0.4
1 parent 7395f3f commit eb321d8

File tree

12 files changed

+240
-26
lines changed

12 files changed

+240
-26
lines changed

cmd/geth/main.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,8 @@ var (
131131
utils.MinerExtraDataFlag,
132132
utils.MinerRecommitIntervalFlag,
133133
utils.MinerNoVerifyFlag,
134-
utils.MinerMaxMergedBundles,
134+
utils.MinerMaxMergedBundlesFlag,
135+
utils.MinerTrustedRelaysFlag,
135136
utils.NATFlag,
136137
utils.NoDiscoverFlag,
137138
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
@@ -490,11 +490,16 @@ var (
490490
Usage: "Time interval to recreate the block being mined",
491491
Value: ethconfig.Defaults.Miner.Recommit,
492492
}
493-
MinerMaxMergedBundles = cli.IntFlag{
493+
MinerMaxMergedBundlesFlag = cli.IntFlag{
494494
Name: "miner.maxmergedbundles",
495495
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.",
496496
Value: 3,
497497
}
498+
MinerTrustedRelaysFlag = cli.StringFlag{
499+
Name: "miner.trustedrelays",
500+
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.",
501+
Value: "0x870e2734DdBe2Fba9864f33f3420d59Bc641f2be",
502+
}
498503
MinerNoVerifyFlag = cli.BoolFlag{
499504
Name: "miner.noverify",
500505
Usage: "Disable remote sealing verification",
@@ -1461,6 +1466,15 @@ func setTxPool(ctx *cli.Context, cfg *core.TxPoolConfig) {
14611466
if ctx.GlobalIsSet(TxPoolLifetimeFlag.Name) {
14621467
cfg.Lifetime = ctx.GlobalDuration(TxPoolLifetimeFlag.Name)
14631468
}
1469+
1470+
addresses := strings.Split(ctx.GlobalString(MinerTrustedRelaysFlag.Name), ",")
1471+
for _, address := range addresses {
1472+
if trimmed := strings.TrimSpace(address); !common.IsHexAddress(trimmed) {
1473+
Fatalf("Invalid account in --miner.trustedrelays: %s", trimmed)
1474+
} else {
1475+
cfg.TrustedRelays = append(cfg.TrustedRelays, common.HexToAddress(trimmed))
1476+
}
1477+
}
14641478
}
14651479

14661480
func setEthash(ctx *cli.Context, cfg *ethconfig.Config) {
@@ -1514,7 +1528,17 @@ func setMiner(ctx *cli.Context, cfg *miner.Config) {
15141528
log.Warn("The generic --miner.gastarget flag is deprecated and will be removed in the future!")
15151529
}
15161530

1517-
cfg.MaxMergedBundles = ctx.GlobalInt(MinerMaxMergedBundles.Name)
1531+
cfg.MaxMergedBundles = ctx.GlobalInt(MinerMaxMergedBundlesFlag.Name)
1532+
1533+
addresses := strings.Split(ctx.GlobalString(MinerTrustedRelaysFlag.Name), ",")
1534+
for _, address := range addresses {
1535+
if trimmed := strings.TrimSpace(address); !common.IsHexAddress(trimmed) {
1536+
Fatalf("Invalid account in --miner.trustedrelays: %s", trimmed)
1537+
} else {
1538+
cfg.TrustedRelays = append(cfg.TrustedRelays, common.HexToAddress(trimmed))
1539+
}
1540+
}
1541+
log.Info("Trusted relays set as", "addresses", cfg.TrustedRelays)
15181542
}
15191543

15201544
func setRequiredBlocks(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
@@ -250,6 +250,10 @@ func (b *EthAPIBackend) SendBundle(ctx context.Context, txs types.Transactions,
250250
return b.eth.txPool.AddMevBundle(txs, big.NewInt(blockNumber.Int64()), minTimestamp, maxTimestamp, revertingTxHashes)
251251
}
252252

253+
func (b *EthAPIBackend) SendMegabundle(ctx context.Context, txs types.Transactions, blockNumber rpc.BlockNumber, minTimestamp uint64, maxTimestamp uint64, revertingTxHashes []common.Hash, relayAddr common.Address) error {
254+
return b.eth.txPool.AddMegabundle(relayAddr, txs, big.NewInt(blockNumber.Int64()), minTimestamp, maxTimestamp, revertingTxHashes)
255+
}
256+
253257
func (b *EthAPIBackend) GetPoolTransactions() (types.Transactions, error) {
254258
pending := b.eth.txPool.Pending(false)
255259
var txs types.Transactions

internal/ethapi/api.go

Lines changed: 75 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2056,7 +2056,7 @@ func NewPrivateTxBundleAPI(b Backend) *PrivateTxBundleAPI {
20562056
return &PrivateTxBundleAPI{b}
20572057
}
20582058

2059-
// SendBundleArgs represents the arguments for a call.
2059+
// SendBundleArgs represents the arguments for a SendBundle call.
20602060
type SendBundleArgs struct {
20612061
Txs []hexutil.Bytes `json:"txs"`
20622062
BlockNumber rpc.BlockNumber `json:"blockNumber"`
@@ -2065,6 +2065,25 @@ type SendBundleArgs struct {
20652065
RevertingTxHashes []common.Hash `json:"revertingTxHashes"`
20662066
}
20672067

2068+
// SendMegabundleArgs represents the arguments for a SendMegabundle call.
2069+
type SendMegabundleArgs struct {
2070+
Txs []hexutil.Bytes `json:"txs"`
2071+
BlockNumber uint64 `json:"blockNumber"`
2072+
MinTimestamp *uint64 `json:"minTimestamp"`
2073+
MaxTimestamp *uint64 `json:"maxTimestamp"`
2074+
RevertingTxHashes []common.Hash `json:"revertingTxHashes"`
2075+
RelaySignature hexutil.Bytes `json:"relaySignature"`
2076+
}
2077+
2078+
// UnsignedMegabundle is used for serialization and subsequent digital signing.
2079+
type UnsignedMegabundle struct {
2080+
Txs []hexutil.Bytes
2081+
BlockNumber uint64
2082+
MinTimestamp uint64
2083+
MaxTimestamp uint64
2084+
RevertingTxHashes []common.Hash
2085+
}
2086+
20682087
// SendBundle will add the signed transaction to the transaction pool.
20692088
// The sender is responsible for signing the transaction and using the correct nonce and ensuring validity
20702089
func (s *PrivateTxBundleAPI) SendBundle(ctx context.Context, args SendBundleArgs) error {
@@ -2094,3 +2113,58 @@ func (s *PrivateTxBundleAPI) SendBundle(ctx context.Context, args SendBundleArgs
20942113

20952114
return s.b.SendBundle(ctx, txs, args.BlockNumber, minTimestamp, maxTimestamp, args.RevertingTxHashes)
20962115
}
2116+
2117+
// Recovers the Ethereum address of the trusted relay that signed the megabundle.
2118+
func RecoverRelayAddress(args SendMegabundleArgs) (common.Address, error) {
2119+
megabundle := UnsignedMegabundle{Txs: args.Txs, BlockNumber: args.BlockNumber, RevertingTxHashes: args.RevertingTxHashes}
2120+
if args.MinTimestamp != nil {
2121+
megabundle.MinTimestamp = *args.MinTimestamp
2122+
} else {
2123+
megabundle.MinTimestamp = 0
2124+
}
2125+
if args.MaxTimestamp != nil {
2126+
megabundle.MaxTimestamp = *args.MaxTimestamp
2127+
} else {
2128+
megabundle.MaxTimestamp = 0
2129+
}
2130+
rlpEncoding, _ := rlp.EncodeToBytes(megabundle)
2131+
signature := args.RelaySignature
2132+
signature[64] -= 27 // account for Ethereum V
2133+
recoveredPubkey, err := crypto.SigToPub(accounts.TextHash(rlpEncoding), args.RelaySignature)
2134+
if err != nil {
2135+
return common.Address{}, err
2136+
}
2137+
return crypto.PubkeyToAddress(*recoveredPubkey), nil
2138+
}
2139+
2140+
// SendMegabundle will add the signed megabundle to one of the workers for evaluation.
2141+
func (s *PrivateTxBundleAPI) SendMegabundle(ctx context.Context, args SendMegabundleArgs) error {
2142+
log.Info("Received a Megabundle request", "signature", args.RelaySignature)
2143+
var txs types.Transactions
2144+
if len(args.Txs) == 0 {
2145+
return errors.New("megabundle missing txs")
2146+
}
2147+
if args.BlockNumber == 0 {
2148+
return errors.New("megabundle missing blockNumber")
2149+
}
2150+
for _, encodedTx := range args.Txs {
2151+
tx := new(types.Transaction)
2152+
if err := tx.UnmarshalBinary(encodedTx); err != nil {
2153+
return err
2154+
}
2155+
txs = append(txs, tx)
2156+
}
2157+
var minTimestamp, maxTimestamp uint64
2158+
if args.MinTimestamp != nil {
2159+
minTimestamp = *args.MinTimestamp
2160+
}
2161+
if args.MaxTimestamp != nil {
2162+
maxTimestamp = *args.MaxTimestamp
2163+
}
2164+
relayAddr, err := RecoverRelayAddress(args)
2165+
log.Info("Megabundle", "relayAddr", relayAddr, "err", err)
2166+
if err != nil {
2167+
return err
2168+
}
2169+
return s.b.SendMegabundle(ctx, txs, rpc.BlockNumber(args.BlockNumber), minTimestamp, maxTimestamp, args.RevertingTxHashes, relayAddr)
2170+
}

internal/ethapi/backend.go

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

internal/web3ext/web3ext.go

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -600,6 +600,11 @@ web3._extend({
600600
call: 'eth_sendBundle',
601601
params: 1,
602602
}),
603+
new web3._extend.Method({
604+
name: 'sendMegabundle',
605+
call: 'eth_sendMegabundle',
606+
params: 1
607+
}),
603608
],
604609
properties: [
605610
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
}

miner/miner.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,7 @@ type Config struct {
5555
Recommit time.Duration // The time interval for miner to re-create mining work.
5656
Noverify bool // Disable remote mining solution verification(only useful in ethash).
5757
MaxMergedBundles int
58+
TrustedRelays []common.Address `toml:",omitempty"` // Trusted relay addresses to receive tasks from.
5859
}
5960

6061
// Miner creates blocks and searches for proof-of-work values.

0 commit comments

Comments
 (0)