diff --git a/cmd/main.go b/cmd/main.go index 3e0b83f..f1d3830 100644 --- a/cmd/main.go +++ b/cmd/main.go @@ -1,25 +1,21 @@ package main import ( - "crypto/ecdsa" "fmt" + "io" + "log/slog" "os" "path/filepath" + "slices" "strings" "time" - "github.com/ethereum/go-ethereum/accounts" - "github.com/ethereum/go-ethereum/accounts/keystore" "github.com/ethereum/go-ethereum/common" - "github.com/ethereum/go-ethereum/crypto" contracts "github.com/primevprotocol/contracts-abi/config" "github.com/primevprotocol/mev-oracle/pkg/keysigner" "github.com/primevprotocol/mev-oracle/pkg/node" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" "github.com/urfave/cli/v2" "github.com/urfave/cli/v2/altsrc" - "golang.org/x/crypto/sha3" ) const ( @@ -29,6 +25,24 @@ const ( defaultKeystore = "keystore" ) +var ( + portCheck = func(c *cli.Context, p int) error { + if p < 0 || p > 65535 { + return fmt.Errorf("invalid port number %d, expected 0 <= port <= 65535", p) + } + return nil + } + + stringInCheck = func(flag string, opts []string) func(c *cli.Context, s string) error { + return func(c *cli.Context, s string) error { + if !slices.Contains(opts, s) { + return fmt.Errorf("invalid %s option %q, expected one of %s", flag, s, strings.Join(opts, ", ")) + } + return nil + } + } +) + var ( optionConfig = &cli.StringFlag{ Name: "config", @@ -48,22 +62,36 @@ var ( Usage: "port to listen on for HTTP requests", EnvVars: []string{"MEV_ORACLE_HTTP_PORT"}, Value: defaultHTTPPort, - Action: func(c *cli.Context, p int) error { - if p < 0 || p > 65535 { - return fmt.Errorf("invalid port number: %d", p) - } - return nil - }, + Action: portCheck, + }) + + optionLogFmt = altsrc.NewStringFlag(&cli.StringFlag{ + Name: "log-fmt", + Usage: "log format to use, options are 'text' or 'json'", + EnvVars: []string{"MEV_ORACLE_LOG_FMT"}, + Value: "text", + Action: stringInCheck("log-fmt", []string{"text", "json"}), }) optionLogLevel = altsrc.NewStringFlag(&cli.StringFlag{ Name: "log-level", - Usage: "log level", + Usage: "log level to use, options are 'debug', 'info', 'warn', 'error'", EnvVars: []string{"MEV_ORACLE_LOG_LEVEL"}, Value: "info", - Action: func(c *cli.Context, l string) error { - _, err := zerolog.ParseLevel(l) - return err + 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 pairs that will be inserted into each log line", + EnvVars: []string{"MEV_ORACLE_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 ", i) + } + } + return nil }, }) @@ -161,7 +189,9 @@ func main() { optionConfig, optionPrivKeyFile, optionHTTPPort, + optionLogFmt, optionLogLevel, + optionLogTags, optionL1RPCUrl, optionSettlementRPCUrl, optionOracleContractAddr, @@ -196,72 +226,6 @@ func main() { } } -func createKeyIfNotExists(c *cli.Context, path string) error { - // check if key already exists - if _, err := os.Stat(path); err == nil { - fmt.Fprintf(c.App.Writer, "Using existing private key: %s\n", path) - return nil - } - - fmt.Fprintf(c.App.Writer, "Creating new private key: %s\n", path) - - // check if parent directory exists - if _, err := os.Stat(filepath.Dir(path)); os.IsNotExist(err) { - // create parent directory - if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { - return err - } - } - - privKey, err := crypto.GenerateKey() - if err != nil { - return err - } - - f, err := os.Create(path) - if err != nil { - return err - } - - defer f.Close() - - if err := crypto.SaveECDSA(path, privKey); err != nil { - return err - } - - wallet := getEthAddressFromPubKey(&privKey.PublicKey) - - fmt.Fprintf(c.App.Writer, "Private key saved to file: %s\n", path) - fmt.Fprintf(c.App.Writer, "Wallet address: %s\n", wallet.Hex()) - return nil -} - -func resolveFilePath(path string) (string, error) { - if path == "" { - return "", fmt.Errorf("path is empty") - } - - if strings.HasPrefix(path, "~") { - home, err := os.UserHomeDir() - if err != nil { - return "", err - } - - return filepath.Join(home, path[1:]), nil - } - - return path, nil -} - -func getEthAddressFromPubKey(key *ecdsa.PublicKey) common.Address { - pbBytes := crypto.FromECDSAPub(key) - hash := sha3.NewLegacyKeccak256() - hash.Write(pbBytes[1:]) - address := hash.Sum(nil)[12:] - - return common.BytesToAddress(address) -} - func initializeApplication(c *cli.Context) error { if err := verifyKeystorePasswordPresence(c); err != nil { return err @@ -283,18 +247,24 @@ func verifyKeystorePasswordPresence(c *cli.Context) error { // launchOracleWithConfig configures and starts the oracle based on the CLI context or config.yaml file. func launchOracleWithConfig(c *cli.Context) error { + logger, err := 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 := setupKeySigner(c) if err != nil { return fmt.Errorf("failed to setup key signer: %w", err) } - - lvl, _ := zerolog.ParseLevel(c.String(optionLogLevel.Name)) - - zerolog.SetGlobalLevel(lvl) - zerolog.TimeFieldFormat = zerolog.TimeFormatUnix - log.Logger = log.Output(os.Stdout).With().Caller().Logger() + logger.Info("key signer account", "address", keySigner.GetAddress().Hex(), "url", keySigner.String()) nd, err := node.NewNode(&node.Options{ + Logger: logger, KeySigner: keySigner, HTTPPort: c.Int(optionHTTPPort.Name), L1RPCUrl: c.String(optionL1RPCUrl.Name), @@ -322,63 +292,69 @@ func launchOracleWithConfig(c *cli.Context) error { err := nd.Close() if err != nil { - log.Error().Err(err).Msg("failed to close node") + logger.Error("failed to close node", "error", err) } }() select { case <-closed: case <-time.After(5 * time.Second): - log.Error().Msg("failed to close node in time") + logger.Error("failed to close node in time", "error", err) } return nil } -func setupKeySigner(c *cli.Context) (keysigner.KeySigner, error) { - if c.IsSet(optionKeystorePath.Name) { - return setupKeystoreSigner(c) +// newLogger initializes a *slog.Logger with specified level, format, and sink. +// - lvl: string representation of slog.Level +// - logFmt: format of the log output: "text", "json", "none" defaults to "json" +// - tags: comma-separated list of pairs that will be inserted into each log line +// - sink: destination for log output (e.g., os.Stdout, file) +// +// Returns a configured *slog.Logger on success or nil on failure. +func newLogger(lvl, logFmt, tags 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) } - return setupPrivateKeySigner(c) -} - -func setupKeystoreSigner(c *cli.Context) (keysigner.KeySigner, error) { - // Load the keystore file - ks := keystore.NewKeyStore(c.String(optionKeystorePath.Name), keystore.LightScryptN, keystore.LightScryptP) - password := c.String(optionKeystorePassword.Name) - ksAccounts := ks.Accounts() - var account accounts.Account - if len(ksAccounts) == 0 { - var err error - account, err = ks.NewAccount(password) - if err != nil { - return nil, fmt.Errorf("failed to create account: %w", err) + var ( + handler slog.Handler + options = &slog.HandlerOptions{ + AddSource: true, + Level: level, } - } else { - account = ksAccounts[0] + ) + 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) } - fmt.Fprintf(c.App.Writer, "Public address of the key: %s\n", account.Address.Hex()) - fmt.Fprintf(c.App.Writer, "Path of the secret key file: %s\n", account.URL.Path) - - return keysigner.NewKeystoreSigner(ks, password, account), nil -} + logger := slog.New(handler) -func setupPrivateKeySigner(c *cli.Context) (keysigner.KeySigner, error) { - privKeyFile, err := resolveFilePath(c.String(optionPrivKeyFile.Name)) - if err != nil { - return nil, fmt.Errorf("failed to get private key file path: %w", err) + if tags == "" { + return logger, nil } - if err := createKeyIfNotExists(c, privKeyFile); err != nil { - return nil, fmt.Errorf("failed to create private key: %w", err) + var args []any + for i, p := range strings.Split(tags, ",") { + kv := strings.Split(p, ":") + if len(kv) != 2 { + return nil, fmt.Errorf("invalid tag at index %d", i) + } + args = append(args, strings.ToValidUTF8(kv[0], "�"), strings.ToValidUTF8(kv[1], "�")) } - privKey, err := crypto.LoadECDSA(privKeyFile) - if err != nil { - return nil, fmt.Errorf("failed to load private key from file '%s': %w", privKeyFile, err) - } + return logger.With(args...), nil +} - return keysigner.NewPrivateKeySigner(privKey), nil +func setupKeySigner(c *cli.Context) (keysigner.KeySigner, error) { + if c.IsSet(optionKeystorePath.Name) { + return keysigner.NewKeystoreSigner(c.String(optionKeystorePath.Name), c.String(optionKeystorePassword.Name)) + } + return keysigner.NewPrivateKeySigner(c.String(optionPrivKeyFile.Name)) } diff --git a/go.mod b/go.mod index be273ea..f865253 100644 --- a/go.mod +++ b/go.mod @@ -8,10 +8,9 @@ require ( github.com/lib/pq v1.10.9 github.com/primevprotocol/contracts-abi v0.2.0 github.com/prometheus/client_golang v1.14.0 - github.com/rs/zerolog v1.31.0 github.com/testcontainers/testcontainers-go v0.27.0 github.com/urfave/cli/v2 v2.27.1 - golang.org/x/crypto v0.18.0 + golang.org/x/crypto v0.21.0 golang.org/x/sync v0.6.0 ) @@ -56,7 +55,6 @@ require ( github.com/klauspost/compress v1.17.5 // indirect github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect github.com/magiconair/properties v1.8.7 // indirect - github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-isatty v0.0.19 // indirect github.com/mattn/go-runewidth v0.0.14 // indirect github.com/matttproud/golang_protobuf_extensions v1.0.4 // indirect @@ -67,7 +65,7 @@ require ( github.com/morikuni/aec v1.0.0 // indirect github.com/opencontainers/go-digest v1.0.0 // indirect github.com/opencontainers/image-spec v1.1.0-rc5 // indirect - github.com/opencontainers/runc v1.1.5 // indirect + github.com/opencontainers/runc v1.1.12 // indirect github.com/pkg/errors v0.9.1 // indirect github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect github.com/prometheus/client_model v0.3.0 // indirect @@ -86,8 +84,8 @@ require ( github.com/yusufpapurcu/wmi v1.2.3 // indirect golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect golang.org/x/mod v0.14.0 // indirect - golang.org/x/net v0.20.0 // indirect - golang.org/x/sys v0.16.0 // indirect + golang.org/x/net v0.21.0 // indirect + golang.org/x/sys v0.18.0 // indirect golang.org/x/time v0.4.0 // indirect golang.org/x/tools v0.17.0 // indirect google.golang.org/genproto/googleapis/rpc v0.0.0-20230711160842-782d3b101e98 // indirect diff --git a/go.sum b/go.sum index d19163b..17483da 100644 --- a/go.sum +++ b/go.sum @@ -41,8 +41,6 @@ github.com/cespare/cp v0.1.0 h1:SE+dxFebS7Iik5LK0tsi1k9ZCxEaFX4AjQmoyA+1dJk= github.com/cespare/cp v0.1.0/go.mod h1:SOGHArjBr4JWaSDEVpWpo/hNg6RoKrls6Oh40hiwW+s= github.com/cespare/xxhash/v2 v2.2.0 h1:DC2CZ1Ep5Y4k3ZQ899DldepgrayRUGE6BBZ/cd9Cj44= github.com/cespare/xxhash/v2 v2.2.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs= -github.com/checkpoint-restore/go-criu/v5 v5.3.0/go.mod h1:E/eQpaFtUKGOOSEBZgmKAcn+zUUwWxqcaKZlF54wK8E= -github.com/cilium/ebpf v0.7.0/go.mod h1:/oI2+1shJiTGAMgl6/RgJr36Eo1jzrRcAWbcXO2usCA= github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw= github.com/cncf/udpa/go v0.0.0-20201120205902-5459f2c99403/go.mod h1:WmhPx2Nbnhtbo57+VJT5O0JRkEi1Wbu0z5j0R8u5Hbk= github.com/cockroachdb/datadriven v1.0.2/go.mod h1:a9RdTaap04u637JoCzcUoIcDmvwSUtcUFtT/C3kJlTU= @@ -62,7 +60,6 @@ github.com/consensys/bavard v0.1.13 h1:oLhMLOFGTLdlda/kma4VOJazblc7IM5y5QPd2A/Yj github.com/consensys/bavard v0.1.13/go.mod h1:9ItSMtA/dXMAiL7BG6bqW2m3NdSEObYWoH223nGHukI= github.com/consensys/gnark-crypto v0.12.1 h1:lHH39WuuFgVHONRl3J0LRBtuYdQTumFSDtJF7HpyG8M= github.com/consensys/gnark-crypto v0.12.1/go.mod h1:v2Gy7L/4ZRosZ7Ivs+9SfUDr0f5UlG+EM5t7MPHiLuY= -github.com/containerd/console v1.0.3/go.mod h1:7LqA/THxQ86k76b8c/EMSiaJ3h1eZkMkXar0TQ1gf3U= github.com/containerd/containerd v1.7.11 h1:lfGKw3eU35sjV0aG2eYZTiwFEY1pCzxdzicHP3SZILw= github.com/containerd/containerd v1.7.11/go.mod h1:5UluHxHTX2rdvYuZ5OJTC5m/KJNs0Zs9wVoJm9zf5ZE= github.com/containerd/log v0.1.0 h1:TCJt7ioM2cr/tfR8GPbGf9/VRAX8D2B4PjzCpfX540I= @@ -70,12 +67,9 @@ github.com/containerd/log v0.1.0/go.mod h1:VRRf09a7mHDIRezVKTRCrOq78v577GXq3bSa3 github.com/coreos/etcd v3.3.10+incompatible/go.mod h1:uF7uidLiAD3TWHmW31ZFd/JWoc32PjwdhPthX9715RE= github.com/coreos/go-etcd v2.0.0+incompatible/go.mod h1:Jez6KQU2B/sWsbdaef3ED8NzMklzPG4d5KIOhIy30Tk= github.com/coreos/go-semver v0.2.0/go.mod h1:nnelYz7RCh+5ahJtPPxZlU+153eP4D4r3EedlOD2RNk= -github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= -github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc= github.com/cpuguy83/dockercfg v0.3.1 h1:/FpZ+JaygUR/lZP2NlFI2DVfrOEMAIKP5wWEJdoYe9E= github.com/cpuguy83/dockercfg v0.3.1/go.mod h1:sugsbF4//dDlL/i+S+rtpIWp+5h0BHJHfjj5/jFyUJc= github.com/cpuguy83/go-md2man v1.0.10/go.mod h1:SmD6nW6nTyfqj6ABTjUi3V3JVMnlJmwcJI5acqYI6dE= -github.com/cpuguy83/go-md2man/v2 v2.0.0-20190314233015-f79a8a8ca69d/go.mod h1:maD7wRr/U5Z6m/iR4s+kqSMx2CaBsrgA7czyZG/E6dU= github.com/cpuguy83/go-md2man/v2 v2.0.3 h1:qMCsGGgs+MAzDFyp9LpAe1Lqy/fY/qCovCm0qnXZOBM= github.com/cpuguy83/go-md2man/v2 v2.0.3/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o= github.com/crate-crypto/go-kzg-4844 v0.7.0 h1:C0vgZRk4q4EZ/JgPfzuSoxdCq3C3mOZMBShovmncxvA= @@ -83,7 +77,6 @@ github.com/crate-crypto/go-kzg-4844 v0.7.0/go.mod h1:1kMhvPgI0Ky3yIa+9lFySEBUBXk github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E= github.com/creack/pty v1.1.18 h1:n56/Zwd5o6whRC5PMGretI4IdRLlmBXYNjScPaBgsbY= github.com/creack/pty v1.1.18/go.mod h1:MOBLtS5ELjhRRrroQr9kyvTxUAFNvYEK993ew/Vr4O4= -github.com/cyphar/filepath-securejoin v0.2.3/go.mod h1:aPGpWjXOXUn2NCNjFvBE6aRxGGx79pTxQpKOJNYHHl4= github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38= @@ -101,7 +94,6 @@ github.com/docker/docker v24.0.7+incompatible h1:Wo6l37AuwP3JaMnZa226lzVXGA3F9Ig github.com/docker/docker v24.0.7+incompatible/go.mod h1:eEKB0N0r5NX/I1kEveEz05bcu8tLC/8azJZsviup8Sk= github.com/docker/go-connections v0.4.0 h1:El9xVISelRB7BuFusrZozjnkIM5YnzCViNKohAFqRJQ= github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5XhDvyHbTtUxmeec= -github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/docker/go-units v0.5.0 h1:69rxXcBk27SvSaaxTtLh/8llcHD8vYHT7WSdRZ/jvr4= github.com/docker/go-units v0.5.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk= github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk= @@ -119,7 +111,6 @@ github.com/fasthttp-contrib/websocket v0.0.0-20160511215533-1f3b11f56072/go.mod github.com/fatih/structs v1.1.0/go.mod h1:9NiDSp5zOcgEDl+j00MP/WkGVPOlPRLejGD8Ga6PJ7M= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5 h1:FtmdgXiUlNeRsoNMFlKLDt+S+6hbjVMEW6RGQ7aUf7c= github.com/fjl/memsize v0.0.0-20190710130421-bcb5799ab5e5/go.mod h1:VvhXpOYNQvB+uIk2RvXzuaQtkQJzzIx6lSBe1xv7hi0= -github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/fsnotify/fsnotify v1.4.7/go.mod h1:jwhsz4b93w/PPRr/qN1Yymfu8t87LnFCMoQvtojpjFo= github.com/fsnotify/fsnotify v1.6.0 h1:n+5WquG0fcWoWp6xPWfHdbskMCQaFnG6PfBrh1Ky4HY= github.com/fsnotify/fsnotify v1.6.0/go.mod h1:sl3t1tCWJFWoRz9R8WJCbQihKKwmorjAbSClcnxKAGw= @@ -143,8 +134,6 @@ github.com/go-stack/stack v1.8.1/go.mod h1:dcoOX6HbPZSZptuspn9bctJ+N/CnF5gGygcUP github.com/gobwas/httphead v0.0.0-20180130184737-2c6c146eadee/go.mod h1:L0fX3K22YWvt/FAX9NnzrNzcI4wNYi9Yku4O0LKYflo= github.com/gobwas/pool v0.2.0/go.mod h1:q8bcK0KcYlCgd9e7WYLm9LpyS+YeLd8JVDW6WezmKEw= github.com/gobwas/ws v1.0.2/go.mod h1:szmBTxLgaFppYjEmNtny/v3w89xOydFnnZMcgRRu/EM= -github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= -github.com/godbus/dbus/v5 v5.0.6/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/gofrs/flock v0.8.1 h1:+gYjHKf32LDeiEEFhQaotPbLuUXjY5ZqxKgXy7n59aw= github.com/gofrs/flock v0.8.1/go.mod h1:F1TvTiK9OcQqauNUHlbJvyl9Qa1QvF/gOUDKA14jxHU= github.com/gogo/googleapis v0.0.0-20180223154316-0cd9801be74a/go.mod h1:gf4bu3Q80BeJ6H1S1vYPm8/ELATdvryBaNFGgqEef3s= @@ -182,7 +171,6 @@ github.com/google/go-cmp v0.3.0/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU= github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= -github.com/google/go-cmp v0.5.4/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE= github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY= @@ -238,7 +226,6 @@ github.com/klauspost/compress v1.17.5 h1:d4vBd+7CHydUqpFBgUEKkSdtSugf9YFmSkvUYPq github.com/klauspost/compress v1.17.5/go.mod h1:/dCuZOvVtNoHsyb+cuJD3itjs3NbnF6KH9zAO4BDxPM= github.com/klauspost/cpuid v1.2.1/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= -github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= @@ -269,7 +256,6 @@ github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hd github.com/mattn/go-isatty v0.0.9/go.mod h1:YNRxwqDuOph6SZLI9vUUz6OYw3QyUt7WiY2yME+cCiQ= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= -github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.19 h1:JITubQf0MOLdlGRuRq+jtsDlekdYPia9ZFsB8h/APPA= github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-runewidth v0.0.14 h1:+xnbZSEeDbOIg5/mE6JF0w6n9duR1l3/WmbinWVwUuU= @@ -290,7 +276,6 @@ github.com/mmcloughlin/addchain v0.4.0/go.mod h1:A86O+tHqZLMNO4w6ZZ4FlVQEadcoqky github.com/mmcloughlin/profile v0.1.1/go.mod h1:IhHD7q1ooxgwTgjxQYkACGA77oFTDdFVejUS1/tS/qU= github.com/moby/patternmatcher v0.6.0 h1:GmP9lR19aU5GqSSFko+5pRqHi+Ohk1O69aFiKkVGiPk= github.com/moby/patternmatcher v0.6.0/go.mod h1:hDPoyOpDY7OrrMDLaYoY3hf52gNCR/YOUYxkhApJIxc= -github.com/moby/sys/mountinfo v0.5.0/go.mod h1:3bMD3Rg+zkqx8MRYPi7Pyb0Ie97QEBmdxbhnCLlSvSU= github.com/moby/sys/sequential v0.5.0 h1:OPvI35Lzn9K04PBbCLW0g4LcFAJgHsvXsRyewg5lXtc= github.com/moby/sys/sequential v0.5.0/go.mod h1:tH2cOOs5V9MlPiXcQzRC+eEyab644PWKGRYaaV5ZZlo= github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0= @@ -302,7 +287,6 @@ github.com/modern-go/reflect2 v1.0.1/go.mod h1:bx2lNnkwVCuqBIxFjflWJWanXIb3Rllmb github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A= github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc= github.com/moul/http2curl v1.0.0/go.mod h1:8UbvGypXm98wA/IqH45anm5Y2Z6ep6O31QGOAZ3H0fQ= -github.com/mrunalp/fileutils v0.5.0/go.mod h1:M1WthSahJixYnrXQl/DFQuteStB1weuxD2QJNHXfbSQ= github.com/nats-io/jwt v0.3.0/go.mod h1:fRYCDE99xlTsqUzISS1Bi75UBJ6ljOJQOAAu5VglpSg= github.com/nats-io/nats.go v1.9.1/go.mod h1:ZjDU1L/7fJ09jvUSRVBR2e7+RnLiiIQyqyzEE/Zbp4w= github.com/nats-io/nkeys v0.1.0/go.mod h1:xpnFELMwJABBLVhffcfd1MZx6VsNRFpEugbxziKVo7w= @@ -316,10 +300,8 @@ github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM= github.com/opencontainers/image-spec v1.1.0-rc5 h1:Ygwkfw9bpDvs+c9E34SdgGOj41dX/cbdlwvlWt0pnFI= github.com/opencontainers/image-spec v1.1.0-rc5/go.mod h1:X4pATf0uXsnn3g5aiGIsVnJBR4mxhKzfwmvK/B2NTm8= -github.com/opencontainers/runc v1.1.5 h1:L44KXEpKmfWDcS02aeGm8QNTFXTo2D+8MYGDIJ/GDEs= -github.com/opencontainers/runc v1.1.5/go.mod h1:1J5XiS+vdZ3wCyZybsuxXZWGrgSr8fFJHLXuG2PsnNg= -github.com/opencontainers/runtime-spec v1.0.3-0.20210326190908-1c3f411f0417/go.mod h1:jwyrGlmzljRJv/Fgzds9SsS/C5hL+LL3ko9hs6T5lQ0= -github.com/opencontainers/selinux v1.10.0/go.mod h1:2i0OySw99QjzBBQByd1Gr9gSjvuho1lHsJxIJ3gGbJI= +github.com/opencontainers/runc v1.1.12 h1:BOIssBaW1La0/qbNZHXOOa71dZfZEQOzW7dqQf3phss= +github.com/opencontainers/runc v1.1.12/go.mod h1:S+lQwSfncpBha7XTy/5lBwWgm5+y5Ma/O44Ekby9FK8= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pingcap/errors v0.11.4/go.mod h1:Oi8TUi2kEtXXLMJk9l1cGmz20kV3TaQ0usTwv5KuLY8= github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA= @@ -350,16 +332,11 @@ github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZV github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs= github.com/rs/cors v1.7.0 h1:+88SsELBHx5r+hZ8TCkggzSstaWNbDvThkVK8H6f9ik= github.com/rs/cors v1.7.0/go.mod h1:gFx+x8UowdsKA9AchylcLynDq+nNFfI8FkUZdN/jGCU= -github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg= -github.com/rs/zerolog v1.31.0 h1:FcTR3NnLWW+NnTwwhFWiJSZr4ECLpqCm6QsEnyvbV4A= -github.com/rs/zerolog v1.31.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss= github.com/russross/blackfriday v1.5.2/go.mod h1:JO/DiYxRf+HjHt06OyowR9PTA263kcR/rfWxYHBV53g= -github.com/russross/blackfriday/v2 v2.0.1/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk= github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM= github.com/ryanuber/columnize v2.1.0+incompatible/go.mod h1:sm1tb6uqfes/u+d4ooFouqFdy9/2g9QGwK3SQygK0Ts= github.com/schollz/closestmatch v2.1.0+incompatible/go.mod h1:RtP1ddjLong6gTkbtmuhtR2uUrrJOpYzYRvbcPAid+g= -github.com/seccomp/libseccomp-golang v0.9.2-0.20220502022130-f33da4d89646/go.mod h1:JA8cRccbGaA1s33RQf7Y1+q9gHmZX1yB/z9WDN1C6fg= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible h1:Bn1aCHHRnjv4Bl16T8rcaFjYSrGrIZvpiGO6P3Q4GpU= github.com/shirou/gopsutil v3.21.4-0.20210419000835-c7a38de76ee5+incompatible/go.mod h1:5b4v6he4MtMOwMlS0TUMTu2PcXUg8+E1lC7eC3UO/RA= @@ -370,7 +347,6 @@ github.com/shoenig/go-m1cpu v0.1.6/go.mod h1:1JJMcUBvfNwpq05QDQVAnx3gUHr9IYF7GNg github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU= github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k= github.com/shurcooL/sanitized_anchor_name v1.0.0/go.mod h1:1NzhyTcUVG4SuEtjjoZeVRXNmyL/1OwPU0+IJeTBvfc= -github.com/sirupsen/logrus v1.8.1/go.mod h1:yWOB1SBYBC5VeMP7gHvWumXLIWorT60ONWic61uBYv0= github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ= github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ= github.com/smartystreets/assertions v0.0.0-20180927180507-b2de0cb4f26d/go.mod h1:OnSkiWE9lh6wB0YB77sQom3nweQdgAjqCqsofrRNTgc= @@ -397,7 +373,6 @@ github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcU github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/supranational/blst v0.3.11 h1:LyU6FolezeWAhvQk0k6O/d49jqgO52MSDDfYgbeoEm4= github.com/supranational/blst v0.3.11/go.mod h1:jZJtfjgudtNl4en1tzwPIV3KjUnQUvG3/j+w+fVonLw= -github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7 h1:epCh84lMvA70Z7CTTCmYQn2CKbY8j86K7/FAIr141uY= github.com/syndtr/goleveldb v1.0.1-0.20210819022825-2ae1ddf74ef7/go.mod h1:q4W45IWZaF22tdD+VEXcAWRA037jwmWEB5VWYORlTpc= github.com/testcontainers/testcontainers-go v0.27.0 h1:IeIrJN4twonTDuMuBNQdKZ+K97yd7VrmNGu+lDpYcDk= @@ -414,7 +389,6 @@ github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGr github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go/codec v0.0.0-20181204163529-d75b2dcb6bc8/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= -github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli/v2 v2.27.1 h1:8xSQ6szndafKVRmfyeUMxkNUJQMjL1F2zmsZ+qHpfho= github.com/urfave/cli/v2 v2.27.1/go.mod h1:8qnjx1vcq5s2/wpsqoZFndg2CE5tNFyrTvS6SinrnYQ= github.com/urfave/negroni v1.0.0/go.mod h1:Meg73S6kFm/4PpbYdq35yYWoCZ9mS/YSx+lKnmiohz4= @@ -423,8 +397,6 @@ github.com/valyala/fasthttp v1.6.0/go.mod h1:FstJa9V+Pj9vQ7OJie2qMHdwemEDaDiSdBn github.com/valyala/fasttemplate v1.0.1/go.mod h1:UQGH1tvbgY+Nz5t2n7tXsz52dQxojPUpymEIMZ47gx8= github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/tcplisten v0.0.0-20161114210144-ceec8f93295a/go.mod h1:v3UYOV9WzVtRmSR+PDvWpU/qWl4Wa5LApYYX4ZtKbio= -github.com/vishvananda/netlink v1.1.0/go.mod h1:cTgwzPIzzgDAYoQrMm0EdrjRUBkTqKYppBueQtXaqoE= -github.com/vishvananda/netns v0.0.0-20191106174202-0a2b9b5464df/go.mod h1:JP3t17pCcGlemwknint6hfoeCVQrEMVwxRLRjXpq+BU= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonschema v1.2.0/go.mod h1:anYRn/JVcOK2ZgGU+IjEV4nwlhoK5sQluxsYJ78Id3Y= @@ -448,8 +420,8 @@ golang.org/x/crypto v0.0.0-20191227163750-53104e6ec876/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20210322153248-0c34fe9e7dc2/go.mod h1:T9bdIzuCu7OtxOm1hfPfRQxPLYneinmdGuTeoZ9dtd4= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= -golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc= -golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg= +golang.org/x/crypto v0.21.0 h1:X31++rzVUdKhX5sWmSOFZxx8UW/ldWx55cbf08iNAMA= +golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA= golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08= @@ -477,12 +449,11 @@ golang.org/x/net v0.0.0-20190827160401-ba9fcec4b297/go.mod h1:z5CRVTTTmAJ677TzLL golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= -golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20211008194852-3b03d305991f/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= -golang.org/x/net v0.20.0 h1:aCL9BSgETF1k+blQaYUBx9hJ9LOGP3gAVemcZlf1Kpo= -golang.org/x/net v0.20.0/go.mod h1:z8BVo6PvndSri0LbOE3hAn0apkU+1YvI6E70E9jsnvY= +golang.org/x/net v0.21.0 h1:AQyQV4dYCvJ7vGmJyKki9+PBdyvhkSd8EIx/qb0AYv4= +golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM= @@ -500,18 +471,14 @@ golang.org/x/sys v0.0.0-20181205085412-a5c9d58dba9a/go.mod h1:STP8DvDyc/dI5b8T5h golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190626221950-04f50cda93cb/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190813064441-fde4db37ae7a/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20191115151921-52ab43148777/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200116001909-b77594299b42/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200223170610-d5e6a3e2c0ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= -golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210403161142-5e06dd20ab57/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= @@ -519,23 +486,18 @@ golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210616094352-59db8d763f22/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20210906170528-6f6e22806c34/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20211007075335-d3039528d8ac/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211025201205-69cdffdb9359/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20211116061358-0a5406a5449c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220209214540-3681064d5158/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220908164124-27713097b956/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.11.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.15.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= -golang.org/x/sys v0.16.0 h1:xWw16ngr6ZMtmxDyKyIgsE93KNKz5HKmMa3b8ALHidU= -golang.org/x/sys v0.16.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= +golang.org/x/sys v0.18.0 h1:DBdB3niSjOA/O0blCZBqDefyWNYveAYMNF1Wum0DYQ4= +golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= @@ -595,7 +557,6 @@ google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpAD google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= -google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.32.0 h1:pPC6BG5ex8PDFnkbrGU3EixyhKcQ2aDuBS36lqK/C7I= google.golang.org/protobuf v1.32.0/go.mod h1:c6P6GXX6sHbq/GpV6MGZEdwhWPcYBgnhAHhKbcUYpos= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= diff --git a/pkg/apiserver/apiserver.go b/pkg/apiserver/apiserver.go index 7903a0b..d59f69f 100644 --- a/pkg/apiserver/apiserver.go +++ b/pkg/apiserver/apiserver.go @@ -5,6 +5,7 @@ import ( "context" "encoding/json" "expvar" + "log/slog" "net" "net/http" "net/http/pprof" @@ -15,7 +16,6 @@ import ( "github.com/prometheus/client_golang/prometheus" "github.com/prometheus/client_golang/prometheus/collectors" "github.com/prometheus/client_golang/prometheus/promhttp" - "github.com/rs/zerolog/log" ) const ( @@ -25,6 +25,7 @@ const ( // Service wraps http.Server with additional functionality for metrics and // other common middlewares. type Service struct { + logger *slog.Logger metricsRegistry *prometheus.Registry router *http.ServeMux srv *http.Server @@ -32,8 +33,9 @@ type Service struct { } // New creates a new Service. -func New(st *store.Store) *Service { +func New(logger *slog.Logger, st *store.Store) *Service { srv := &Service{ + logger: logger, router: http.NewServeMux(), metricsRegistry: newMetrics(), storage: st, @@ -44,12 +46,12 @@ func New(st *store.Store) *Service { return srv } -func (a *Service) registerDebugEndpoints() { +func (s *Service) registerDebugEndpoints() { // register metrics handler - a.router.Handle("/metrics", promhttp.HandlerFor(a.metricsRegistry, promhttp.HandlerOpts{})) + s.router.Handle("/metrics", promhttp.HandlerFor(s.metricsRegistry, promhttp.HandlerOpts{})) // register pprof handlers - a.router.Handle( + s.router.Handle( "/debug/pprof", http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { u := r.URL @@ -57,17 +59,17 @@ func (a *Service) registerDebugEndpoints() { http.Redirect(w, r, u.String(), http.StatusPermanentRedirect) }), ) - a.router.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index)) - a.router.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline)) - a.router.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile)) - a.router.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol)) - a.router.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace)) - a.router.Handle("/debug/pprof/{profile}", http.HandlerFunc(pprof.Index)) - a.router.Handle("/debug/vars", expvar.Handler()) + s.router.Handle("/debug/pprof/", http.HandlerFunc(pprof.Index)) + s.router.Handle("/debug/pprof/cmdline", http.HandlerFunc(pprof.Cmdline)) + s.router.Handle("/debug/pprof/profile", http.HandlerFunc(pprof.Profile)) + s.router.Handle("/debug/pprof/symbol", http.HandlerFunc(pprof.Symbol)) + s.router.Handle("/debug/pprof/trace", http.HandlerFunc(pprof.Trace)) + s.router.Handle("/debug/pprof/{profile}", http.HandlerFunc(pprof.Index)) + s.router.Handle("/debug/vars", expvar.Handler()) } -func (a *Service) registerStatsEndpoints() { - a.router.HandleFunc("/processed_blocks", func(w http.ResponseWriter, r *http.Request) { +func (s *Service) registerStatsEndpoints() { + s.router.HandleFunc("/processed_blocks", func(w http.ResponseWriter, r *http.Request) { pg := r.URL.Query().Get("page") lim := r.URL.Query().Get("limit") @@ -83,16 +85,16 @@ func (a *Service) registerStatsEndpoints() { } } - blocks, err := a.storage.ProcessedBlocks(limit, page) + blocks, err := s.storage.ProcessedBlocks(limit, page) if err != nil { - log.Error().Err(err).Msg("failed to get processed blocks") + s.logger.Error("failed to get processed blocks", "error", err) w.WriteHeader(http.StatusInternalServerError) return } resp, err := json.Marshal(blocks) if err != nil { - log.Error().Err(err).Msg("failed to marshal processed blocks") + s.logger.Error("failed to marshal processed blocks", "error", err) w.WriteHeader(http.StatusInternalServerError) return } @@ -101,21 +103,21 @@ func (a *Service) registerStatsEndpoints() { w.WriteHeader(http.StatusOK) _, err = w.Write(resp) if err != nil { - log.Error().Err(err).Msg("failed to write response") + s.logger.Error("failed to write response", "error", err) } }) - a.router.HandleFunc("/stats", func(w http.ResponseWriter, r *http.Request) { - stats, err := a.storage.CommitmentStats() + s.router.HandleFunc("/stats", func(w http.ResponseWriter, r *http.Request) { + stats, err := s.storage.CommitmentStats() if err != nil { - log.Error().Err(err).Msg("failed to get stats") + s.logger.Error("failed to get stats", "error", err) w.WriteHeader(http.StatusInternalServerError) return } resp, err := json.Marshal(stats) if err != nil { - log.Error().Err(err).Msg("failed to marshal stats") + s.logger.Error("failed to marshal stats", "error", err) w.WriteHeader(http.StatusInternalServerError) return } @@ -124,7 +126,7 @@ func (a *Service) registerStatsEndpoints() { w.WriteHeader(http.StatusOK) _, err = w.Write(resp) if err != nil { - log.Error().Err(err).Msg("failed to write response") + s.logger.Error("failed to write response", "error", err) } }) } @@ -143,8 +145,8 @@ func newMetrics() (r *prometheus.Registry) { return r } -func (a *Service) Start(addr string) <-chan struct{} { - log.Info().Msg("starting api server") +func (s *Service) Start(addr string) <-chan struct{} { + s.logger.Info("starting api server") srv := &http.Server{ Addr: addr, @@ -152,16 +154,17 @@ func (a *Service) Start(addr string) <-chan struct{} { recorder := &responseStatusRecorder{ResponseWriter: w} start := time.Now() - a.router.ServeHTTP(recorder, req) - log.Info(). - Int("status", recorder.status). - Str("method", req.Method). - Str("path", req.URL.Path). - Dur("duration", time.Since(start)). - Msg("api access") + s.router.ServeHTTP(recorder, req) + s.logger.Info( + "api access", + slog.Int("status", recorder.status), + slog.String("method", req.Method), + slog.String("path", req.URL.Path), + slog.Duration("duration", time.Since(start)), + ) }), } - a.srv = srv + s.srv = srv done := make(chan struct{}) go func() { @@ -169,24 +172,24 @@ func (a *Service) Start(addr string) <-chan struct{} { err := srv.ListenAndServe() if err != nil && err != http.ErrServerClosed { - log.Fatal().Err(err).Msg("api server failed") + s.logger.Error("api server failed", "error", err) } }() return done } -func (a *Service) Stop() error { - log.Info().Msg("stopping api server") - if a.srv == nil { +func (s *Service) Stop() error { + s.logger.Info("stopping api server") + if s.srv == nil { return nil } - return a.srv.Shutdown(context.Background()) + return s.srv.Shutdown(context.Background()) } // RegisterMetricsCollectors registers prometheus collectors. -func (a *Service) RegisterMetricsCollectors(cs ...prometheus.Collector) { - a.metricsRegistry.MustRegister(cs...) +func (s *Service) RegisterMetricsCollectors(cs ...prometheus.Collector) { + s.metricsRegistry.MustRegister(cs...) } type responseStatusRecorder struct { diff --git a/pkg/keysigner/keysigner.go b/pkg/keysigner/keysigner.go index 3b9fd7e..6ca3c5b 100644 --- a/pkg/keysigner/keysigner.go +++ b/pkg/keysigner/keysigner.go @@ -2,7 +2,11 @@ package keysigner import ( "crypto/ecdsa" + "fmt" "math/big" + "os" + "path/filepath" + "strings" "github.com/ethereum/go-ethereum/accounts" "github.com/ethereum/go-ethereum/accounts/abi/bind" @@ -12,50 +16,158 @@ import ( ) type KeySigner interface { + fmt.Stringer + GetAddress() common.Address GetAuth(chainID *big.Int) (*bind.TransactOpts, error) + GetPrivateKey() (*ecdsa.PrivateKey, error) } -type privateKeySigner struct { +type PrivateKeySigner struct { + path string privKey *ecdsa.PrivateKey } -func NewPrivateKeySigner(privKey *ecdsa.PrivateKey) *privateKeySigner { - return &privateKeySigner{ - privKey: privKey, +func NewPrivateKeySigner(path string) (*PrivateKeySigner, error) { + privKeyFile, err := resolveFilePath(path) + if err != nil { + return nil, fmt.Errorf("failed to get private key file path: %w", err) + } + + if err := createKeyIfNotExists(privKeyFile); err != nil { + return nil, fmt.Errorf("failed to create private key: %w", err) + } + + privKey, err := crypto.LoadECDSA(privKeyFile) + if err != nil { + return nil, fmt.Errorf("failed to load private key from file '%s': %w", privKeyFile, err) } + + return &PrivateKeySigner{ + path: privKeyFile, + privKey: privKey, + }, nil } -func (pks *privateKeySigner) GetAddress() common.Address { +func (pks *PrivateKeySigner) GetAddress() common.Address { return crypto.PubkeyToAddress(pks.privKey.PublicKey) } -func (pks *privateKeySigner) GetAuth(chainID *big.Int) (*bind.TransactOpts, error) { +func (pks *PrivateKeySigner) GetAuth(chainID *big.Int) (*bind.TransactOpts, error) { return bind.NewKeyedTransactorWithChainID(pks.privKey, chainID) } -type keystoreSigner struct { +func (pks *PrivateKeySigner) GetPrivateKey() (*ecdsa.PrivateKey, error) { + return pks.privKey, nil +} + +func (pks *PrivateKeySigner) String() string { + return pks.path +} + +type KeystoreSigner struct { keystore *keystore.KeyStore password string account accounts.Account } -func NewKeystoreSigner(keystore *keystore.KeyStore, password string, account accounts.Account) *keystoreSigner { - return &keystoreSigner{ - keystore: keystore, +func NewKeystoreSigner(path, password string) (*KeystoreSigner, error) { + ks := keystore.NewKeyStore(path, keystore.LightScryptN, keystore.LightScryptP) + ksAccounts := ks.Accounts() + + var account accounts.Account + if len(ksAccounts) == 0 { + var err error + account, err = ks.NewAccount(password) + if err != nil { + return nil, fmt.Errorf("failed to create account: %w", err) + } + } else { + account = ksAccounts[0] + } + + return &KeystoreSigner{ + keystore: ks, password: password, account: account, - } + }, nil } -func (kss *keystoreSigner) GetAddress() common.Address { +func (kss *KeystoreSigner) GetAddress() common.Address { return kss.account.Address } -func (kss *keystoreSigner) GetAuth(chainID *big.Int) (*bind.TransactOpts, error) { +func (kss *KeystoreSigner) GetAuth(chainID *big.Int) (*bind.TransactOpts, error) { if err := kss.keystore.Unlock(kss.account, kss.password); err != nil { return nil, err } return bind.NewKeyStoreTransactorWithChainID(kss.keystore, kss.account, chainID) } + +func (kss *KeystoreSigner) GetPrivateKey() (*ecdsa.PrivateKey, error) { + return extractPrivateKey(kss.account.URL.Path, kss.password) +} + +func (kss *KeystoreSigner) String() string { + return kss.account.URL.String() +} + +func resolveFilePath(path string) (string, error) { + if path == "" { + return "", fmt.Errorf("path is empty") + } + + if strings.HasPrefix(path, "~") { + home, err := os.UserHomeDir() + if err != nil { + return "", err + } + + return filepath.Join(home, path[1:]), nil + } + + return path, nil +} + +func createKeyIfNotExists(path string) error { + // check if key already exists + if _, err := os.Stat(path); err == nil { + return nil + } + + // check if parent directory exists + if _, err := os.Stat(filepath.Dir(path)); os.IsNotExist(err) { + // create parent directory + if err := os.MkdirAll(filepath.Dir(path), 0700); err != nil { + return err + } + } + + privKey, err := crypto.GenerateKey() + if err != nil { + return err + } + + return crypto.SaveECDSA(path, privKey) +} + +func extractPrivateKey(keystoreFile, passphrase string) (*ecdsa.PrivateKey, error) { + keyjson, err := os.ReadFile(keystoreFile) + if err != nil { + return nil, err + } + + key, err := keystore.DecryptKey(keyjson, passphrase) + if err != nil { + return nil, err + } + + // Overwrite the keyjson slice with zeros to wipe the sensitive data from memory. + // This is a security measure to reduce the risk of the encrypted key being extracted from memory. + for i := range keyjson { + keyjson[i] = 0 + } + + return key.PrivateKey, nil +} diff --git a/pkg/l1Listener/l1Listener.go b/pkg/l1Listener/l1Listener.go index ad6d981..b5e9e2e 100644 --- a/pkg/l1Listener/l1Listener.go +++ b/pkg/l1Listener/l1Listener.go @@ -3,12 +3,12 @@ package l1Listener import ( "bytes" "context" + "log/slog" "math/big" "time" "github.com/ethereum/go-ethereum/core/types" "github.com/prometheus/client_golang/prometheus" - "github.com/rs/zerolog/log" ) var checkInterval = 2 * time.Second @@ -23,16 +23,19 @@ type EthClient interface { } type L1Listener struct { + logger *slog.Logger l1Client EthClient winnerRegister WinnerRegister metrics *metrics } func NewL1Listener( + logger *slog.Logger, l1Client EthClient, winnerRegister WinnerRegister, ) *L1Listener { return &L1Listener{ + logger: logger, l1Client: l1Client, winnerRegister: winnerRegister, metrics: newMetrics(), @@ -60,7 +63,7 @@ func (l *L1Listener) Start(ctx context.Context) <-chan struct{} { case <-ticker.C: blockNum, err := l.l1Client.BlockNumber(ctx) if err != nil { - log.Error().Err(err).Msg("failed to get block number") + l.logger.Error("failed to get block number", "error", err) continue } @@ -70,34 +73,25 @@ func (l *L1Listener) Start(ctx context.Context) <-chan struct{} { header, err := l.l1Client.HeaderByNumber(ctx, big.NewInt(int64(blockNum))) if err != nil { - log.Error().Err(err). - Uint64("block", blockNum). - Msg("failed to get header") + l.logger.Error("failed to get header", "block", blockNum, "error", err) continue } winner := string(bytes.ToValidUTF8(header.Extra, []byte("�"))) if len(winner) == 0 { - log.Warn(). - Int64("block", header.Number.Int64()). - Msg("no winner registered") + l.logger.Warn("no winner registered", "block", header.Number.Int64()) continue } else { err = l.winnerRegister.RegisterWinner(ctx, int64(blockNum), winner) if err != nil { - log.Error().Err(err). - Uint64("block", blockNum). - Msg("failed to register winner for block") + l.logger.Error("failed to register winner for block", "block", blockNum, "error", err) return } l.metrics.WinnerRoundCount.WithLabelValues(winner).Inc() l.metrics.WinnerCount.Inc() - log.Info(). - Str("winner", winner). - Int64("block", header.Number.Int64()). - Msg("registered winner") + l.logger.Info("registered winner", "winner", winner, "block", header.Number.Int64()) } currentBlockNo = int(blockNum) } diff --git a/pkg/l1Listener/l1Listener_test.go b/pkg/l1Listener/l1Listener_test.go index 69c327b..f644df8 100644 --- a/pkg/l1Listener/l1Listener_test.go +++ b/pkg/l1Listener/l1Listener_test.go @@ -4,6 +4,8 @@ import ( "context" "errors" "fmt" + "io" + "log/slog" "math/big" "sort" "sync" @@ -25,7 +27,11 @@ func TestL1Listener(t *testing.T) { errC: make(chan error, 1), } - l := l1Listener.NewL1Listener(ethClient, reg) + l := l1Listener.NewL1Listener( + slog.New(slog.NewTextHandler(io.Discard, nil)), + ethClient, + reg, + ) ctx, cancel := context.WithCancel(context.Background()) cl := l1Listener.SetCheckInterval(100 * time.Millisecond) diff --git a/pkg/node/node.go b/pkg/node/node.go index fec8fdd..08cb042 100644 --- a/pkg/node/node.go +++ b/pkg/node/node.go @@ -6,6 +6,7 @@ import ( "errors" "fmt" "io" + "log/slog" "math/big" "time" @@ -21,10 +22,10 @@ import ( "github.com/primevprotocol/mev-oracle/pkg/settler" "github.com/primevprotocol/mev-oracle/pkg/store" "github.com/primevprotocol/mev-oracle/pkg/updater" - "github.com/rs/zerolog/log" ) type Options struct { + Logger *slog.Logger KeySigner keysigner.KeySigner HTTPPort int SettlementRPCUrl string @@ -41,23 +42,24 @@ type Options struct { } type Node struct { + logger *slog.Logger waitClose func() dbCloser io.Closer } func NewNode(opts *Options) (*Node, error) { - nd := &Node{} + nd := &Node{logger: opts.Logger} db, err := initDB(opts) if err != nil { - log.Error().Err(err).Msg("failed initializing DB") + opts.Logger.Error("failed initializing DB", "error", err) return nil, err } nd.dbCloser = db st, err := store.NewStore(db) if err != nil { - log.Error().Err(err).Msg("failed initializing store") + nd.logger.Error("failed initializing store", "error", err) return nil, err } @@ -65,19 +67,19 @@ func NewNode(opts *Options) (*Node, error) { settlementClient, err := ethclient.Dial(opts.SettlementRPCUrl) if err != nil { - log.Fatal().Err(err).Msg("failed to connect to the settlement layer") + nd.logger.Error("failed to connect to the settlement layer", "error", err) return nil, err } chainID, err := settlementClient.ChainID(context.Background()) if err != nil { - log.Fatal().Err(err).Msg("failed getting chain ID") + nd.logger.Error("failed getting chain ID", "error", err) return nil, err } l1Client, err := ethclient.Dial(opts.L1RPCUrl) if err != nil { - log.Fatal().Err(err).Msg("Failed to connect to the L1 Ethereum client") + nd.logger.Error("Failed to connect to the L1 Ethereum client", "error", err) return nil, err } @@ -95,14 +97,14 @@ func NewNode(opts *Options) (*Node, error) { settlementClient, ) if err != nil { - log.Fatal().Err(err).Msg("failed to instantiate preconf contract") + nd.logger.Error("failed to instantiate preconf contract", "error", err) cancel() return nil, err } oracleContract, err := rollupclient.NewOracle(opts.OracleContractAddr, settlementClient) if err != nil { - log.Fatal().Err(err).Msg("failed to instantiate oracle contract") + nd.logger.Error("failed to instantiate oracle contract", "error", err) cancel() return nil, err } @@ -120,14 +122,14 @@ func NewNode(opts *Options) (*Node, error) { winner, ) if err != nil { - log.Fatal().Err(err).Msg("failed to set builder mapping") + nd.logger.Error("failed to set builder mapping", "error", err) cancel() return nil, err } } } - l1Lis := l1Listener.NewL1Listener(listenerL1Client, st) + l1Lis := l1Listener.NewL1Listener(nd.logger.With("component", "l1_listener"), listenerL1Client, st) l1LisClosed := l1Lis.Start(ctx) callOpts := bind.CallOpts{ @@ -142,10 +144,11 @@ func NewNode(opts *Options) (*Node, error) { } oc := &rollupclient.OracleSession{Contract: oracleContract, CallOpts: callOpts} - updtr := updater.NewUpdater(l1Client, st, oc, pc) + updtr := updater.NewUpdater(nd.logger.With("component", "updater"), l1Client, st, oc, pc) updtrClosed := updtr.Start(ctx) settlr := settler.NewSettler( + nd.logger.With("component", "settler"), opts.KeySigner, chainID, owner, @@ -155,7 +158,7 @@ func NewNode(opts *Options) (*Node, error) { ) settlrClosed := settlr.Start(ctx) - srv := apiserver.New(st) + srv := apiserver.New(nd.logger.With("component", "apiserver"), st) srv.RegisterMetricsCollectors(l1Lis.Metrics()...) srv.RegisterMetricsCollectors(updtr.Metrics()...) srv.RegisterMetricsCollectors(settlr.Metrics()...) @@ -202,10 +205,10 @@ func (n *Node) Close() (err error) { select { case <-workersClosed: - log.Info().Msg("All workers closed") + n.logger.Info("all workers closed") return nil case <-time.After(10 * time.Second): - log.Error().Msg("Timeout waiting for workers to close") + n.logger.Error("timeout waiting for workers to close") return errors.New("timeout waiting for workers to close") } } diff --git a/pkg/settler/settler.go b/pkg/settler/settler.go index 19ac995..21cc08c 100644 --- a/pkg/settler/settler.go +++ b/pkg/settler/settler.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "log/slog" "math/big" "strings" "sync" @@ -14,7 +15,6 @@ import ( "github.com/ethereum/go-ethereum/core/types" "github.com/primevprotocol/mev-oracle/pkg/keysigner" "github.com/prometheus/client_golang/prometheus" - "github.com/rs/zerolog/log" "golang.org/x/sync/errgroup" ) @@ -83,6 +83,7 @@ type Transactor interface { } type Settler struct { + logger *slog.Logger keySigner keysigner.KeySigner chainID *big.Int owner common.Address @@ -94,6 +95,7 @@ type Settler struct { } func NewSettler( + logger *slog.Logger, keySigner keysigner.KeySigner, chainID *big.Int, owner common.Address, @@ -102,6 +104,7 @@ func NewSettler( client Transactor, ) *Settler { return &Settler{ + logger: logger, rollupClient: rollupClient, settlerRegister: settlerRegister, owner: owner, @@ -166,7 +169,7 @@ func (s *Settler) settlementUpdater(ctx context.Context) error { currentBlock, err := s.client.BlockNumber(ctx) if err != nil { - log.Error().Err(err).Msg("failed to get block number") + s.logger.Error("failed to get block number", "error", err) continue } @@ -180,13 +183,13 @@ func (s *Settler) settlementUpdater(ctx context.Context) error { new(big.Int).SetUint64(currentBlock), ) if err != nil { - log.Error().Err(err).Msg("failed to get nonce") + s.logger.Error("failed to get nonce", "error", err) continue } count, err := s.settlerRegister.MarkSettlementComplete(ctx, lastNonce) if err != nil { - log.Error().Err(err).Msg("failed to mark settlement complete") + s.logger.Error("failed to mark settlement complete", "error", err) continue } @@ -195,7 +198,7 @@ func (s *Settler) settlementUpdater(ctx context.Context) error { s.metrics.SettlementsConfirmedCount.Add(float64(count)) if count > 0 { - log.Info().Int("count", count).Msg("marked settlement complete") + s.logger.Info("marked settlement complete", "count", count) } lastBlock = currentBlock @@ -223,9 +226,7 @@ RESTART: defer s.txMtx.Unlock() if settlement.Type == SettlementTypeReturn { - log.Warn(). - Str("commitmentIdx", fmt.Sprintf("%x", settlement.CommitmentIdx)). - Msg("return settlement") + s.logger.Warn("return settlement", "commitmentIdx", fmt.Sprintf("%x", settlement.CommitmentIdx)) return nil } @@ -274,18 +275,19 @@ RESTART: s.metrics.SettlementsPostedCount.Inc() s.metrics.CurrentSettlementL1Block.Set(float64(settlement.BlockNum)) - log.Info(). - Int64("blockNum", settlement.BlockNum). - Str("txHash", commitmentPostingTxn.Hash().Hex()). - Str("builder", settlement.Builder). - Str("settlementType", string(settlement.Type)). - Uint64("nonce", commitmentPostingTxn.Nonce()). - Msg("builder commitment processed") + s.logger.Info( + "builder commitment processed", + "blockNum", settlement.BlockNum, + "txHash", commitmentPostingTxn.Hash().Hex(), + "builder", settlement.Builder, + "settlementType", string(settlement.Type), + "nonce", commitmentPostingTxn.Nonce(), + ) return nil }() if err != nil { - log.Error().Err(err).Msg("failed to process builder commitment") + s.logger.Error("failed to process builder commitment", "error", err) unsub() time.Sleep(5 * time.Second) goto RESTART @@ -335,10 +337,7 @@ RESTART: bidIDs = append(bidIDs, b) } - log.Debug(). - Stringer("bidIDs", returns). - Int("count", len(returns.BidIDs)). - Msg("processing return") + s.logger.Debug("processing return", "bidIDs", returns, "count", len(returns.BidIDs)) commitmentPostingTxn, err := s.rollupClient.UnlockFunds( opts, @@ -361,16 +360,17 @@ RESTART: s.metrics.LastUsedNonce.Set(float64(commitmentPostingTxn.Nonce())) s.metrics.SettlementsPostedCount.Inc() - log.Info(). - Str("txHash", commitmentPostingTxn.Hash().Hex()). - Int("batchSize", len(returns.BidIDs)). - Uint64("nonce", commitmentPostingTxn.Nonce()). - Msg("builder return processed") + s.logger.Info( + "builder return processed", + "txHash", commitmentPostingTxn.Hash().Hex(), + "batchSize", len(returns.BidIDs), + "nonce", commitmentPostingTxn.Nonce(), + ) return nil }() if err != nil { - log.Error().Err(err).Msg("failed to process return") + s.logger.Error("failed to process return", "error", err) unsub() time.Sleep(5 * time.Second) goto RESTART @@ -399,7 +399,7 @@ func (s *Settler) Start(ctx context.Context) <-chan struct{} { go func() { defer close(doneChan) if err := eg.Wait(); err != nil { - log.Error().Err(err).Msg("settler error") + s.logger.Error("settler error", "error", err) } }() diff --git a/pkg/settler/settler_test.go b/pkg/settler/settler_test.go index b86d5be..78bbf66 100644 --- a/pkg/settler/settler_test.go +++ b/pkg/settler/settler_test.go @@ -4,7 +4,10 @@ import ( "context" "crypto/ecdsa" "fmt" + "io" + "log/slog" "math/big" + "path" "sync" "sync/atomic" "testing" @@ -13,7 +16,6 @@ import ( "github.com/ethereum/go-ethereum/accounts/abi/bind" "github.com/ethereum/go-ethereum/common" "github.com/ethereum/go-ethereum/core/types" - "github.com/ethereum/go-ethereum/crypto" "github.com/primevprotocol/mev-oracle/pkg/keysigner" "github.com/primevprotocol/mev-oracle/pkg/settler" ) @@ -196,14 +198,17 @@ func waitForCount(dur time.Duration, expected int, f func() int) error { func TestSettler(t *testing.T) { t.Parallel() - key, err := crypto.GenerateKey() + ks, err := keysigner.NewPrivateKeySigner(path.Join(t.TempDir(), "key")) if err != nil { t.Fatal(err) } - - ks := keysigner.NewPrivateKeySigner(key) ownerAddr := common.HexToAddress("0xabcd") + key, err := ks.GetPrivateKey() + if err != nil { + t.Fatal(err) + } + orcl := &testOracle{key: key} reg := &testRegister{ settlementChan: make(chan settler.Settlement), @@ -212,6 +217,7 @@ func TestSettler(t *testing.T) { transactor := &testTransactor{} s := settler.NewSettler( + slog.New(slog.NewTextHandler(io.Discard, nil)), ks, big.NewInt(1000), ownerAddr, diff --git a/pkg/updater/updater.go b/pkg/updater/updater.go index 2704f40..1a4bcba 100644 --- a/pkg/updater/updater.go +++ b/pkg/updater/updater.go @@ -4,6 +4,7 @@ import ( "context" "errors" "fmt" + "log/slog" "math/big" "strings" @@ -13,7 +14,6 @@ import ( preconf "github.com/primevprotocol/contracts-abi/clients/PreConfCommitmentStore" "github.com/primevprotocol/mev-oracle/pkg/settler" "github.com/prometheus/client_golang/prometheus" - "github.com/rs/zerolog/log" ) type BlockWinner struct { @@ -50,6 +50,7 @@ type Preconf interface { } type Updater struct { + logger *slog.Logger l1Client L1Client winnerRegister WinnerRegister preconfClient Preconf @@ -59,12 +60,14 @@ type Updater struct { } func NewUpdater( + logger *slog.Logger, l1Client L1Client, winnerRegister WinnerRegister, rollupClient Oracle, preconfClient Preconf, ) *Updater { return &Updater{ + logger: logger, l1Client: l1Client, winnerRegister: winnerRegister, preconfClient: preconfClient, @@ -107,9 +110,7 @@ func (u *Updater) Start(ctx context.Context) <-chan struct{} { builderAddr, err = u.rollupClient.GetBuilder(winner.Winner) if err != nil { if errors.Is(err, ethereum.NotFound) { - log.Warn(). - Str("builder", winner.Winner). - Msg("builder not registered") + u.logger.Warn("builder not registered", "builder", winner.Winner) return u.winnerRegister.UpdateComplete(ctx, winner.BlockNumber) } return fmt.Errorf("failed to get builder address: %w", err) @@ -134,11 +135,12 @@ func (u *Updater) Start(ctx context.Context) <-chan struct{} { return fmt.Errorf("failed to get commitments by block number: %w", err) } - log.Debug(). - Int("commitments_count", len(commitmentIndexes)). - Int("txns_count", len(txnsInBlock)). - Int64("blockNumber", winner.BlockNumber). - Msg("commitment indexes") + u.logger.Debug( + "commitment indexes", + "commitments_count", len(commitmentIndexes), + "txns_count", len(txnsInBlock), + "blockNumber", winner.BlockNumber, + ) total, rewards, slashes := 0, 0, 0 for _, index := range commitmentIndexes { @@ -196,22 +198,20 @@ func (u *Updater) Start(ctx context.Context) <-chan struct{} { u.metrics.SlashesCount.Add(float64(slashes)) u.metrics.BlockCommitmentsCount.Inc() - log.Info(). - Int("total", total). - Int("rewards", rewards). - Int("slashes", slashes). - Int64("blockNumber", winner.BlockNumber). - Str("winner", winner.Winner). - Msg("added settlements") + u.logger.Info( + "added settlements", + "total", total, + "rewards", rewards, + "slashes", slashes, + "blockNumber", winner.BlockNumber, + "winner", winner.Winner, + ) return nil }() if err != nil { - log.Error().Err(err). - Int64("blockNumber", winner.BlockNumber). - Str("winner", winner.Winner). - Msg("failed to process settlements") + u.logger.Error("failed to process settlements", "blockNumber", winner.BlockNumber, "winner", winner.Winner, "error", err) unsub() goto RESTART } diff --git a/pkg/updater/updater_test.go b/pkg/updater/updater_test.go index 9c219e1..9d5657f 100644 --- a/pkg/updater/updater_test.go +++ b/pkg/updater/updater_test.go @@ -5,6 +5,8 @@ import ( "errors" "fmt" "hash" + "io" + "log/slog" "math/big" "strings" "testing" @@ -131,6 +133,7 @@ func TestUpdater(t *testing.T) { } updtr := updater.NewUpdater( + slog.New(slog.NewTextHandler(io.Discard, nil)), testL1Client, testWinnerRegister, testOracle, @@ -248,6 +251,7 @@ func TestUpdaterBundlesFailure(t *testing.T) { } updtr := updater.NewUpdater( + slog.New(slog.NewTextHandler(io.Discard, nil)), testL1Client, testWinnerRegister, testOracle,