diff --git a/cmd/zetaclientd/start.go b/cmd/zetaclientd/start.go index 9906d735fc..38182d1c13 100644 --- a/cmd/zetaclientd/start.go +++ b/cmd/zetaclientd/start.go @@ -6,8 +6,6 @@ import ( _ "net/http/pprof" // #nosec G108 -- pprof enablement is intentional "os" "os/signal" - "path/filepath" - "strings" "syscall" "github.com/pkg/errors" @@ -15,7 +13,6 @@ import ( "github.com/rs/zerolog/log" "github.com/spf13/cobra" - "github.com/zeta-chain/node/pkg/authz" "github.com/zeta-chain/node/pkg/chains" "github.com/zeta-chain/node/pkg/constant" zetaos "github.com/zeta-chain/node/pkg/os" @@ -27,7 +24,6 @@ import ( "github.com/zeta-chain/node/zetaclient/metrics" "github.com/zeta-chain/node/zetaclient/orchestrator" zetatss "github.com/zeta-chain/node/zetaclient/tss" - "github.com/zeta-chain/node/zetaclient/zetacore" ) const ( @@ -36,119 +32,80 @@ const ( envPprofAddr = "PPROF_ADDR" ) -// Start starts zetaclientd process todo revamp -// https://github.com/zeta-chain/node/issues/3112 +// Start starts zetaclientd process func Start(_ *cobra.Command, _ []string) error { - // Prompt for Hotkey, TSS key-share and relayer key passwords - titles := []string{"HotKey", "TSS", "Solana Relayer Key"} - passwords, err := zetaos.PromptPasswords(titles) + // Load Config file given path + cfg, err := config.Load(globalOpts.ZetacoreHome) if err != nil { - return errors.Wrap(err, "unable to get passwords") - } - hotkeyPass, tssKeyPass, solanaKeyPass := passwords[0], passwords[1], passwords[2] - relayerKeyPasswords := map[string]string{ - chains.Network_solana.String(): solanaKeyPass, + return errors.Wrap(err, "unable to load config") } - // Load Config file given path - cfg, err := config.Load(globalOpts.ZetacoreHome) + dbPath, err := config.ResolveDBPath() if err != nil { - return err + return errors.Wrap(err, "unable to resolve db path") } - logger, err := base.InitLogger(cfg) + // Configure logger (also overrides the default log level) + logger, err := base.NewLogger(cfg) if err != nil { - return errors.Wrap(err, "initLogger failed") + return errors.Wrap(err, "unable to create logger") } - masterLogger := logger.Std - startLogger := logger.Std.With().Str("module", "startup").Logger() + passes, err := promptPasswords() + if err != nil { + return errors.Wrap(err, "unable to prompt for passwords") + } - appContext := zctx.New(cfg, relayerKeyPasswords, masterLogger) + appContext := zctx.New(cfg, passes.relayerKeys(), logger.Std) ctx := zctx.WithAppContext(context.Background(), appContext) - // Wait until zetacore is up - waitForZetaCore(cfg, startLogger) - startLogger.Info().Msgf("Zetacore is ready, trying to connect to %s", cfg.Peer) - + // TODO graceful telemetryServer := metrics.NewTelemetryServer() go func() { err := telemetryServer.Start() if err != nil { - startLogger.Error().Err(err).Msg("telemetryServer error") - panic("telemetryServer error") + log.Fatal().Err(err).Msg("telemetryServer error") } }() - go runPprof(startLogger) - - // CreateZetacoreClient: zetacore client is used for all communication to zetacore , which this client connects to. - // Zetacore accumulates votes , and provides a centralized source of truth for all clients - zetacoreClient, err := createZetacoreClient(cfg, hotkeyPass, masterLogger) + m, err := metrics.NewMetrics() if err != nil { - return errors.Wrap(err, "unable to create zetacore client") + return errors.Wrap(err, "unable to create metrics") } + m.Start() - // Wait until zetacore is ready to create blocks - if err = waitForZetacoreToCreateBlocks(ctx, zetacoreClient, startLogger); err != nil { - startLogger.Error().Err(err).Msg("WaitForZetacoreToCreateBlocks error") - return err - } - startLogger.Info().Msgf("Zetacore client is ready") + metrics.Info.WithLabelValues(constant.Version).Set(1) + metrics.LastStartTime.SetToCurrentTime() - // Set grantee account number and sequence number - err = zetacoreClient.SetAccountNumber(authz.ZetaClientGranteeKey) - if err != nil { - startLogger.Error().Err(err).Msg("SetAccountNumber error") - return err - } + telemetryServer.SetIPAddress(cfg.PublicIP) - // cross-check chainid - res, err := zetacoreClient.GetNodeInfo(ctx) + // TODO graceful + go runPprof(logger.Std) + + // zetacore client is used for all communication to zeta node. + // it accumulates votes, and provides a source of truth for all clients + zetacoreClient, err := createZetacoreClient(cfg, passes.hotkey, logger.Std) if err != nil { - startLogger.Error().Err(err).Msg("GetNodeInfo error") - return err + return errors.Wrap(err, "unable to create zetacore client") } - if strings.Compare(res.GetDefaultNodeInfo().Network, cfg.ChainID) != 0 { - startLogger.Warn(). - Msgf("chain id mismatch, zetacore chain id %s, zetaclient configured chain id %s; reset zetaclient chain id", res.GetDefaultNodeInfo().Network, cfg.ChainID) - cfg.ChainID = res.GetDefaultNodeInfo().Network - err := zetacoreClient.UpdateChainID(cfg.ChainID) - if err != nil { - return err - } + // Wait until zetacore is ready to produce blocks + if err = waitForBlocks(ctx, zetacoreClient, logger.Std); err != nil { + return errors.Wrap(err, "zetacore unavailable") } - // CreateAuthzSigner : which is used to sign all authz messages . All votes broadcast to zetacore are wrapped in authz exec . - // This is to ensure that the user does not need to keep their operator key online , and can use a cold key to sign votes - signerAddress, err := zetacoreClient.GetKeys().GetAddress() - if err != nil { - return errors.Wrap(err, "error getting signer address") + if err = prepareZetacoreClient(ctx, zetacoreClient, &cfg, logger.Std); err != nil { + return errors.Wrap(err, "unable to prepare zetacore client") } - createAuthzSigner(zetacoreClient.GetKeys().GetOperatorAddress().String(), signerAddress) - startLogger.Debug().Msgf("createAuthzSigner is ready") - // Initialize core parameters from zetacore - if err = orchestrator.UpdateAppContext(ctx, appContext, zetacoreClient, startLogger); err != nil { + if err = orchestrator.UpdateAppContext(ctx, appContext, zetacoreClient, logger.Std); err != nil { return errors.Wrap(err, "unable to update app context") } - startLogger.Info().Msgf("Config is updated from zetacore\n %s", cfg.StringMasked()) + log.Info().Msgf("Config is updated from zetacore\n %s", cfg.StringMasked()) - m, err := metrics.NewMetrics() - if err != nil { - return errors.Wrap(err, "unable to create metrics") - } - m.Start() - - metrics.Info.WithLabelValues(constant.Version).Set(1) - metrics.LastStartTime.SetToCurrentTime() - - telemetryServer.SetIPAddress(cfg.PublicIP) - - granteePubKeyBech32, err := resolveObserverPubKeyBech32(cfg, hotkeyPass) + granteePubKeyBech32, err := resolveObserverPubKeyBech32(cfg, passes.hotkey) if err != nil { return errors.Wrap(err, "unable to resolve observer pub key bech32") } @@ -157,44 +114,30 @@ func Start(_ *cobra.Command, _ []string) error { Config: cfg, Zetacore: zetacoreClient, GranteePubKeyBech32: granteePubKeyBech32, - HotKeyPassword: hotkeyPass, - TSSKeyPassword: tssKeyPass, + HotKeyPassword: passes.hotkey, + TSSKeyPassword: passes.tss, BitcoinChainIDs: btcChainIDsFromContext(appContext), PostBlame: isEnvFlagEnabled(envFlagPostBlame), Telemetry: telemetryServer, } - tss, err := zetatss.Setup(ctx, tssSetupProps, startLogger) + tss, err := zetatss.Setup(ctx, tssSetupProps, logger.Std) if err != nil { return errors.Wrap(err, "unable to setup TSS service") } // Creating a channel to listen for os signals (or other signals) + // TODO graceful signalChannel := make(chan os.Signal, 1) signal.Notify(signalChannel, syscall.SIGINT, syscall.SIGTERM) // Starts various background TSS listeners. // Shuts down zetaclientd if any is triggered. - maintenance.NewTSSListener(zetacoreClient, masterLogger).Listen(ctx, func() { - masterLogger.Info().Msg("TSS listener received an action to shutdown zetaclientd.") + maintenance.NewTSSListener(zetacoreClient, logger.Std).Listen(ctx, func() { + logger.Std.Info().Msg("TSS listener received an action to shutdown zetaclientd.") signalChannel <- syscall.SIGTERM }) - if len(appContext.ListChainIDs()) == 0 { - startLogger.Error().Interface("config", cfg).Msgf("No chains in updated config") - } - - isObserver, err := isObserverNode(ctx, zetacoreClient) - switch { - case err != nil: - startLogger.Error().Msgf("Unable to determine if node is an observer") - return err - case !isObserver: - addr := zetacoreClient.GetKeys().GetOperatorAddress().String() - startLogger.Info().Str("operator_address", addr).Msg("This node is not an observer. Exit 0") - return nil - } - // CreateSignerMap: This creates a map of all signers for each chain. // Each signer is responsible for signing transactions for a particular chain signerMap, err := orchestrator.CreateSignerMap(ctx, tss, logger) @@ -203,16 +146,9 @@ func Start(_ *cobra.Command, _ []string) error { return err } - userDir, err := os.UserHomeDir() - if err != nil { - log.Error().Err(err).Msg("os.UserHomeDir") - return err - } - dbpath := filepath.Join(userDir, ".zetaclient/chainobserver") - // Creates a map of all chain observers for each chain. // Each chain observer is responsible for observing events on the chain and processing them. - observerMap, err := orchestrator.CreateChainObserverMap(ctx, zetacoreClient, tss, dbpath, logger, telemetryServer) + observerMap, err := orchestrator.CreateChainObserverMap(ctx, zetacoreClient, tss, dbPath, logger, telemetryServer) if err != nil { return errors.Wrap(err, "unable to create chain observer map") } @@ -226,7 +162,7 @@ func Start(_ *cobra.Command, _ []string) error { signerMap, observerMap, tss, - dbpath, + dbPath, logger, telemetryServer, ) @@ -239,48 +175,17 @@ func Start(_ *cobra.Command, _ []string) error { return errors.Wrap(err, "unable to start orchestrator") } - // start zeta supply checker - // TODO: enable - // https://github.com/zeta-chain/node/issues/1354 - // NOTE: this is disabled for now because we need to determine the frequency on how to handle invalid check - // The method uses GRPC query to the node we might need to improve for performance - //zetaSupplyChecker, err := mc.NewZetaSupplyChecker(cfg, zetacoreClient, masterLogger) - //if err != nil { - // startLogger.Err(err).Msg("NewZetaSupplyChecker") - //} - //if err == nil { - // zetaSupplyChecker.Start() - // defer zetaSupplyChecker.Stop() - //} - - startLogger.Info().Msg("zetaclientd is running") + log.Info().Msg("zetaclientd is running") + // todo graceful sig := <-signalChannel - startLogger.Info().Msgf("Stop signal received: %q. Stopping zetaclientd", sig) + log.Info().Msgf("Stop signal received: %q. Stopping zetaclientd", sig) maestro.Stop() return nil } -// isObserverNode checks whether THIS node is an observer node. -func isObserverNode(ctx context.Context, client *zetacore.Client) (bool, error) { - observers, err := client.GetObserverList(ctx) - if err != nil { - return false, errors.Wrap(err, "unable to get observers list") - } - - operatorAddress := client.GetKeys().GetOperatorAddress().String() - - for _, observer := range observers { - if observer == operatorAddress { - return true, nil - } - } - - return false, nil -} - func resolveObserverPubKeyBech32(cfg config.Config, hotKeyPassword string) (string, error) { // Get observer's public key ("grantee pub key") _, granteePubKeyBech32, err := keys.GetKeyringKeybase(cfg, hotKeyPassword) @@ -307,3 +212,31 @@ func runPprof(logger zerolog.Logger) { logger.Error().Err(err).Msg("pprof http server error") } } + +type passwords struct { + hotkey string + tss string + solanaRelayerKey string +} + +// promptPasswords prompts for Hotkey, TSS key-share and relayer key passwords +func promptPasswords() (passwords, error) { + titles := []string{"HotKey", "TSS", "Solana Relayer Key"} + + res, err := zetaos.PromptPasswords(titles) + if err != nil { + return passwords{}, errors.Wrap(err, "unable to get passwords") + } + + return passwords{ + hotkey: res[0], + tss: res[1], + solanaRelayerKey: res[2], + }, nil +} + +func (p passwords) relayerKeys() map[string]string { + return map[string]string{ + chains.Network_solana.String(): p.solanaRelayerKey, + } +} diff --git a/cmd/zetaclientd/utils.go b/cmd/zetaclientd/utils.go index f7ef2f91bc..1da8393272 100644 --- a/cmd/zetaclientd/utils.go +++ b/cmd/zetaclientd/utils.go @@ -10,21 +10,16 @@ import ( sdk "github.com/cosmos/cosmos-sdk/types" "github.com/pkg/errors" "github.com/rs/zerolog" - "google.golang.org/grpc" - "google.golang.org/grpc/credentials/insecure" + authz2 "github.com/zeta-chain/node/pkg/authz" + "github.com/zeta-chain/node/pkg/ticker" "github.com/zeta-chain/node/zetaclient/authz" - "github.com/zeta-chain/node/zetaclient/chains/interfaces" "github.com/zeta-chain/node/zetaclient/config" zctx "github.com/zeta-chain/node/zetaclient/context" "github.com/zeta-chain/node/zetaclient/keys" "github.com/zeta-chain/node/zetaclient/zetacore" ) -func createAuthzSigner(granter string, grantee sdk.AccAddress) { - authz.SetupAuthZSignerList(granter, grantee) -} - func createZetacoreClient(cfg config.Config, hotkeyPassword string, logger zerolog.Logger) (*zetacore.Client, error) { hotKey := cfg.AuthzHotkey @@ -42,6 +37,15 @@ func createZetacoreClient(cfg config.Config, hotkeyPassword string, logger zerol k := keys.NewKeysWithKeybase(kb, granterAddress, cfg.AuthzHotkey, hotkeyPassword) + // All votes broadcasts to zetacore are wrapped in authz. + // This is to ensure that the user does not need to keep their operator key online, and can use a cold key to sign votes + signerAddress, err := k.GetAddress() + if err != nil { + return nil, errors.Wrap(err, "failed to get signer address") + } + + authz.SetupAuthZSignerList(k.GetOperatorAddress().String(), signerAddress) + client, err := zetacore.NewClient(k, chainIP, hotKey, cfg.ChainID, logger) if err != nil { return nil, errors.Wrap(err, "failed to create zetacore client") @@ -50,31 +54,8 @@ func createZetacoreClient(cfg config.Config, hotkeyPassword string, logger zerol return client, nil } -func waitForZetaCore(config config.Config, logger zerolog.Logger) { - const ( - port = 9090 - retry = 5 * time.Second - ) - - var ( - url = fmt.Sprintf("%s:%d", config.ZetaCoreURL, port) - opt = grpc.WithTransportCredentials(insecure.NewCredentials()) - ) - - // wait until zetacore is up - logger.Debug().Msgf("Waiting for zetacore to open %d port...", port) - - for { - if _, err := grpc.Dial(url, opt); err != nil { - logger.Warn().Err(err).Msg("grpc dial fail") - time.Sleep(retry) - } else { - break - } - } -} - -func waitForZetacoreToCreateBlocks(ctx context.Context, zc interfaces.ZetacoreClient, logger zerolog.Logger) error { +// waitForBlocks waits for zetacore to be ready (i.e. producing blocks) +func waitForBlocks(ctx context.Context, zc *zetacore.Client, logger zerolog.Logger) error { const ( interval = 5 * time.Second attempts = 15 @@ -85,10 +66,12 @@ func waitForZetacoreToCreateBlocks(ctx context.Context, zc interfaces.ZetacoreCl start = time.Now() ) - for { + task := func(ctx context.Context, t *ticker.Ticker) error { blockHeight, err := zc.GetBlockHeight(ctx) + if err == nil && blockHeight > 1 { - logger.Info().Msgf("Zeta block height: %d", blockHeight) + logger.Info().Msgf("Zetacore is ready, block height: %d", blockHeight) + t.Stop() return nil } @@ -97,9 +80,68 @@ func waitForZetacoreToCreateBlocks(ctx context.Context, zc interfaces.ZetacoreCl return fmt.Errorf("zetacore is not ready, timeout %s", time.Since(start).String()) } - logger.Info().Msgf("Failed to get block number, retry : %d/%d", retryCount, attempts) - time.Sleep(interval) + logger.Info().Msgf("Failed to get block number, retry: %d/%d", retryCount, attempts) + return nil } + + return ticker.Run(ctx, interval, task) +} + +// prepareZetacoreClient prepares the zetacore client for use. +// EXITS THE PROGRAM IF THIS NODE IS NOT AN OBSERVER. +func prepareZetacoreClient(ctx context.Context, zc *zetacore.Client, cfg *config.Config, logger zerolog.Logger) error { + // Set grantee account number and sequence number + if err := zc.SetAccountNumber(authz2.ZetaClientGranteeKey); err != nil { + return errors.Wrap(err, "failed to set account number") + } + + res, err := zc.GetNodeInfo(ctx) + if err != nil { + return errors.Wrap(err, "failed to get node info") + } + + network := res.GetDefaultNodeInfo().Network + if network != cfg.ChainID { + logger.Warn(). + Str("got", cfg.ChainID). + Str("want", network). + Msg("Zetacore chain id config mismatch. Forcing update from the network") + + cfg.ChainID = network + if err = zc.UpdateChainID(cfg.ChainID); err != nil { + return errors.Wrap(err, "failed to update chain id") + } + } + + isObserver, err := isObserverNode(ctx, zc) + switch { + case err != nil: + return errors.Wrap(err, "failed to check if this node is an observer") + case !isObserver: + addr := zc.GetKeys().GetOperatorAddress().String() + logger.Info().Str("operator_address", addr).Msg("This node is not an observer. Exit 0") + os.Exit(0) + } + + return nil +} + +// isObserverNode checks whether THIS node is an observer node. +func isObserverNode(ctx context.Context, zc *zetacore.Client) (bool, error) { + observers, err := zc.GetObserverList(ctx) + if err != nil { + return false, errors.Wrap(err, "unable to get observers list") + } + + operatorAddress := zc.GetKeys().GetOperatorAddress().String() + + for _, observer := range observers { + if observer == operatorAddress { + return true, nil + } + } + + return false, nil } func isEnvFlagEnabled(flag string) bool { diff --git a/pkg/os/console.go b/pkg/os/console.go index c4a7c505c7..6782bb6b43 100644 --- a/pkg/os/console.go +++ b/pkg/os/console.go @@ -33,11 +33,11 @@ func PromptPasswords(passwordTitles []string) ([]string, error) { // readPassword is a helper function that reads a password from bufio.Reader func readPassword(reader *bufio.Reader, passwordTitle string) (string, error) { - const delimitor = '\n' + const delimiter = '\n' // prompt for password fmt.Printf("%s Password: ", passwordTitle) - password, err := reader.ReadString(delimitor) + password, err := reader.ReadString(delimiter) if err != nil { return "", err } diff --git a/zetaclient/chains/base/logger.go b/zetaclient/chains/base/logger.go index c70c1fd738..d5ff2948af 100644 --- a/zetaclient/chains/base/logger.go +++ b/zetaclient/chains/base/logger.go @@ -1,6 +1,7 @@ package base import ( + "io" "os" "path/filepath" "time" @@ -11,9 +12,7 @@ import ( "github.com/zeta-chain/node/zetaclient/config" ) -const ( - ComplianceLogFile = "compliance.log" -) +const complianceLogFile = "compliance.log" // Logger contains the base loggers type Logger struct { @@ -21,7 +20,7 @@ type Logger struct { Compliance zerolog.Logger } -// DefaultLoggers creates default base loggers for tests +// DefaultLogger creates default base loggers for tests func DefaultLogger() Logger { return Logger{ Std: log.Logger, @@ -50,39 +49,38 @@ type ObserverLogger struct { Compliance zerolog.Logger } -// InitLogger initializes the base loggers -func InitLogger(cfg config.Config) (Logger, error) { +// NewLogger initializes the base loggers +func NewLogger(cfg config.Config) (Logger, error) { // open compliance log file - file, err := openComplianceLogFile(cfg) + complianceFile, err := openComplianceLogFile(cfg) if err != nil { - return DefaultLogger(), err + return Logger{}, err } - level := zerolog.Level(cfg.LogLevel) + augmentLogger := func(logger zerolog.Logger) zerolog.Logger { + level := zerolog.Level(cfg.LogLevel) + + return logger.Level(level).With().Timestamp().Logger() + } // create loggers based on configured level and format - var std zerolog.Logger - var compliance zerolog.Logger - switch cfg.LogFormat { - case "json": - std = zerolog.New(os.Stdout).Level(level).With().Timestamp().Logger() - compliance = zerolog.New(file).Level(level).With().Timestamp().Logger() - case "text": - std = zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}). - Level(zerolog.Level(cfg.LogLevel)). - With(). - Timestamp(). - Logger() - compliance = zerolog.New(file).Level(level).With().Timestamp().Logger() - default: - std = zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}) - compliance = zerolog.New(file).With().Timestamp().Logger() + var stdWriter io.Writer = os.Stdout + if cfg.LogFormat != "json" { + stdWriter = zerolog.ConsoleWriter{ + Out: os.Stdout, + TimeFormat: time.RFC3339, + } } + std := augmentLogger(zerolog.New(stdWriter)) + compliance := augmentLogger(zerolog.New(complianceFile)) + if cfg.LogSampler { std = std.Sample(&zerolog.BasicSampler{N: 5}) } - log.Logger = std // set global logger + + // set global logger + log.Logger = std return Logger{ Std: std, @@ -99,11 +97,12 @@ func openComplianceLogFile(cfg config.Config) (*os.File, error) { } // clean file name - name := filepath.Join(logPath, ComplianceLogFile) + name := filepath.Join(logPath, complianceLogFile) name, err := filepath.Abs(name) if err != nil { return nil, err } + name = filepath.Clean(name) // open (or create) compliance log file diff --git a/zetaclient/chains/interfaces/interfaces.go b/zetaclient/chains/interfaces/interfaces.go index cd195912bb..4f00b7a2bb 100644 --- a/zetaclient/chains/interfaces/interfaces.go +++ b/zetaclient/chains/interfaces/interfaces.go @@ -19,7 +19,6 @@ import ( "github.com/gagliardetto/solana-go" solrpc "github.com/gagliardetto/solana-go/rpc" "github.com/onrik/ethrpc" - "github.com/rs/zerolog" "gitlab.com/thorchain/tss/go-tss/blame" "github.com/zeta-chain/node/pkg/chains" @@ -102,7 +101,6 @@ type ZetacoreClient interface { ZetacoreVoter Chain() chains.Chain - GetLogger() *zerolog.Logger GetKeys() keyinterfaces.ObserverKeys GetSupportedChains(ctx context.Context) ([]chains.Chain, error) diff --git a/zetaclient/config/config.go b/zetaclient/config/config.go index 82cb3f97f8..8bd3e9eff9 100644 --- a/zetaclient/config/config.go +++ b/zetaclient/config/config.go @@ -7,6 +7,8 @@ import ( "os" "path/filepath" "strings" + + "github.com/pkg/errors" ) // restrictedAddressBook is a map of restricted addresses @@ -114,3 +116,15 @@ func ContainRestrictedAddress(addrs ...string) bool { } return false } + +// ResolveDBPath resolves the path to chain observer database +func ResolveDBPath() (string, error) { + const dbpath = ".zetaclient/chainobserver" + + userDir, err := os.UserHomeDir() + if err != nil { + return "", errors.Wrap(err, "unable to resolve user home directory") + } + + return filepath.Join(userDir, dbpath), nil +} diff --git a/zetaclient/zetacore/client.go b/zetaclient/zetacore/client.go index de54435c7e..df5b6dbeb6 100644 --- a/zetaclient/zetacore/client.go +++ b/zetaclient/zetacore/client.go @@ -254,10 +254,6 @@ func (c *Client) Chain() chains.Chain { return c.chain } -func (c *Client) GetLogger() *zerolog.Logger { - return &c.logger -} - func (c *Client) GetKeys() keyinterfaces.ObserverKeys { return c.keys }