Skip to content

Commit

Permalink
op-node: Add p2p utils (ethereum-optimism#3153)
Browse files Browse the repository at this point in the history
* op-node: Add p2p utils

* Update op-node/flags/flags.go

Co-authored-by: Diederik Loerakker <[email protected]>

Co-authored-by: Diederik Loerakker <[email protected]>
  • Loading branch information
mslipper and protolambda authored Aug 1, 2022
1 parent 0c5ad1d commit 0e7184b
Show file tree
Hide file tree
Showing 6 changed files with 199 additions and 34 deletions.
12 changes: 10 additions & 2 deletions op-node/cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@ import (
"syscall"
"time"

"github.com/ethereum-optimism/optimism/op-node/cmd/p2p"

"github.com/ethereum-optimism/optimism/op-node/metrics"

opnode "github.com/ethereum-optimism/optimism/op-node"
Expand Down Expand Up @@ -53,13 +55,19 @@ func main() {
)

app := cli.NewApp()
app.Flags = flags.Flags
app.Version = VersionWithMeta
app.Flags = flags.Flags
app.Name = "opnode"
app.Usage = "Optimism Rollup Node"
app.Description = "The deposit only rollup node drives the L2 execution engine based on L1 deposits."

app.Action = RollupNodeMain
app.Commands = []cli.Command{
{
Name: "p2p",
Subcommands: p2p.Subcommands,
},
}

err := app.Run(os.Args)
if err != nil {
log.Crit("Application failed", "message", err)
Expand Down
106 changes: 106 additions & 0 deletions op-node/cmd/p2p/cmd.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,106 @@
package p2p

import (
"crypto/rand"
"encoding/hex"
"fmt"
"io"
"io/ioutil"
"os"
"strings"

"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/urfave/cli"
)

func Priv2PeerID(r io.Reader) (string, error) {
b, err := readHexData(r)
if err != nil {
return "", nil
}

p, err := crypto.UnmarshalSecp256k1PrivateKey(b)
if err != nil {
return "", fmt.Errorf("failed to parse priv key from %d bytes: %w", len(b), err)
}

pid, err := peer.IDFromPrivateKey(p)
if err != nil {
return "", fmt.Errorf("failed to parse peer ID from private key: %w", err)
}
return pid.String(), nil
}

func Pub2PeerID(r io.Reader) (string, error) {
b, err := readHexData(r)
if err != nil {
return "", nil
}

p, err := crypto.UnmarshalSecp256k1PublicKey(b)
if err != nil {
return "", fmt.Errorf("failed to parse pub key from %d bytes: %w", len(b), err)
}

pid, err := peer.IDFromPublicKey(p)
if err != nil {
return "", fmt.Errorf("failed to parse peer ID from public key: %w", err)
}

return pid.String(), nil
}

func readHexData(r io.Reader) ([]byte, error) {
data, err := ioutil.ReadAll(r)
if err != nil {
return nil, err
}

rawStr := strings.TrimSpace(string(data))
rawStr = strings.TrimPrefix(rawStr, "0x")
b, err := hex.DecodeString(rawStr)
if err != nil {
return nil, fmt.Errorf("p2p key is not formatted in hex chars: %w", err)
}
return b, nil
}

var Subcommands = cli.Commands{
{
Name: "priv2id",
Usage: "Reads a private key from STDIN, and returns a peer ID",
Action: func(ctx *cli.Context) error {
key, err := Priv2PeerID(os.Stdin)
if err != nil {
return err
}
fmt.Println(key)
return nil
},
},
{
Name: "pub2id",
Usage: "Reads a public key from STDIN, and returns a peer ID",
Action: func(ctx *cli.Context) error {
key, err := Pub2PeerID(os.Stdin)
if err != nil {
return err
}
fmt.Println(key)
return nil
},
},
{
Name: "genkey",
Usage: "Generates a private key",
Action: func(ctx *cli.Context) error {
buf := make([]byte, 32)
if _, err := rand.Read(buf); err != nil {
return fmt.Errorf("failed to get entropy: %w", err)
}
fmt.Println(hex.EncodeToString(buf))
return nil
},
},
}
35 changes: 35 additions & 0 deletions op-node/cmd/p2p/cmd_test.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package p2p

import (
"bytes"
"encoding/hex"
"testing"

"github.com/libp2p/go-libp2p-core/crypto"
"github.com/libp2p/go-libp2p-core/peer"
"github.com/stretchr/testify/require"
)

func TestPrivPub2PeerID(t *testing.T) {
priv, pub, err := crypto.GenerateKeyPair(crypto.Secp256k1, 32)
require.NoError(t, err)
privRaw, err := priv.Raw()
require.NoError(t, err)
pubRaw, err := pub.Raw()
require.NoError(t, err)

t.Run("with a private key", func(t *testing.T) {
privPidLib, err := peer.IDFromPrivateKey(priv)
require.NoError(t, err)
privPidImpl, err := Priv2PeerID(bytes.NewReader([]byte(hex.EncodeToString(privRaw))))
require.NoError(t, err)
require.Equal(t, privPidLib.String(), privPidImpl)
})
t.Run("with a public key", func(t *testing.T) {
pubPidLib, err := peer.IDFromPublicKey(pub)
require.NoError(t, err)
pubPidImpl, err := Pub2PeerID(bytes.NewReader([]byte(hex.EncodeToString(pubRaw))))
require.NoError(t, err)
require.Equal(t, pubPidLib.String(), pubPidImpl)
})
}
66 changes: 44 additions & 22 deletions op-node/flags/flags.go
Original file line number Diff line number Diff line change
@@ -1,6 +1,10 @@
package flags

import "github.com/urfave/cli"
import (
"fmt"

"github.com/urfave/cli"
)

// Flags

Expand All @@ -13,35 +17,30 @@ func prefixEnvVar(name string) string {
var (
/* Required Flags */
L1NodeAddr = cli.StringFlag{
Name: "l1",
Usage: "Address of L1 User JSON-RPC endpoint to use (eth namespace required)",
Required: true,
Value: "http://127.0.0.1:8545",
EnvVar: prefixEnvVar("L1_ETH_RPC"),
Name: "l1",
Usage: "Address of L1 User JSON-RPC endpoint to use (eth namespace required)",
Value: "http://127.0.0.1:8545",
EnvVar: prefixEnvVar("L1_ETH_RPC"),
}
L2EngineAddr = cli.StringFlag{
Name: "l2",
Usage: "Address of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)",
Required: true,
EnvVar: prefixEnvVar("L2_ENGINE_RPC"),
Name: "l2",
Usage: "Address of L2 Engine JSON-RPC endpoints to use (engine and eth namespace required)",
EnvVar: prefixEnvVar("L2_ENGINE_RPC"),
}
RollupConfig = cli.StringFlag{
Name: "rollup.config",
Usage: "Rollup chain parameters",
Required: true,
EnvVar: prefixEnvVar("ROLLUP_CONFIG"),
Name: "rollup.config",
Usage: "Rollup chain parameters",
EnvVar: prefixEnvVar("ROLLUP_CONFIG"),
}
RPCListenAddr = cli.StringFlag{
Name: "rpc.addr",
Usage: "RPC listening address",
Required: true,
EnvVar: prefixEnvVar("RPC_ADDR"),
Name: "rpc.addr",
Usage: "RPC listening address",
EnvVar: prefixEnvVar("RPC_ADDR"),
}
RPCListenPort = cli.IntFlag{
Name: "rpc.port",
Usage: "RPC listening port",
Required: true,
EnvVar: prefixEnvVar("RPC_PORT"),
Name: "rpc.port",
Usage: "RPC listening port",
EnvVar: prefixEnvVar("RPC_PORT"),
}

/* Optional Flags */
Expand Down Expand Up @@ -164,3 +163,26 @@ var optionalFlags = append([]cli.Flag{

// Flags contains the list of configuration options available to the binary.
var Flags = append(requiredFlags, optionalFlags...)

func CheckRequired(ctx *cli.Context) error {
l1NodeAddr := ctx.GlobalString(L1NodeAddr.Name)
if l1NodeAddr == "" {
return fmt.Errorf("flag %s is required", L1NodeAddr.Name)
}
l2EngineAddr := ctx.GlobalString(L2EngineAddr.Name)
if l2EngineAddr == "" {
return fmt.Errorf("flag %s is required", L2EngineAddr.Name)
}
rollupConfig := ctx.GlobalString(RollupConfig.Name)
if rollupConfig == "" {
return fmt.Errorf("flag %s is required", RollupConfig.Name)
}
rpcListenAddr := ctx.GlobalString(RPCListenAddr.Name)
if rpcListenAddr == "" {
return fmt.Errorf("flag %s is required", RPCListenAddr.Name)
}
if !ctx.GlobalIsSet(RPCListenPort.Name) {
return fmt.Errorf("flag %s is required", RPCListenPort.Name)
}
return nil
}
10 changes: 0 additions & 10 deletions op-node/flags/flags_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,16 +7,6 @@ import (
"github.com/urfave/cli"
)

// TestRequiredFlagsSetRequired asserts that all flags deemed required properly
// have the Required field set to true.
func TestRequiredFlagsSetRequired(t *testing.T) {
for _, flag := range requiredFlags {
reqFlag, ok := flag.(cli.RequiredFlag)
require.True(t, ok)
require.True(t, reqFlag.IsRequired())
}
}

// TestOptionalFlagsDontSetRequired asserts that all flags deemed optional set
// the Required field to false.
func TestOptionalFlagsDontSetRequired(t *testing.T) {
Expand Down
4 changes: 4 additions & 0 deletions op-node/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,10 @@ import (

// NewConfig creates a Config from the provided flags or environment variables.
func NewConfig(ctx *cli.Context, log log.Logger) (*node.Config, error) {
if err := flags.CheckRequired(ctx); err != nil {
return nil, err
}

rollupConfig, err := NewRollupConfig(ctx)
if err != nil {
return nil, err
Expand Down

0 comments on commit 0e7184b

Please sign in to comment.