Skip to content

Commit

Permalink
Merge pull request #27 from chainbound/feat/relay-constraint-flow
Browse files Browse the repository at this point in the history
feat(relay): submit constraints endpoint
  • Loading branch information
thedevbirb authored May 28, 2024
2 parents 4408178 + c346b4f commit c5389e2
Show file tree
Hide file tree
Showing 17 changed files with 1,196 additions and 450 deletions.
36 changes: 31 additions & 5 deletions mev-boost-relay/beaconclient/mock_multi_beacon_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,22 @@ package beaconclient
import (
"github.com/attestantio/go-eth2-client/spec/capella"
"github.com/flashbots/mev-boost-relay/common"
"github.com/sirupsen/logrus"
uberatomic "go.uber.org/atomic"
)

type MockMultiBeaconClient struct{}
type MockMultiBeaconClient struct {
log *logrus.Entry
bestBeaconIndex uberatomic.Int64
beaconInstances []IBeaconInstance
}

func NewMockMultiBeaconClient() *MockMultiBeaconClient {
return &MockMultiBeaconClient{}
func NewMockMultiBeaconClient(log *logrus.Entry, beaconInstances []IBeaconInstance) *MockMultiBeaconClient {
return &MockMultiBeaconClient{
log: log.WithField("component", "mockMultiBeaconClient"),
bestBeaconIndex: uberatomic.Int64{},
beaconInstances: beaconInstances,
}
}

func (*MockMultiBeaconClient) BestSyncStatus() (*SyncStatusPayloadData, error) {
Expand All @@ -20,8 +30,24 @@ func (*MockMultiBeaconClient) SubscribeToHeadEvents(slotC chan HeadEventData) {}
func (*MockMultiBeaconClient) SubscribeToPayloadAttributesEvents(payloadAttrC chan PayloadAttributesEvent) {
}

func (*MockMultiBeaconClient) GetStateValidators(stateID string) (*GetStateValidatorsResponse, error) {
return nil, nil
func (c *MockMultiBeaconClient) GetStateValidators(stateID string) (*GetStateValidatorsResponse, error) {
for i, client := range c.beaconInstances {
log := c.log.WithField("uri", client.GetURI())
log.Debug("fetching validators")

validators, err := client.GetStateValidators(stateID)
if err != nil {
log.WithError(err).Error("failed to fetch validators")
continue
}

c.bestBeaconIndex.Store(int64(i))

// Received successful response. Set this index as last successful beacon node
return validators, nil
}

return nil, ErrBeaconNodesUnavailable
}

func (*MockMultiBeaconClient) GetProposerDuties(epoch uint64) (*ProposerDutiesResponse, error) {
Expand Down
2 changes: 1 addition & 1 deletion mev-boost-relay/common/common.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import (
"fmt"
"time"

"github.com/flashbots/go-utils/cli"
"github.com/thedevbirb/flashbots-go-utils/cli"
)

var (
Expand Down
2 changes: 1 addition & 1 deletion mev-boost-relay/datastore/memcached.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ import (

builderApi "github.com/attestantio/go-builder-client/api"
"github.com/bradfitz/gomemcache/memcache"
"github.com/flashbots/go-utils/cli"
"github.com/thedevbirb/flashbots-go-utils/cli"
)

var (
Expand Down
2 changes: 1 addition & 1 deletion mev-boost-relay/datastore/redis.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ import (
builderSpec "github.com/attestantio/go-builder-client/spec"
"github.com/attestantio/go-eth2-client/spec"
"github.com/attestantio/go-eth2-client/spec/capella"
"github.com/flashbots/go-utils/cli"
"github.com/thedevbirb/flashbots-go-utils/cli"
"github.com/flashbots/mev-boost-relay/common"
"github.com/go-redis/redis/v9"
"github.com/sirupsen/logrus"
Expand Down
8 changes: 5 additions & 3 deletions mev-boost-relay/go.mod
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module github.com/flashbots/mev-boost-relay

go 1.21
go 1.22.2

require (
github.com/NYTimes/gziphandler v1.1.1
Expand All @@ -12,27 +12,28 @@ require (
github.com/buger/jsonparser v1.1.1
github.com/ethereum/go-ethereum v1.13.15
github.com/flashbots/go-boost-utils v1.8.0
github.com/flashbots/go-utils v0.5.0
github.com/go-redis/redis/v9 v9.0.0-rc.1
github.com/gorilla/mux v1.8.1
github.com/holiman/uint256 v1.2.4
github.com/jmoiron/sqlx v1.3.5
github.com/lib/pq v1.10.8
github.com/pkg/errors v0.9.1
github.com/r3labs/sse/v2 v2.10.0
github.com/chainbound/shardmap v0.0.2
github.com/sirupsen/logrus v1.9.3
github.com/spf13/cobra v1.8.0
github.com/stretchr/testify v1.8.4
github.com/tdewolff/minify v2.3.6+incompatible
github.com/thedevbirb/flashbots-go-utils v0.0.0-20240522160613-f4f36d8f39af
go.uber.org/atomic v1.11.0
golang.org/x/exp v0.0.0-20231110203233-9a3e6036ecaa
golang.org/x/text v0.14.0
gotest.tools v2.2.0+incompatible
)

require (
github.com/DataDog/zstd v1.5.2 // indirect
github.com/StackExchange/wmi v1.2.1 // indirect
github.com/VictoriaMetrics/fastcache v1.12.1 // indirect
github.com/beorn7/perks v1.0.1 // indirect
github.com/bits-and-blooms/bitset v1.10.0 // indirect
github.com/cockroachdb/errors v1.9.1 // indirect
Expand All @@ -55,6 +56,7 @@ require (
github.com/gogo/protobuf v1.3.2 // indirect
github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.5-0.20220116011046-fa5810519dcb // indirect
github.com/google/go-cmp v0.5.9 // indirect
github.com/google/uuid v1.3.1 // indirect
github.com/klauspost/compress v1.15.15 // indirect
github.com/kr/pretty v0.3.1 // indirect
Expand Down
11 changes: 4 additions & 7 deletions mev-boost-relay/go.sum
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a h1:HbKu58rmZp
github.com/alicebob/gopher-json v0.0.0-20200520072559-a9ecdc9d1d3a/go.mod h1:SGnFV6hVsYE877CKEZ6tDNTjaSXYUk6QqoIK6PrAtcc=
github.com/alicebob/miniredis/v2 v2.31.0 h1:ObEFUNlJwoIiyjxdrYF0QIDE7qXcLc7D3WpSH4c22PU=
github.com/alicebob/miniredis/v2 v2.31.0/go.mod h1:UB/T2Uztp7MlFSDakaX1sTXUv5CASoprx0wulRT6HBg=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156 h1:eMwmnE/GDgah4HI848JfFxHt+iPb26b4zyfspmqY0/8=
github.com/allegro/bigcache v1.2.1-0.20190218064605-e24eb225f156/go.mod h1:Cb/ax3seSYIx7SuZdm2G2xzfwmv3TPSk2ucNfQESPXM=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
github.com/attestantio/go-builder-client v0.4.3-0.20240124194555-d44db06f45fa h1:Kj6d1tXAA+EAi7fK8z8NakBEpY4WYzZMuCmLZjwBpTM=
github.com/attestantio/go-builder-client v0.4.3-0.20240124194555-d44db06f45fa/go.mod h1:e02i/WO4fjs3/u9oIZEjiC8CK1Qyxy4cpiMMGKx4VqQ=
Expand Down Expand Up @@ -65,6 +63,8 @@ github.com/buger/jsonparser v1.1.1/go.mod h1:6RYKKt7H4d4+iWqouImQ9R2FZql3VbhNgx2
github.com/census-instrumentation/opencensus-proto v0.2.1/go.mod h1:f6KPmirojxKA12rnyqOA5BBL4O983OfeGPqjHWSTneU=
github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44=
github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
github.com/chainbound/shardmap v0.0.2 h1:yB1weccdm2vC6dnqzzLwPIvyAnRj7815mJWbkPybiYw=
github.com/chainbound/shardmap v0.0.2/go.mod h1:TBvIzhHyFUbt+oa3UzbijobTUh221st6xIbuki7WzPc=
github.com/chzyer/logex v1.1.10/go.mod h1:+Ywpsq7O8HXn0nuIou7OrIPyXbp3wmkHB+jjWRnGsAI=
github.com/chzyer/readline v0.0.0-20180603132655-2972be24d48e/go.mod h1:nSuG5e5PlCu98SY8svDHJxuZscDgtXS6KTTbou5AhLI=
github.com/chzyer/test v0.0.0-20180213035817-a1ea475d72b1/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
Expand Down Expand Up @@ -123,8 +123,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/etcd-io/bbolt v1.3.3/go.mod h1:ZF2nL25h33cCyBtcyWeZ2/I3HQOfTP+0PIEvHjkjCrw=
github.com/ethereum/c-kzg-4844 v0.4.0 h1:3MS1s4JtA868KpJxroZoepdV0ZKBp3u/O5HcZ7R3nlY=
github.com/ethereum/c-kzg-4844 v0.4.0/go.mod h1:VewdlzQmpT5QSrVhbBuGoCdFJkpaJlO1aQputP83wc0=
github.com/ethereum/go-ethereum v1.13.10 h1:Ppdil79nN+Vc+mXfge0AuUgmKWuVv4eMqzoIVSdqZek=
github.com/ethereum/go-ethereum v1.13.10/go.mod h1:sc48XYQxCzH3fG9BcrXCOOgQk2JfZzNAmIKnceogzsA=
github.com/ethereum/go-ethereum v1.13.15 h1:U7sSGYGo4SPjP6iNIifNoyIAiNjrmQkz6EwQG+/EZWo=
github.com/ethereum/go-ethereum v1.13.15/go.mod h1:TN8ZiHrdJwSe8Cb6x+p0hs5CxhJZPbqB7hHkaUXcmIU=
github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod h1:duJ4Jxv5lDcvg4QuQr0oowTf7dz4/CR8NtyCooz9HL8=
Expand All @@ -135,8 +133,6 @@ github.com/ferranbt/fastssz v0.1.3 h1:ZI+z3JH05h4kgmFXdHuR1aWYsgrg7o+Fw7/NCzM16M
github.com/ferranbt/fastssz v0.1.3/go.mod h1:0Y9TEd/9XuFlh7mskMPfXiI2Dkw4Ddg9EyXt1W7MRvE=
github.com/flashbots/go-boost-utils v1.8.0 h1:z3K1hw+Fbl9AGMNQKnK7Bvf0M/rKgjfruAEvra+Z8Mg=
github.com/flashbots/go-boost-utils v1.8.0/go.mod h1:Ry1Rw8Lx5v1rpAR0+IvR4sV10jYAeQaGVM3vRD8mYdM=
github.com/flashbots/go-utils v0.5.0 h1:ldjWta9B9//DJU2QcwRbErez3+1aKhSn6EoFc6d5kPY=
github.com/flashbots/go-utils v0.5.0/go.mod h1:LauDwifaRdSK0mS5X34GR59pJtUu1T/lOFNdff1BqtI=
github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo=
github.com/fsnotify/fsnotify v1.4.9/go.mod h1:znqG4EE+3YCdAaPaxE2ZRY/06pZUdp0tY4IgpuI1SZQ=
github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY=
Expand All @@ -156,7 +152,6 @@ github.com/go-errors/errors v1.4.2/go.mod h1:sIVyrIiJhuEF+Pj9Ebtd6P/rEYROXFi3Bop
github.com/go-gorp/gorp/v3 v3.1.0 h1:ItKF/Vbuj31dmV4jxA1qblpSwkl9g1typ24xoe70IGs=
github.com/go-gorp/gorp/v3 v3.1.0/go.mod h1:dLEjIyyRNiXvNZ8PSmzpt1GsWAUK8kjVhEpjH8TixEw=
github.com/go-martini/martini v0.0.0-20170121215854-22fa46961aab/go.mod h1:/P9AEU963A2AYjv4d1V5eVL1CQbEJq6aCNHDDjibzu8=
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
Expand Down Expand Up @@ -434,6 +429,8 @@ github.com/tdewolff/parse v2.3.4+incompatible h1:x05/cnGwIMf4ceLuDMBOdQ1qGniMoxp
github.com/tdewolff/parse v2.3.4+incompatible/go.mod h1:8oBwCsVmUkgHO8M5iCzSIDtpzXOT0WXX9cWhz+bIzJQ=
github.com/tdewolff/test v1.0.7 h1:8Vs0142DmPFW/bQeHRP3MV19m1gvndjUb1sn8yy74LM=
github.com/tdewolff/test v1.0.7/go.mod h1:6DAvZliBAAnD7rhVgwaM7DE5/d9NMOAJ09SqYqeK4QE=
github.com/thedevbirb/flashbots-go-utils v0.0.0-20240522160613-f4f36d8f39af h1:VwsEpQJqCFCT+oZXfJj8alj3FkIpKLvn0wV7GO/cEQY=
github.com/thedevbirb/flashbots-go-utils v0.0.0-20240522160613-f4f36d8f39af/go.mod h1:Xcc4QMCD1U+HqHayd9nqVMcJVV4eAzNyAQVWY1AqhEE=
github.com/tklauser/go-sysconf v0.3.12 h1:0QaGUFOdQaIVdPgfITYzaTegZvdCjmYO52cSFAEVmqU=
github.com/tklauser/go-sysconf v0.3.12/go.mod h1:Ho14jnntGE1fpdOqQEEaiKRpvIavV0hSfmBq8nJbHYI=
github.com/tklauser/numcpus v0.6.1 h1:ng9scYS7az0Bk4OZLvrNXNSAO2Pxr1XXRAPyjhIx+Fk=
Expand Down
4 changes: 2 additions & 2 deletions mev-boost-relay/services/api/blocksim_ratelimiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,8 @@ import (
"time"

"github.com/attestantio/go-eth2-client/spec"
"github.com/flashbots/go-utils/cli"
"github.com/flashbots/go-utils/jsonrpc"
"github.com/thedevbirb/flashbots-go-utils/cli"
"github.com/thedevbirb/flashbots-go-utils/jsonrpc"
"github.com/flashbots/mev-boost-relay/common"
)

Expand Down
159 changes: 159 additions & 0 deletions mev-boost-relay/services/api/constraints.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,159 @@
// This code is taken from https://github.com/chainbound/bolt/pull/11/files#diff-0fa8405accc1cdc5b108ba0210a8f1d99e25e1a5173e45e1516d73c294b061c4
package api

import (
"encoding/hex"
"encoding/json"
"fmt"
"strings"

"github.com/attestantio/go-eth2-client/spec/phase0"
"github.com/pkg/errors"
)

type SignedConstraintSubmission struct {
Message *ConstraintSubmission
Signature phase0.BLSSignature `ssz-size:"96"`
ProposerIndex uint64
}

type signedConstraintSubmissionJSON struct {
Message *ConstraintSubmission `json:"message"`
Signature string `json:"signature"`
ProposerIndex uint64 `json:"proposerIndex"`
}

func (s *SignedConstraintSubmission) MarshalJSON() ([]byte, error) {
return json.Marshal(&signedConstraintSubmissionJSON{
Message: s.Message,
Signature: fmt.Sprintf("%#x", s.Signature),
ProposerIndex: s.ProposerIndex,
})
}

func (s *SignedConstraintSubmission) UnmarshalJSON(input []byte) error {
var data signedConstraintSubmissionJSON
if err := json.Unmarshal(input, &data); err != nil {
return errors.Wrap(err, "invalid JSON")
}

if data.Message == nil {
return errors.New("message missing")
}

s.Message = data.Message
s.ProposerIndex = data.ProposerIndex

if data.Signature == "" {
return errors.New("signature missing")
}

signature, err := hex.DecodeString(strings.TrimPrefix(data.Signature, "0x"))
if err != nil {
return errors.Wrap(err, "invalid signature")
}

if len(signature) != phase0.SignatureLength {
return errors.New("incorrect length for signature")
}
copy(s.Signature[:], signature)

return nil
}

type ConstraintSubmission struct {
Slot uint64
TxHash phase0.Hash32 `ssz-size:"32"`
RawTx Transaction `ssz-max:"1073741824"`
}

type constraintSubmissionJSON struct {
Slot uint64 `json:"slot"`
TxHash string `json:"txHash"`
RawTx string `json:"rawTx"`
}

func (c *ConstraintSubmission) MarshalJSON() ([]byte, error) {
return json.Marshal(&constraintSubmissionJSON{
Slot: c.Slot,
TxHash: c.TxHash.String(),
RawTx: fmt.Sprintf("%#x", c.RawTx),
})
}

func (c *ConstraintSubmission) UnmarshalJSON(input []byte) error {
var data constraintSubmissionJSON
if err := json.Unmarshal(input, &data); err != nil {
return err
}

c.Slot = data.Slot

txHash, err := hex.DecodeString((strings.TrimPrefix(data.TxHash, "0x")))
if err != nil {
return errors.Wrap(err, "invalid tx hash")
}

copy(c.TxHash[:], txHash)

rawTx, err := hex.DecodeString((strings.TrimPrefix(data.RawTx, "0x")))
if err != nil {
return errors.Wrap(err, "invalid raw tx")
}

c.RawTx = rawTx

return nil
}

func (c *ConstraintSubmission) String() string {
data, err := json.Marshal(c)
if err != nil {
return fmt.Sprintf("ERR: %v", err)
}
return string(data)
}

// Constraints is a map of constraints for a block.
type Constraints = map[phase0.Hash32]*Constraint

// Constraint is a constraint on a block. For now just preconfirmations
// or inclusion constraints.
type Constraint struct {
RawTx Transaction `json:"rawTx"`
}

// ConstraintCache is a cache for constraints.
type ConstraintCache struct {
// map of slots to constraints
constraints map[uint64]Constraints
}

// NewConstraintCache creates a new constraint cache.
func NewConstraintCache() *ConstraintCache {
return &ConstraintCache{
// TODO: there should be a maximum length here that we can pre-allocate (probably the lookahead window size)
constraints: make(map[uint64]Constraints),
}
}

// AddInclusionConstraint adds an inclusion constraint to the cache at the given slot for the given transaction.
func (c *ConstraintCache) AddInclusionConstraint(slot uint64, txHash phase0.Hash32, rawTx Transaction) {
if _, exists := c.constraints[slot]; !exists {
c.constraints[slot] = make(map[phase0.Hash32]*Constraint)
}

c.constraints[slot][txHash] = &Constraint{
RawTx: rawTx,
}
}

// Get gets the constraints at the given slot.
func (c *ConstraintCache) Get(slot uint64) Constraints {
return c.constraints[slot]
}

// Delete deletes the constraints at the given slot.
func (c *ConstraintCache) Delete(slot uint64) {
delete(c.constraints, slot)
}
2 changes: 1 addition & 1 deletion mev-boost-relay/services/api/optimistic_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ func startTestBackend(t *testing.T) (*phase0.BLSPubKey, *bls.SecretKey, *testBac
},
}
backend.relay.opts.BlockBuilderAPI = true
backend.relay.beaconClient = beaconclient.NewMockMultiBeaconClient()
backend.relay.beaconClient = &beaconclient.MockMultiBeaconClient{}
backend.relay.blockSimRateLimiter = &MockBlockSimulationRateLimiter{}
backend.relay.blockBuildersCache = map[string]*blockBuilderCacheEntry{
pkStr: {
Expand Down
Loading

0 comments on commit c5389e2

Please sign in to comment.