Skip to content

Commit

Permalink
cmd: write expanded form of enr in charon enr (#913)
Browse files Browse the repository at this point in the history
- `charon create enr` now errors when `charon-enr-private-key` already exists.
- `charon enr` now also outputs`secp256k1 pubkey`, `signature` and `seq` in addition to the `enr` when the `--verbose` flag is provided.

category: refactor
ticket: #893
  • Loading branch information
xenowits authored Aug 4, 2022
1 parent b7d5237 commit 4453fee
Show file tree
Hide file tree
Showing 3 changed files with 57 additions and 7 deletions.
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`,
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())
}

0 comments on commit 4453fee

Please sign in to comment.