Skip to content

Commit

Permalink
wip: develop -> main (#147)
Browse files Browse the repository at this point in the history
* Add signature verifications (#138)

* Add signature verification for getHeader response

Signed-off-by: Luca Georges Francois <[email protected]>

* Remove typo

Signed-off-by: Luca Georges Francois <[email protected]>

* Add signature verification for registerValidator request

Signed-off-by: Luca Georges Francois <[email protected]>

* Update mergemock integration tests

Signed-off-by: Luca Georges Francois <[email protected]>

* Fix typo in flag

Signed-off-by: Luca Georges Francois <[email protected]>

* Add error logging

Signed-off-by: Luca Georges Francois <[email protected]>

* Add signature verification tests

Signed-off-by: Luca Georges Francois <[email protected]>

* Require the relay pubkey (#143)

* mev-boost cli flags for setting genesis fork version, computing correct domain (#148)

* better errors on failed signature validation (#151)

Co-authored-by: Luca G.F <[email protected]>
  • Loading branch information
metachris and 0xpanoramix authored Jun 14, 2022
1 parent ffee660 commit 6dcbd28
Show file tree
Hide file tree
Showing 12 changed files with 236 additions and 101 deletions.
11 changes: 4 additions & 7 deletions .github/pull_request_template.md
Original file line number Diff line number Diff line change
@@ -1,18 +1,15 @@
Related issue(s):
## Description


Description:
## Context & references


Problem(s) & goal(s):


Additional context & references:
## Additional comments


---

I have run these commands:
## I have run these commands

* [ ] `make lint`
* [ ] `make test`
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/go.yml
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ jobs:
runs-on: ubuntu-latest
env:
CGO_CFLAGS_ALLOW: "-O -D__BLST_PORTABLE__"
CGO_CFLAGS: "-O -D__BLST_PORTABLE__"
CGO_CFLAGS: "-O -D__BLST_PORTABLE__"
steps:
- name: Set up Go 1.x
uses: actions/setup-go@v2
Expand Down
4 changes: 2 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ run:
./mev-boost

run-boost-with-relay:
./mev-boost -relays 127.0.0.1:28545
./mev-boost -mainnet -relays http://0x821961b64d99b997c934c22b4fd6109790acf00f7969322c4e9dbf1ca278c333148284c01c5ef551a1536ddd14b178b9@127.0.0.1:28545

run-dev:
go run cmd/mev-boost/main.go
Expand All @@ -58,7 +58,7 @@ run-mergemock-consensus:
cd $(MERGEMOCK_DIR) && $(MERGEMOCK_BIN) consensus --slot-time=4s --engine http://127.0.0.1:8551 --builder http://127.0.0.1:18550 --slot-bound 10

run-mergemock-relay:
cd $(MERGEMOCK_DIR) && $(MERGEMOCK_BIN) relay --listen-addr 127.0.0.1:28545
cd $(MERGEMOCK_DIR) && $(MERGEMOCK_BIN) relay --listen-addr 127.0.0.1:28545 --secret-key 1e64a14cb06073c2d7c8b0b891e5dc3dc719b86e5bf4c131ddbaa115f09f8f52

run-mergemock-integration: build
make -j3 run-boost-with-relay run-mergemock-consensus run-mergemock-relay
Expand Down
21 changes: 17 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,16 +70,29 @@ go install github.com/ferranbt/fastssz/sszgen@latest
go install github.com/mgechev/revive@latest
go install honnef.co/go/tools/cmd/staticcheck@master
```
## Build
## Build & Run

```
```bash
make build
./mev-boost -h
./mev-boost -kiln -relays http://0x821961b64d99b997c934c22b4fd6109790acf00f7969322c4e9dbf1ca278c333148284c01c5ef551a1536ddd14b178b9@localhost:28545
```

and then run it with:
Alternatively, run mev-boost without compile step:

```bash
go run cmd/mev-boost/main.go -h
go run cmd/mev-boost/main.go -kiln -relays http://0x821961b64d99b997c934c22b4fd6109790acf00f7969322c4e9dbf1ca278c333148284c01c5ef551a1536ddd14b178b9@localhost:28545
```
./mev-boost

Note that you'll need to set the correct genesis fork version (either manually with `-genesis-fork-version` or a helper flag `-mainnet`/`-kiln`/`-ropsten`).

If the test or target application crashes with an "illegal instruction" exception, run/rebuild with CGO_CFLAGS environment variable set to `-O -D__BLST_PORTABLE__`. This error also happens if you are on an ARM-based system, including the Apple M1/M2 chip.


```bash
export CGO_CFLAGS_ALLOW="-O -D__BLST_PORTABLE__"
export CGO_CFLAGS="-O -D__BLST_PORTABLE__"
```

## Lint & Test
Expand Down
38 changes: 32 additions & 6 deletions cmd/mev-boost/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,20 +11,32 @@ import (
"github.com/sirupsen/logrus"
)

const (
genesisForkVersionMainnet = "0x00000000"
genesisForkVersionKiln = "0x70000069"
genesisForkVersionRopsten = "0x80000069"
)

var (
version = "dev" // is set during build process

// defaults
defaultListenAddr = getEnv("BOOST_LISTEN_ADDR", "localhost:18550")
defaultRelayURLs = getEnv("RELAY_URLS", "localhost:28545") // can be IP@PORT, PUBKEY@IP:PORT, https://IP, etc.
defaultRelayTimeoutMs = getEnvInt("RELAY_TIMEOUT_MS", 2000) // timeout for all the requests to the relay
defaultRelayCheck = os.Getenv("RELAY_STARTUP_CHECK") != ""
defaultListenAddr = getEnv("BOOST_LISTEN_ADDR", "localhost:18550")
defaultRelayTimeoutMs = getEnvInt("RELAY_TIMEOUT_MS", 2000) // timeout for all the requests to the relay
defaultRelayCheck = os.Getenv("RELAY_STARTUP_CHECK") != ""
defaultGenesisForkVersion = getEnv("GENESIS_FORK_VERSION", "")

// cli flags
listenAddr = flag.String("addr", defaultListenAddr, "listen-address for mev-boost server")
relayURLs = flag.String("relays", defaultRelayURLs, "relay urls - single entry or comma-separated list (pubkey@ip:port)")
relayURLs = flag.String("relays", "", "relay urls - single entry or comma-separated list (schema://pubkey@ip:port)")
relayTimeoutMs = flag.Int("request-timeout", defaultRelayTimeoutMs, "timeout for requests to a relay [ms]")
relayCheck = flag.Bool("relay-check", defaultRelayCheck, "whether to check relay status on startup")

// helpers
useGenesisForkVersionMainnet = flag.Bool("mainnet", false, "use Mainnet genesis fork version 0x00000000 (for signature validation)")
useGenesisForkVersionKiln = flag.Bool("kiln", false, "use Kiln genesis fork version 0x70000069 (for signature validation)")
useGenesisForkVersionRopsten = flag.Bool("ropsten", false, "use Ropsten genesis fork version 0x80000069 (for signature validation)")
useCustomGenesisForkVersion = flag.String("genesis-fork-version", defaultGenesisForkVersion, "use a custom genesis fork version (for signature validation)")
)

var log = logrus.WithField("module", "cmd/mev-boost")
Expand All @@ -33,6 +45,20 @@ func main() {
flag.Parse()
log.Printf("mev-boost %s", version)

genesisForkVersionHex := ""
if *useCustomGenesisForkVersion != "" {
genesisForkVersionHex = *useCustomGenesisForkVersion
} else if *useGenesisForkVersionMainnet {
genesisForkVersionHex = genesisForkVersionMainnet
} else if *useGenesisForkVersionKiln {
genesisForkVersionHex = genesisForkVersionKiln
} else if *useGenesisForkVersionRopsten {
genesisForkVersionHex = genesisForkVersionRopsten
} else {
log.Fatal("Please specify a genesis fork version (eg. -mainnet or -kiln or -ropsten or -genesis-fork-version flags)")
}
log.Infof("Using genesis fork version: %s", genesisForkVersionHex)

relays := parseRelayURLs(*relayURLs)
if len(relays) == 0 {
log.Fatal("No relays specified")
Expand All @@ -44,7 +70,7 @@ func main() {
}

relayTimeout := time.Duration(*relayTimeoutMs) * time.Millisecond
server, err := server.NewBoostService(*listenAddr, relays, log, relayTimeout)
server, err := server.NewBoostService(*listenAddr, relays, log, genesisForkVersionHex, relayTimeout)
if err != nil {
log.WithError(err).Fatal("failed creating the server")
}
Expand Down
33 changes: 16 additions & 17 deletions cmd/test-cli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import (
"strconv"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/common/hexutil"
boostTypes "github.com/flashbots/go-boost-utils/types"
"github.com/sirupsen/logrus"

Expand Down Expand Up @@ -206,35 +205,35 @@ func main() {
doGenerateValidator(validatorDataFile, gasLimit, validatorFeeRecipient)
case "register":
registerCommand.Parse(os.Args[2:])
builderSigningDomain := computeDomain(boostTypes.DomainTypeAppBuilder, genesisForkVersionStr, boostTypes.Root{}.String())
builderSigningDomain, err := server.ComputeDomain(boostTypes.DomainTypeAppBuilder, genesisForkVersionStr, boostTypes.Root{}.String())
if err != nil {
log.WithError(err).Fatal("computing signing domain failed")
}
doRegisterValidator(mustLoadValidator(validatorDataFile), boostEndpoint, builderSigningDomain)
case "getHeader":
getHeaderCommand.Parse(os.Args[2:])
builderSigningDomain := computeDomain(boostTypes.DomainTypeAppBuilder, genesisForkVersionStr, boostTypes.Root{}.String())
builderSigningDomain, err := server.ComputeDomain(boostTypes.DomainTypeAppBuilder, genesisForkVersionStr, boostTypes.Root{}.String())
if err != nil {
log.WithError(err).Fatal("computing signing domain failed")
}
doGetHeader(mustLoadValidator(validatorDataFile), boostEndpoint, createBeacon(isMergemock, beaconEndpoint, engineEndpoint), engineEndpoint, builderSigningDomain)
case "getPayload":
getPayloadCommand.Parse(os.Args[2:])
builderSigningDomain := computeDomain(boostTypes.DomainTypeAppBuilder, genesisForkVersionStr, boostTypes.Root{}.String())
proposerSigningDomain := computeDomain(boostTypes.DomainTypeBeaconProposer, bellatrixForkVersionStr, genesisValidatorsRootStr)
builderSigningDomain, err := server.ComputeDomain(boostTypes.DomainTypeAppBuilder, genesisForkVersionStr, boostTypes.Root{}.String())
if err != nil {
log.WithError(err).Fatal("computing signing domain failed")
}
proposerSigningDomain, err := server.ComputeDomain(boostTypes.DomainTypeBeaconProposer, bellatrixForkVersionStr, genesisValidatorsRootStr)
if err != nil {
log.WithError(err).Fatal("computing signing domain failed")
}
doGetPayload(mustLoadValidator(validatorDataFile), boostEndpoint, createBeacon(isMergemock, beaconEndpoint, engineEndpoint), engineEndpoint, builderSigningDomain, proposerSigningDomain)
default:
fmt.Println("Expected generate|register|getHeader|getPayload subcommand")
os.Exit(1)
}
}

func computeDomain(domainType boostTypes.DomainType, forkVersionHex string, genesisValidatorsRootHex string) boostTypes.Domain {
genesisValidatorsRoot := boostTypes.Root(common.HexToHash(genesisValidatorsRootHex))
forkVersionBytes, err := hexutil.Decode(forkVersionHex)
if err != nil || len(forkVersionBytes) > 4 {
fmt.Println("Invalid fork version passed")
os.Exit(1)
}
var forkVersion [4]byte
copy(forkVersion[:], forkVersionBytes[:4])
return boostTypes.ComputeDomain(domainType, forkVersion, genesisValidatorsRoot)
}

func getEnv(key string, defaultValue string) string {
if value, ok := os.LookupEnv(key); ok {
return value
Expand Down
22 changes: 16 additions & 6 deletions server/mock_relay.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,18 @@ package server
import (
"encoding/json"
"fmt"
"github.com/flashbots/go-boost-utils/bls"
"github.com/flashbots/go-boost-utils/types"
"github.com/gorilla/mux"
"github.com/stretchr/testify/require"
"net/http"
"net/http/httptest"
"net/url"
"sync"
"testing"
"time"

"github.com/ethereum/go-ethereum/common/hexutil"
"github.com/flashbots/go-boost-utils/bls"
"github.com/flashbots/go-boost-utils/types"
"github.com/gorilla/mux"
"github.com/stretchr/testify/require"
)

// mockRelay is used to fake a relay's behavior.
Expand All @@ -22,8 +25,9 @@ type mockRelay struct {
t *testing.T

// KeyPair used to sign messages
secretKey *bls.SecretKey
publicKey *bls.PublicKey
secretKey *bls.SecretKey
publicKey *bls.PublicKey
RelayEntry RelayEntry

// Used to count each Request made to the relay, either if it fails or not, for each method
mu sync.Mutex
Expand Down Expand Up @@ -52,6 +56,12 @@ func newMockRelay(t *testing.T, secretKey *bls.SecretKey) *mockRelay {
// Initialize server
relay.Server = httptest.NewServer(relay.getRouter())

// Create the RelayEntry with correct pubkey
url, err := url.Parse(relay.Server.URL)
require.NoError(t, err)
urlWithKey := fmt.Sprintf("%s://%s@%s", url.Scheme, hexutil.Encode(publicKey.Compress()), url.Host)
relay.RelayEntry, err = NewRelayEntry(urlWithKey)
require.NoError(t, err)
return relay
}

Expand Down
9 changes: 3 additions & 6 deletions server/relay_entry.go
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
package server

import (
"github.com/flashbots/go-boost-utils/types"
"net/url"
"strings"

"github.com/flashbots/go-boost-utils/types"
)

// RelayEntry represents a relay that mev-boost connects to.
Expand Down Expand Up @@ -37,10 +38,6 @@ func NewRelayEntry(relayURL string) (entry RelayEntry, err error) {
entry.Address = entry.URL.Scheme + "://" + entry.URL.Host

// Extract the relay's public key from the parsed URL.
// TODO: Remove the if condition, as it is mandatory to verify relay's message signature.
if entry.URL.User.Username() != "" {
err = entry.PublicKey.UnmarshalText([]byte(entry.URL.User.Username()))
}

err = entry.PublicKey.UnmarshalText([]byte(entry.URL.User.Username()))
return entry, err
}
33 changes: 17 additions & 16 deletions server/relay_entry_test.go
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
package server

import (
"fmt"
"testing"

"github.com/flashbots/go-boost-utils/types"
"github.com/stretchr/testify/require"
"testing"
)

func TestParseRelaysURLs(t *testing.T) {
zeroPublicKey := types.PublicKey{0x0}
// Used to fake a relay's public key.
publicKey := types.PublicKey{0x01}

Expand All @@ -22,21 +23,21 @@ func TestParseRelaysURLs(t *testing.T) {
}{
{
name: "Relay URL with protocol scheme",
relayURL: "http://foo.com",
relayURL: fmt.Sprintf("http://%s@foo.com", publicKey.String()),

expectedErr: nil,
expectedAddress: "http://foo.com",
expectedPublicKey: zeroPublicKey.String(),
expectedURL: "http://foo.com",
expectedPublicKey: publicKey.String(),
expectedURL: fmt.Sprintf("http://%s@foo.com", publicKey.String()),
},
{
name: "Relay URL without protocol scheme",
name: "Relay URL without protocol scheme, without public key",
relayURL: "foo.com",

expectedErr: nil,
expectedAddress: "http://foo.com",
expectedPublicKey: zeroPublicKey.String(),
expectedURL: "http://foo.com",
expectedErr: types.ErrLength,
expectedAddress: "",
expectedPublicKey: "",
expectedURL: "",
},
{
name: "Relay URL without protocol scheme and with public key",
Expand All @@ -58,21 +59,21 @@ func TestParseRelaysURLs(t *testing.T) {
},
{
name: "Relay URL with IP and port",
relayURL: "12.345.678:9999",
relayURL: publicKey.String() + "@12.345.678:9999",

expectedErr: nil,
expectedAddress: "http://12.345.678:9999",
expectedPublicKey: zeroPublicKey.String(),
expectedURL: "http://12.345.678:9999",
expectedPublicKey: publicKey.String(),
expectedURL: "http://" + publicKey.String() + "@12.345.678:9999",
},
{
name: "Relay URL with https IP and port",
relayURL: "https://12.345.678:9999",
relayURL: "https://" + publicKey.String() + "@12.345.678:9999",

expectedErr: nil,
expectedAddress: "https://12.345.678:9999",
expectedPublicKey: zeroPublicKey.String(),
expectedURL: "https://12.345.678:9999",
expectedPublicKey: publicKey.String(),
expectedURL: "https://" + publicKey.String() + "@12.345.678:9999",
},
{
name: "Invalid relay public key",
Expand Down
Loading

0 comments on commit 6dcbd28

Please sign in to comment.