Skip to content
This repository has been archived by the owner on Jun 20, 2024. It is now read-only.

Commit

Permalink
feat: introduce log tags
Browse files Browse the repository at this point in the history
  • Loading branch information
mrekucci committed Mar 14, 2024
1 parent 164b836 commit 8afb18b
Show file tree
Hide file tree
Showing 11 changed files with 158 additions and 108 deletions.
63 changes: 27 additions & 36 deletions cmd/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@ package main

import (
"fmt"
"io"
"log/slog"
"os"
"path/filepath"
"slices"
Expand All @@ -14,6 +12,7 @@ import (
mevcommit "github.com/primevprotocol/mev-commit"
ks "github.com/primevprotocol/mev-commit/pkg/keysigner"
"github.com/primevprotocol/mev-commit/pkg/node"
"github.com/primevprotocol/mev-commit/pkg/util"
"github.com/urfave/cli/v2"
"github.com/urfave/cli/v2/altsrc"
)
Expand Down Expand Up @@ -158,6 +157,20 @@ var (
Action: stringInCheck("log-level", []string{"debug", "info", "warn", "error"}),
})

optionLogTags = altsrc.NewStringFlag(&cli.StringFlag{
Name: "log-tags",
Usage: "log tags is a comma-separated list of <name:value> pairs that will be inserted into each log line",
EnvVars: []string{"MEV_COMMIT_LOG_TAGS"},
Action: func(ctx *cli.Context, s string) error {
for i, p := range strings.Split(s, ",") {
if len(strings.Split(p, ":")) != 2 {
return fmt.Errorf("invalid log-tags at index %d, expecting <name:value>", i)
}
}
return nil
},
})

