forked from bnb-chain/bsc
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathapi_mev.go
More file actions
101 lines (83 loc) · 3.38 KB
/
Copy pathapi_mev.go
File metadata and controls
101 lines (83 loc) · 3.38 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
package ethapi
import (
"context"
"fmt"
"time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/params"
)
// MevAPI implements the interfaces that defined in the BEP-322.
// It offers methods for the interaction between builders and validators.
type MevAPI struct {
b Backend
}
// NewMevAPI creates a new MevAPI.
func NewMevAPI(b Backend) *MevAPI {
return &MevAPI{b}
}
// SendBid receives bid from the builders.
// If mev is not running or bid is invalid, return error.
// Otherwise, creates a builder bid for the given argument, submit it to the miner.
func (m *MevAPI) SendBid(ctx context.Context, args types.BidArgs) (common.Hash, error) {
ctx = context.WithValue(ctx, "receiveTime", time.Now().UnixMilli())
if !m.b.MevRunning() {
return common.Hash{}, types.ErrMevNotRunning
}
var (
rawBid = args.RawBid
currentBlock = m.b.CurrentBlock() // `CurrentBlock` might change during use.
)
if rawBid == nil {
return common.Hash{}, types.NewInvalidBidError("rawBid should not be nil")
}
// only support bidding for the next block not for the future block
if latestBlockNumber := currentBlock.Number.Uint64(); rawBid.BlockNumber < latestBlockNumber+1 {
return common.Hash{}, types.NewInvalidBidError(
fmt.Sprintf("stale block number: %d, latest block: %d", rawBid.BlockNumber, latestBlockNumber))
} else if rawBid.BlockNumber > latestBlockNumber+1 {
// For the first block of a validator's turn, the previous block must be imported first.
// If a builder sends bids before the import is complete, the following error message will be returned.
// However, this is not a significant issue because:
// a. Each turn consists of 16 blocks, so this situation can only occur at most 1/16 of the time.
// b. Each builder is allowed to submit multiple bids for each block.
return common.Hash{}, types.NewInvalidBidError(
fmt.Sprintf("block in future: %d, latest block: %d", rawBid.BlockNumber, latestBlockNumber))
} else if !m.b.MinerInTurn() {
return common.Hash{}, types.ErrMevNotInTurn
}
if rawBid.ParentHash != currentBlock.Hash() {
return common.Hash{}, types.NewInvalidBidError(
fmt.Sprintf("non-aligned parent hash: %v", currentBlock.Hash()))
}
if rawBid.GasFee == nil || rawBid.GasFee.Cmp(common.Big0) == 0 || rawBid.GasUsed == 0 {
return common.Hash{}, types.NewInvalidBidError("empty gasFee or empty gasUsed")
}
if rawBid.BuilderFee != nil {
builderFee := rawBid.BuilderFee
if builderFee.Cmp(common.Big0) < 0 {
return common.Hash{}, types.NewInvalidBidError("builder fee should not be less than 0")
}
if builderFee.Cmp(rawBid.GasFee) >= 0 {
return common.Hash{}, types.NewInvalidBidError("builder fee must be less than gas fee")
}
}
if len(args.PayBidTx) == 0 || args.PayBidTxGasUsed == 0 {
return common.Hash{}, types.NewInvalidPayBidTxError("payBidTx and payBidTxGasUsed are must-have")
}
if args.PayBidTxGasUsed > params.PayBidTxGasLimit {
return common.Hash{}, types.NewInvalidBidError(
fmt.Sprintf("transfer tx gas used must be no more than %v", params.PayBidTxGasLimit))
}
return m.b.SendBid(ctx, &args)
}
func (m *MevAPI) Params() *types.MevParams {
return m.b.MevParams()
}
func (m *MevAPI) HasBuilder(builder common.Address) bool {
return m.b.HasBuilder(builder)
}
// Running returns true if mev is running
func (m *MevAPI) Running() bool {
return m.b.MevRunning()
}