From 2c76429ac3b19f9ada74ea22b194de1a78e5acae Mon Sep 17 00:00:00 2001 From: Charlie Chen <34498985+ws4charlie@users.noreply.github.com> Date: Wed, 19 Jun 2024 11:46:25 -0500 Subject: [PATCH] refactor: create base signer and signer structs to group common data of EVM/Bitcoin signer and observer (#2344) * save local new files to remote * initiated base observer * move base to chains folder * moved logger to base package * added base signer and logger * added changelog entry * added metrics server to base signer/observer * added more descriptions for constants and base structs --------- Co-authored-by: Lucas Bertrand --- changelog.md | 1 + cmd/zetaclientd/main.go | 64 ---- cmd/zetaclientd/start.go | 9 +- cmd/zetaclientd/utils.go | 26 +- zetaclient/chains/base/logger.go | 109 ++++++ zetaclient/chains/base/logger_test.go | 97 +++++ zetaclient/chains/base/observer.go | 343 +++++++++++++++++ zetaclient/chains/base/observer_test.go | 359 ++++++++++++++++++ zetaclient/chains/base/signer.go | 96 +++++ zetaclient/chains/base/signer_test.go | 74 ++++ .../chains/bitcoin/observer/live_test.go | 4 +- .../chains/bitcoin/observer/observer.go | 8 +- .../chains/bitcoin/observer/observer_test.go | 6 +- zetaclient/chains/bitcoin/signer/signer.go | 8 +- .../chains/bitcoin/signer/signer_test.go | 8 +- zetaclient/chains/evm/observer/observer.go | 10 +- .../chains/evm/observer/observer_test.go | 4 +- zetaclient/chains/evm/signer/signer.go | 12 +- zetaclient/chains/evm/signer/signer_test.go | 6 +- zetaclient/common/logger.go | 20 - zetaclient/context/zetacore_context_test.go | 8 +- zetaclient/types/defs.go | 5 - 22 files changed, 1133 insertions(+), 144 deletions(-) create mode 100644 zetaclient/chains/base/logger.go create mode 100644 zetaclient/chains/base/logger_test.go create mode 100644 zetaclient/chains/base/observer.go create mode 100644 zetaclient/chains/base/observer_test.go create mode 100644 zetaclient/chains/base/signer.go create mode 100644 zetaclient/chains/base/signer_test.go delete mode 100644 zetaclient/common/logger.go delete mode 100644 zetaclient/types/defs.go diff --git a/changelog.md b/changelog.md index 41d63adac2..970f77a4da 100644 --- a/changelog.md +++ b/changelog.md @@ -46,6 +46,7 @@ * [2269](https://github.com/zeta-chain/node/pull/2269) - refactor MsgUpdateCrosschainFlags into MsgEnableCCTX, MsgDisableCCTX and MsgUpdateGasPriceIncreaseFlags * [2306](https://github.com/zeta-chain/node/pull/2306) - refactor zetaclient outbound transaction signing logic * [2296](https://github.com/zeta-chain/node/pull/2296) - move `testdata` package to `testutil` to organize test-related utilities +* [2344](https://github.com/zeta-chain/node/pull/2344) - group common data of EVM/Bitcoin signer and observer using base structs ### Tests diff --git a/cmd/zetaclientd/main.go b/cmd/zetaclientd/main.go index fdac54a7d0..99aaf55c10 100644 --- a/cmd/zetaclientd/main.go +++ b/cmd/zetaclientd/main.go @@ -3,24 +3,15 @@ package main import ( "math/rand" "os" - "path/filepath" "time" ecdsakeygen "github.com/binance-chain/tss-lib/ecdsa/keygen" "github.com/cosmos/cosmos-sdk/server" svrcmd "github.com/cosmos/cosmos-sdk/server/cmd" "github.com/cosmos/cosmos-sdk/types" - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" "github.com/zeta-chain/zetacore/app" "github.com/zeta-chain/zetacore/cmd" - clientcommon "github.com/zeta-chain/zetacore/zetaclient/common" - "github.com/zeta-chain/zetacore/zetaclient/config" -) - -const ( - ComplianceLogFile = "compliance.log" ) var ( @@ -53,58 +44,3 @@ func SetupConfigForTest() { rand.Seed(time.Now().UnixNano()) } - -func InitLogger(cfg config.Config) (clientcommon.ClientLogger, error) { - // open compliance log file - file, err := OpenComplianceLogFile(cfg) - if err != nil { - return clientcommon.DefaultLoggers(), err - } - - var logger zerolog.Logger - var loggerCompliance zerolog.Logger - switch cfg.LogFormat { - case "json": - logger = zerolog.New(os.Stdout).Level(zerolog.Level(cfg.LogLevel)).With().Timestamp().Logger() - loggerCompliance = zerolog.New(file).Level(zerolog.Level(cfg.LogLevel)).With().Timestamp().Logger() - case "text": - logger = zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}). - Level(zerolog.Level(cfg.LogLevel)). - With(). - Timestamp(). - Logger() - loggerCompliance = zerolog.New(file).Level(zerolog.Level(cfg.LogLevel)).With().Timestamp().Logger() - default: - logger = zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}) - loggerCompliance = zerolog.New(file).With().Timestamp().Logger() - } - - if cfg.LogSampler { - logger = logger.Sample(&zerolog.BasicSampler{N: 5}) - } - log.Logger = logger // set global logger - - return clientcommon.ClientLogger{ - Std: log.Logger, - Compliance: loggerCompliance, - }, nil -} - -func OpenComplianceLogFile(cfg config.Config) (*os.File, error) { - // use zetacore home as default - logPath := cfg.ZetaCoreHome - if cfg.ComplianceConfig.LogPath != "" { - logPath = cfg.ComplianceConfig.LogPath - } - - // clean file name - 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 - return os.OpenFile(name, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) -} diff --git a/cmd/zetaclientd/start.go b/cmd/zetaclientd/start.go index 9c964ea26e..c815b616c0 100644 --- a/cmd/zetaclientd/start.go +++ b/cmd/zetaclientd/start.go @@ -24,6 +24,7 @@ import ( "github.com/zeta-chain/zetacore/pkg/authz" "github.com/zeta-chain/zetacore/pkg/constant" observerTypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/config" "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/metrics" @@ -61,7 +62,7 @@ func start(_ *cobra.Command, _ []string) error { if err != nil { return err } - loggers, err := InitLogger(cfg) + logger, err := base.InitLogger(cfg) if err != nil { log.Error().Err(err).Msg("InitLogger failed") return err @@ -76,7 +77,7 @@ func start(_ *cobra.Command, _ []string) error { } } - masterLogger := loggers.Std + masterLogger := logger.Std startLogger := masterLogger.With().Str("module", "startup").Logger() // Wait until zetacore is up @@ -267,7 +268,7 @@ func start(_ *cobra.Command, _ []string) error { } // CreateSignerMap: This creates a map of all signers for each chain . Each signer is responsible for signing transactions for a particular chain - signerMap, err := CreateSignerMap(appContext, tss, loggers, telemetryServer) + signerMap, err := CreateSignerMap(appContext, tss, logger, telemetryServer) if err != nil { log.Error().Err(err).Msg("CreateSignerMap") return err @@ -281,7 +282,7 @@ func start(_ *cobra.Command, _ []string) error { 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 := CreateChainObserverMap(appContext, zetacoreClient, tss, dbpath, loggers, telemetryServer) + observerMap, err := CreateChainObserverMap(appContext, zetacoreClient, tss, dbpath, logger, telemetryServer) if err != nil { startLogger.Err(err).Msg("CreateChainObserverMap") return err diff --git a/cmd/zetaclientd/utils.go b/cmd/zetaclientd/utils.go index 7c37c00380..521c6dc858 100644 --- a/cmd/zetaclientd/utils.go +++ b/cmd/zetaclientd/utils.go @@ -5,12 +5,12 @@ import ( ethcommon "github.com/ethereum/go-ethereum/common" "github.com/zeta-chain/zetacore/zetaclient/authz" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" btcobserver "github.com/zeta-chain/zetacore/zetaclient/chains/bitcoin/observer" btcsigner "github.com/zeta-chain/zetacore/zetaclient/chains/bitcoin/signer" evmobserver "github.com/zeta-chain/zetacore/zetaclient/chains/evm/observer" evmsigner "github.com/zeta-chain/zetacore/zetaclient/chains/evm/signer" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" - clientcommon "github.com/zeta-chain/zetacore/zetaclient/common" "github.com/zeta-chain/zetacore/zetaclient/config" "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/keys" @@ -57,7 +57,7 @@ func CreateZetacoreClient( func CreateSignerMap( appContext *context.AppContext, tss interfaces.TSSSigner, - loggers clientcommon.ClientLogger, + logger base.Logger, ts *metrics.TelemetryServer, ) (map[int64]interfaces.ChainSigner, error) { coreContext := appContext.ZetacoreContext() @@ -70,7 +70,7 @@ func CreateSignerMap( } evmChainParams, found := coreContext.GetEVMChainParams(evmConfig.Chain.ChainId) if !found { - loggers.Std.Error().Msgf("ChainParam not found for chain %s", evmConfig.Chain.String()) + logger.Std.Error().Msgf("ChainParam not found for chain %s", evmConfig.Chain.String()) continue } mpiAddress := ethcommon.HexToAddress(evmChainParams.ConnectorContractAddress) @@ -84,10 +84,10 @@ func CreateSignerMap( mpiAddress, erc20CustodyAddress, coreContext, - loggers, + logger, ts) if err != nil { - loggers.Std.Error().Err(err).Msgf("NewEVMSigner error for chain %s", evmConfig.Chain.String()) + logger.Std.Error().Err(err).Msgf("NewEVMSigner error for chain %s", evmConfig.Chain.String()) continue } signerMap[evmConfig.Chain.ChainId] = signer @@ -95,9 +95,9 @@ func CreateSignerMap( // BTC signer btcChain, btcConfig, enabled := appContext.GetBTCChainAndConfig() if enabled { - signer, err := btcsigner.NewSigner(btcConfig, tss, loggers, ts, coreContext) + signer, err := btcsigner.NewSigner(btcConfig, tss, logger, ts, coreContext) if err != nil { - loggers.Std.Error().Err(err).Msgf("NewBTCSigner error for chain %s", btcChain.String()) + logger.Std.Error().Err(err).Msgf("NewBTCSigner error for chain %s", btcChain.String()) } else { signerMap[btcChain.ChainId] = signer } @@ -112,7 +112,7 @@ func CreateChainObserverMap( zetacoreClient *zetacore.Client, tss interfaces.TSSSigner, dbpath string, - loggers clientcommon.ClientLogger, + logger base.Logger, ts *metrics.TelemetryServer, ) (map[int64]interfaces.ChainObserver, error) { observerMap := make(map[int64]interfaces.ChainObserver) @@ -123,12 +123,12 @@ func CreateChainObserverMap( } _, found := appContext.ZetacoreContext().GetEVMChainParams(evmConfig.Chain.ChainId) if !found { - loggers.Std.Error().Msgf("ChainParam not found for chain %s", evmConfig.Chain.String()) + logger.Std.Error().Msgf("ChainParam not found for chain %s", evmConfig.Chain.String()) continue } - co, err := evmobserver.NewObserver(appContext, zetacoreClient, tss, dbpath, loggers, evmConfig, ts) + co, err := evmobserver.NewObserver(appContext, zetacoreClient, tss, dbpath, logger, evmConfig, ts) if err != nil { - loggers.Std.Error().Err(err).Msgf("NewObserver error for evm chain %s", evmConfig.Chain.String()) + logger.Std.Error().Err(err).Msgf("NewObserver error for evm chain %s", evmConfig.Chain.String()) continue } observerMap[evmConfig.Chain.ChainId] = co @@ -136,9 +136,9 @@ func CreateChainObserverMap( // BTC observer btcChain, btcConfig, enabled := appContext.GetBTCChainAndConfig() if enabled { - co, err := btcobserver.NewObserver(appContext, btcChain, zetacoreClient, tss, dbpath, loggers, btcConfig, ts) + co, err := btcobserver.NewObserver(appContext, btcChain, zetacoreClient, tss, dbpath, logger, btcConfig, ts) if err != nil { - loggers.Std.Error().Err(err).Msgf("NewObserver error for bitcoin chain %s", btcChain.String()) + logger.Std.Error().Err(err).Msgf("NewObserver error for bitcoin chain %s", btcChain.String()) } else { observerMap[btcChain.ChainId] = co diff --git a/zetaclient/chains/base/logger.go b/zetaclient/chains/base/logger.go new file mode 100644 index 0000000000..eeffcfab3b --- /dev/null +++ b/zetaclient/chains/base/logger.go @@ -0,0 +1,109 @@ +package base + +import ( + "os" + "path/filepath" + "time" + + "github.com/rs/zerolog" + "github.com/rs/zerolog/log" + + "github.com/zeta-chain/zetacore/zetaclient/config" +) + +const ( + ComplianceLogFile = "compliance.log" +) + +// Logger contains the base loggers +type Logger struct { + Std zerolog.Logger + Compliance zerolog.Logger +} + +// DefaultLoggers creates default base loggers for tests +func DefaultLogger() Logger { + return Logger{ + Std: log.Logger, + Compliance: log.Logger, + } +} + +// ObserverLogger contains the loggers for chain observers +type ObserverLogger struct { + // the parent logger for the chain observer + Chain zerolog.Logger + + // the logger for inbound transactions + Inbound zerolog.Logger + + // the logger for outbound transactions + Outbound zerolog.Logger + + // the logger for the chain's gas price + GasPrice zerolog.Logger + + // the logger for block headers + Headers zerolog.Logger + + // the logger for the compliance check + Compliance zerolog.Logger +} + +// InitLogger initializes the base loggers +func InitLogger(cfg config.Config) (Logger, error) { + // open compliance log file + file, err := openComplianceLogFile(cfg) + if err != nil { + return DefaultLogger(), err + } + + // 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(zerolog.Level(cfg.LogLevel)).With().Timestamp().Logger() + compliance = zerolog.New(file).Level(zerolog.Level(cfg.LogLevel)).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(zerolog.Level(cfg.LogLevel)).With().Timestamp().Logger() + default: + std = zerolog.New(zerolog.ConsoleWriter{Out: os.Stdout, TimeFormat: time.RFC3339}) + compliance = zerolog.New(file).With().Timestamp().Logger() + } + + if cfg.LogSampler { + std = std.Sample(&zerolog.BasicSampler{N: 5}) + } + log.Logger = std // set global logger + + return Logger{ + Std: std, + Compliance: compliance, + }, nil +} + +// openComplianceLogFile opens the compliance log file +func openComplianceLogFile(cfg config.Config) (*os.File, error) { + // use zetacore home as default + logPath := cfg.ZetaCoreHome + if cfg.ComplianceConfig.LogPath != "" { + logPath = cfg.ComplianceConfig.LogPath + } + + // clean file name + 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 + return os.OpenFile(name, os.O_APPEND|os.O_WRONLY|os.O_CREATE, 0600) +} diff --git a/zetaclient/chains/base/logger_test.go b/zetaclient/chains/base/logger_test.go new file mode 100644 index 0000000000..07c2859b0e --- /dev/null +++ b/zetaclient/chains/base/logger_test.go @@ -0,0 +1,97 @@ +package base_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/zeta-chain/zetacore/zetaclient/chains/base" + "github.com/zeta-chain/zetacore/zetaclient/config" +) + +func TestInitLogger(t *testing.T) { + // test cases + tests := []struct { + name string + t *testing.T + cfg config.Config + fail bool + }{ + { + name: "should be able to initialize json formatted logger", + cfg: config.Config{ + LogFormat: "json", + LogLevel: 1, // zerolog.InfoLevel, + ComplianceConfig: config.ComplianceConfig{ + LogPath: createTempDir(t), + }, + }, + fail: false, + }, + { + name: "should be able to initialize plain text logger", + cfg: config.Config{ + LogFormat: "text", + LogLevel: 2, // zerolog.WarnLevel, + ComplianceConfig: config.ComplianceConfig{ + LogPath: createTempDir(t), + }, + }, + fail: false, + }, + { + name: "should be able to initialize default formatted logger", + cfg: config.Config{ + LogFormat: "unknown", + LogLevel: 3, // zerolog.ErrorLevel, + ComplianceConfig: config.ComplianceConfig{ + LogPath: createTempDir(t), + }, + }, + fail: false, + }, + { + name: "should be able to initialize sampled logger", + cfg: config.Config{ + LogFormat: "json", + LogLevel: 4, // zerolog.DebugLevel, + LogSampler: true, + ComplianceConfig: config.ComplianceConfig{ + LogPath: createTempDir(t), + }, + }, + }, + { + name: "should fail on invalid compliance log path", + cfg: config.Config{ + LogFormat: "json", + LogLevel: 1, // zerolog.InfoLevel, + ComplianceConfig: config.ComplianceConfig{ + LogPath: "/invalid/123path", + }, + }, + fail: true, + }, + } + + // run tests + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + // init logger + logger, err := base.InitLogger(tt.cfg) + + // check if error is expected + if tt.fail { + require.Error(t, err) + return + } + + // check if logger is initialized + require.NoError(t, err) + + // should be able to print log + logger.Std.Info().Msg("print standard log") + logger.Compliance.Info().Msg("print compliance log") + }) + } +} diff --git a/zetaclient/chains/base/observer.go b/zetaclient/chains/base/observer.go new file mode 100644 index 0000000000..905775b2b2 --- /dev/null +++ b/zetaclient/chains/base/observer.go @@ -0,0 +1,343 @@ +package base + +import ( + "fmt" + "os" + "strconv" + "sync/atomic" + + lru "github.com/hashicorp/golang-lru" + "github.com/pkg/errors" + "github.com/rs/zerolog" + "gorm.io/driver/sqlite" + "gorm.io/gorm" + + "github.com/zeta-chain/zetacore/pkg/chains" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" + "github.com/zeta-chain/zetacore/zetaclient/context" + "github.com/zeta-chain/zetacore/zetaclient/metrics" + clienttypes "github.com/zeta-chain/zetacore/zetaclient/types" +) + +const ( + // EnvVarLatestBlock is the environment variable that forces the observer to scan from the latest block + EnvVarLatestBlock = "latest" + + // DefaultBlockCacheSize is the default number of blocks that the observer will keep in cache for performance (without RPC calls) + // Cached blocks can be used to get block information and verify transactions + DefaultBlockCacheSize = 1000 + + // DefaultHeadersCacheSize is the default number of headers that the observer will keep in cache for performance (without RPC calls) + // Cached headers can be used to get header information + DefaultHeadersCacheSize = 1000 +) + +// Observer is the base structure for chain observers, grouping the common logic for each chain observer client. +// The common logic includes: chain, chainParams, contexts, zetacore client, tss, lastBlock, db, metrics, loggers etc. +type Observer struct { + // chain contains static information about the observed chain + chain chains.Chain + + // chainParams contains the dynamic chain parameters of the observed chain + chainParams observertypes.ChainParams + + // coreContext contains context data of ZetaChain + zetacoreContext *context.ZetacoreContext + + // zetacoreClient is the client to interact with ZetaChain + zetacoreClient interfaces.ZetacoreClient + + // tss is the TSS signer + tss interfaces.TSSSigner + + // lastBlock is the last block height of the observed chain + lastBlock uint64 + + // lastBlockScanned is the last block height scanned by the observer + lastBlockScanned uint64 + + // blockCache is the cache for blocks + blockCache *lru.Cache + + // headerCache is the cache for headers + headerCache *lru.Cache + + // db is the database to persist data + db *gorm.DB + + // ts is the telemetry server for metrics + ts *metrics.TelemetryServer + + // logger contains the loggers used by observer + logger ObserverLogger + + // stop is the channel to signal the observer to stop + stop chan struct{} +} + +// NewObserver creates a new base observer. +func NewObserver( + chain chains.Chain, + chainParams observertypes.ChainParams, + zetacoreContext *context.ZetacoreContext, + zetacoreClient interfaces.ZetacoreClient, + tss interfaces.TSSSigner, + blockCacheSize int, + headersCacheSize int, + dbPath string, + ts *metrics.TelemetryServer, + logger Logger, +) (*Observer, error) { + ob := Observer{ + chain: chain, + chainParams: chainParams, + zetacoreContext: zetacoreContext, + zetacoreClient: zetacoreClient, + tss: tss, + lastBlock: 0, + lastBlockScanned: 0, + ts: ts, + stop: make(chan struct{}), + } + + // setup loggers + ob.WithLogger(logger) + + // create block cache + var err error + ob.blockCache, err = lru.New(blockCacheSize) + if err != nil { + return nil, errors.Wrap(err, "error creating block cache") + } + + // create header cache + ob.headerCache, err = lru.New(headersCacheSize) + if err != nil { + return nil, errors.Wrap(err, "error creating header cache") + } + + // open database + err = ob.OpenDB(dbPath) + if err != nil { + return nil, errors.Wrap(err, fmt.Sprintf("error opening observer db for chain: %s", chain.ChainName)) + } + + return &ob, nil +} + +// Chain returns the chain for the observer. +func (ob *Observer) Chain() chains.Chain { + return ob.chain +} + +// WithChain attaches a new chain to the observer. +func (ob *Observer) WithChain(chain chains.Chain) *Observer { + ob.chain = chain + return ob +} + +// ChainParams returns the chain params for the observer. +func (ob *Observer) ChainParams() observertypes.ChainParams { + return ob.chainParams +} + +// WithChainParams attaches a new chain params to the observer. +func (ob *Observer) WithChainParams(params observertypes.ChainParams) *Observer { + ob.chainParams = params + return ob +} + +// ZetacoreContext returns the zetacore context for the observer. +func (ob *Observer) ZetacoreContext() *context.ZetacoreContext { + return ob.zetacoreContext +} + +// WithZetacoreContext attaches a new zetacore context to the observer. +func (ob *Observer) WithZetacoreContext(context *context.ZetacoreContext) *Observer { + ob.zetacoreContext = context + return ob +} + +// ZetacoreClient returns the zetacore client for the observer. +func (ob *Observer) ZetacoreClient() interfaces.ZetacoreClient { + return ob.zetacoreClient +} + +// WithZetacoreClient attaches a new zetacore client to the observer. +func (ob *Observer) WithZetacoreClient(client interfaces.ZetacoreClient) *Observer { + ob.zetacoreClient = client + return ob +} + +// Tss returns the tss signer for the observer. +func (ob *Observer) TSS() interfaces.TSSSigner { + return ob.tss +} + +// WithTSS attaches a new tss signer to the observer. +func (ob *Observer) WithTSS(tss interfaces.TSSSigner) *Observer { + ob.tss = tss + return ob +} + +// LastBlock get external last block height. +func (ob *Observer) LastBlock() uint64 { + return atomic.LoadUint64(&ob.lastBlock) +} + +// WithLastBlock set external last block height. +func (ob *Observer) WithLastBlock(lastBlock uint64) *Observer { + atomic.StoreUint64(&ob.lastBlock, lastBlock) + return ob +} + +// LastBlockScanned get last block scanned (not necessarily caught up with the chain; could be slow/paused). +func (ob *Observer) LastBlockScanned() uint64 { + height := atomic.LoadUint64(&ob.lastBlockScanned) + return height +} + +// WithLastBlockScanned set last block scanned (not necessarily caught up with the chain; could be slow/paused). +func (ob *Observer) WithLastBlockScanned(blockNumber uint64) *Observer { + atomic.StoreUint64(&ob.lastBlockScanned, blockNumber) + metrics.LastScannedBlockNumber.WithLabelValues(ob.chain.ChainName.String()).Set(float64(blockNumber)) + return ob +} + +// BlockCache returns the block cache for the observer. +func (ob *Observer) BlockCache() *lru.Cache { + return ob.blockCache +} + +// WithBlockCache attaches a new block cache to the observer. +func (ob *Observer) WithBlockCache(cache *lru.Cache) *Observer { + ob.blockCache = cache + return ob +} + +// HeaderCache returns the header cache for the observer. +func (ob *Observer) HeaderCache() *lru.Cache { + return ob.headerCache +} + +// WithHeaderCache attaches a new header cache to the observer. +func (ob *Observer) WithHeaderCache(cache *lru.Cache) *Observer { + ob.headerCache = cache + return ob +} + +// DB returns the database for the observer. +func (ob *Observer) DB() *gorm.DB { + return ob.db +} + +// Logger returns the logger for the observer. +func (ob *Observer) Logger() ObserverLogger { + return ob.logger +} + +// WithLogger attaches a new logger to the observer. +func (ob *Observer) WithLogger(logger Logger) *Observer { + chainLogger := logger.Std.With().Int64("chain", ob.chain.ChainId).Logger() + ob.logger = ObserverLogger{ + Chain: chainLogger, + Inbound: chainLogger.With().Str("module", "inbound").Logger(), + Outbound: chainLogger.With().Str("module", "outbound").Logger(), + GasPrice: chainLogger.With().Str("module", "gasprice").Logger(), + Headers: chainLogger.With().Str("module", "headers").Logger(), + Compliance: logger.Compliance, + } + return ob +} + +// Stop returns the stop channel for the observer. +func (ob *Observer) Stop() chan struct{} { + return ob.stop +} + +// OpenDB open sql database in the given path. +func (ob *Observer) OpenDB(dbPath string) error { + if dbPath != "" { + // create db path if not exist + if _, err := os.Stat(dbPath); os.IsNotExist(err) { + err := os.MkdirAll(dbPath, os.ModePerm) + if err != nil { + return errors.Wrap(err, "error creating db path") + } + } + + // open db by chain name + chainName := ob.chain.ChainName.String() + path := fmt.Sprintf("%s/%s", dbPath, chainName) + db, err := gorm.Open(sqlite.Open(path), &gorm.Config{}) + if err != nil { + return errors.Wrap(err, "error opening db") + } + + // migrate db + err = db.AutoMigrate(&clienttypes.ReceiptSQLType{}, + &clienttypes.TransactionSQLType{}, + &clienttypes.LastBlockSQLType{}) + if err != nil { + return errors.Wrap(err, "error migrating db") + } + ob.db = db + } + return nil +} + +// LoadLastBlockScanned loads last scanned block from environment variable or from database. +// The last scanned block is the height from which the observer should continue scanning. +func (ob *Observer) LoadLastBlockScanned(logger zerolog.Logger) (fromLatest bool, err error) { + // get environment variable + envvar := EnvVarLatestBlockByChain(ob.chain) + scanFromBlock := os.Getenv(envvar) + + // load from environment variable if set + if scanFromBlock != "" { + logger.Info(). + Msgf("LoadLastBlockScanned: envvar %s is set; scan from block %s", envvar, scanFromBlock) + if scanFromBlock == EnvVarLatestBlock { + return true, nil + } + blockNumber, err := strconv.ParseUint(scanFromBlock, 10, 64) + if err != nil { + return false, err + } + ob.WithLastBlockScanned(blockNumber) + return false, nil + } + + // load from DB otherwise. If not found, start from latest block + blockNumber, err := ob.ReadLastBlockScannedFromDB() + if err != nil { + logger.Info().Msgf("LoadLastBlockScanned: chain %d starts scanning from latest block", ob.chain.ChainId) + return true, nil + } + ob.WithLastBlockScanned(blockNumber) + logger.Info(). + Msgf("LoadLastBlockScanned: chain %d starts scanning from block %d", ob.chain.ChainId, ob.LastBlockScanned()) + + return false, nil +} + +// WriteLastBlockScannedToDB saves the last scanned block to the database. +func (ob *Observer) WriteLastBlockScannedToDB(lastScannedBlock uint64) error { + return ob.db.Save(clienttypes.ToLastBlockSQLType(lastScannedBlock)).Error +} + +// ReadLastBlockScannedFromDB reads the last scanned block from the database. +func (ob *Observer) ReadLastBlockScannedFromDB() (uint64, error) { + var lastBlock clienttypes.LastBlockSQLType + if err := ob.db.First(&lastBlock, clienttypes.LastBlockNumID).Error; err != nil { + // record not found + return 0, err + } + return lastBlock.Num, nil +} + +// EnvVarLatestBlock returns the environment variable for the latest block by chain. +func EnvVarLatestBlockByChain(chain chains.Chain) string { + return chain.ChainName.String() + "_SCAN_FROM" +} diff --git a/zetaclient/chains/base/observer_test.go b/zetaclient/chains/base/observer_test.go new file mode 100644 index 0000000000..7dd2f18081 --- /dev/null +++ b/zetaclient/chains/base/observer_test.go @@ -0,0 +1,359 @@ +package base_test + +import ( + "os" + "testing" + + lru "github.com/hashicorp/golang-lru" + "github.com/rs/zerolog/log" + "github.com/stretchr/testify/require" + + "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/testutil/sample" + observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" + "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" + "github.com/zeta-chain/zetacore/zetaclient/config" + "github.com/zeta-chain/zetacore/zetaclient/context" + "github.com/zeta-chain/zetacore/zetaclient/testutils/mocks" +) + +// create a temporary directory for testing +func createTempDir(t *testing.T) string { + tempPath, err := os.MkdirTemp("", "tempdir-") + require.NoError(t, err) + return tempPath +} + +// createObserver creates a new observer for testing +func createObserver(t *testing.T, dbPath string) *base.Observer { + // constructor parameters + chain := chains.Ethereum + chainParams := *sample.ChainParams(chain.ChainId) + zetacoreContext := context.NewZetacoreContext(config.NewConfig()) + zetacoreClient := mocks.NewMockZetacoreClient() + tss := mocks.NewTSSMainnet() + + // create observer + logger := base.DefaultLogger() + ob, err := base.NewObserver( + chain, + chainParams, + zetacoreContext, + zetacoreClient, + tss, + base.DefaultBlockCacheSize, + base.DefaultHeadersCacheSize, + dbPath, + nil, + logger, + ) + require.NoError(t, err) + + return ob +} + +func TestNewObserver(t *testing.T) { + // constructor parameters + chain := chains.Ethereum + chainParams := *sample.ChainParams(chain.ChainId) + zetacoreContext := context.NewZetacoreContext(config.NewConfig()) + zetacoreClient := mocks.NewMockZetacoreClient() + tss := mocks.NewTSSMainnet() + blockCacheSize := base.DefaultBlockCacheSize + headersCacheSize := base.DefaultHeadersCacheSize + dbPath := createTempDir(t) + + // test cases + tests := []struct { + name string + chain chains.Chain + chainParams observertypes.ChainParams + zetacoreContext *context.ZetacoreContext + zetacoreClient interfaces.ZetacoreClient + tss interfaces.TSSSigner + blockCacheSize int + headersCacheSize int + dbPath string + fail bool + message string + }{ + { + name: "should be able to create new observer", + chain: chain, + chainParams: chainParams, + zetacoreContext: zetacoreContext, + zetacoreClient: zetacoreClient, + tss: tss, + blockCacheSize: blockCacheSize, + headersCacheSize: headersCacheSize, + dbPath: dbPath, + fail: false, + }, + { + name: "should return error on invalid block cache size", + chain: chain, + chainParams: chainParams, + zetacoreContext: zetacoreContext, + zetacoreClient: zetacoreClient, + tss: tss, + blockCacheSize: 0, + headersCacheSize: headersCacheSize, + dbPath: dbPath, + fail: true, + message: "error creating block cache", + }, + { + name: "should return error on invalid header cache size", + chain: chain, + chainParams: chainParams, + zetacoreContext: zetacoreContext, + zetacoreClient: zetacoreClient, + tss: tss, + blockCacheSize: blockCacheSize, + headersCacheSize: 0, + dbPath: dbPath, + fail: true, + message: "error creating header cache", + }, + { + name: "should return error on invalid db path", + chain: chain, + chainParams: chainParams, + zetacoreContext: zetacoreContext, + zetacoreClient: zetacoreClient, + tss: tss, + blockCacheSize: blockCacheSize, + headersCacheSize: headersCacheSize, + dbPath: "/invalid/123db", + fail: true, + message: "error opening observer db", + }, + } + + // run tests + for _, tt := range tests { + t.Run(tt.name, func(t *testing.T) { + ob, err := base.NewObserver( + tt.chain, + tt.chainParams, + tt.zetacoreContext, + tt.zetacoreClient, + tt.tss, + tt.blockCacheSize, + tt.headersCacheSize, + tt.dbPath, + nil, + base.DefaultLogger(), + ) + if tt.fail { + require.ErrorContains(t, err, tt.message) + require.Nil(t, ob) + return + } + + require.NoError(t, err) + require.NotNil(t, ob) + }) + } +} + +func TestObserverGetterAndSetter(t *testing.T) { + dbPath := createTempDir(t) + + t.Run("should be able to update chain", func(t *testing.T) { + ob := createObserver(t, dbPath) + + // update chain + newChain := chains.BscMainnet + ob = ob.WithChain(chains.BscMainnet) + require.Equal(t, newChain, ob.Chain()) + }) + t.Run("should be able to update chain params", func(t *testing.T) { + ob := createObserver(t, dbPath) + + // update chain params + newChainParams := *sample.ChainParams(chains.BscMainnet.ChainId) + ob = ob.WithChainParams(newChainParams) + require.True(t, observertypes.ChainParamsEqual(newChainParams, ob.ChainParams())) + }) + t.Run("should be able to update zetacore context", func(t *testing.T) { + ob := createObserver(t, dbPath) + + // update zetacore context + newZetacoreContext := context.NewZetacoreContext(config.NewConfig()) + ob = ob.WithZetacoreContext(newZetacoreContext) + require.Equal(t, newZetacoreContext, ob.ZetacoreContext()) + }) + t.Run("should be able to update zetacore client", func(t *testing.T) { + ob := createObserver(t, dbPath) + + // update zetacore client + newZetacoreClient := mocks.NewMockZetacoreClient() + ob = ob.WithZetacoreClient(newZetacoreClient) + require.Equal(t, newZetacoreClient, ob.ZetacoreClient()) + }) + t.Run("should be able to update tss", func(t *testing.T) { + ob := createObserver(t, dbPath) + + // update tss + newTSS := mocks.NewTSSAthens3() + ob = ob.WithTSS(newTSS) + require.Equal(t, newTSS, ob.TSS()) + }) + t.Run("should be able to update last block", func(t *testing.T) { + ob := createObserver(t, dbPath) + + // update last block + newLastBlock := uint64(100) + ob = ob.WithLastBlock(newLastBlock) + require.Equal(t, newLastBlock, ob.LastBlock()) + }) + t.Run("should be able to update last block scanned", func(t *testing.T) { + ob := createObserver(t, dbPath) + + // update last block scanned + newLastBlockScanned := uint64(100) + ob = ob.WithLastBlockScanned(newLastBlockScanned) + require.Equal(t, newLastBlockScanned, ob.LastBlockScanned()) + }) + t.Run("should be able to replace block cache", func(t *testing.T) { + ob := createObserver(t, dbPath) + + // update block cache + newBlockCache, err := lru.New(200) + require.NoError(t, err) + + ob = ob.WithBlockCache(newBlockCache) + require.Equal(t, newBlockCache, ob.BlockCache()) + }) + t.Run("should be able to replace headers cache", func(t *testing.T) { + ob := createObserver(t, dbPath) + + // update headers cache + newHeadersCache, err := lru.New(200) + require.NoError(t, err) + + ob = ob.WithHeaderCache(newHeadersCache) + require.Equal(t, newHeadersCache, ob.HeaderCache()) + }) + t.Run("should be able to get database", func(t *testing.T) { + ob := createObserver(t, dbPath) + + db := ob.DB() + require.NotNil(t, db) + }) + t.Run("should be able to get logger", func(t *testing.T) { + ob := createObserver(t, dbPath) + logger := ob.Logger() + + // should be able to print log + logger.Chain.Info().Msg("print chain log") + logger.Inbound.Info().Msg("print inbound log") + logger.Outbound.Info().Msg("print outbound log") + logger.GasPrice.Info().Msg("print gasprice log") + logger.Headers.Info().Msg("print headers log") + logger.Compliance.Info().Msg("print compliance log") + }) +} + +func TestOpenDB(t *testing.T) { + dbPath := createTempDir(t) + ob := createObserver(t, dbPath) + + t.Run("should be able to open db", func(t *testing.T) { + err := ob.OpenDB(dbPath) + require.NoError(t, err) + }) + t.Run("should return error on invalid db path", func(t *testing.T) { + err := ob.OpenDB("/invalid/123db") + require.ErrorContains(t, err, "error creating db path") + }) +} + +func TestLoadLastBlockScanned(t *testing.T) { + chain := chains.Ethereum + envvar := base.EnvVarLatestBlockByChain(chain) + + t.Run("should be able to load last block scanned", func(t *testing.T) { + // create db and write 100 as last block scanned + dbPath := createTempDir(t) + ob := createObserver(t, dbPath) + ob.WriteLastBlockScannedToDB(100) + + // read last block scanned + fromLatest, err := ob.LoadLastBlockScanned(log.Logger) + require.NoError(t, err) + require.EqualValues(t, 100, ob.LastBlockScanned()) + require.False(t, fromLatest) + }) + t.Run("should use latest block if last block scanned not found", func(t *testing.T) { + // create empty db + dbPath := createTempDir(t) + ob := createObserver(t, dbPath) + + // read last block scanned + fromLatest, err := ob.LoadLastBlockScanned(log.Logger) + require.NoError(t, err) + require.True(t, fromLatest) + }) + t.Run("should overwrite last block scanned if env var is set", func(t *testing.T) { + // create db and write 100 as last block scanned + dbPath := createTempDir(t) + ob := createObserver(t, dbPath) + ob.WriteLastBlockScannedToDB(100) + + // set env var + os.Setenv(envvar, "101") + + // read last block scanned + fromLatest, err := ob.LoadLastBlockScanned(log.Logger) + require.NoError(t, err) + require.EqualValues(t, 101, ob.LastBlockScanned()) + require.False(t, fromLatest) + + // set env var to 'latest' + os.Setenv(envvar, base.EnvVarLatestBlock) + + // read last block scanned + fromLatest, err = ob.LoadLastBlockScanned(log.Logger) + require.NoError(t, err) + require.True(t, fromLatest) + }) + t.Run("should return error on invalid env var", func(t *testing.T) { + // create db and write 100 as last block scanned + dbPath := createTempDir(t) + ob := createObserver(t, dbPath) + + // set invalid env var + os.Setenv(envvar, "invalid") + + // read last block scanned + fromLatest, err := ob.LoadLastBlockScanned(log.Logger) + require.Error(t, err) + require.False(t, fromLatest) + }) +} + +func TestReadWriteLastBlockScannedToDB(t *testing.T) { + t.Run("should be able to write and read last block scanned to db", func(t *testing.T) { + // create db and write 100 as last block scanned + dbPath := createTempDir(t) + ob := createObserver(t, dbPath) + err := ob.WriteLastBlockScannedToDB(100) + require.NoError(t, err) + + lastBlockScanned, err := ob.ReadLastBlockScannedFromDB() + require.NoError(t, err) + require.EqualValues(t, 100, lastBlockScanned) + }) + t.Run("should return error when last block scanned not found in db", func(t *testing.T) { + // create empty db + dbPath := createTempDir(t) + ob := createObserver(t, dbPath) + + lastScannedBlock, err := ob.ReadLastBlockScannedFromDB() + require.Error(t, err) + require.Zero(t, lastScannedBlock) + }) +} diff --git a/zetaclient/chains/base/signer.go b/zetaclient/chains/base/signer.go new file mode 100644 index 0000000000..2585218767 --- /dev/null +++ b/zetaclient/chains/base/signer.go @@ -0,0 +1,96 @@ +package base + +import ( + "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" + "github.com/zeta-chain/zetacore/zetaclient/context" + "github.com/zeta-chain/zetacore/zetaclient/metrics" +) + +// Signer is the base structure for grouping the common logic between chain signers. +// The common logic includes: chain, chainParams, contexts, tss, metrics, loggers etc. +type Signer struct { + // chain contains static information about the external chain + chain chains.Chain + + // zetacoreContext is the Zetacore client to interact with ZetaChain + zetacoreContext *context.ZetacoreContext + + // tss is the TSS signer + tss interfaces.TSSSigner + + // ts is the telemetry server for metrics + ts *metrics.TelemetryServer + + // logger contains the loggers used by signer + logger Logger +} + +// NewSigner creates a new base signer +func NewSigner( + chain chains.Chain, + zetacoreContext *context.ZetacoreContext, + tss interfaces.TSSSigner, + ts *metrics.TelemetryServer, + logger Logger, +) *Signer { + return &Signer{ + chain: chain, + zetacoreContext: zetacoreContext, + tss: tss, + ts: ts, + logger: Logger{ + Std: logger.Std.With().Int64("chain", chain.ChainId).Str("module", "signer").Logger(), + Compliance: logger.Compliance, + }, + } +} + +// Chain returns the chain for the signer +func (s *Signer) Chain() chains.Chain { + return s.chain +} + +// WithChain attaches a new chain to the signer +func (s *Signer) WithChain(chain chains.Chain) *Signer { + s.chain = chain + return s +} + +// ZetacoreContext returns the zetacore context for the signer +func (s *Signer) ZetacoreContext() *context.ZetacoreContext { + return s.zetacoreContext +} + +// WithZetacoreContext attaches a new zetacore context to the signer +func (s *Signer) WithZetacoreContext(context *context.ZetacoreContext) *Signer { + s.zetacoreContext = context + return s +} + +// Tss returns the tss signer for the signer +func (s *Signer) TSS() interfaces.TSSSigner { + return s.tss +} + +// WithTSS attaches a new tss signer to the signer +func (s *Signer) WithTSS(tss interfaces.TSSSigner) *Signer { + s.tss = tss + return s +} + +// TelemetryServer returns the telemetry server for the signer +func (s *Signer) TelemetryServer() *metrics.TelemetryServer { + return s.ts +} + +// WithTelemetryServer attaches a new telemetry server to the signer +func (s *Signer) WithTelemetryServer(ts *metrics.TelemetryServer) *Signer { + s.ts = ts + return s +} + +// Logger returns the logger for the signer +func (s *Signer) Logger() *Logger { + return &s.logger +} diff --git a/zetaclient/chains/base/signer_test.go b/zetaclient/chains/base/signer_test.go new file mode 100644 index 0000000000..960c508d6e --- /dev/null +++ b/zetaclient/chains/base/signer_test.go @@ -0,0 +1,74 @@ +package base_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + + "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" + "github.com/zeta-chain/zetacore/zetaclient/config" + "github.com/zeta-chain/zetacore/zetaclient/context" + "github.com/zeta-chain/zetacore/zetaclient/metrics" + "github.com/zeta-chain/zetacore/zetaclient/testutils/mocks" +) + +// createSigner creates a new signer for testing +func createSigner(_ *testing.T) *base.Signer { + // constructor parameters + chain := chains.Ethereum + zetacoreContext := context.NewZetacoreContext(config.NewConfig()) + tss := mocks.NewTSSMainnet() + logger := base.DefaultLogger() + + // create signer + return base.NewSigner(chain, zetacoreContext, tss, nil, logger) +} + +func TestNewSigner(t *testing.T) { + signer := createSigner(t) + require.NotNil(t, signer) +} + +func TestSignerGetterAndSetter(t *testing.T) { + t.Run("should be able to update chain", func(t *testing.T) { + signer := createSigner(t) + + // update chain + newChain := chains.BscMainnet + signer = signer.WithChain(chains.BscMainnet) + require.Equal(t, newChain, signer.Chain()) + }) + t.Run("should be able to update zetacore context", func(t *testing.T) { + signer := createSigner(t) + + // update zetacore context + newZetacoreContext := context.NewZetacoreContext(config.NewConfig()) + signer = signer.WithZetacoreContext(newZetacoreContext) + require.Equal(t, newZetacoreContext, signer.ZetacoreContext()) + }) + t.Run("should be able to update tss", func(t *testing.T) { + signer := createSigner(t) + + // update tss + newTSS := mocks.NewTSSAthens3() + signer = signer.WithTSS(newTSS) + require.Equal(t, newTSS, signer.TSS()) + }) + t.Run("should be able to update telemetry server", func(t *testing.T) { + signer := createSigner(t) + + // update telemetry server + newTs := metrics.NewTelemetryServer() + signer = signer.WithTelemetryServer(newTs) + require.Equal(t, newTs, signer.TelemetryServer()) + }) + t.Run("should be able to get logger", func(t *testing.T) { + ob := createSigner(t) + logger := ob.Logger() + + // should be able to print log + logger.Std.Info().Msg("print standard log") + logger.Compliance.Info().Msg("print compliance log") + }) +} diff --git a/zetaclient/chains/bitcoin/observer/live_test.go b/zetaclient/chains/bitcoin/observer/live_test.go index 51bedbf1ef..dd1053f620 100644 --- a/zetaclient/chains/bitcoin/observer/live_test.go +++ b/zetaclient/chains/bitcoin/observer/live_test.go @@ -21,8 +21,8 @@ import ( "github.com/stretchr/testify/suite" "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/chains/bitcoin" - clientcommon "github.com/zeta-chain/zetacore/zetaclient/common" "github.com/zeta-chain/zetacore/zetaclient/config" clientcontext "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/testutils" @@ -49,7 +49,7 @@ func (suite *BitcoinObserverTestSuite) SetupTest() { } appContext := clientcontext.NewAppContext(&clientcontext.ZetacoreContext{}, config.Config{}) client, err := NewObserver(appContext, chains.BitcoinRegtest, nil, tss, tempSQLiteDbPath, - clientcommon.DefaultLoggers(), config.BTCConfig{}, nil) + base.DefaultLogger(), config.BTCConfig{}, nil) suite.Require().NoError(err) suite.rpcClient, err = getRPCClient(18332) suite.Require().NoError(err) diff --git a/zetaclient/chains/bitcoin/observer/observer.go b/zetaclient/chains/bitcoin/observer/observer.go index 062f00c2c7..6b93ba12cd 100644 --- a/zetaclient/chains/bitcoin/observer/observer.go +++ b/zetaclient/chains/bitcoin/observer/observer.go @@ -28,9 +28,9 @@ import ( "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/pkg/proofs" observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/chains/bitcoin" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" - clientcommon "github.com/zeta-chain/zetacore/zetaclient/common" "github.com/zeta-chain/zetacore/zetaclient/config" "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/metrics" @@ -138,7 +138,7 @@ func NewObserver( zetacoreClient interfaces.ZetacoreClient, tss interfaces.TSSSigner, dbpath string, - loggers clientcommon.ClientLogger, + logger base.Logger, btcCfg config.BTCConfig, ts *metrics.TelemetryServer, ) (*Observer, error) { @@ -158,14 +158,14 @@ func NewObserver( ob.Mu = &sync.Mutex{} - chainLogger := loggers.Std.With().Str("chain", chain.ChainName.String()).Logger() + chainLogger := logger.Std.With().Str("chain", chain.ChainName.String()).Logger() ob.logger = Logger{ Chain: chainLogger, Inbound: chainLogger.With().Str("module", "WatchInbound").Logger(), Outbound: chainLogger.With().Str("module", "WatchOutbound").Logger(), UTXOs: chainLogger.With().Str("module", "WatchUTXOs").Logger(), GasPrice: chainLogger.With().Str("module", "WatchGasPrice").Logger(), - Compliance: loggers.Compliance, + Compliance: logger.Compliance, } ob.zetacoreClient = zetacoreClient diff --git a/zetaclient/chains/bitcoin/observer/observer_test.go b/zetaclient/chains/bitcoin/observer/observer_test.go index dfba6b3dbc..2d2494dd16 100644 --- a/zetaclient/chains/bitcoin/observer/observer_test.go +++ b/zetaclient/chains/bitcoin/observer/observer_test.go @@ -14,7 +14,7 @@ import ( "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/testutil/sample" observertypes "github.com/zeta-chain/zetacore/x/observer/types" - clientcommon "github.com/zeta-chain/zetacore/zetaclient/common" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/config" "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/metrics" @@ -75,11 +75,11 @@ func TestNewBitcoinObserver(t *testing.T) { chain := chains.BitcoinMainnet zetacoreClient := mocks.NewMockZetacoreClient() tss := mocks.NewMockTSS(chains.BitcoinTestnet, sample.EthAddress().String(), "") - loggers := clientcommon.ClientLogger{} + logger := base.Logger{} btcCfg := cfg.BitcoinConfig ts := metrics.NewTelemetryServer() - client, err := NewObserver(appContext, chain, zetacoreClient, tss, tempSQLiteDbPath, loggers, btcCfg, ts) + client, err := NewObserver(appContext, chain, zetacoreClient, tss, tempSQLiteDbPath, logger, btcCfg, ts) require.ErrorContains(t, err, "btc chains params not initialized") require.Nil(t, client) }) diff --git a/zetaclient/chains/bitcoin/signer/signer.go b/zetaclient/chains/bitcoin/signer/signer.go index 12c5b2b100..f2d47fd988 100644 --- a/zetaclient/chains/bitcoin/signer/signer.go +++ b/zetaclient/chains/bitcoin/signer/signer.go @@ -21,10 +21,10 @@ import ( "github.com/zeta-chain/zetacore/pkg/coin" "github.com/zeta-chain/zetacore/x/crosschain/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/chains/bitcoin" "github.com/zeta-chain/zetacore/zetaclient/chains/bitcoin/observer" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" - clientcommon "github.com/zeta-chain/zetacore/zetaclient/common" "github.com/zeta-chain/zetacore/zetaclient/compliance" "github.com/zeta-chain/zetacore/zetaclient/config" "github.com/zeta-chain/zetacore/zetaclient/context" @@ -56,7 +56,7 @@ type Signer struct { func NewSigner( cfg config.BTCConfig, tssSigner interfaces.TSSSigner, - loggers clientcommon.ClientLogger, + logger base.Logger, ts *metrics.TelemetryServer, coreContext *context.ZetacoreContext) (*Signer, error) { connCfg := &rpcclient.ConnConfig{ @@ -75,8 +75,8 @@ func NewSigner( return &Signer{ tssSigner: tssSigner, rpcClient: client, - logger: loggers.Std.With().Str("chain", "BTC").Str("module", "BTCSigner").Logger(), - loggerCompliance: loggers.Compliance, + logger: logger.Std.With().Str("chain", "BTC").Str("module", "BTCSigner").Logger(), + loggerCompliance: logger.Compliance, ts: ts, coreContext: coreContext, }, nil diff --git a/zetaclient/chains/bitcoin/signer/signer_test.go b/zetaclient/chains/bitcoin/signer/signer_test.go index 6d048c7bba..74628211a4 100644 --- a/zetaclient/chains/bitcoin/signer/signer_test.go +++ b/zetaclient/chains/bitcoin/signer/signer_test.go @@ -18,8 +18,8 @@ import ( . "gopkg.in/check.v1" "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/chains/bitcoin" - clientcommon "github.com/zeta-chain/zetacore/zetaclient/common" "github.com/zeta-chain/zetacore/zetaclient/config" "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/metrics" @@ -52,7 +52,7 @@ func (s *BTCSignerSuite) SetUpTest(c *C) { s.btcSigner, err = NewSigner( config.BTCConfig{}, tss, - clientcommon.DefaultLoggers(), + base.DefaultLogger(), &metrics.TelemetryServer{}, context.NewZetacoreContext(cfg)) c.Assert(err, IsNil) @@ -233,7 +233,7 @@ func TestAddWithdrawTxOutputs(t *testing.T) { signer, err := NewSigner( config.BTCConfig{}, mocks.NewTSSMainnet(), - clientcommon.DefaultLoggers(), + base.DefaultLogger(), &metrics.TelemetryServer{}, nil, ) @@ -396,7 +396,7 @@ func TestNewBTCSigner(t *testing.T) { btcSigner, err := NewSigner( config.BTCConfig{}, tss, - clientcommon.DefaultLoggers(), + base.DefaultLogger(), &metrics.TelemetryServer{}, context.NewZetacoreContext(cfg)) require.NoError(t, err) diff --git a/zetaclient/chains/evm/observer/observer.go b/zetaclient/chains/evm/observer/observer.go index 795aa3b13b..99db258f5a 100644 --- a/zetaclient/chains/evm/observer/observer.go +++ b/zetaclient/chains/evm/observer/observer.go @@ -30,9 +30,9 @@ import ( "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/pkg/proofs" observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/chains/evm" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" - clientcommon "github.com/zeta-chain/zetacore/zetaclient/common" "github.com/zeta-chain/zetacore/zetaclient/config" clientcontext "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/metrics" @@ -93,7 +93,7 @@ func NewObserver( zetacoreClient interfaces.ZetacoreClient, tss interfaces.TSSSigner, dbpath string, - loggers clientcommon.ClientLogger, + logger base.Logger, evmCfg config.EVMConfig, ts *metrics.TelemetryServer, ) (*Observer, error) { @@ -101,13 +101,13 @@ func NewObserver( ts: ts, } - chainLogger := loggers.Std.With().Str("chain", evmCfg.Chain.ChainName.String()).Logger() + chainLogger := logger.Std.With().Str("chain", evmCfg.Chain.ChainName.String()).Logger() ob.logger = Logger{ Chain: chainLogger, Inbound: chainLogger.With().Str("module", "WatchInbound").Logger(), Outbound: chainLogger.With().Str("module", "WatchOutbound").Logger(), GasPrice: chainLogger.With().Str("module", "WatchGasPrice").Logger(), - Compliance: loggers.Compliance, + Compliance: logger.Compliance, } ob.coreContext = appContext.ZetacoreContext() @@ -581,7 +581,7 @@ func (ob *Observer) LoadLastScannedBlock() error { if scanFromBlock != "" { ob.logger.Chain.Info(). Msgf("LoadLastScannedBlock: envvar %s is set; scan from block %s", envvar, scanFromBlock) - if scanFromBlock == clienttypes.EnvVarLatest { + if scanFromBlock == base.EnvVarLatestBlock { header, err := ob.evmClient.HeaderByNumber(context.Background(), nil) if err != nil { return err diff --git a/zetaclient/chains/evm/observer/observer_test.go b/zetaclient/chains/evm/observer/observer_test.go index bfc85e15e1..0601c083f2 100644 --- a/zetaclient/chains/evm/observer/observer_test.go +++ b/zetaclient/chains/evm/observer/observer_test.go @@ -15,9 +15,9 @@ import ( "github.com/zeta-chain/zetacore/testutil/sample" "github.com/zeta-chain/zetacore/x/crosschain/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/chains/evm/observer" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" - "github.com/zeta-chain/zetacore/zetaclient/common" "github.com/zeta-chain/zetacore/zetaclient/config" "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/keys" @@ -83,7 +83,7 @@ func MockEVMObserver( appCtx, evmCfg := getAppContext(chain, ¶ms) // create chain observer - client, err := observer.NewObserver(appCtx, zetacoreClient, tss, "", common.ClientLogger{}, evmCfg, nil) + client, err := observer.NewObserver(appCtx, zetacoreClient, tss, "", base.Logger{}, evmCfg, nil) require.NoError(t, err) client.WithEvmClient(evmClient) client.WithEvmJSONRPC(evmJSONRPC) diff --git a/zetaclient/chains/evm/signer/signer.go b/zetaclient/chains/evm/signer/signer.go index 00f6f35fd5..d49895e2a3 100644 --- a/zetaclient/chains/evm/signer/signer.go +++ b/zetaclient/chains/evm/signer/signer.go @@ -27,10 +27,10 @@ import ( crosschainkeeper "github.com/zeta-chain/zetacore/x/crosschain/keeper" "github.com/zeta-chain/zetacore/x/crosschain/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/chains/evm" "github.com/zeta-chain/zetacore/zetaclient/chains/evm/observer" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" - clientcommon "github.com/zeta-chain/zetacore/zetaclient/common" "github.com/zeta-chain/zetacore/zetaclient/compliance" clientcontext "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/metrics" @@ -52,7 +52,7 @@ type Signer struct { chain *chains.Chain tssSigner interfaces.TSSSigner ethSigner ethtypes.Signer - logger clientcommon.ClientLogger + logger base.Logger ts *metrics.TelemetryServer coreContext *clientcontext.ZetacoreContext @@ -74,7 +74,7 @@ func NewSigner( zetaConnectorAddress ethcommon.Address, erc20CustodyAddress ethcommon.Address, coreContext *clientcontext.ZetacoreContext, - loggers clientcommon.ClientLogger, + logger base.Logger, ts *metrics.TelemetryServer, ) (*Signer, error) { client, ethSigner, err := getEVMRPC(endpoint) @@ -100,9 +100,9 @@ func NewSigner( zetaConnectorAddress: zetaConnectorAddress, er20CustodyAddress: erc20CustodyAddress, coreContext: coreContext, - logger: clientcommon.ClientLogger{ - Std: loggers.Std.With().Str("chain", chain.ChainName.String()).Str("module", "EVMSigner").Logger(), - Compliance: loggers.Compliance, + logger: base.Logger{ + Std: logger.Std.With().Str("chain", chain.ChainName.String()).Str("module", "EVMSigner").Logger(), + Compliance: logger.Compliance, }, ts: ts, mu: &sync.Mutex{}, diff --git a/zetaclient/chains/evm/signer/signer_test.go b/zetaclient/chains/evm/signer/signer_test.go index 06e33571a5..186582dd24 100644 --- a/zetaclient/chains/evm/signer/signer_test.go +++ b/zetaclient/chains/evm/signer/signer_test.go @@ -15,9 +15,9 @@ import ( "github.com/zeta-chain/zetacore/pkg/constant" "github.com/zeta-chain/zetacore/testutil/sample" crosschaintypes "github.com/zeta-chain/zetacore/x/crosschain/types" + "github.com/zeta-chain/zetacore/zetaclient/chains/base" "github.com/zeta-chain/zetacore/zetaclient/chains/evm/observer" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" - "github.com/zeta-chain/zetacore/zetaclient/common" "github.com/zeta-chain/zetacore/zetaclient/config" "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/keys" @@ -42,7 +42,7 @@ func getNewEvmSigner(tss interfaces.TSSSigner) (*Signer, error) { mpiAddress := ConnectorAddress erc20CustodyAddress := ERC20CustodyAddress - logger := common.ClientLogger{} + logger := base.Logger{} ts := &metrics.TelemetryServer{} cfg := config.NewConfig() @@ -66,7 +66,7 @@ func getNewEvmChainObserver(tss interfaces.TSSSigner) (*observer.Observer, error tss = mocks.NewTSSMainnet() } - logger := common.ClientLogger{} + logger := base.Logger{} ts := &metrics.TelemetryServer{} cfg := config.NewConfig() diff --git a/zetaclient/common/logger.go b/zetaclient/common/logger.go deleted file mode 100644 index ebe773abfc..0000000000 --- a/zetaclient/common/logger.go +++ /dev/null @@ -1,20 +0,0 @@ -package common - -import ( - "github.com/rs/zerolog" - "github.com/rs/zerolog/log" -) - -// ClientLogger is a struct that contains the logger for a chain observer -type ClientLogger struct { - Std zerolog.Logger - Compliance zerolog.Logger -} - -// DefaultLoggers returns the default loggers for a chain observer -func DefaultLoggers() ClientLogger { - return ClientLogger{ - Std: log.Logger, - Compliance: log.Logger, - } -} diff --git a/zetaclient/context/zetacore_context_test.go b/zetaclient/context/zetacore_context_test.go index 0ee7d5bc8a..d8117e124b 100644 --- a/zetaclient/context/zetacore_context_test.go +++ b/zetaclient/context/zetacore_context_test.go @@ -4,13 +4,13 @@ import ( "testing" "github.com/rs/zerolog" + "github.com/rs/zerolog/log" "github.com/stretchr/testify/require" "github.com/zeta-chain/zetacore/pkg/chains" "github.com/zeta-chain/zetacore/testutil/sample" lightclienttypes "github.com/zeta-chain/zetacore/x/lightclient/types" observertypes "github.com/zeta-chain/zetacore/x/observer/types" - clientcommon "github.com/zeta-chain/zetacore/zetaclient/common" "github.com/zeta-chain/zetacore/zetaclient/config" context "github.com/zeta-chain/zetacore/zetaclient/context" ) @@ -179,7 +179,6 @@ func TestUpdateZetacoreContext(t *testing.T) { ChainId: 3, } tssPubKeyToUpdate := "tsspubkeytest" - loggers := clientcommon.DefaultLoggers() crosschainFlags := sample.CrosschainFlags() verificationFlags := sample.HeaderSupportedChains() @@ -193,7 +192,7 @@ func TestUpdateZetacoreContext(t *testing.T) { *crosschainFlags, verificationFlags, false, - loggers.Std, + log.Logger, ) // assert keygen updated @@ -285,7 +284,6 @@ func TestUpdateZetacoreContext(t *testing.T) { crosschainFlags := sample.CrosschainFlags() verificationFlags := sample.HeaderSupportedChains() require.NotNil(t, crosschainFlags) - loggers := clientcommon.DefaultLoggers() zetaContext.Update( &keyGenToUpdate, enabledChainsToUpdate, @@ -295,7 +293,7 @@ func TestUpdateZetacoreContext(t *testing.T) { *crosschainFlags, verificationFlags, false, - loggers.Std, + log.Logger, ) // assert keygen updated diff --git a/zetaclient/types/defs.go b/zetaclient/types/defs.go deleted file mode 100644 index 8bc79913fe..0000000000 --- a/zetaclient/types/defs.go +++ /dev/null @@ -1,5 +0,0 @@ -package types - -const ( - EnvVarLatest = "latest" -)