Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cmd: write expanded form of enr in charon enr #913

Merged
merged 6 commits into from
Aug 4, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions cmd/createenr.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import (
"github.com/spf13/cobra"

"github.com/obolnetwork/charon/app/errors"
"github.com/obolnetwork/charon/app/z"
"github.com/obolnetwork/charon/p2p"
)

Expand All @@ -48,7 +49,13 @@ func newCreateEnrCmd(runFunc func(io.Writer, p2p.Config, string) error) *cobra.C
}

// runCreateEnrCmd stores a new charon-enr-private-key to disk and prints the ENR for the provided config.
// It returns an error if the key already exists.
func runCreateEnrCmd(w io.Writer, config p2p.Config, dataDir string) error {
_, err := p2p.LoadPrivKey(dataDir)
if err == nil {
return errors.New("charon-enr-private-key already exists", z.Str("enr_path", p2p.KeyPath(dataDir)))
}

key, err := p2p.NewSavedPrivKey(dataDir)
if err != nil {
return err
Expand Down
55 changes: 49 additions & 6 deletions cmd/enr.go
Original file line number Diff line number Diff line change
Expand Up @@ -16,41 +16,47 @@
package cmd

import (
"crypto/ecdsa"
"fmt"
"io"
"io/fs"
"strings"

"github.com/ethereum/go-ethereum/crypto"
"github.com/spf13/cobra"
"github.com/spf13/pflag"

"github.com/obolnetwork/charon/app/errors"
"github.com/obolnetwork/charon/app/z"
"github.com/obolnetwork/charon/p2p"
)

func newEnrCmd(runFunc func(io.Writer, p2p.Config, string) error) *cobra.Command {
func newEnrCmd(runFunc func(io.Writer, p2p.Config, string, bool) error) *cobra.Command {
var (
config p2p.Config
dataDir string
verbose bool
)

cmd := &cobra.Command{
Use: "enr",
Short: "Print this client's Ethereum Node Record",
Long: `Return information on this node's Ethereum Node Record (ENR)`,
Short: "Prints a new ENR for this node",
Long: `Prints a newly generated Ethereum Node Record (ENR) from this node's charon-enr-private-key`,
xenowits marked this conversation as resolved.
Show resolved Hide resolved
Args: cobra.NoArgs,
RunE: func(cmd *cobra.Command, args []string) error {
return runFunc(cmd.OutOrStdout(), config, dataDir)
return runFunc(cmd.OutOrStdout(), config, dataDir, verbose)
},
}

bindDataDirFlag(cmd.Flags(), &dataDir)
bindP2PFlags(cmd.Flags(), &config)
bindEnrFlags(cmd.Flags(), &verbose)

return cmd
}

// runNewENR loads the p2pkey from disk and prints the ENR for the provided config.
func runNewENR(w io.Writer, config p2p.Config, dataDir string) error {
func runNewENR(w io.Writer, config p2p.Config, dataDir string, verbose bool) error {
key, err := p2p.LoadPrivKey(dataDir)
if errors.Is(err, fs.ErrNotExist) {
return errors.New("private key not found. If this is your first time running this client, create one with `charon create enr`.", z.Str("enr_path", p2p.KeyPath(dataDir))) //nolint:revive
Expand All @@ -64,7 +70,44 @@ func runNewENR(w io.Writer, config p2p.Config, dataDir string) error {
}
defer db.Close()

_, _ = fmt.Fprintln(w, localEnode.Node().String())
newEnr := localEnode.Node().String()
_, _ = fmt.Fprintln(w, newEnr)

if !verbose {
return nil
}

r, err := p2p.DecodeENR(newEnr)
if err != nil {
return err
}

writeExpandedEnr(w, r.Signature(), r.Seq(), pubkeyHex(key.PublicKey))

return nil
}

// writeExpandedEnr writes the expanded form of ENR to the terminal.
func writeExpandedEnr(w io.Writer, sig []byte, seq uint64, pubkey string) {
var sb strings.Builder
_, _ = sb.WriteString("\n")
_, _ = sb.WriteString("***************** Decoded ENR (see https://enr-viewer.com/ for additional fields) **********************\n")
_, _ = sb.WriteString(fmt.Sprintf("secp256k1 pubkey: %#x\n", pubkey))
_, _ = sb.WriteString(fmt.Sprintf("signature: %#x\n", sig))
_, _ = sb.WriteString(fmt.Sprintf("seq: %d\n", seq))
_, _ = sb.WriteString("********************************************************************************************************\n")
_, _ = sb.WriteString("\n")

_, _ = w.Write([]byte(sb.String()))
}

// pubkeyHex returns compressed public key bytes.
func pubkeyHex(pubkey ecdsa.PublicKey) string {
b := crypto.CompressPubkey(&pubkey)

return fmt.Sprintf("%#x", b)
}

func bindEnrFlags(flags *pflag.FlagSet, verbose *bool) {
flags.BoolVar(verbose, "verbose", false, "Prints the expanded form of ENR.")
}
2 changes: 1 addition & 1 deletion cmd/enr_internal_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ func TestRunNewEnr(t *testing.T) {
temp, err := os.MkdirTemp("", "")
require.NoError(t, err)

got := runNewENR(io.Discard, p2p.Config{}, temp)
got := runNewENR(io.Discard, p2p.Config{}, temp, false)
expected := errors.New("private key not found. If this is your first time running this client, create one with `charon create enr`.", z.Str("enr_path", p2p.KeyPath(temp)))
require.Equal(t, expected.Error(), got.Error())
}