diff --git a/cmd/zetaclientd/start.go b/cmd/zetaclientd/start.go index 5043afe3ad..f00abdcde1 100644 --- a/cmd/zetaclientd/start.go +++ b/cmd/zetaclientd/start.go @@ -275,7 +275,8 @@ func start(_ *cobra.Command, _ []string) error { btcChainIDs[i] = chain.ID() } - // Make sure the TSS EVM/BTC addresses are well formed + // Make sure the TSS EVM/BTC addresses are well formed. + // Zetaclient should not start if TSS addresses cannot be properly derived. tss.CurrentPubkey = currentTss.TssPubkey err = tss.ValidateAddresses(btcChainIDs) if err != nil { diff --git a/x/crosschain/keeper/cctx_orchestrator_validate_inbound_test.go b/x/crosschain/keeper/cctx_orchestrator_validate_inbound_test.go index 916a443d9c..af1521c988 100644 --- a/x/crosschain/keeper/cctx_orchestrator_validate_inbound_test.go +++ b/x/crosschain/keeper/cctx_orchestrator_validate_inbound_test.go @@ -567,7 +567,7 @@ func TestKeeper_CheckMigration(t *testing.T) { } err := k.CheckIfTSSMigrationTransfer(ctx, &msg) - require.ErrorContains(t, err, "no Bitcoin net params for chain ID: 999") + require.ErrorContains(t, err, "no Bitcoin network params for chain ID: 999") }) t.Run("fails if gateway is not observer ", func(t *testing.T) { diff --git a/zetaclient/chains/base/observer.go b/zetaclient/chains/base/observer.go index 5d8950c4da..6cf8af9de6 100644 --- a/zetaclient/chains/base/observer.go +++ b/zetaclient/chains/base/observer.go @@ -217,13 +217,17 @@ func (ob *Observer) WithTSS(tss interfaces.TSSSigner) *Observer { return ob } -// TSSAddress returns the TSS address for the chain. +// TSSAddressString returns the TSS address for the chain. // // Note: all chains uses TSS EVM address except Bitcoin chain. -func (ob *Observer) TSSAddress() string { +func (ob *Observer) TSSAddressString() string { switch ob.chain.Consensus { case chains.Consensus_bitcoin: - return ob.tss.BTCAddress(ob.Chain().ChainId).EncodeAddress() + address, err := ob.tss.BTCAddress(ob.Chain().ChainId) + if err != nil { + return "" + } + return address.EncodeAddress() default: return ob.tss.EVMAddress().String() } @@ -298,7 +302,7 @@ func (ob *Observer) WithHeaderCache(cache *lru.Cache) *Observer { // OutboundID returns a unique identifier for the outbound transaction. // The identifier is now used as the key for maps that store outbound related data (e.g. transaction, receipt, etc). func (ob *Observer) OutboundID(nonce uint64) string { - tssAddress := ob.TSSAddress() + tssAddress := ob.TSSAddressString() return fmt.Sprintf("%d-%s-%d", ob.chain.ChainId, tssAddress, nonce) } diff --git a/zetaclient/chains/base/observer_test.go b/zetaclient/chains/base/observer_test.go index 675f4491b8..0e772e31f9 100644 --- a/zetaclient/chains/base/observer_test.go +++ b/zetaclient/chains/base/observer_test.go @@ -274,13 +274,14 @@ func TestObserverGetterAndSetter(t *testing.T) { }) } -func TestTSSAddress(t *testing.T) { +func TestTSSAddressString(t *testing.T) { testConfig := sdk.GetConfig() testConfig.SetBech32PrefixForAccount(cmd.Bech32PrefixAccAddr, cmd.Bech32PrefixAccPub) tests := []struct { name string chain chains.Chain + forceError bool addrExpected string }{ { @@ -298,6 +299,12 @@ func TestTSSAddress(t *testing.T) { chain: chains.SolanaDevnet, addrExpected: testutils.TSSAddressEVMMainnet, }, + { + name: "should return empty address for unknown BTC chain", + chain: chains.BitcoinMainnet, + forceError: true, + addrExpected: "", + }, } // run tests @@ -306,8 +313,16 @@ func TestTSSAddress(t *testing.T) { // create observer ob := createObserver(t, tt.chain, defaultAlertLatency) + // force error if needed + if tt.forceError { + // pause TSS to cause error + tss := mocks.NewTSSMainnet() + tss.Pause() + ob = ob.WithTSS(tss) + } + // get TSS address - addr := ob.TSSAddress() + addr := ob.TSSAddressString() require.Equal(t, tt.addrExpected, addr) }) } @@ -390,7 +405,7 @@ func TestOutboundID(t *testing.T) { outboundID := ob.OutboundID(tt.nonce) // expected outbound id - exepctedID := fmt.Sprintf("%d-%s-%d", tt.chain.ChainId, ob.TSSAddress(), tt.nonce) + exepctedID := fmt.Sprintf("%d-%s-%d", tt.chain.ChainId, ob.TSSAddressString(), tt.nonce) require.Equal(t, exepctedID, outboundID) }) } diff --git a/zetaclient/chains/bitcoin/observer/inbound.go b/zetaclient/chains/bitcoin/observer/inbound.go index 3d16f8ec35..e75d9cc1a0 100644 --- a/zetaclient/chains/bitcoin/observer/inbound.go +++ b/zetaclient/chains/bitcoin/observer/inbound.go @@ -146,7 +146,7 @@ func (ob *Observer) ObserveInbound(ctx context.Context) error { // add block header to zetacore if len(res.Block.Tx) > 1 { // filter incoming txs to TSS address - tssAddress := ob.TSSAddress() + tssAddress := ob.TSSAddressString() // #nosec G115 always positive events, err := FilterAndParseIncomingTx( diff --git a/zetaclient/chains/bitcoin/observer/observer.go b/zetaclient/chains/bitcoin/observer/observer.go index 5083325d0f..80781fdd33 100644 --- a/zetaclient/chains/bitcoin/observer/observer.go +++ b/zetaclient/chains/bitcoin/observer/observer.go @@ -369,8 +369,8 @@ func (ob *Observer) FetchUTXOs(ctx context.Context) error { maxConfirmations := int(bh) // List all unspent UTXOs (160ms) - tssAddr := ob.TSS().BTCAddress(ob.Chain().ChainId) - if tssAddr == nil { + tssAddr, err := ob.TSS().BTCAddress(ob.Chain().ChainId) + if err != nil { return fmt.Errorf("error getting bitcoin tss address") } utxos, err := ob.btcClient.ListUnspentMinMaxAddresses(0, maxConfirmations, []btcutil.Address{tssAddr}) diff --git a/zetaclient/chains/bitcoin/observer/outbound.go b/zetaclient/chains/bitcoin/observer/outbound.go index 4f67e9dfcf..3b25d8c0c1 100644 --- a/zetaclient/chains/bitcoin/observer/outbound.go +++ b/zetaclient/chains/bitcoin/observer/outbound.go @@ -414,7 +414,7 @@ func (ob *Observer) getOutboundIDByNonce(ctx context.Context, nonce uint64, test // findNonceMarkUTXO finds the nonce-mark UTXO in the list of UTXOs. func (ob *Observer) findNonceMarkUTXO(nonce uint64, txid string) (int, error) { - tssAddress := ob.TSSAddress() + tssAddress := ob.TSSAddressString() amount := chains.NonceMarkAmount(nonce) for i, utxo := range ob.utxos { sats, err := bitcoin.GetSatoshis(utxo.Amount) @@ -599,7 +599,7 @@ func (ob *Observer) checkTSSVout(params *crosschaintypes.OutboundParams, vouts [ } nonce := params.TssNonce - tssAddress := ob.TSSAddress() + tssAddress := ob.TSSAddressString() for _, vout := range vouts { // decode receiver and amount from vout receiverExpected := tssAddress @@ -658,7 +658,7 @@ func (ob *Observer) checkTSSVoutCancelled(params *crosschaintypes.OutboundParams } nonce := params.TssNonce - tssAddress := ob.TSSAddress() + tssAddress := ob.TSSAddressString() for _, vout := range vouts { // decode receiver and amount from vout receiverVout, amount, err := bitcoin.DecodeTSSVout(vout, tssAddress, ob.Chain()) diff --git a/zetaclient/chains/bitcoin/observer/outbound_test.go b/zetaclient/chains/bitcoin/observer/outbound_test.go index d25eb8f4c5..1507c7d416 100644 --- a/zetaclient/chains/bitcoin/observer/outbound_test.go +++ b/zetaclient/chains/bitcoin/observer/outbound_test.go @@ -61,27 +61,29 @@ func createObserverWithPrivateKey(t *testing.T) *Observer { func createObserverWithUTXOs(t *testing.T) *Observer { // Create Bitcoin observer ob := createObserverWithPrivateKey(t) - tssAddress := ob.TSS().BTCAddress(chains.BitcoinTestnet.ChainId).EncodeAddress() + tssAddress, err := ob.TSS().BTCAddress(chains.BitcoinTestnet.ChainId) + require.NoError(t, err) // Create 10 dummy UTXOs (22.44 BTC in total) ob.utxos = make([]btcjson.ListUnspentResult, 0, 10) amounts := []float64{0.01, 0.12, 0.18, 0.24, 0.5, 1.26, 2.97, 3.28, 5.16, 8.72} for _, amount := range amounts { - ob.utxos = append(ob.utxos, btcjson.ListUnspentResult{Address: tssAddress, Amount: amount}) + ob.utxos = append(ob.utxos, btcjson.ListUnspentResult{Address: tssAddress.EncodeAddress(), Amount: amount}) } return ob } -func mineTxNSetNonceMark(ob *Observer, nonce uint64, txid string, preMarkIndex int) { +func mineTxNSetNonceMark(t *testing.T, ob *Observer, nonce uint64, txid string, preMarkIndex int) { // Mine transaction outboundID := ob.OutboundID(nonce) ob.includedTxResults[outboundID] = &btcjson.GetTransactionResult{TxID: txid} // Set nonce mark - tssAddress := ob.TSS().BTCAddress(chains.BitcoinTestnet.ChainId).EncodeAddress() + tssAddress, err := ob.TSS().BTCAddress(chains.BitcoinTestnet.ChainId) + require.NoError(t, err) nonceMark := btcjson.ListUnspentResult{ TxID: txid, - Address: tssAddress, + Address: tssAddress.EncodeAddress(), Amount: float64(chains.NonceMarkAmount(nonce)) * 1e-8, } if preMarkIndex >= 0 { // replace nonce-mark utxo @@ -268,7 +270,7 @@ func TestSelectUTXOs(t *testing.T) { require.Nil(t, result) require.Zero(t, amount) require.Equal(t, "getOutboundIDByNonce: cannot find outbound txid for nonce 0", err.Error()) - mineTxNSetNonceMark(ob, 0, dummyTxID, -1) // mine a transaction and set nonce-mark utxo for nonce 0 + mineTxNSetNonceMark(t, ob, 0, dummyTxID, -1) // mine a transaction and set nonce-mark utxo for nonce 0 // Case3: nonce = 1, should pass now // input: utxoCap = 5, amount = 0.5, nonce = 1 @@ -277,7 +279,7 @@ func TestSelectUTXOs(t *testing.T) { require.NoError(t, err) require.Equal(t, 0.55002, amount) require.Equal(t, ob.utxos[0:5], result) - mineTxNSetNonceMark(ob, 1, dummyTxID, 0) // mine a transaction and set nonce-mark utxo for nonce 1 + mineTxNSetNonceMark(t, ob, 1, dummyTxID, 0) // mine a transaction and set nonce-mark utxo for nonce 1 // Case4: // input: utxoCap = 5, amount = 1.0, nonce = 2 @@ -286,7 +288,7 @@ func TestSelectUTXOs(t *testing.T) { require.NoError(t, err) require.InEpsilon(t, 1.05002001, amount, 1e-8) require.Equal(t, ob.utxos[0:6], result) - mineTxNSetNonceMark(ob, 2, dummyTxID, 0) // mine a transaction and set nonce-mark utxo for nonce 2 + mineTxNSetNonceMark(t, ob, 2, dummyTxID, 0) // mine a transaction and set nonce-mark utxo for nonce 2 // Case5: should include nonce-mark utxo on the LEFT // input: utxoCap = 5, amount = 8.05, nonce = 3 @@ -296,7 +298,7 @@ func TestSelectUTXOs(t *testing.T) { require.InEpsilon(t, 8.25002002, amount, 1e-8) expected := append([]btcjson.ListUnspentResult{ob.utxos[0]}, ob.utxos[4:9]...) require.Equal(t, expected, result) - mineTxNSetNonceMark(ob, 24105431, dummyTxID, 0) // mine a transaction and set nonce-mark utxo for nonce 24105431 + mineTxNSetNonceMark(t, ob, 24105431, dummyTxID, 0) // mine a transaction and set nonce-mark utxo for nonce 24105431 // Case6: should include nonce-mark utxo on the RIGHT // input: utxoCap = 5, amount = 0.503, nonce = 24105432 @@ -306,7 +308,7 @@ func TestSelectUTXOs(t *testing.T) { require.InEpsilon(t, 0.79107431, amount, 1e-8) expected = append([]btcjson.ListUnspentResult{ob.utxos[4]}, ob.utxos[0:4]...) require.Equal(t, expected, result) - mineTxNSetNonceMark(ob, 24105432, dummyTxID, 4) // mine a transaction and set nonce-mark utxo for nonce 24105432 + mineTxNSetNonceMark(t, ob, 24105432, dummyTxID, 4) // mine a transaction and set nonce-mark utxo for nonce 24105432 // Case7: should include nonce-mark utxo in the MIDDLE // input: utxoCap = 5, amount = 1.0, nonce = 24105433 @@ -348,7 +350,7 @@ func TestUTXOConsolidation(t *testing.T) { t.Run("should not consolidate", func(t *testing.T) { ob := createObserverWithUTXOs(t) - mineTxNSetNonceMark(ob, 0, dummyTxID, -1) // mine a transaction and set nonce-mark utxo for nonce 0 + mineTxNSetNonceMark(t, ob, 0, dummyTxID, -1) // mine a transaction and set nonce-mark utxo for nonce 0 // input: utxoCap = 10, amount = 0.01, nonce = 1, rank = 10 // output: [0.00002, 0.01], 0.01002 @@ -362,7 +364,7 @@ func TestUTXOConsolidation(t *testing.T) { t.Run("should consolidate 1 utxo", func(t *testing.T) { ob := createObserverWithUTXOs(t) - mineTxNSetNonceMark(ob, 0, dummyTxID, -1) // mine a transaction and set nonce-mark utxo for nonce 0 + mineTxNSetNonceMark(t, ob, 0, dummyTxID, -1) // mine a transaction and set nonce-mark utxo for nonce 0 // input: utxoCap = 9, amount = 0.01, nonce = 1, rank = 9 // output: [0.00002, 0.01, 0.12], 0.13002 @@ -376,7 +378,7 @@ func TestUTXOConsolidation(t *testing.T) { t.Run("should consolidate 3 utxos", func(t *testing.T) { ob := createObserverWithUTXOs(t) - mineTxNSetNonceMark(ob, 0, dummyTxID, -1) // mine a transaction and set nonce-mark utxo for nonce 0 + mineTxNSetNonceMark(t, ob, 0, dummyTxID, -1) // mine a transaction and set nonce-mark utxo for nonce 0 // input: utxoCap = 5, amount = 0.01, nonce = 0, rank = 5 // output: [0.00002, 0.014, 1.26, 0.5, 0.2], 2.01002 @@ -395,7 +397,7 @@ func TestUTXOConsolidation(t *testing.T) { t.Run("should consolidate all utxos using rank 1", func(t *testing.T) { ob := createObserverWithUTXOs(t) - mineTxNSetNonceMark(ob, 0, dummyTxID, -1) // mine a transaction and set nonce-mark utxo for nonce 0 + mineTxNSetNonceMark(t, ob, 0, dummyTxID, -1) // mine a transaction and set nonce-mark utxo for nonce 0 // input: utxoCap = 12, amount = 0.01, nonce = 0, rank = 1 // output: [0.00002, 0.01, 8.72, 5.16, 3.28, 2.97, 1.26, 0.5, 0.24, 0.18, 0.12], 22.44002 @@ -415,6 +417,7 @@ func TestUTXOConsolidation(t *testing.T) { t.Run("should consolidate 3 utxos sparse", func(t *testing.T) { ob := createObserverWithUTXOs(t) mineTxNSetNonceMark( + t, ob, 24105431, dummyTxID, @@ -438,6 +441,7 @@ func TestUTXOConsolidation(t *testing.T) { t.Run("should consolidate all utxos sparse", func(t *testing.T) { ob := createObserverWithUTXOs(t) mineTxNSetNonceMark( + t, ob, 24105431, dummyTxID, diff --git a/zetaclient/chains/bitcoin/observer/rpc_status.go b/zetaclient/chains/bitcoin/observer/rpc_status.go index e3b63bf028..e0fc3c651d 100644 --- a/zetaclient/chains/bitcoin/observer/rpc_status.go +++ b/zetaclient/chains/bitcoin/observer/rpc_status.go @@ -29,7 +29,12 @@ func (ob *Observer) watchRPCStatus(_ context.Context) error { // checkRPCStatus checks the RPC status of the Bitcoin chain func (ob *Observer) checkRPCStatus() { - tssAddress := ob.TSS().BTCAddress(ob.Chain().ChainId) + tssAddress, err := ob.TSS().BTCAddress(ob.Chain().ChainId) + if err != nil { + ob.Logger().Chain.Error().Err(err).Msg("unable to get TSS BTC address") + return + } + blockTime, err := rpc.CheckRPCStatus(ob.btcClient, tssAddress) if err != nil { ob.Logger().Chain.Error().Err(err).Msg("CheckRPCStatus failed") diff --git a/zetaclient/chains/bitcoin/signer/signer.go b/zetaclient/chains/bitcoin/signer/signer.go index d7a549dc9a..128b75b537 100644 --- a/zetaclient/chains/bitcoin/signer/signer.go +++ b/zetaclient/chains/bitcoin/signer/signer.go @@ -154,7 +154,10 @@ func (signer *Signer) AddWithdrawTxOutputs( } // 1st output: the nonce-mark btc to TSS self - tssAddrP2WPKH := signer.TSS().BTCAddress(signer.Chain().ChainId) + tssAddrP2WPKH, err := signer.TSS().BTCAddress(signer.Chain().ChainId) + if err != nil { + return err + } payToSelfScript, err := bitcoin.PayToAddrScript(tssAddrP2WPKH) if err != nil { return err diff --git a/zetaclient/chains/bitcoin/signer/signer_keysign_test.go b/zetaclient/chains/bitcoin/signer/signer_keysign_test.go index 4898a9e7f2..1ad50f0af5 100644 --- a/zetaclient/chains/bitcoin/signer/signer_keysign_test.go +++ b/zetaclient/chains/bitcoin/signer/signer_keysign_test.go @@ -39,7 +39,8 @@ func (suite *BTCSignTestSuite) SetupTest() { suite.testSigner = &mocks.TSS{ // fake TSS PrivKey: privateKey.ToECDSA(), } - addr := suite.testSigner.BTCAddress(chains.BitcoinTestnet.ChainId) + addr, err := suite.testSigner.BTCAddress(chains.BitcoinTestnet.ChainId) + suite.Require().NoError(err) suite.T().Logf("segwit addr: %s", addr) } diff --git a/zetaclient/chains/bitcoin/signer/signer_test.go b/zetaclient/chains/bitcoin/signer/signer_test.go index 0e304e7afd..b9decf25b1 100644 --- a/zetaclient/chains/bitcoin/signer/signer_test.go +++ b/zetaclient/chains/bitcoin/signer/signer_test.go @@ -238,7 +238,8 @@ func TestAddWithdrawTxOutputs(t *testing.T) { require.NoError(t, err) // tss address and script - tssAddr := signer.TSS().BTCAddress(chains.BitcoinTestnet.ChainId) + tssAddr, err := signer.TSS().BTCAddress(chains.BitcoinTestnet.ChainId) + require.NoError(t, err) tssScript, err := bitcoin.PayToAddrScript(tssAddr) require.NoError(t, err) fmt.Printf("tss address: %s", tssAddr.EncodeAddress()) diff --git a/zetaclient/chains/interfaces/interfaces.go b/zetaclient/chains/interfaces/interfaces.go index 9a3339df8c..ab58456de6 100644 --- a/zetaclient/chains/interfaces/interfaces.go +++ b/zetaclient/chains/interfaces/interfaces.go @@ -256,6 +256,6 @@ type TSSSigner interface { EVMAddress() ethcommon.Address EVMAddressList() []ethcommon.Address - BTCAddress(chainID int64) *btcutil.AddressWitnessPubKeyHash + BTCAddress(chainID int64) (*btcutil.AddressWitnessPubKeyHash, error) PubKeyCompressedBytes() []byte } diff --git a/zetaclient/testutils/mocks/tss_signer.go b/zetaclient/testutils/mocks/tss_signer.go index 0e8d421446..e0d9bd384c 100644 --- a/zetaclient/testutils/mocks/tss_signer.go +++ b/zetaclient/testutils/mocks/tss_signer.go @@ -112,18 +112,23 @@ func (s *TSS) EVMAddressList() []ethcommon.Address { return []ethcommon.Address{s.EVMAddress()} } -func (s *TSS) BTCAddress(_ int64) *btcutil.AddressWitnessPubKeyHash { +func (s *TSS) BTCAddress(_ int64) (*btcutil.AddressWitnessPubKeyHash, error) { + // return error if tss is paused + if s.paused { + return nil, fmt.Errorf("tss is paused") + } + // force use static btcAddress if set if s.btcAddress != "" { net, err := chains.GetBTCChainParams(s.chain.ChainId) if err != nil { - return nil + return nil, err } addr, err := btcutil.DecodeAddress(s.btcAddress, net) if err != nil { - return nil + return nil, err } - return addr.(*btcutil.AddressWitnessPubKeyHash) + return addr.(*btcutil.AddressWitnessPubKeyHash), nil } // if privkey is set, use it to generate a segwit address if s.PrivKey != nil { @@ -131,7 +136,7 @@ func (s *TSS) BTCAddress(_ int64) *btcutil.AddressWitnessPubKeyHash { pk, err := btcec.ParsePubKey(pkBytes) if err != nil { fmt.Printf("error parsing pubkey: %v", err) - return nil + return nil, err } // witness program: https://github.com/bitcoin/bips/blob/master/bip-0141.mediawiki#Witness_program @@ -142,12 +147,12 @@ func (s *TSS) BTCAddress(_ int64) *btcutil.AddressWitnessPubKeyHash { ) if err != nil { fmt.Printf("error NewAddressWitnessPubKeyHash: %v", err) - return nil + return nil, err } - return addrWPKH + return addrWPKH, nil } - return nil + return nil, nil } // PubKeyCompressedBytes returns 33B compressed pubkey diff --git a/zetaclient/tss/tss_signer.go b/zetaclient/tss/tss_signer.go index 57aede5cdc..cfd958f8fb 100644 --- a/zetaclient/tss/tss_signer.go +++ b/zetaclient/tss/tss_signer.go @@ -413,9 +413,9 @@ func (tss *TSS) SignBatch( return sigBytes, nil } -// ValidateAddresses validates the TSS EVM and BTC addresses +// ValidateAddresses try deriving both the EVM and BTC addresses from the pubkey and make sure they are valid. func (tss *TSS) ValidateAddresses(btcChainIDs []int64) error { - log.Info().Msgf("tss.pubkey: %s", tss.CurrentPubkey) + tss.logger.Info().Msgf("tss.pubkey: %s", tss.CurrentPubkey) // validate TSS EVM address evmAddress := tss.EVMAddress() @@ -423,14 +423,15 @@ func (tss *TSS) ValidateAddresses(btcChainIDs []int64) error { if evmAddress == blankAddress { return fmt.Errorf("blank tss evm address: %s", evmAddress.String()) } - log.Info().Msgf("tss.eth: %s", tss.EVMAddress().String()) + tss.logger.Info().Msgf("tss.eth: %s", tss.EVMAddress().String()) // validate TSS BTC address for each btc chain for _, chainID := range btcChainIDs { - if tss.BTCAddress(chainID) == nil { + address, err := tss.BTCAddress(chainID) + if err != nil { return fmt.Errorf("cannot derive btc address for chain %d from tss pubkey %s", chainID, tss.CurrentPubkey) } - log.Info().Msgf("tss.btc [chain %d]: %s", chainID, tss.BTCAddress(chainID).EncodeAddress()) + tss.logger.Info().Msgf("tss.btc [chain %d]: %s", chainID, address.EncodeAddress()) } return nil @@ -460,13 +461,13 @@ func (tss *TSS) EVMAddressList() []ethcommon.Address { } // BTCAddress generates a bech32 p2wpkh address from pubkey -func (tss *TSS) BTCAddress(chainID int64) *btcutil.AddressWitnessPubKeyHash { +func (tss *TSS) BTCAddress(chainID int64) (*btcutil.AddressWitnessPubKeyHash, error) { addrWPKH, err := getKeyAddrBTCWitnessPubkeyHash(tss.CurrentPubkey, chainID) if err != nil { log.Error().Err(err).Msg("BTCAddressPubkeyHash error") - return nil + return nil, err } - return addrWPKH + return addrWPKH, nil } // PubKeyCompressedBytes returns the compressed bytes of the current pubkey diff --git a/zetaclient/tss/tss_signer_test.go b/zetaclient/tss/tss_signer_test.go index dc5b0540ec..c17caf8b63 100644 --- a/zetaclient/tss/tss_signer_test.go +++ b/zetaclient/tss/tss_signer_test.go @@ -12,6 +12,7 @@ import ( "github.com/zeta-chain/node/cmd" "github.com/zeta-chain/node/pkg/chains" + "github.com/zeta-chain/node/pkg/constant" "github.com/zeta-chain/node/pkg/cosmos" "github.com/zeta-chain/node/pkg/crypto" "github.com/zeta-chain/node/zetaclient/testutils" @@ -110,7 +111,7 @@ func Test_EVMAddress(t *testing.T) { { name: "should return empty TSS EVM address on invalid TSS pubkey", tssPubkey: "invalidpubkey", - expectedEVMAddr: "0x0000000000000000000000000000000000000000", + expectedEVMAddr: constant.EVMZeroAddress, }, } @@ -159,8 +160,9 @@ func Test_BTCAddress(t *testing.T) { tss := TSS{ CurrentPubkey: tc.tssPubkey, } - address := tss.BTCAddress(tc.btcChainID) + address, err := tss.BTCAddress(tc.btcChainID) if tc.wantAddr != "" { + require.NoError(t, err) require.Equal(t, tc.wantAddr, address.EncodeAddress()) } else { require.Nil(t, address)