Documentation ¶
Overview ¶
Package mevshare implements mev share node Here is a full flow of data through the node:
bundle-relay-api -> API sends:
- private transaction
- mev share bundle
API -> SimQueue schedules simulation SimQueue -> SimulationWorker calls with the next simulation to process
SimulationWorker -> SimulationBackend is used to do simulation SimulationWorker -> SimulationResultBackend is used to consume simulation result
SimulationResultBackend -> RedisHintBackend is used to send hint to hint-relay-api SimulationResultBackend -> BuilderBackend is used to send bundle to the builders
Index ¶
- Constants
- Variables
- func Intersect(a, b []string) []string
- func MergeBuilders(topLevel, inner *MevBundlePrivacy)
- func MergeInclusionIntervals(topLevel, inner *MevBundleInclusion) error
- func MergePrivacyBuilders(bundle *SendMevBundleArgs)
- func RoundUpWithPrecision(number *big.Int, precisionDigits int) *big.Int
- func ValidateBundle(bundle *SendMevBundleArgs, currentBlock uint64, signer types.Signer) (hash common.Hash, unmatched bool, err error)
- type API
- func (m *API) CancelBundleByHash(ctx context.Context, hash common.Hash) (err error)
- func (m *API) SendBundle(ctx context.Context, bundle SendMevBundleArgs) (_ SendMevBundleResponse, err error)
- func (m *API) SimBundle(ctx context.Context, bundle SendMevBundleArgs, aux SimMevBundleAuxArgs) (_ *SimMevBundleResponse, err error)
- type BuilderAPI
- type BuilderBackend
- type BuildersBackend
- type BuildersConfig
- type BundleStorage
- type CleanLog
- type DBBackend
- func (b *DBBackend) CancelBundleByHash(ctx context.Context, hash common.Hash, signer common.Address) error
- func (b *DBBackend) Close() error
- func (b *DBBackend) GetBundleByMatchingHash(ctx context.Context, hash common.Hash) (*SendMevBundleArgs, error)
- func (b *DBBackend) InsertBundleForBuilder(ctx context.Context, bundle *SendMevBundleArgs, result *SimMevBundleResponse, ...) error
- func (b *DBBackend) InsertBundleForStats(ctx context.Context, bundle *SendMevBundleArgs, result *SimMevBundleResponse) (known bool, err error)
- func (b *DBBackend) InsertHistoricalHint(ctx context.Context, currentBlock uint64, hint *Hint) error
- type DBSbundle
- type DBSbundleBody
- type DBSbundleBuilder
- type DBSbundleHistoricalHint
- type EthCachingClient
- type EthClient
- type Hint
- type HintBackend
- type HintIntent
- type JSONRPCBuilder
- type JSONRPCBuilderBackend
- type JSONRPCSimulationBackend
- type MevBundleBody
- type MevBundleInclusion
- type MevBundleMetadata
- type MevBundlePrivacy
- type MevBundleValidity
- type RedisCancellationCache
- type RedisHintBackend
- type RefundConfig
- type RefundConstraint
- type SendMevBundleArgs
- type SendMevBundleResponse
- type SendRefundRecBundleArgs
- type SimMevBodyLogs
- type SimMevBundleAuxArgs
- type SimMevBundleResponse
- type SimQueue
- type SimScheduler
- type SimulationBackend
- type SimulationResult
- type SimulationResultBackend
- type SimulationWorker
- type Storage
- type TxHint
Constants ¶
const ( MaxBlockOffset uint64 = 5 MaxBlockRange uint64 = 30 MaxBodySize = 50 MaxNestingLevel = 1 RefundPercent = 90 HintGasPriceNumberPrecisionDigits = 3 HintGasNumberPrecisionDigits = 2 )
const ( SendBundleEndpointName = "mev_sendBundle" SimBundleEndpointName = "mev_simBundle" CancelBundleByHashEndpointName = "mev_cancelBundleByHash" )
Variables ¶
var ( ErrInvalidInclusion = errors.New("invalid inclusion") ErrInvalidBundleBodySize = errors.New("invalid bundle body size") ErrInvalidBundleBody = errors.New("invalid bundle body") ErrBackrunNotFound = errors.New("backrun not found") ErrBackrunInvalidBundle = errors.New("backrun invalid bundle") ErrBackrunInclusion = errors.New("backrun invalid inclusion") ErrInternalServiceError = errors.New("mev-share service error") )
var ( ErrUnsupportedBundleVersion = errors.New("unsupported bundle version") ErrBundleTooDeep = errors.New("bundle too deep") ErrInvalidBundleConstraints = errors.New("invalid bundle constraints") ErrInvalidBundlePrivacy = errors.New("invalid bundle privacy") )
var ( ErrInvalidHintIntent = errors.New("invalid hint intent") ErrNilBundleMetadata = errors.New("bundle metadata is nil") )
var (
ErrBundleNotCancelled = errors.New("bundle not cancelled")
)
var ErrBundleNotFound = errors.New("bundle not found")
var ErrCannotExtractHints = errors.New("cannot extract hints")
var ErrCantConvertToRefRecBundle = errors.New("can't convert bundle to ref recipient bundle")
var ErrInvalidBuilder = errors.New("invalid builder specification")
Functions ¶
func MergeBuilders ¶
func MergeBuilders(topLevel, inner *MevBundlePrivacy)
MergeBuilders writes to the topLevel builder value of overlap between inner and topLevel
func MergeInclusionIntervals ¶
func MergeInclusionIntervals(topLevel, inner *MevBundleInclusion) error
MergeInclusionIntervals writes to the topLevel inclusion value of overlap between inner and topLevel or return error if there is no overlap
func MergePrivacyBuilders ¶
func MergePrivacyBuilders(bundle *SendMevBundleArgs)
MergePrivacyBuilders Sets privacy.builders to the intersection of all privacy.builders in the bundle
func RoundUpWithPrecision ¶
RoundUpWithPrecision rounds number up leaving only precisionDigits non-zero examples: RoundUpWithPrecision(123456, 2) = 130000 RoundUpWithPrecision(111, 2) = 120 RoundUpWithPrecision(199, 2) = 120
func ValidateBundle ¶
Types ¶
type API ¶
type API struct {
// contains filtered or unexported fields
}
func NewAPI ¶
func NewAPI( log *zap.Logger, scheduler SimScheduler, bundleStorage BundleStorage, eth EthClient, signer types.Signer, simBackends []SimulationBackend, simRateLimit rate.Limit, builders BuildersBackend, cancellationCache *RedisCancellationCache, sbundleValidDuration time.Duration, ) *API
func (*API) CancelBundleByHash ¶
CancelBundleByHash cancels a bundle by hash This method is not exposed on the bundle relay. However, it is used by the Flashbots bundle relay for now to handle the cancellation of private transactions.
func (*API) SendBundle ¶
func (m *API) SendBundle(ctx context.Context, bundle SendMevBundleArgs) (_ SendMevBundleResponse, err error)
func (*API) SimBundle ¶
func (m *API) SimBundle(ctx context.Context, bundle SendMevBundleArgs, aux SimMevBundleAuxArgs) (_ *SimMevBundleResponse, err error)
type BuilderAPI ¶
type BuilderAPI uint8
const ( BuilderAPIRefundRecipient BuilderAPI = iota OrderflowHeaderName = "x-orderflow-origin" )
type BuilderBackend ¶
type BuildersBackend ¶
type BuildersBackend struct {
// contains filtered or unexported fields
}
func LoadBuilderConfig ¶
func LoadBuilderConfig(file string) (BuildersBackend, error)
LoadBuilderConfig parses a builder config from a file
func (*BuildersBackend) CancelBundleByHash ¶
func (*BuildersBackend) SendBundle ¶
func (b *BuildersBackend) SendBundle(ctx context.Context, logger *zap.Logger, bundle *SendMevBundleArgs, targetBlock uint64)
SendBundle sends a bundle to all builders. Bundles are sent to all builders in parallel.
type BuildersConfig ¶
type BuildersConfig struct { Builders []struct { Name string `yaml:"name"` URL string `yaml:"url"` API string `yaml:"api"` Internal bool `yaml:"internal,omitempty"` Disabled bool `yaml:"disabled,omitempty"` } `yaml:"builders"` OrderflowHeader bool `yaml:"orderflowHeader,omitempty"` OrderflowHeaderValue string `yaml:"orderflowHeaderValue,omitempty"` }
type BundleStorage ¶
type DBBackend ¶
type DBBackend struct {
// contains filtered or unexported fields
}
func NewDBBackend ¶
func (*DBBackend) CancelBundleByHash ¶
func (*DBBackend) GetBundleByMatchingHash ¶
func (*DBBackend) InsertBundleForBuilder ¶
func (b *DBBackend) InsertBundleForBuilder(ctx context.Context, bundle *SendMevBundleArgs, result *SimMevBundleResponse, targetBlock uint64) error
InsertBundleForBuilder inserts a bundle into the database for a builder to use Target block is the block the bundle is trying to get in. When it's called for the known bundle, we update the bundle with fresh simulation results and new target block.
func (*DBBackend) InsertBundleForStats ¶
func (b *DBBackend) InsertBundleForStats(ctx context.Context, bundle *SendMevBundleArgs, result *SimMevBundleResponse) (known bool, err error)
InsertBundleForStats inserts a bundle into the database. When called for the second time for the known bundle, it will return known = true and update bundle simulation results with the last inserted simulation results.
type DBSbundle ¶
type DBSbundle struct { Hash []byte `db:"hash"` MatchingHash []byte `db:"matching_hash"` Signer []byte `db:"signer"` Cancelled bool `db:"cancelled"` AllowMatching bool `db:"allow_matching"` Prematched bool `db:"prematched"` ReceivedAt time.Time `db:"received_at"` SimSuccess bool `db:"sim_success"` SimError sql.NullString `db:"sim_error"` SimulatedAt sql.NullTime `db:"simulated_at"` SimEffGasPrice sql.NullString `db:"sim_eff_gas_price"` SimProfit sql.NullString `db:"sim_profit"` SimRefundableValue sql.NullString `db:"sim_refundable_value"` SimGasUsed sql.NullInt64 `db:"sim_gas_used"` // sum of all simulations gas used SimAllSimsGasUsed sql.NullInt64 `db:"sim_all_sims_gas_used"` // number of simulations that were run for this bundle SimTotalSimCount sql.NullInt64 `db:"sim_total_sim_count"` Body []byte `db:"body"` BodySize int `db:"body_size"` OriginID sql.NullString `db:"origin_id"` InsertedAt time.Time `db:"inserted_at"` }
type DBSbundleBody ¶
type DBSbundleBuilder ¶
type DBSbundleBuilder struct { Hash []byte `db:"hash"` Cancelled bool `db:"cancelled"` Block int64 `db:"block"` MaxBlock int64 `db:"max_block"` SimStateBlock sql.NullInt64 `db:"sim_state_block"` SimEffGasPrice sql.NullString `db:"sim_eff_gas_price"` SimProfit sql.NullString `db:"sim_profit"` Body []byte `db:"body"` InsertedAt time.Time `db:"inserted_at"` }
type DBSbundleHistoricalHint ¶
type EthCachingClient ¶
type EthCachingClient struct {
// contains filtered or unexported fields
}
func NewCachingEthClient ¶
func NewCachingEthClient(ethClient *ethclient.Client) *EthCachingClient
func (*EthCachingClient) BlockNumber ¶
func (c *EthCachingClient) BlockNumber(ctx context.Context) (uint64, error)
BlockNumber returns the most recent block number, cached for 5 seconds
type Hint ¶
type Hint struct { Hash common.Hash `json:"hash"` Logs []CleanLog `json:"logs"` Txs []TxHint `json:"txs"` MevGasPrice *hexutil.Big `json:"mevGasPrice,omitempty"` GasUsed *hexutil.Uint64 `json:"gasUsed,omitempty"` }
func ExtractHints ¶
func ExtractHints(bundle *SendMevBundleArgs, simRes *SimMevBundleResponse, shareGasUsed, shareMevGasPrice bool) (Hint, error)
type HintIntent ¶
type HintIntent uint8
HintIntent is a set of hint intents its marshalled as an array of strings
const ( HintContractAddress HintIntent = 1 << iota HintFunctionSelector HintLogs HintCallData HintHash HintSpecialLogs HintTxHash HintNone = 0 )
func (*HintIntent) HasHint ¶
func (b *HintIntent) HasHint(flag HintIntent) bool
func (HintIntent) MarshalJSON ¶
func (b HintIntent) MarshalJSON() ([]byte, error)
func (*HintIntent) SetHint ¶
func (b *HintIntent) SetHint(flag HintIntent)
func (*HintIntent) UnmarshalJSON ¶
func (b *HintIntent) UnmarshalJSON(data []byte) error
type JSONRPCBuilder ¶
type JSONRPCBuilder struct {
// contains filtered or unexported fields
}
func NewJSONRPCBuilder ¶
func NewJSONRPCBuilder(url string) *JSONRPCBuilder
func (*JSONRPCBuilder) CancelBundleByHash ¶
func (*JSONRPCBuilder) SendMatchedShareBundle ¶
func (b *JSONRPCBuilder) SendMatchedShareBundle(ctx context.Context, bundle *SendMevBundleArgs) error
func (*JSONRPCBuilder) String ¶
func (b *JSONRPCBuilder) String() string
type JSONRPCBuilderBackend ¶
type JSONRPCBuilderBackend struct { Name string Client jsonrpc.RPCClient API BuilderAPI }
func (*JSONRPCBuilderBackend) CancelBundleByHash ¶
func (*JSONRPCBuilderBackend) SendBundle ¶
func (b *JSONRPCBuilderBackend) SendBundle(ctx context.Context, bundle *SendMevBundleArgs) (err error)
type JSONRPCSimulationBackend ¶
type JSONRPCSimulationBackend struct {
// contains filtered or unexported fields
}
func NewJSONRPCSimulationBackend ¶
func NewJSONRPCSimulationBackend(url string) *JSONRPCSimulationBackend
func (*JSONRPCSimulationBackend) SimulateBundle ¶
func (b *JSONRPCSimulationBackend) SimulateBundle(ctx context.Context, bundle *SendMevBundleArgs, aux *SimMevBundleAuxArgs) (*SimMevBundleResponse, error)
type MevBundleBody ¶
type MevBundleInclusion ¶
type MevBundleMetadata ¶
type MevBundleMetadata struct { BundleHash common.Hash `json:"bundleHash,omitempty"` BodyHashes []common.Hash `json:"bodyHashes,omitempty"` Signer common.Address `json:"signer,omitempty"` OriginID string `json:"originId,omitempty"` ReceivedAt hexutil.Uint64 `json:"receivedAt,omitempty"` MatchingHash common.Hash `json:"matchingHash,omitempty"` Prematched bool `json:"prematched"` }
type MevBundlePrivacy ¶
type MevBundlePrivacy struct { Hints HintIntent `json:"hints,omitempty"` Builders []string `json:"builders,omitempty"` WantRefund *int `json:"wantRefund,omitempty"` }
type MevBundleValidity ¶
type MevBundleValidity struct { Refund []RefundConstraint `json:"refund,omitempty"` RefundConfig []RefundConfig `json:"refundConfig,omitempty"` }
type RedisCancellationCache ¶
type RedisCancellationCache struct {
// contains filtered or unexported fields
}
func NewRedisCancellationCache ¶
func NewRedisCancellationCache(client *redis.Client, expireDuration time.Duration, keyPrefix string) *RedisCancellationCache
func (*RedisCancellationCache) DeleteAll ¶
func (c *RedisCancellationCache) DeleteAll(ctx context.Context) error
DeleteAll deletes all the keys in the cache. It can be very slow and should only be used for testing.
func (*RedisCancellationCache) IsCancelled ¶
type RedisHintBackend ¶
type RedisHintBackend struct {
// contains filtered or unexported fields
}
func NewRedisHintBackend ¶
func NewRedisHintBackend(redisClient *redis.Client, pubChannel string) *RedisHintBackend
func (*RedisHintBackend) NotifyHint ¶
func (b *RedisHintBackend) NotifyHint(ctx context.Context, hint *Hint) error
type RefundConfig ¶
type RefundConstraint ¶
type SendMevBundleArgs ¶
type SendMevBundleArgs struct { Version string `json:"version"` Inclusion MevBundleInclusion `json:"inclusion"` Body []MevBundleBody `json:"body"` Validity MevBundleValidity `json:"validity"` Privacy *MevBundlePrivacy `json:"privacy,omitempty"` Metadata *MevBundleMetadata `json:"metadata,omitempty"` }
type SendMevBundleResponse ¶
type SendRefundRecBundleArgs ¶
type SendRefundRecBundleArgs struct { BlockNumber hexutil.Uint64 `json:"blockNumber"` Txs []hexutil.Bytes `json:"txs"` RevertingTxHashes []common.Hash `json:"revertingTxHashes,omitempty"` RefundPercent *int `json:"refundPercent,omitempty"` RefundRecipient *common.Address `json:"refundRecipient,omitempty"` }
func ConvertBundleToRefundRecipient ¶
func ConvertBundleToRefundRecipient(bundle *SendMevBundleArgs) (res SendRefundRecBundleArgs, err error)
type SimMevBodyLogs ¶
type SimMevBodyLogs struct { TxLogs []*types.Log `json:"txLogs,omitempty"` BundleLogs []SimMevBodyLogs `json:"bundleLogs,omitempty"` }
type SimMevBundleAuxArgs ¶
type SimMevBundleAuxArgs struct { ParentBlock *rpc.BlockNumberOrHash `json:"parentBlock"` // override the default values for the block header BlockNumber *hexutil.Big `json:"blockNumber"` Coinbase *common.Address `json:"coinbase"` Timestamp *hexutil.Uint64 `json:"timestamp"` GasLimit *hexutil.Uint64 `json:"gasLimit"` BaseFee *hexutil.Big `json:"baseFee"` Timeout *int64 `json:"timeout"` }
type SimMevBundleResponse ¶
type SimMevBundleResponse struct { Success bool `json:"success"` Error string `json:"error,omitempty"` StateBlock hexutil.Uint64 `json:"stateBlock"` MevGasPrice hexutil.Big `json:"mevGasPrice"` Profit hexutil.Big `json:"profit"` RefundableValue hexutil.Big `json:"refundableValue"` GasUsed hexutil.Uint64 `json:"gasUsed"` BodyLogs []SimMevBodyLogs `json:"logs,omitempty"` }
type SimQueue ¶
type SimQueue struct {
// contains filtered or unexported fields
}
func NewQueue ¶
func NewQueue( log *zap.Logger, queue simqueue.Queue, eth EthClient, sim []SimulationBackend, simRes SimulationResult, workersPerNode int, backgroundWg *sync.WaitGroup, cancelCache *RedisCancellationCache, ) *SimQueue
func (*SimQueue) ScheduleBundleSimulation ¶
type SimScheduler ¶
type SimScheduler interface {
ScheduleBundleSimulation(ctx context.Context, bundle *SendMevBundleArgs, highPriority bool) error
}
type SimulationBackend ¶
type SimulationBackend interface {
SimulateBundle(ctx context.Context, bundle *SendMevBundleArgs, aux *SimMevBundleAuxArgs) (*SimMevBundleResponse, error)
}
SimulationBackend is an interface for simulating transactions There should be one simulation backend per worker node
type SimulationResult ¶
type SimulationResult interface {
SimulatedBundle(ctx context.Context, args *SendMevBundleArgs, result *SimMevBundleResponse, info simqueue.QueueItemInfo) error
}
SimulationResult is responsible for processing simulation results NOTE: That error should be returned only if simulation should be retried, for example if redis is down or none of the builders responded
type SimulationResultBackend ¶
type SimulationResultBackend struct {
// contains filtered or unexported fields
}
func NewSimulationResultBackend ¶
func NewSimulationResultBackend(log *zap.Logger, hint HintBackend, builders BuildersBackend, eth EthClient, store Storage, shareGasUsed, shareMevGasPrice bool) *SimulationResultBackend
func (*SimulationResultBackend) ProcessHints ¶
func (s *SimulationResultBackend) ProcessHints(ctx context.Context, bundle *SendMevBundleArgs, sim *SimMevBundleResponse) error
func (*SimulationResultBackend) SimulatedBundle ¶
func (s *SimulationResultBackend) SimulatedBundle(ctx context.Context, bundle *SendMevBundleArgs, sim *SimMevBundleResponse, _ simqueue.QueueItemInfo, ) error
SimulatedBundle is called when simulation is done NOTE: we return error only if we want to retry the simulation
type SimulationWorker ¶
type SimulationWorker struct {
// contains filtered or unexported fields
}
func (*SimulationWorker) Process ¶
func (w *SimulationWorker) Process(ctx context.Context, data []byte, info simqueue.QueueItemInfo) (err error)
type Storage ¶
type Storage interface { InsertBundleForStats(ctx context.Context, bundle *SendMevBundleArgs, result *SimMevBundleResponse) (known bool, err error) InsertBundleForBuilder(ctx context.Context, bundle *SendMevBundleArgs, result *SimMevBundleResponse, targetBlock uint64) error InsertHistoricalHint(ctx context.Context, currentBlock uint64, hint *Hint) error }