diff --git a/changelog.md b/changelog.md index 1d213ca4f7..f08d5aa0a8 100644 --- a/changelog.md +++ b/changelog.md @@ -55,6 +55,7 @@ * [2357](https://github.com/zeta-chain/node/pull/2357) - integrate base Signer structure into EVM/Bitcoin Signer * [2359](https://github.com/zeta-chain/node/pull/2359) - integrate base Observer structure into EVM/Bitcoin Observer * [2375](https://github.com/zeta-chain/node/pull/2375) - improve & speedup code formatting +* [2395](https://github.com/zeta-chain/node/pull/2395) - converge AppContext with ZetaCoreContext in zetaclient ### Tests diff --git a/cmd/zetaclientd/debug.go b/cmd/zetaclientd/debug.go index 50022b9c20..d64cee7df5 100644 --- a/cmd/zetaclientd/debug.go +++ b/cmd/zetaclientd/debug.go @@ -42,163 +42,166 @@ func init() { } func DebugCmd() *cobra.Command { - cmd := &cobra.Command{ + return &cobra.Command{ Use: "get-inbound-ballot [inboundHash] [chainID]", Short: "provide txHash and chainID to get the ballot status for the txHash", - RunE: func(_ *cobra.Command, args []string) error { - cobra.ExactArgs(2) - cfg, err := config.Load(debugArgs.zetaCoreHome) - if err != nil { - return err - } - appContext := clientcontext.NewAppContext(cfg) - chainID, err := strconv.ParseInt(args[1], 10, 64) - if err != nil { - return err - } - inboundHash := args[0] - var ballotIdentifier string - - // create a new zetacore client - client, err := zetacore.NewClient( - &keys.Keys{OperatorAddress: sdk.MustAccAddressFromBech32(sample.AccAddress())}, - debugArgs.zetaNode, - "", - debugArgs.zetaChainID, - false, - nil) - if err != nil { - return err - } - chainParams, err := client.GetChainParams() - if err != nil { - return err - } - tssEthAddress, err := client.GetEthTssAddress() - if err != nil { - return err - } - chain := chains.GetChainFromChainID(chainID) - if chain == nil { - return fmt.Errorf("invalid chain id") - } + RunE: debugCmd, + } +} - // get ballot identifier according to the chain type - if chains.IsEVMChain(chain.ChainId) { - evmObserver := evmobserver.Observer{} - evmObserver.WithZetacoreClient(client) - var ethRPC *ethrpc.EthRPC - var client *ethclient.Client - coinType := coin.CoinType_Cmd - for chain, evmConfig := range cfg.GetAllEVMConfigs() { - if chainID == chain { - ethRPC = ethrpc.NewEthRPC(evmConfig.Endpoint) - client, err = ethclient.Dial(evmConfig.Endpoint) - if err != nil { - return err - } - evmObserver.WithEvmClient(client) - evmObserver.WithEvmJSONRPC(ethRPC) - evmObserver.WithChain(*chains.GetChainFromChainID(chainID)) - } - } - hash := ethcommon.HexToHash(inboundHash) - tx, isPending, err := evmObserver.TransactionByHash(inboundHash) - if err != nil { - return fmt.Errorf("tx not found on chain %s , %d", err.Error(), chain.ChainId) - } - if isPending { - return fmt.Errorf("tx is still pending") - } - receipt, err := client.TransactionReceipt(context.Background(), hash) - if err != nil { - return fmt.Errorf("tx receipt not found on chain %s, %d", err.Error(), chain.ChainId) - } +func debugCmd(_ *cobra.Command, args []string) error { + cobra.ExactArgs(2) + cfg, err := config.Load(debugArgs.zetaCoreHome) + if err != nil { + return err + } - for _, chainParams := range chainParams { - if chainParams.ChainId == chainID { - evmObserver.SetChainParams(observertypes.ChainParams{ - ChainId: chainID, - ConnectorContractAddress: chainParams.ConnectorContractAddress, - ZetaTokenContractAddress: chainParams.ZetaTokenContractAddress, - Erc20CustodyContractAddress: chainParams.Erc20CustodyContractAddress, - }) - evmChainParams, found := appContext.GetExternalChainParams(chainID) - if !found { - return fmt.Errorf("missing chain params for chain %d", chainID) - } - evmChainParams.ZetaTokenContractAddress = chainParams.ZetaTokenContractAddress - if strings.EqualFold(tx.To, chainParams.ConnectorContractAddress) { - coinType = coin.CoinType_Zeta - } else if strings.EqualFold(tx.To, chainParams.Erc20CustodyContractAddress) { - coinType = coin.CoinType_ERC20 - } else if strings.EqualFold(tx.To, tssEthAddress) { - coinType = coin.CoinType_Gas - } - } - } + appContext := clientcontext.NewAppContext(cfg) - switch coinType { - case coin.CoinType_Zeta: - ballotIdentifier, err = evmObserver.CheckAndVoteInboundTokenZeta(tx, receipt, false) - if err != nil { - return err - } - - case coin.CoinType_ERC20: - ballotIdentifier, err = evmObserver.CheckAndVoteInboundTokenERC20(tx, receipt, false) - if err != nil { - return err - } - - case coin.CoinType_Gas: - ballotIdentifier, err = evmObserver.CheckAndVoteInboundTokenGas(tx, receipt, false) - if err != nil { - return err - } - default: - fmt.Println("CoinType not detected") - } - fmt.Println("CoinType : ", coinType) - } else if chains.IsBitcoinChain(chain.ChainId) { - btcObserver := btcobserver.Observer{} - btcObserver.WithZetacoreClient(client) - btcObserver.WithChain(*chains.GetChainFromChainID(chainID)) - connCfg := &rpcclient.ConnConfig{ - Host: cfg.BitcoinConfig.RPCHost, - User: cfg.BitcoinConfig.RPCUsername, - Pass: cfg.BitcoinConfig.RPCPassword, - HTTPPostMode: true, - DisableTLS: true, - Params: cfg.BitcoinConfig.RPCParams, - } + chainID, err := strconv.ParseInt(args[1], 10, 64) + if err != nil { + return err + } + + inboundHash := args[0] + var ballotIdentifier string + + // create a new zetacore client + client, err := zetacore.NewClient( + &keys.Keys{OperatorAddress: sdk.MustAccAddressFromBech32(sample.AccAddress())}, + debugArgs.zetaNode, + "", + debugArgs.zetaChainID, + false, + nil) + if err != nil { + return err + } + chainParams, err := client.GetChainParams() + if err != nil { + return err + } + tssEthAddress, err := client.GetEthTssAddress() + if err != nil { + return err + } + chain := chains.GetChainFromChainID(chainID) + if chain == nil { + return fmt.Errorf("invalid chain id") + } - btcClient, err := rpcclient.New(connCfg, nil) + // get ballot identifier according to the chain type + if chains.IsEVMChain(chain.ChainId) { + evmObserver := evmobserver.Observer{} + evmObserver.WithZetacoreClient(client) + var ethRPC *ethrpc.EthRPC + var client *ethclient.Client + coinType := coin.CoinType_Cmd + for chain, evmConfig := range cfg.GetAllEVMConfigs() { + if chainID == chain { + ethRPC = ethrpc.NewEthRPC(evmConfig.Endpoint) + client, err = ethclient.Dial(evmConfig.Endpoint) if err != nil { return err } - btcObserver.WithBtcClient(btcClient) - ballotIdentifier, err = btcObserver.CheckReceiptForBtcTxHash(inboundHash, false) - if err != nil { - return err + evmObserver.WithEvmClient(client) + evmObserver.WithEvmJSONRPC(ethRPC) + evmObserver.WithChain(*chains.GetChainFromChainID(chainID)) + } + } + hash := ethcommon.HexToHash(inboundHash) + tx, isPending, err := evmObserver.TransactionByHash(inboundHash) + if err != nil { + return fmt.Errorf("tx not found on chain %s , %d", err.Error(), chain.ChainId) + } + if isPending { + return fmt.Errorf("tx is still pending") + } + receipt, err := client.TransactionReceipt(context.Background(), hash) + if err != nil { + return fmt.Errorf("tx receipt not found on chain %s, %d", err.Error(), chain.ChainId) + } + + for _, chainParams := range chainParams { + if chainParams.ChainId == chainID { + evmObserver.SetChainParams(observertypes.ChainParams{ + ChainId: chainID, + ConnectorContractAddress: chainParams.ConnectorContractAddress, + ZetaTokenContractAddress: chainParams.ZetaTokenContractAddress, + Erc20CustodyContractAddress: chainParams.Erc20CustodyContractAddress, + }) + evmChainParams, found := appContext.GetExternalChainParams(chainID) + if !found { + return fmt.Errorf("missing chain params for chain %d", chainID) + } + evmChainParams.ZetaTokenContractAddress = chainParams.ZetaTokenContractAddress + if strings.EqualFold(tx.To, chainParams.ConnectorContractAddress) { + coinType = coin.CoinType_Zeta + } else if strings.EqualFold(tx.To, chainParams.Erc20CustodyContractAddress) { + coinType = coin.CoinType_ERC20 + } else if strings.EqualFold(tx.To, tssEthAddress) { + coinType = coin.CoinType_Gas } } - fmt.Println("BallotIdentifier : ", ballotIdentifier) + } - // query ballot - ballot, err := client.GetBallot(ballotIdentifier) + switch coinType { + case coin.CoinType_Zeta: + ballotIdentifier, err = evmObserver.CheckAndVoteInboundTokenZeta(tx, receipt, false) if err != nil { return err } - for _, vote := range ballot.Voters { - fmt.Printf("%s : %s \n", vote.VoterAddress, vote.VoteType) + case coin.CoinType_ERC20: + ballotIdentifier, err = evmObserver.CheckAndVoteInboundTokenERC20(tx, receipt, false) + if err != nil { + return err } - fmt.Println("BallotStatus : ", ballot.BallotStatus) - return nil - }, + case coin.CoinType_Gas: + ballotIdentifier, err = evmObserver.CheckAndVoteInboundTokenGas(tx, receipt, false) + if err != nil { + return err + } + default: + fmt.Println("CoinType not detected") + } + fmt.Println("CoinType : ", coinType) + } else if chains.IsBitcoinChain(chain.ChainId) { + btcObserver := btcobserver.Observer{} + btcObserver.WithZetacoreClient(client) + btcObserver.WithChain(*chains.GetChainFromChainID(chainID)) + connCfg := &rpcclient.ConnConfig{ + Host: cfg.BitcoinConfig.RPCHost, + User: cfg.BitcoinConfig.RPCUsername, + Pass: cfg.BitcoinConfig.RPCPassword, + HTTPPostMode: true, + DisableTLS: true, + Params: cfg.BitcoinConfig.RPCParams, + } + + btcClient, err := rpcclient.New(connCfg, nil) + if err != nil { + return err + } + btcObserver.WithBtcClient(btcClient) + ballotIdentifier, err = btcObserver.CheckReceiptForBtcTxHash(inboundHash, false) + if err != nil { + return err + } + } + fmt.Println("BallotIdentifier : ", ballotIdentifier) + + // query ballot + ballot, err := client.GetBallot(ballotIdentifier) + if err != nil { + return err + } + + for _, vote := range ballot.Voters { + fmt.Printf("%s : %s \n", vote.VoterAddress, vote.VoteType) } + fmt.Println("BallotStatus : ", ballot.BallotStatus) - return cmd + return nil } diff --git a/zetaclient/chains/base/observer.go b/zetaclient/chains/base/observer.go index 890b68e09f..fe6238d731 100644 --- a/zetaclient/chains/base/observer.go +++ b/zetaclient/chains/base/observer.go @@ -45,7 +45,7 @@ type Observer struct { // chainParams contains the dynamic chain parameters of the observed chain chainParams observertypes.ChainParams - // appContext contains context data of zetaclient + // appContext contains context data for zetaclient & zetacore (e.g. supported chains) appContext *context.AppContext // zetacoreClient is the client to interact with ZetaChain @@ -170,12 +170,6 @@ func (ob *Observer) AppContext() *context.AppContext { return ob.appContext } -// WithAppContext attaches a new app context to the observer. -func (ob *Observer) WithAppContext(context *context.AppContext) *Observer { - ob.appContext = context - return ob -} - // ZetacoreClient returns the zetacore client for the observer. func (ob *Observer) ZetacoreClient() interfaces.ZetacoreClient { return ob.zetacoreClient diff --git a/zetaclient/chains/base/observer_test.go b/zetaclient/chains/base/observer_test.go index 2be07d2a1f..2ec1bcd14a 100644 --- a/zetaclient/chains/base/observer_test.go +++ b/zetaclient/chains/base/observer_test.go @@ -164,14 +164,6 @@ func TestObserverGetterAndSetter(t *testing.T) { ob = ob.WithChainParams(newChainParams) require.True(t, observertypes.ChainParamsEqual(newChainParams, ob.ChainParams())) }) - t.Run("should be able to update app context", func(t *testing.T) { - ob := createObserver(t) - - // update app context - newAppContext := context.NewAppContext(config.NewConfig()) - ob = ob.WithAppContext(newAppContext) - require.Equal(t, newAppContext, ob.AppContext()) - }) t.Run("should be able to update zetacore client", func(t *testing.T) { ob := createObserver(t) diff --git a/zetaclient/chains/base/signer.go b/zetaclient/chains/base/signer.go index b4dde840d3..21dde4a746 100644 --- a/zetaclient/chains/base/signer.go +++ b/zetaclient/chains/base/signer.go @@ -68,12 +68,6 @@ func (s *Signer) AppContext() *context.AppContext { return s.appContext } -// WithAppContext attaches a new app context to the signer -func (s *Signer) WithAppContext(context *context.AppContext) *Signer { - s.appContext = context - return s -} - // Tss returns the tss signer for the signer func (s *Signer) TSS() interfaces.TSSSigner { return s.tss diff --git a/zetaclient/chains/base/signer_test.go b/zetaclient/chains/base/signer_test.go index 1cd25cec7a..ea38f79122 100644 --- a/zetaclient/chains/base/signer_test.go +++ b/zetaclient/chains/base/signer_test.go @@ -39,14 +39,6 @@ func TestSignerGetterAndSetter(t *testing.T) { signer = signer.WithChain(chains.BscMainnet) require.Equal(t, newChain, signer.Chain()) }) - t.Run("should be able to update app context", func(t *testing.T) { - signer := createSigner(t) - - // update app context - newAppContext := context.NewAppContext(config.NewConfig()) - signer = signer.WithAppContext(newAppContext) - require.Equal(t, newAppContext, signer.AppContext()) - }) t.Run("should be able to update tss", func(t *testing.T) { signer := createSigner(t) diff --git a/zetaclient/chains/bitcoin/observer/inbound.go b/zetaclient/chains/bitcoin/observer/inbound.go index f068c41311..26079f4303 100644 --- a/zetaclient/chains/bitcoin/observer/inbound.go +++ b/zetaclient/chains/bitcoin/observer/inbound.go @@ -19,7 +19,6 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/chains/bitcoin" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" "github.com/zeta-chain/zetacore/zetaclient/compliance" - "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/types" "github.com/zeta-chain/zetacore/zetaclient/zetacore" ) @@ -42,7 +41,7 @@ func (ob *Observer) WatchInbound() { for { select { case <-ticker.C(): - if !context.IsInboundObservationEnabled(ob.AppContext(), ob.GetChainParams()) { + if !ob.AppContext().IsInboundObservationEnabled(ob.GetChainParams()) { sampledLogger.Info(). Msgf("WatchInbound: inbound observation is disabled for chain %d", ob.Chain().ChainId) continue @@ -186,7 +185,7 @@ func (ob *Observer) WatchInboundTracker() { for { select { case <-ticker.C(): - if !context.IsInboundObservationEnabled(ob.AppContext(), ob.GetChainParams()) { + if !ob.AppContext().IsInboundObservationEnabled(ob.GetChainParams()) { continue } err := ob.ProcessInboundTrackers() diff --git a/zetaclient/chains/bitcoin/observer/outbound.go b/zetaclient/chains/bitcoin/observer/outbound.go index abe9f837cd..681604d48b 100644 --- a/zetaclient/chains/bitcoin/observer/outbound.go +++ b/zetaclient/chains/bitcoin/observer/outbound.go @@ -16,7 +16,6 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/chains/bitcoin/rpc" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" "github.com/zeta-chain/zetacore/zetaclient/compliance" - "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/types" ) @@ -44,7 +43,7 @@ func (ob *Observer) WatchOutbound() { for { select { case <-ticker.C(): - if !context.IsOutboundObservationEnabled(ob.AppContext(), ob.GetChainParams()) { + if !ob.AppContext().IsOutboundObservationEnabled(ob.GetChainParams()) { sampledLogger.Info(). Msgf("WatchOutbound: outbound observation is disabled for chain %d", chainID) continue diff --git a/zetaclient/chains/evm/observer/inbound.go b/zetaclient/chains/evm/observer/inbound.go index 0eb6fd6403..ce7924f150 100644 --- a/zetaclient/chains/evm/observer/inbound.go +++ b/zetaclient/chains/evm/observer/inbound.go @@ -27,7 +27,6 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/chains/evm" "github.com/zeta-chain/zetacore/zetaclient/compliance" "github.com/zeta-chain/zetacore/zetaclient/config" - clientcontext "github.com/zeta-chain/zetacore/zetaclient/context" "github.com/zeta-chain/zetacore/zetaclient/metrics" clienttypes "github.com/zeta-chain/zetacore/zetaclient/types" "github.com/zeta-chain/zetacore/zetaclient/zetacore" @@ -52,7 +51,7 @@ func (ob *Observer) WatchInbound() { for { select { case <-ticker.C(): - if !clientcontext.IsInboundObservationEnabled(ob.AppContext(), ob.GetChainParams()) { + if !ob.AppContext().IsInboundObservationEnabled(ob.GetChainParams()) { sampledLogger.Info(). Msgf("WatchInbound: inbound observation is disabled for chain %d", ob.Chain().ChainId) continue @@ -87,7 +86,7 @@ func (ob *Observer) WatchInboundTracker() { for { select { case <-ticker.C(): - if !clientcontext.IsInboundObservationEnabled(ob.AppContext(), ob.GetChainParams()) { + if !ob.AppContext().IsInboundObservationEnabled(ob.GetChainParams()) { continue } err := ob.ProcessInboundTrackers() @@ -662,7 +661,7 @@ func (ob *Observer) BuildInboundVoteMsgForZetaSentEvent( paramsDest, found := ob.AppContext().GetExternalChainParams(destChain.ChainId) if !found { ob.Logger().Inbound.Warn(). - Msgf("chain id not present in EVMChainParams %d", event.DestinationChainId.Int64()) + Msgf("chain params id not present in AppContext %d", destChain.ChainId) return nil } diff --git a/zetaclient/chains/evm/observer/outbound.go b/zetaclient/chains/evm/observer/outbound.go index 5c3e4c2c9f..2b04bbf43f 100644 --- a/zetaclient/chains/evm/observer/outbound.go +++ b/zetaclient/chains/evm/observer/outbound.go @@ -23,7 +23,6 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/chains/evm" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" "github.com/zeta-chain/zetacore/zetaclient/compliance" - clientcontext "github.com/zeta-chain/zetacore/zetaclient/context" clienttypes "github.com/zeta-chain/zetacore/zetaclient/types" ) @@ -52,7 +51,7 @@ func (ob *Observer) WatchOutbound() { for { select { case <-ticker.C(): - if !clientcontext.IsOutboundObservationEnabled(ob.AppContext(), ob.GetChainParams()) { + if !ob.AppContext().IsOutboundObservationEnabled(ob.GetChainParams()) { sampledLogger.Info(). Msgf("WatchOutbound: outbound observation is disabled for chain %d", ob.Chain().ChainId) continue diff --git a/zetaclient/chains/evm/signer/signer_test.go b/zetaclient/chains/evm/signer/signer_test.go index 9aa7c32546..40a5792501 100644 --- a/zetaclient/chains/evm/signer/signer_test.go +++ b/zetaclient/chains/evm/signer/signer_test.go @@ -71,7 +71,7 @@ func getNewEvmChainObserver(t *testing.T, tss interfaces.TSSSigner) (*observer.O evmClient := mocks.NewMockEvmClient().WithBlockNumber(1000) params := mocks.MockChainParams(evmcfg.Chain.ChainId, 10) cfg.EVMChainConfigs[chains.BscMainnet.ChainId] = evmcfg - appCTX := context.NewAppContext(cfg) + appContext := context.NewAppContext(cfg) logger := base.Logger{} ts := &metrics.TelemetryServer{} @@ -79,7 +79,7 @@ func getNewEvmChainObserver(t *testing.T, tss interfaces.TSSSigner) (*observer.O evmcfg, evmClient, params, - appCTX, + appContext, mocks.NewMockZetacoreClient(), tss, logger, diff --git a/zetaclient/config/config_chain.go b/zetaclient/config/config_chain.go index 5c2ed1d077..5946c4ca62 100644 --- a/zetaclient/config/config_chain.go +++ b/zetaclient/config/config_chain.go @@ -1,6 +1,10 @@ package config -import "github.com/zeta-chain/zetacore/pkg/chains" +import ( + "sync" + + "github.com/zeta-chain/zetacore/pkg/chains" +) const ( MaxBlocksPerPeriod = 100 @@ -32,6 +36,7 @@ func GetERC20CustodyABI() string { // It is initialize with default chain configs func New() Config { return Config{ + cfgLock: &sync.RWMutex{}, EVMChainConfigs: evmChainsConfigs, BitcoinConfig: bitcoinConfigRegnet, } diff --git a/zetaclient/context/app_context.go b/zetaclient/context/app_context.go index be9b9a25fc..818eccd8b3 100644 --- a/zetaclient/context/app_context.go +++ b/zetaclient/context/app_context.go @@ -46,52 +46,52 @@ func NewAppContext(cfg *config.Config) *AppContext { } // SetConfig sets a new config to the app context -func (c *AppContext) SetConfig(cfg *config.Config) { - c.mu.Lock() - defer c.mu.Unlock() - c.config = cfg +func (a *AppContext) SetConfig(cfg *config.Config) { + a.mu.Lock() + defer a.mu.Unlock() + a.config = cfg } // Config returns the app context config -func (c *AppContext) Config() *config.Config { - c.mu.RLock() - defer c.mu.RUnlock() - return c.config +func (a *AppContext) Config() *config.Config { + a.mu.RLock() + defer a.mu.RUnlock() + return a.config } // GetKeygen returns the current keygen information -func (c *AppContext) GetKeygen() observertypes.Keygen { - c.mu.RLock() - defer c.mu.RUnlock() +func (a *AppContext) GetKeygen() observertypes.Keygen { + a.mu.RLock() + defer a.mu.RUnlock() var copiedPubkeys []string - if c.keygen.GranteePubkeys != nil { - copiedPubkeys = make([]string, len(c.keygen.GranteePubkeys)) - copy(copiedPubkeys, c.keygen.GranteePubkeys) + if a.keygen.GranteePubkeys != nil { + copiedPubkeys = make([]string, len(a.keygen.GranteePubkeys)) + copy(copiedPubkeys, a.keygen.GranteePubkeys) } return observertypes.Keygen{ - Status: c.keygen.Status, + Status: a.keygen.Status, GranteePubkeys: copiedPubkeys, - BlockNumber: c.keygen.BlockNumber, + BlockNumber: a.keygen.BlockNumber, } } // GetCurrentTssPubkey returns the current TSS public key -func (c *AppContext) GetCurrentTssPubkey() string { - c.mu.RLock() - defer c.mu.RUnlock() - return c.currentTssPubkey +func (a *AppContext) GetCurrentTssPubkey() string { + a.mu.RLock() + defer a.mu.RUnlock() + return a.currentTssPubkey } // GetEnabledExternalChains returns all enabled external chains (excluding zetachain) -func (c *AppContext) GetEnabledExternalChains() []chains.Chain { - c.mu.RLock() - defer c.mu.RUnlock() +func (a *AppContext) GetEnabledExternalChains() []chains.Chain { + a.mu.RLock() + defer a.mu.RUnlock() // deep copy chains externalChains := make([]chains.Chain, 0) - for _, chain := range c.chainsEnabled { + for _, chain := range a.chainsEnabled { if chain.IsExternal { externalChains = append(externalChains, chain) } @@ -100,13 +100,13 @@ func (c *AppContext) GetEnabledExternalChains() []chains.Chain { } // GetEnabledBTCChains returns the enabled bitcoin chains -func (c *AppContext) GetEnabledBTCChains() []chains.Chain { - c.mu.RLock() - defer c.mu.RUnlock() +func (a *AppContext) GetEnabledBTCChains() []chains.Chain { + a.mu.RLock() + defer a.mu.RUnlock() // deep copy btc chains btcChains := make([]chains.Chain, 0) - for _, chain := range c.chainsEnabled { + for _, chain := range a.chainsEnabled { if chain.Consensus == chains.Consensus_bitcoin { btcChains = append(btcChains, chain) } @@ -115,13 +115,13 @@ func (c *AppContext) GetEnabledBTCChains() []chains.Chain { } // GetEnabledExternalChainParams returns all enabled chain params -func (c *AppContext) GetEnabledExternalChainParams() map[int64]*observertypes.ChainParams { - c.mu.RLock() - defer c.mu.RUnlock() +func (a *AppContext) GetEnabledExternalChainParams() map[int64]*observertypes.ChainParams { + a.mu.RLock() + defer a.mu.RUnlock() // deep copy chain params - copied := make(map[int64]*observertypes.ChainParams, len(c.chainParamMap)) - for chainID, chainParams := range c.chainParamMap { + copied := make(map[int64]*observertypes.ChainParams, len(a.chainParamMap)) + for chainID, chainParams := range a.chainParamMap { copied[chainID] = &observertypes.ChainParams{} *copied[chainID] = *chainParams } @@ -129,33 +129,33 @@ func (c *AppContext) GetEnabledExternalChainParams() map[int64]*observertypes.Ch } // GetExternalChainParams returns chain params for a specific chain ID -func (c *AppContext) GetExternalChainParams(chainID int64) (*observertypes.ChainParams, bool) { - c.mu.RLock() - defer c.mu.RUnlock() +func (a *AppContext) GetExternalChainParams(chainID int64) (*observertypes.ChainParams, bool) { + a.mu.RLock() + defer a.mu.RUnlock() - chainParams, found := c.chainParamMap[chainID] + chainParams, found := a.chainParamMap[chainID] return chainParams, found } // GetBTCNetParams returns bitcoin network params -func (c *AppContext) GetBTCNetParams() *chaincfg.Params { - c.mu.RLock() - defer c.mu.RUnlock() - return c.btcNetParams +func (a *AppContext) GetBTCNetParams() *chaincfg.Params { + a.mu.RLock() + defer a.mu.RUnlock() + return a.btcNetParams } // GetCrossChainFlags returns crosschain flags -func (c *AppContext) GetCrossChainFlags() observertypes.CrosschainFlags { - c.mu.RLock() - defer c.mu.RUnlock() - return c.crosschainFlags +func (a *AppContext) GetCrossChainFlags() observertypes.CrosschainFlags { + a.mu.RLock() + defer a.mu.RUnlock() + return a.crosschainFlags } // GetBlockHeaderEnabledChains checks if block header verification is enabled for a specific chain -func (c *AppContext) GetBlockHeaderEnabledChains(chainID int64) (lightclienttypes.HeaderSupportedChain, bool) { - c.mu.RLock() - defer c.mu.RUnlock() - for _, flags := range c.blockHeaderEnabledChains { +func (a *AppContext) GetBlockHeaderEnabledChains(chainID int64) (lightclienttypes.HeaderSupportedChain, bool) { + a.mu.RLock() + defer a.mu.RUnlock() + for _, flags := range a.blockHeaderEnabledChains { if flags.ChainId == chainID { return flags, true } @@ -165,7 +165,7 @@ func (c *AppContext) GetBlockHeaderEnabledChains(chainID int64) (lightclienttype // Update updates app context and params for all chains // this must be the ONLY function that writes to app context -func (c *AppContext) Update( +func (a *AppContext) Update( keygen observertypes.Keygen, tssPubKey string, chainsEnabled []chains.Chain, @@ -175,8 +175,8 @@ func (c *AppContext) Update( blockHeaderEnabledChains []lightclienttypes.HeaderSupportedChain, logger zerolog.Logger, ) { - c.mu.Lock() - defer c.mu.Unlock() + a.mu.Lock() + defer a.mu.Unlock() // Ignore whatever order zetacore organizes chain list in state sort.SliceStable(chainsEnabled, func(i, j int) bool { @@ -188,36 +188,36 @@ func (c *AppContext) Update( } // Add log print if the number of enabled chains changes at runtime - if len(c.chainsEnabled) != len(chainsEnabled) { + if len(a.chainsEnabled) != len(chainsEnabled) { logger.Info().Msgf( "UpdateChainParams: number of enabled chains changed at runtime!! before: %d, after: %d", - len(c.chainsEnabled), + len(a.chainsEnabled), len(chainsEnabled), ) } // btcNetParams points one of [mainnet, testnet, regnet] // btcNetParams initialize only once and should never change - if c.btcNetParams == nil { - c.btcNetParams = btcNetParams + if a.btcNetParams == nil { + a.btcNetParams = btcNetParams } - c.keygen = keygen - c.chainsEnabled = chainsEnabled - c.chainParamMap = chainParamMap - c.currentTssPubkey = tssPubKey - c.crosschainFlags = crosschainFlags - c.blockHeaderEnabledChains = blockHeaderEnabledChains + a.keygen = keygen + a.chainsEnabled = chainsEnabled + a.chainParamMap = chainParamMap + a.currentTssPubkey = tssPubKey + a.crosschainFlags = crosschainFlags + a.blockHeaderEnabledChains = blockHeaderEnabledChains } // IsOutboundObservationEnabled returns true if the chain is supported and outbound flag is enabled -func IsOutboundObservationEnabled(c *AppContext, chainParams observertypes.ChainParams) bool { - flags := c.GetCrossChainFlags() +func (a *AppContext) IsOutboundObservationEnabled(chainParams observertypes.ChainParams) bool { + flags := a.GetCrossChainFlags() return chainParams.IsSupported && flags.IsOutboundEnabled } // IsInboundObservationEnabled returns true if the chain is supported and inbound flag is enabled -func IsInboundObservationEnabled(c *AppContext, chainParams observertypes.ChainParams) bool { - flags := c.GetCrossChainFlags() +func (a *AppContext) IsInboundObservationEnabled(chainParams observertypes.ChainParams) bool { + flags := a.GetCrossChainFlags() return chainParams.IsSupported && flags.IsInboundEnabled } diff --git a/zetaclient/context/app_context_test.go b/zetaclient/context/app_context_test.go index 92aa39be20..13d01350ec 100644 --- a/zetaclient/context/app_context_test.go +++ b/zetaclient/context/app_context_test.go @@ -16,43 +16,6 @@ import ( context "github.com/zeta-chain/zetacore/zetaclient/context" ) -// getTestAppContext creates a test app context with provided chain params and flags -func getTestAppContext( - evmChain chains.Chain, - evmChainParams *observertypes.ChainParams, - ccFlags *observertypes.CrosschainFlags, - headerSupportedChains []lightclienttypes.HeaderSupportedChain, -) *context.AppContext { - // create config - cfg := config.NewConfig() - cfg.EVMChainConfigs[evmChain.ChainId] = config.EVMConfig{ - Chain: evmChain, - } - - // create app context - appContext := context.NewAppContext(cfg) - newChainParams := make(map[int64]*observertypes.ChainParams) - newChainParams[evmChain.ChainId] = evmChainParams - - // create crosschain flags if not provided - if ccFlags == nil { - ccFlags = sample.CrosschainFlags() - } - - // feed app context fields - appContext.Update( - observertypes.Keygen{}, - "", - []chains.Chain{evmChain}, - newChainParams, - &chaincfg.RegressionNetParams, - *ccFlags, - headerSupportedChains, - zerolog.Logger{}, - ) - return appContext -} - func Test_NewAppContext(t *testing.T) { t.Run("should create new app context with empty config", func(t *testing.T) { testCfg := config.NewConfig() @@ -173,40 +136,40 @@ func Test_UpdateAndGetters(t *testing.T) { }) } -func Test_IsOutboundObservationEnabled(t *testing.T) { +func TestIsOutboundObservationEnabled(t *testing.T) { // create test chain params and flags evmChain := chains.Ethereum - ccFlags := *sample.CrosschainFlags() - headerSupportedFlags := sample.HeaderSupportedChains() - evmChainParams := &observertypes.ChainParams{ + ccFlags := sample.CrosschainFlags() + verificationFlags := sample.HeaderSupportedChains() + chainParams := &observertypes.ChainParams{ ChainId: evmChain.ChainId, IsSupported: true, } t.Run("should return true if chain is supported and outbound flag is enabled", func(t *testing.T) { - appCTX := getTestAppContext(evmChain, evmChainParams, &ccFlags, headerSupportedFlags) - require.True(t, context.IsOutboundObservationEnabled(appCTX, *evmChainParams)) + appContext := makeAppContext(evmChain, chainParams, *ccFlags, verificationFlags) + + require.True(t, appContext.IsOutboundObservationEnabled(*chainParams)) }) t.Run("should return false if chain is not supported yet", func(t *testing.T) { - paramsUnsupported := &observertypes.ChainParams{ - ChainId: evmChain.ChainId, - IsSupported: false, - } - appCTXUnsupported := getTestAppContext(evmChain, paramsUnsupported, &ccFlags, headerSupportedFlags) - require.False(t, context.IsOutboundObservationEnabled(appCTXUnsupported, *paramsUnsupported)) + paramsUnsupported := &observertypes.ChainParams{ChainId: evmChain.ChainId, IsSupported: false} + appContextUnsupported := makeAppContext(evmChain, paramsUnsupported, *ccFlags, verificationFlags) + + require.False(t, appContextUnsupported.IsOutboundObservationEnabled(*paramsUnsupported)) }) t.Run("should return false if outbound flag is disabled", func(t *testing.T) { flagsDisabled := ccFlags flagsDisabled.IsOutboundEnabled = false - appCTXDisabled := getTestAppContext(evmChain, evmChainParams, &flagsDisabled, headerSupportedFlags) - require.False(t, context.IsOutboundObservationEnabled(appCTXDisabled, *evmChainParams)) + coreContextDisabled := makeAppContext(evmChain, chainParams, *flagsDisabled, verificationFlags) + + require.False(t, coreContextDisabled.IsOutboundObservationEnabled(*chainParams)) }) } func TestIsInboundObservationEnabled(t *testing.T) { // create test chain params and flags evmChain := chains.Ethereum - ccFlags := *sample.CrosschainFlags() + ccFlags := sample.CrosschainFlags() verificationFlags := sample.HeaderSupportedChains() chainParams := &observertypes.ChainParams{ ChainId: evmChain.ChainId, @@ -214,21 +177,55 @@ func TestIsInboundObservationEnabled(t *testing.T) { } t.Run("should return true if chain is supported and inbound flag is enabled", func(t *testing.T) { - appCTX := getTestAppContext(evmChain, chainParams, &ccFlags, verificationFlags) - require.True(t, context.IsInboundObservationEnabled(appCTX, *chainParams)) + appContext := makeAppContext(evmChain, chainParams, *ccFlags, verificationFlags) + + require.True(t, appContext.IsInboundObservationEnabled(*chainParams)) }) + t.Run("should return false if chain is not supported yet", func(t *testing.T) { - paramsUnsupported := &observertypes.ChainParams{ - ChainId: evmChain.ChainId, - IsSupported: false, - } - appCTXUnsupported := getTestAppContext(evmChain, paramsUnsupported, &ccFlags, verificationFlags) - require.False(t, context.IsInboundObservationEnabled(appCTXUnsupported, *paramsUnsupported)) + paramsUnsupported := &observertypes.ChainParams{ChainId: evmChain.ChainId, IsSupported: false} + appContextUnsupported := makeAppContext(evmChain, paramsUnsupported, *ccFlags, verificationFlags) + + require.False(t, appContextUnsupported.IsInboundObservationEnabled(*paramsUnsupported)) }) + t.Run("should return false if inbound flag is disabled", func(t *testing.T) { flagsDisabled := ccFlags flagsDisabled.IsInboundEnabled = false - appCTXDisabled := getTestAppContext(evmChain, chainParams, &flagsDisabled, verificationFlags) - require.False(t, context.IsInboundObservationEnabled(appCTXDisabled, *chainParams)) + appContextDisabled := makeAppContext(evmChain, chainParams, *flagsDisabled, verificationFlags) + + require.False(t, appContextDisabled.IsInboundObservationEnabled(*chainParams)) }) } + +// makeAppContext makes a test app context with provided chain params and flags +func makeAppContext( + evmChain chains.Chain, + evmChainParams *observertypes.ChainParams, + ccFlags observertypes.CrosschainFlags, + headerSupportedChains []lightclienttypes.HeaderSupportedChain, +) *context.AppContext { + // create config + cfg := config.NewConfig() + cfg.EVMChainConfigs[evmChain.ChainId] = config.EVMConfig{ + Chain: evmChain, + } + + // create app context + appContext := context.NewAppContext(cfg) + newChainParams := make(map[int64]*observertypes.ChainParams) + newChainParams[evmChain.ChainId] = evmChainParams + + // feed app context fields + appContext.Update( + observertypes.Keygen{}, + "", + []chains.Chain{evmChain}, + newChainParams, + &chaincfg.RegressionNetParams, + ccFlags, + headerSupportedChains, + zerolog.Logger{}, + ) + return appContext +} diff --git a/zetaclient/orchestrator/orchestrator.go b/zetaclient/orchestrator/orchestrator.go index 4217cd1c3e..9f583902b5 100644 --- a/zetaclient/orchestrator/orchestrator.go +++ b/zetaclient/orchestrator/orchestrator.go @@ -358,7 +358,7 @@ func (oc *Orchestrator) SchedulePendingCctxs() { Msgf("StartCctxScheduler: GetUpdatedChainObserver failed for chain %d", c.ChainId) continue } - if !context.IsOutboundObservationEnabled(oc.appContext, ob.GetChainParams()) { + if !oc.appContext.IsOutboundObservationEnabled(ob.GetChainParams()) { continue } diff --git a/zetaclient/orchestrator/orchestrator_test.go b/zetaclient/orchestrator/orchestrator_test.go index 8326dd1107..e9ffffa584 100644 --- a/zetaclient/orchestrator/orchestrator_test.go +++ b/zetaclient/orchestrator/orchestrator_test.go @@ -56,7 +56,11 @@ func MockOrchestrator( return orchestrator } +<<<<<<< HEAD func CreateTestAppContext( +======= +func CreateAppContext( +>>>>>>> 2d5519f4d64bb05b64e6f2c7ec9ef6a87e97610f evmChain, btcChain chains.Chain, evmChainParams, btcChainParams *observertypes.ChainParams, ) *context.AppContext { @@ -68,24 +72,42 @@ func CreateTestAppContext( cfg.BitcoinConfig = config.BTCConfig{ RPCHost: "localhost", } +<<<<<<< HEAD // new app context appContext := context.NewAppContext(cfg) chainParamsMap := make(map[int64]*observertypes.ChainParams) chainParamsMap[evmChain.ChainId] = evmChainParams chainParamsMap[btcChain.ChainId] = btcChainParams +======= + // new zetacore context + appContext := context.New(cfg, zerolog.Nop()) + evmChainParamsMap := make(map[int64]*observertypes.ChainParams) + evmChainParamsMap[evmChain.ChainId] = evmChainParams +>>>>>>> 2d5519f4d64bb05b64e6f2c7ec9ef6a87e97610f ccFlags := sample.CrosschainFlags() verificationFlags := sample.HeaderSupportedChains() // feed chain params appContext.Update( +<<<<<<< HEAD observertypes.Keygen{}, +======= + &observertypes.Keygen{}, + []chains.Chain{evmChain, btcChain}, + evmChainParamsMap, + btcChainParams, +>>>>>>> 2d5519f4d64bb05b64e6f2c7ec9ef6a87e97610f "", []chains.Chain{evmChain, btcChain}, chainParamsMap, &chaincfg.RegressionNetParams, *ccFlags, verificationFlags, +<<<<<<< HEAD zerolog.Logger{}, +======= + true, +>>>>>>> 2d5519f4d64bb05b64e6f2c7ec9ef6a87e97610f ) return appContext } @@ -109,16 +131,26 @@ func Test_GetUpdatedSigner(t *testing.T) { } t.Run("signer should not be found", func(t *testing.T) { +<<<<<<< HEAD appCtx := CreateTestAppContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) orchestrator := MockOrchestrator(t, appCtx, nil, evmChain, btcChain, evmChainParams, btcChainParams) +======= + orchestrator := MockOrchestrator(t, nil, evmChain, btcChain, evmChainParams, btcChainParams) + context := CreateAppContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) +>>>>>>> 2d5519f4d64bb05b64e6f2c7ec9ef6a87e97610f // BSC signer should not be found _, err := orchestrator.GetUpdatedSigner(chains.BscMainnet.ChainId) require.ErrorContains(t, err, "signer not found") }) t.Run("should be able to update connector and erc20 custody address", func(t *testing.T) { +<<<<<<< HEAD appCtx := CreateTestAppContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) orchestrator := MockOrchestrator(t, appCtx, nil, evmChain, btcChain, evmChainParams, btcChainParams) +======= + orchestrator := MockOrchestrator(t, nil, evmChain, btcChain, evmChainParams, btcChainParams) + context := CreateAppContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) +>>>>>>> 2d5519f4d64bb05b64e6f2c7ec9ef6a87e97610f // update signer with new connector and erc20 custody address signer, err := orchestrator.GetUpdatedSigner(evmChain.ChainId) require.NoError(t, err) @@ -175,17 +207,27 @@ func Test_GetUpdatedChainObserver(t *testing.T) { } t.Run("evm chain observer should not be found", func(t *testing.T) { +<<<<<<< HEAD appCtx := CreateTestAppContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) orchestrator := MockOrchestrator(t, appCtx, nil, evmChain, btcChain, evmChainParams, btcChainParams) +======= + orchestrator := MockOrchestrator(t, nil, evmChain, btcChain, evmChainParams, btcChainParams) + coreContext := CreateAppContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) +>>>>>>> 2d5519f4d64bb05b64e6f2c7ec9ef6a87e97610f // BSC chain observer should not be found _, err := orchestrator.GetUpdatedChainObserver(chains.BscMainnet.ChainId) require.ErrorContains(t, err, "chain observer not found") }) t.Run("chain params in evm chain observer should be updated successfully", func(t *testing.T) { +<<<<<<< HEAD appCtx := CreateTestAppContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) orchestrator := MockOrchestrator(t, appCtx, nil, evmChain, btcChain, evmChainParams, btcChainParams) +======= + orchestrator := MockOrchestrator(t, nil, evmChain, btcChain, evmChainParams, btcChainParams) + coreContext := CreateAppContext(evmChain, btcChain, evmChainParamsNew, btcChainParams) +>>>>>>> 2d5519f4d64bb05b64e6f2c7ec9ef6a87e97610f // update evm chain observer with new chain params chainOb, err := orchestrator.GetUpdatedChainObserver(evmChain.ChainId) require.NoError(t, err) @@ -193,17 +235,27 @@ func Test_GetUpdatedChainObserver(t *testing.T) { require.True(t, observertypes.ChainParamsEqual(*evmChainParamsNew, chainOb.GetChainParams())) }) t.Run("btc chain observer should not be found", func(t *testing.T) { +<<<<<<< HEAD appCtx := CreateTestAppContext(btcChain, btcChain, evmChainParams, btcChainParamsNew) orchestrator := MockOrchestrator(t, appCtx, nil, evmChain, btcChain, evmChainParams, btcChainParams) +======= + orchestrator := MockOrchestrator(t, nil, evmChain, btcChain, evmChainParams, btcChainParams) + coreContext := CreateAppContext(btcChain, btcChain, evmChainParams, btcChainParamsNew) +>>>>>>> 2d5519f4d64bb05b64e6f2c7ec9ef6a87e97610f // BTC testnet chain observer should not be found _, err := orchestrator.GetUpdatedChainObserver(chains.BitcoinTestnet.ChainId) require.ErrorContains(t, err, "chain observer not found") }) t.Run("chain params in btc chain observer should be updated successfully", func(t *testing.T) { +<<<<<<< HEAD appCtx := CreateTestAppContext(btcChain, btcChain, evmChainParams, btcChainParamsNew) orchestrator := MockOrchestrator(t, appCtx, nil, evmChain, btcChain, evmChainParams, btcChainParams) +======= + orchestrator := MockOrchestrator(t, nil, evmChain, btcChain, evmChainParams, btcChainParams) + coreContext := CreateAppContext(btcChain, btcChain, evmChainParams, btcChainParamsNew) +>>>>>>> 2d5519f4d64bb05b64e6f2c7ec9ef6a87e97610f // update btc chain observer with new chain params chainOb, err := orchestrator.GetUpdatedChainObserver(btcChain.ChainId) require.NoError(t, err) diff --git a/zetaclient/supplychecker/zeta_supply_checker.go b/zetaclient/supplychecker/zeta_supply_checker.go index bf79110739..f068a9ef59 100644 --- a/zetaclient/supplychecker/zeta_supply_checker.go +++ b/zetaclient/supplychecker/zeta_supply_checker.go @@ -120,12 +120,12 @@ func (zs *ZetaSupplyChecker) Stop() { func (zs *ZetaSupplyChecker) CheckZetaTokenSupply() error { externalChainTotalSupply := sdkmath.ZeroInt() for _, chain := range zs.externalEvmChain { - externalEvmChainParams, ok := zs.appContext.GetExternalChainParams(chain.ChainId) + evmChainParams, ok := zs.appContext.GetExternalChainParams(chain.ChainId) if !ok { return fmt.Errorf("externalEvmChainParams not found for chain id %d", chain.ChainId) } - zetaTokenAddressString := externalEvmChainParams.ZetaTokenContractAddress + zetaTokenAddressString := evmChainParams.ZetaTokenContractAddress zetaTokenAddress := ethcommon.HexToAddress(zetaTokenAddressString) zetatokenNonEth, err := observer.FetchZetaTokenContract(zetaTokenAddress, zs.evmClient[chain.ChainId]) if err != nil {