optionBidderRegistryAddr = altsrc.NewStringFlag(&cli.StringFlag{
Name: "bidder-registry-contract",
Usage: "address of the bidder registry contract",
Expand Down Expand Up @@ -229,6 +242,7 @@ func main() {
optionSecret,
optionLogFmt,
optionLogLevel,
optionLogTags,
optionBidderRegistryAddr,
optionProviderRegistryAddr,
optionPreconfStoreAddr,
Expand Down Expand Up @@ -274,20 +288,22 @@ func verifyKeystorePasswordPresence(c *cli.Context) error {

// launchNodeWithConfig configures and starts the p2p node based on the CLI context.
func launchNodeWithConfig(c *cli.Context) error {
keysigner, err := newKeySigner(c)
if err != nil {
return fmt.Errorf("failed to create keysigner: %w", err)
}

logger, err := newLogger(
logger, err := util.NewLogger(
c.String(optionLogLevel.Name),
c.String(optionLogFmt.Name),
c.String(optionLogTags.Name),
c.App.Writer,
)
if err != nil {
return fmt.Errorf("failed to create logger: %w", err)
}

keysigner, err := newKeySigner(c)
if err != nil {
return fmt.Errorf("failed to create keysigner: %w", err)
}
logger.Info("key signer account", "address", keysigner.GetAddress().Hex(), "url", keysigner.String())

httpAddr := fmt.Sprintf("%s:%d", c.String(optionHTTPAddr.Name), c.Int(optionHTTPPort.Name))
rpcAddr := fmt.Sprintf("%s:%d", c.String(optionRPCAddr.Name), c.Int(optionRPCPort.Name))
natAddr := ""
Expand Down Expand Up @@ -324,7 +340,7 @@ func launchNodeWithConfig(c *cli.Context) error {
}

<-c.Done()
fmt.Fprintln(c.App.Writer, "shutting down...")
logger.Info("shutting down...")
closed := make(chan struct{})

go func() {
Expand All @@ -345,34 +361,9 @@ func launchNodeWithConfig(c *cli.Context) error {
return nil
}

func newLogger(lvl, logFmt string, sink io.Writer) (*slog.Logger, error) {
level := new(slog.LevelVar)
if err := level.UnmarshalText([]byte(lvl)); err != nil {
return nil, fmt.Errorf("invalid log level: %w", err)
}

var (
handler slog.Handler
options = &slog.HandlerOptions{
AddSource: true,
Level: level,
}
)
switch logFmt {
case "text":
handler = slog.NewTextHandler(sink, options)
case "json", "none":
handler = slog.NewJSONHandler(sink, options)
default:
return nil, fmt.Errorf("invalid log format: %s", logFmt)
}

return slog.New(handler), nil
}

func newKeySigner(c *cli.Context) (ks.KeySigner, error) {
if c.IsSet(optionKeystorePath.Name) {
return ks.NewKeystoreSigner(c.App.Writer, c.String(optionKeystorePath.Name), c.String(optionKeystorePassword.Name))
return ks.NewKeystoreSigner(c.String(optionKeystorePath.Name), c.String(optionKeystorePassword.Name))
}
return ks.NewPrivateKeySigner(c.App.Writer, c.String(optionPrivKeyFile.Name))
return ks.NewPrivateKeySigner(c.String(optionPrivKeyFile.Name))
}
1 change: 0 additions & 1 deletion examples/biddercli/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,6 @@ func main() {

app.Before = func(c *cli.Context) error {
configFile := c.String(optionConfig.Name)
fmt.Printf("using configuration file: %s\n", configFile)

buf, err := os.ReadFile(configFile)
if err != nil {
Expand Down
29 changes: 18 additions & 11 deletions integrationtest/bidder/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ import (
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethclient"
pb "github.com/primevprotocol/mev-commit/gen/go/rpc/bidderapi/v1"
"github.com/primevprotocol/mev-commit/pkg/util"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
"google.golang.org/grpc"
Expand All @@ -44,6 +45,16 @@ var (
"debug",
"Verbosity level (debug|info|warn|error)",
)
logFmt = flag.String(
"log-fmt",
"text",
"Format of the log output: 'text', 'json'",
)
logTags = flag.String(
"log-tags",
"",
"Comma-separated list of <name:value> pairs that will be inserted into each log line",
)
httpPort = flag.Int(
"http-port",
8080,
Expand Down Expand Up @@ -85,22 +96,18 @@ var (

func main() {
flag.Parse()
if *serverAddr == "" {
fmt.Println("Please provide a valid server address with the -serverAddr flag")

logger, err := util.NewLogger(*logLevel, *logFmt, *logTags, os.Stdout)
if err != nil {
fmt.Printf("failed to create logger: %v", err)
return
}

level := new(slog.LevelVar)
if err := level.UnmarshalText([]byte(*logLevel)); err != nil {
level.Set(slog.LevelDebug)
fmt.Printf("Invalid log level: %s; using %q", err, level)
if *serverAddr == "" {
fmt.Println("Please provide a valid server address with the -serverAddr flag")
return
}

logger := slog.New(slog.NewTextHandler(
os.Stdout,
&slog.HandlerOptions{Level: level},
))

registry := prometheus.NewRegistry()
registry.MustRegister(
receivedPreconfs,
Expand Down
32 changes: 20 additions & 12 deletions integrationtest/provider/main.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,12 +6,12 @@ import (
"errors"
"flag"
"fmt"
"log/slog"
"math/rand"
"net/http"
"os"

providerapiv1 "github.com/primevprotocol/mev-commit/gen/go/rpc/providerapi/v1"
"github.com/primevprotocol/mev-commit/pkg/util"
"github.com/prometheus/client_golang/prometheus"
"github.com/prometheus/client_golang/prometheus/promhttp"
)
Expand All @@ -21,6 +21,8 @@ import (
const (
serverAddrFlagName = "server-addr"
logLevelFlagName = "log-level"
logFmtFlagName = "log-fmt"
logTagsFlagName = "log-tags"
httpPortFlagName = "http-port"
errorProbabilityFlagName = "error-probability"
)
Expand All @@ -36,6 +38,16 @@ var (
"debug",
"Verbosity level (debug|info|warn|error)",
)
logFmt = flag.String(
logFmtFlagName,
"text",
"Format of the log output: 'text', 'json'",
)
logTags = flag.String(
logTagsFlagName,
"",
"Comma-separated list of <name:value> pairs that will be inserted into each log line",
)
httpPort = flag.Int(
httpPortFlagName,
8080,
Expand Down Expand Up @@ -71,22 +83,18 @@ var (

func main() {
flag.Parse()
if *serverAddr == "" {
fmt.Printf("please provide a valid server address with the -%s flag\n", serverAddrFlagName)

logger, err := util.NewLogger(*logLevel, *logFmt, *logTags, os.Stdout)
if err != nil {
fmt.Printf("failed to create logger: %v", err)
return
}

level := new(slog.LevelVar)
if err := level.UnmarshalText([]byte(*logLevel)); err != nil {
level.Set(slog.LevelDebug)
fmt.Printf("invalid log level: %s; using %q", err, level)
if *serverAddr == "" {
fmt.Printf("please provide a valid server address with the -%s flag\n", serverAddrFlagName)
return
}

logger := slog.New(slog.NewTextHandler(
os.Stdout,
&slog.HandlerOptions{Level: level},
))

registry := prometheus.NewRegistry()
registry.MustRegister(receivedBids, sentBids)

Expand Down
3 changes: 3 additions & 0 deletions pkg/keysigner/keysigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,16 @@ package keysigner

import (
"crypto/ecdsa"
"fmt"
"math/big"

"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)

type KeySigner interface {
fmt.Stringer

SignHash(data []byte) ([]byte, error)
SignTx(tx *types.Transaction, chainID *big.Int) (*types.Transaction, error)
GetAddress() common.Address
Expand Down
24 changes: 12 additions & 12 deletions pkg/keysigner/keystoresigner.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package keysigner
import (
"crypto/ecdsa"
"fmt"
"io"
"math/big"
"runtime"

Expand All @@ -13,13 +12,13 @@ import (
"github.com/ethereum/go-ethereum/core/types"
)

type keystoreSigner struct {
type KeystoreSigner struct {
keystore *keystore.KeyStore
password string
account accounts.Account
}

func NewKeystoreSigner(wr io.Writer, path, password string) (*keystoreSigner, error) {
func NewKeystoreSigner(path, password string) (*KeystoreSigner, error) {
// lightscripts are using 4MB memory and taking approximately 100ms CPU time on a modern processor to decrypt
keystore := keystore.NewKeyStore(path, keystore.LightScryptN, keystore.LightScryptP)
ksAccounts := keystore.Accounts()
Expand All @@ -35,37 +34,38 @@ func NewKeystoreSigner(wr io.Writer, path, password string) (*keystoreSigner, er
account = ksAccounts[0]
}

fmt.Fprintf(wr, "Public address of the key: %s\n", account.Address.Hex())
fmt.Fprintf(wr, "Path of the secret key file: %s\n", account.URL.Path)

return &keystoreSigner{
return &KeystoreSigner{
keystore: keystore,
password: password,
account: account,
}, nil
}

func (kss *keystoreSigner) SignHash(hash []byte) ([]byte, error) {
func (kss *KeystoreSigner) SignHash(hash []byte) ([]byte, error) {
return kss.keystore.SignHashWithPassphrase(kss.account, kss.password, hash)
}

func (kss *keystoreSigner) SignTx(tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
func (kss *KeystoreSigner) SignTx(tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
return kss.keystore.SignTxWithPassphrase(kss.account, kss.password, tx, chainID)
}

func (kss *keystoreSigner) GetAddress() common.Address {
func (kss *KeystoreSigner) GetAddress() common.Address {
return kss.account.Address
}

func (kss *keystoreSigner) GetPrivateKey() (*ecdsa.PrivateKey, error) {
func (kss *KeystoreSigner) GetPrivateKey() (*ecdsa.PrivateKey, error) {
return extractPrivateKey(kss.account.URL.Path, kss.password)
}

func (kss *keystoreSigner) ZeroPrivateKey(key *ecdsa.PrivateKey) {
func (kss *KeystoreSigner) ZeroPrivateKey(key *ecdsa.PrivateKey) {
b := key.D.Bits()
for i := range b {
b[i] = 0
}
// Force garbage collection to remove the key from memory
runtime.GC()
}

func (kss *KeystoreSigner) String() string {
return kss.account.URL.String()
}
20 changes: 12 additions & 8 deletions pkg/keysigner/mock/mock.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,29 +9,33 @@ import (
"github.com/ethereum/go-ethereum/crypto"
)

type mockKeySigner struct {
type MockKeySigner struct {
privKey *ecdsa.PrivateKey
address common.Address
}

func NewMockKeySigner(privKey *ecdsa.PrivateKey, address common.Address) *mockKeySigner {
return &mockKeySigner{privKey: privKey, address: address}
func NewMockKeySigner(privKey *ecdsa.PrivateKey, address common.Address) *MockKeySigner {
return &MockKeySigner{privKey: privKey, address: address}
}

func (m *mockKeySigner) SignTx(tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
func (m *MockKeySigner) SignTx(tx *types.Transaction, chainID *big.Int) (*types.Transaction, error) {
return tx, nil
}

func (m *mockKeySigner) SignHash(hash []byte) ([]byte, error) {
func (m *MockKeySigner) SignHash(hash []byte) ([]byte, error) {
return crypto.Sign(hash, m.privKey)
}

func (m *mockKeySigner) GetAddress() common.Address {
func (m *MockKeySigner) GetAddress() common.Address {
return m.address
}

func (m *mockKeySigner) GetPrivateKey() (*ecdsa.PrivateKey, error) {
func (m *MockKeySigner) GetPrivateKey() (*ecdsa.PrivateKey, error) {
return m.privKey, nil
}

func (m *mockKeySigner) ZeroPrivateKey(key *ecdsa.PrivateKey) {}
func (m *MockKeySigner) ZeroPrivateKey(key *ecdsa.PrivateKey) {}

func (m *MockKeySigner) String() string {
return "mock"
}
Loading

0 comments on commit 8afb18b

Please sign in to comment.