diff --git a/Makefile b/Makefile index 920f00f7a5..e7a58fb3e3 100644 --- a/Makefile +++ b/Makefile @@ -230,10 +230,6 @@ install-zetae2e: go.sum @go install -mod=readonly $(BUILD_FLAGS) ./cmd/zetae2e .PHONY: install-zetae2e -start-e2e-test: zetanode - @echo "--> Starting e2e test" - cd contrib/localnet/ && $(DOCKER) compose up -d - start-e2e-test: zetanode @echo "--> Starting e2e test" cd contrib/localnet/ && $(DOCKER) compose up -d diff --git a/cmd/zetaclientd-supervisor/lib.go b/cmd/zetaclientd-supervisor/lib.go index fd66773978..7b8cfbb4dd 100644 --- a/cmd/zetaclientd-supervisor/lib.go +++ b/cmd/zetaclientd-supervisor/lib.go @@ -84,6 +84,7 @@ func newZetaclientdSupervisor( if err != nil { return nil, fmt.Errorf("grpc dial: %w", err) } + // these signals will result in the supervisor process only restarting zetaclientd restartChan := make(chan os.Signal, 1) return &zetaclientdSupervisor{ zetacoredConn: conn, @@ -208,7 +209,7 @@ func (s *zetaclientdSupervisor) handleTssUpdate(ctx context.Context) { tss = tssNew s.logger.Warn().Msg(fmt.Sprintf("tss address is updated from %s to %s", tss.TSS.TssPubkey, tssNew.TSS.TssPubkey)) time.Sleep(6 * time.Second) - s.logger.Warn().Msg("restarting zetaclientd to update tss address") + s.logger.Info().Msg("restarting zetaclientd to update tss address") s.restartChan <- syscall.SIGHUP } } @@ -253,7 +254,7 @@ func (s *zetaclientdSupervisor) handleNewTssKeyGeneration(ctx context.Context) { tssLenCurrent = tssLenUpdated s.logger.Warn().Msg(fmt.Sprintf("tss list updated from %d to %d", tssLenCurrent, tssLenUpdated)) time.Sleep(5 * time.Second) - s.logger.Warn().Msg("restarting zetaclientd to update tss list") + s.logger.Info().Msg("restarting zetaclientd to update tss list") s.restartChan <- syscall.SIGHUP } } @@ -287,7 +288,7 @@ func (s *zetaclientdSupervisor) handleNewKeygen(ctx context.Context) { continue } prevKeygenBlock = keygenBlock - s.logger.Warn().Msgf("got new keygen at block %d", keygenBlock) + s.logger.Info().Msgf("got new keygen at block %d", keygenBlock) s.restartChan <- syscall.SIGHUP } } diff --git a/cmd/zetaclientd-supervisor/main.go b/cmd/zetaclientd-supervisor/main.go index 72f8443c79..203fbb5786 100644 --- a/cmd/zetaclientd-supervisor/main.go +++ b/cmd/zetaclientd-supervisor/main.go @@ -23,7 +23,6 @@ func main() { fmt.Println("failed to load config: ", err) os.Exit(1) } - fmt.Println("Starting zetaclientd-supervisor") // log outputs must be serialized since we are writing log messages in this process and // also directly from the zetaclient process @@ -37,9 +36,6 @@ func main() { shutdownChan := make(chan os.Signal, 1) signal.Notify(shutdownChan, syscall.SIGINT, syscall.SIGTERM) - // these signals will result in the supervisor process only restarting zetaclientd - //restartChan := make(chan os.Signal, 1) - hotkeyPassword, tssPassword, err := promptPasswords() if err != nil { logger.Error().Err(err).Msg("unable to get passwords") diff --git a/cmd/zetaclientd/keygen_tss.go b/cmd/zetaclientd/keygen_tss.go index fd883d1666..2c7fa2f594 100644 --- a/cmd/zetaclientd/keygen_tss.go +++ b/cmd/zetaclientd/keygen_tss.go @@ -7,11 +7,9 @@ import ( "fmt" "time" - "github.com/cometbft/cometbft/crypto/secp256k1" "github.com/rs/zerolog" tsscommon "github.com/zeta-chain/go-tss/common" "github.com/zeta-chain/go-tss/keygen" - "github.com/zeta-chain/go-tss/p2p" "github.com/zeta-chain/go-tss/tss" "github.com/zeta-chain/zetacore/zetaclient/chains/interfaces" "golang.org/x/crypto/sha3" @@ -24,7 +22,8 @@ import ( "github.com/zeta-chain/zetacore/zetaclient/zetacore" ) -// GenerateTss generates a new TSS +// GenerateTss generates a new TSS if keygen is set. +// If a TSS was generated successfully in the past,and the keygen was successful, the function will return without doing anything. // If a keygen has been set the functions will wait for the correct block to arrive and generate a new TSS. // In case of a successful keygen a TSS success vote is broadcasted to zetacore and the newly generate TSS is tested. The generated keyshares are stored in the correct directory // In case of a failed keygen a TSS failed vote is broadcasted to zetacore. @@ -32,19 +31,8 @@ func GenerateTss( appContext *context.AppContext, logger zerolog.Logger, zetaCoreClient *zetacore.Client, - peers p2p.AddrList, - priKey secp256k1.PrivKey, - ts *metrics.TelemetryServer, - tssHistoricalList []observertypes.TSS, - tssPassword string, - hotkeyPassword string, keygenTssServer *tss.TssServer) error { keygenLogger := logger.With().Str("module", "keygen").Logger() - //keygenTssServer, err := mc.SetupTSSServer(peers, priKey, preParams, appContext.Config(), tssPassword, false) - //if err != nil { - // keygenLogger.Error().Err(err).Msg("NewTSS server error") - // return err - //} // If Keygen block is set it will try to generate new TSS at the block // This is a blocking thread and will wait until the ceremony is complete successfully @@ -60,7 +48,6 @@ func GenerateTss( // Break out of loop only when TSS is generated successfully, either at the keygenBlock or if it has been generated already , Block set as zero in genesis file // This loop will try keygen at the keygen block and then wait for keygen to be successfully reported by all nodes before breaking out of the loop. // If keygen is unsuccessful, it will reset the triedKeygenAtBlock flag and try again at a new keygen block. - keyGen := appContext.GetKeygen() if keyGen.Status == observertypes.KeygenStatus_KeyGenSuccess { return nil diff --git a/cmd/zetaclientd/start.go b/cmd/zetaclientd/start.go index ae4d7db638..62e43e61aa 100644 --- a/cmd/zetaclientd/start.go +++ b/cmd/zetaclientd/start.go @@ -204,23 +204,17 @@ func start(_ *cobra.Command, _ []string) error { telemetryServer.SetIPAddress(cfg.PublicIP) + // Create TSS server server, err := mc.SetupTSSServer(peers, priKey, preParams, appContext.Config(), tssKeyPass, true) if err != nil { return fmt.Errorf("SetupTSSServer error: %w", err) } + // Set P2P ID for telemetry telemetryServer.SetP2PID(server.GetLocalPeerID()) - err = GenerateTss( - appContext, - masterLogger, - zetacoreClient, - peers, - priKey, - telemetryServer, - tssHistoricalList, - tssKeyPass, - hotkeyPass, - server, - ) + + // Generate a new TSS if keygen is set and add it into the tss server + // If TSS has already been generated, and keygen was successful ; we use the existing TSS + err = GenerateTss(appContext, masterLogger, zetacoreClient, server) if err != nil { return err } @@ -232,15 +226,10 @@ func start(_ *cobra.Command, _ []string) error { } tss, err := mc.NewTSS( appContext, - peers, - priKey, - preParams, zetacoreClient, tssHistoricalList, bitcoinChainID, - tssKeyPass, hotkeyPass, - true, server, ) if cfg.TestTssKeysign { @@ -262,9 +251,6 @@ func start(_ *cobra.Command, _ []string) error { break } - keyGen := appContext.ZetacoreContext().GetKeygen() - tss.Signers = keyGen.GranteePubkeys - // Update Current TSS value from zetacore, if TSS keygen is successful, the TSS address is set on zeta-core // Returns err if the RPC call fails as zeta client needs the current TSS address to be set // This is only needed in case of a new Keygen , as the TSS address is set on zetacore only after the keygen is successful i.e enough votes have been broadcast diff --git a/x/crosschain/keeper/cctx_orchestrator_validate_inbound.go b/x/crosschain/keeper/cctx_orchestrator_validate_inbound.go index 893983fe61..bd960010ab 100644 --- a/x/crosschain/keeper/cctx_orchestrator_validate_inbound.go +++ b/x/crosschain/keeper/cctx_orchestrator_validate_inbound.go @@ -17,7 +17,7 @@ func (k Keeper) ValidateInbound( shouldPayGas bool, ) (*types.CrossChainTx, error) { - err := k.IsMigration(ctx, msg) + err := k.CheckMigration(ctx, msg) if err != nil { return nil, err } @@ -57,11 +57,17 @@ func (k Keeper) ValidateInbound( return &cctx, nil } -func (k Keeper) IsMigration(ctx sdk.Context, msg *types.MsgVoteInbound) error { +// CheckMigration checks if the sender is a TSS address and returns an error if it is. +// If the sender is an older TSS address, this means that it is a migration transfer, and we do not need to treat this as a deposit. +func (k Keeper) CheckMigration(ctx sdk.Context, msg *types.MsgVoteInbound) error { historicalTssList := k.zetaObserverKeeper.GetAllTSS(ctx) - chain := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, msg.SenderChainId) + chain, found := k.zetaObserverKeeper.GetSupportedChainFromChainID(ctx, msg.SenderChainId) + if !found { + return observertypes.ErrSupportedChains.Wrapf("chain not found for chainID %d", msg.SenderChainId) + } + additionalChains := k.GetAuthorityKeeper().GetAdditionalChainList(ctx) for _, tss := range historicalTssList { - if chains.IsEVMChain(chain.ChainId) { + if chains.IsEVMChain(chain.ChainId, additionalChains) { ethTssAddress, err := crypto.GetTssAddrEVM(tss.TssPubkey) if err != nil { return errors.Wrap(types.ErrInvalidAddress, err.Error()) @@ -70,7 +76,7 @@ func (k Keeper) IsMigration(ctx sdk.Context, msg *types.MsgVoteInbound) error { ctx.Logger().Info("Sender is a TSS, cannot create CCTX") return types.ErrTssAddress } - } else if chains.IsBitcoinChain(chain.ChainId) { + } else if chains.IsBitcoinChain(chain.ChainId, additionalChains) { bitcoinParams, err := chains.BitcoinNetParamsFromChainID(chain.ChainId) if err != nil { return err @@ -80,11 +86,9 @@ func (k Keeper) IsMigration(ctx sdk.Context, msg *types.MsgVoteInbound) error { return errors.Wrap(types.ErrInvalidAddress, err.Error()) } if btcTssAddress == msg.Sender { - ctx.Logger().Info("Sender is a TSS, cannot create CCTX") return types.ErrTssAddress } } - } return nil } diff --git a/x/crosschain/keeper/cctx_orchestrator_validate_inbound_test.go b/x/crosschain/keeper/cctx_orchestrator_validate_inbound_test.go new file mode 100644 index 0000000000..6e3c41ee29 --- /dev/null +++ b/x/crosschain/keeper/cctx_orchestrator_validate_inbound_test.go @@ -0,0 +1,240 @@ +package keeper_test + +import ( + "testing" + + "github.com/stretchr/testify/require" + "github.com/zeta-chain/zetacore/pkg/chains" + "github.com/zeta-chain/zetacore/pkg/crypto" + keepertest "github.com/zeta-chain/zetacore/testutil/keeper" + "github.com/zeta-chain/zetacore/testutil/sample" + "github.com/zeta-chain/zetacore/x/crosschain/types" + observerTypes "github.com/zeta-chain/zetacore/x/observer/types" +) + +func TestKeeper_CheckMigration(t *testing.T) { + t.Run("Do not return error if sender is not a TSS address for evm chain", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, + keepertest.CrosschainMockOptions{ + UseAuthorityMock: true, + UseObserverMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) + chain := chains.Goerli + tssList := sample.TssList(3) + sender := sample.AccAddress() + + // Set up mocks + observerMock.On("GetAllTSS", ctx).Return(tssList) + observerMock.On("GetSupportedChainFromChainID", ctx, chain.ChainId).Return(chain, true) + authorityMock.On("GetAdditionalChainList", ctx).Return([]chains.Chain{}) + + msg := types.MsgVoteInbound{ + SenderChainId: chain.ChainId, + Sender: sender, + } + + err := k.CheckMigration(ctx, &msg) + require.NoError(t, err) + }) + + t.Run("Do not return error if sender is not a TSS address for btc chain", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, + keepertest.CrosschainMockOptions{ + UseAuthorityMock: true, + UseObserverMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) + chain := chains.BitcoinTestnet + tssList := sample.TssList(3) + sender := sample.AccAddress() + + // Set up mocks + observerMock.On("GetAllTSS", ctx).Return(tssList) + observerMock.On("GetSupportedChainFromChainID", ctx, chain.ChainId).Return(chain, true) + authorityMock.On("GetAdditionalChainList", ctx).Return([]chains.Chain{}) + + msg := types.MsgVoteInbound{ + SenderChainId: chain.ChainId, + Sender: sender, + } + + err := k.CheckMigration(ctx, &msg) + require.NoError(t, err) + }) + + t.Run("fails when chain is not supported", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, + keepertest.CrosschainMockOptions{ + UseAuthorityMock: true, + UseObserverMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + chain := chains.Chain{ + ChainId: 999, + } + tssList := sample.TssList(3) + sender := sample.AccAddress() + + // Set up mocks + observerMock.On("GetAllTSS", ctx).Return(tssList) + observerMock.On("GetSupportedChainFromChainID", ctx, chain.ChainId).Return(chain, false) + + msg := types.MsgVoteInbound{ + SenderChainId: chain.ChainId, + Sender: sender, + } + + err := k.CheckMigration(ctx, &msg) + require.ErrorIs(t, err, observerTypes.ErrSupportedChains) + }) + + t.Run("fails when tss address is invalid for bitcoin chain", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, + keepertest.CrosschainMockOptions{ + UseAuthorityMock: true, + UseObserverMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) + chain := chains.BitcoinTestnet + tssList := sample.TssList(3) + tssList[0].TssPubkey = "invalid" + sender := sample.AccAddress() + + // Set up mocks + observerMock.On("GetAllTSS", ctx).Return(tssList) + observerMock.On("GetSupportedChainFromChainID", ctx, chain.ChainId).Return(chain, true) + authorityMock.On("GetAdditionalChainList", ctx).Return([]chains.Chain{}) + + msg := types.MsgVoteInbound{ + SenderChainId: chain.ChainId, + Sender: sender, + } + + err := k.CheckMigration(ctx, &msg) + require.ErrorIs(t, err, types.ErrInvalidAddress) + }) + + t.Run("fails when tss address is invalid for evm chain", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, + keepertest.CrosschainMockOptions{ + UseAuthorityMock: true, + UseObserverMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) + chain := chains.Goerli + tssList := sample.TssList(3) + tssList[0].TssPubkey = "invalid" + sender := sample.AccAddress() + + // Set up mocks + observerMock.On("GetAllTSS", ctx).Return(tssList) + observerMock.On("GetSupportedChainFromChainID", ctx, chain.ChainId).Return(chain, true) + authorityMock.On("GetAdditionalChainList", ctx).Return([]chains.Chain{}) + + msg := types.MsgVoteInbound{ + SenderChainId: chain.ChainId, + Sender: sender, + } + + err := k.CheckMigration(ctx, &msg) + require.ErrorIs(t, err, types.ErrInvalidAddress) + }) + + t.Run("fails when sender is a TSS address for evm chain for evm chain", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, + keepertest.CrosschainMockOptions{ + UseAuthorityMock: true, + UseObserverMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) + chain := chains.Goerli + tssList := sample.TssList(3) + sender, err := crypto.GetTssAddrEVM(tssList[0].TssPubkey) + require.NoError(t, err) + + // Set up mocks + observerMock.On("GetAllTSS", ctx).Return(tssList) + observerMock.On("GetSupportedChainFromChainID", ctx, chain.ChainId).Return(chain, true) + authorityMock.On("GetAdditionalChainList", ctx).Return([]chains.Chain{}) + + msg := types.MsgVoteInbound{ + SenderChainId: chain.ChainId, + Sender: sender.String(), + } + + err = k.CheckMigration(ctx, &msg) + require.ErrorIs(t, err, types.ErrTssAddress) + }) + + t.Run("fails when sender is a TSS address for btc chain for btc chain", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, + keepertest.CrosschainMockOptions{ + UseAuthorityMock: true, + UseObserverMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) + chain := chains.BitcoinTestnet + tssList := sample.TssList(3) + bitcoinParams, err := chains.BitcoinNetParamsFromChainID(chain.ChainId) + require.NoError(t, err) + sender, err := crypto.GetTssAddrBTC(tssList[0].TssPubkey, bitcoinParams) + require.NoError(t, err) + + // Set up mocks + observerMock.On("GetAllTSS", ctx).Return(tssList) + observerMock.On("GetSupportedChainFromChainID", ctx, chain.ChainId).Return(chain, true) + authorityMock.On("GetAdditionalChainList", ctx).Return([]chains.Chain{}) + + msg := types.MsgVoteInbound{ + SenderChainId: chain.ChainId, + Sender: sender, + } + + err = k.CheckMigration(ctx, &msg) + require.ErrorIs(t, err, types.ErrTssAddress) + }) + + t.Run("fails if bitcoin network params not found for BTC chain", func(t *testing.T) { + k, ctx, _, _ := keepertest.CrosschainKeeperWithMocks(t, + keepertest.CrosschainMockOptions{ + UseAuthorityMock: true, + UseObserverMock: true, + }) + + observerMock := keepertest.GetCrosschainObserverMock(t, k) + authorityMock := keepertest.GetCrosschainAuthorityMock(t, k) + chain := chains.Chain{ + ChainId: 999, + Consensus: chains.Consensus_bitcoin, + } + tssList := sample.TssList(3) + sender := sample.AccAddress() + + // Set up mocks + observerMock.On("GetAllTSS", ctx).Return(tssList) + observerMock.On("GetSupportedChainFromChainID", ctx, chain.ChainId).Return(chain, true) + authorityMock.On("GetAdditionalChainList", ctx).Return([]chains.Chain{chain}) + + msg := types.MsgVoteInbound{ + SenderChainId: chain.ChainId, + Sender: sender, + } + + err := k.CheckMigration(ctx, &msg) + require.ErrorContains(t, err, "no Bitcoin net params for chain ID: 999") + }) +} diff --git a/zetaclient/chains/evm/observer/outbound.go b/zetaclient/chains/evm/observer/outbound.go index b2a7d1e4ba..807aa932b0 100644 --- a/zetaclient/chains/evm/observer/outbound.go +++ b/zetaclient/chains/evm/observer/outbound.go @@ -333,10 +333,6 @@ func ParseOutboundReceivedValue( default: return nil, chains.ReceiveStatus_failed, fmt.Errorf("unknown coin type %s", cointype) } - - if receipt.Status == ethtypes.ReceiptStatusFailed { - fmt.Println("Receipt status is failed") - } return receiveValue, receiveStatus, nil } diff --git a/zetaclient/tss/tss_signer.go b/zetaclient/tss/tss_signer.go index 1d916bd177..171062d957 100644 --- a/zetaclient/tss/tss_signer.go +++ b/zetaclient/tss/tss_signer.go @@ -88,25 +88,16 @@ type TSS struct { BitcoinChainID int64 } -// NewTSS creates a new TSS instance +// NewTSS creates a new TSS instance which can be used to sign transactions func NewTSS( appContext *appcontext.AppContext, - peer p2p.AddrList, - privkey tmcrypto.PrivKey, - preParams *keygen.LocalPreParams, client interfaces.ZetacoreClient, tssHistoricalList []observertypes.TSS, bitcoinChainID int64, - tssPassword string, hotkeyPassword string, - enableMonitor bool, tssServer *tss.TssServer, ) (*TSS, error) { logger := log.With().Str("module", "tss_signer").Logger() - //server, err := SetupTSSServer(peer, privkey, preParams, appContext.Config(), tssPassword, enableMonitor) - //if err != nil { - // return nil, fmt.Errorf("SetupTSSServer error: %w", err) - //} newTss := TSS{ Server: tssServer, @@ -144,6 +135,8 @@ func NewTSS( } metrics.NumActiveMsgSigns.Set(0) + newTss.Signers = appContext.GetKeygen().GranteePubkeys + return &newTss, nil }