From 0a451149f74ae6acc1f43e436bebe47a18f06283 Mon Sep 17 00:00:00 2001 From: charliec Date: Fri, 27 Oct 2023 15:55:25 -0500 Subject: [PATCH 1/6] skip some more recent garbage outTx trackers --- x/emissions/types/events.pb.go | 4 ++-- zetaclient/evm_client.go | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/x/emissions/types/events.pb.go b/x/emissions/types/events.pb.go index a1a96178cc..201211e96f 100644 --- a/x/emissions/types/events.pb.go +++ b/x/emissions/types/events.pb.go @@ -51,8 +51,8 @@ func (EmissionType) EnumDescriptor() ([]byte, []int) { } type ObserverEmission struct { - EmissionType EmissionType `protobuf:"varint,1,opt,name=emission_type,json=emissionType,proto3,enum=zetachain.zetacore.emissions.EmissionType" json:"emission_type,omitempty"` - ObserverAddress string `protobuf:"bytes,2,opt,name=observer_address,json=observerAddress,proto3" json:"observer_address,omitempty"` + EmissionType EmissionType `protobuf:"varint,1,opt,name=emission_type,json=emissionType,proto3,enum=zetachain.zetacore.emissions.EmissionType" json:"emission_type,omitempty"` + ObserverAddress string `protobuf:"bytes,2,opt,name=observer_address,json=observerAddress,proto3" json:"observer_address,omitempty"` Amount github_com_cosmos_cosmos_sdk_types.Int `protobuf:"bytes,3,opt,name=amount,proto3,customtype=github.com/cosmos/cosmos-sdk/types.Int" json:"amount"` } diff --git a/zetaclient/evm_client.go b/zetaclient/evm_client.go index d828364f63..eb0ed1341b 100644 --- a/zetaclient/evm_client.go +++ b/zetaclient/evm_client.go @@ -462,9 +462,9 @@ func (ob *EVMChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64, co // The lowest nonce we observe outTx for each chain var lowestOutTxNonceToObserve = map[int64]uint64{ - 5: 70000, // Goerli - 97: 95000, // BSC testnet - 80001: 120000, // Mumbai + 5: 110900, // Goerli + 97: 102200, // BSC testnet + 80001: 153000, // Mumbai } // FIXME: there's a chance that a txhash in OutTxChan may not deliver when Stop() is called @@ -556,7 +556,7 @@ func (ob *EVMChainClient) queryTxByHash(txHash string, nonce uint64) (*ethtypes. receipt, err := ob.EvmClient.TransactionReceipt(ctxt, ethcommon.HexToHash(txHash)) if err != nil { if err != ethereum.NotFound { - logger.Warn().Err(err).Msg("TransactionReceipt/TransactionByHash error") + logger.Warn().Err(err).Msgf("TransactionReceipt/TransactionByHash error, txHash %s", txHash) } return nil, nil, err } From 6e1fb4af29b3ab388a7fed8ace067a846bbceadd Mon Sep 17 00:00:00 2001 From: charliec Date: Wed, 1 Nov 2023 00:28:37 -0500 Subject: [PATCH 2/6] skip garbage trackers and increase btc gas fee --- zetaclient/bitcoin_client.go | 5 +---- zetaclient/btc_signer.go | 8 ++++++++ zetaclient/evm_client.go | 6 +++--- zetaclient/utils.go | 9 +++++++++ 4 files changed, 21 insertions(+), 7 deletions(-) diff --git a/zetaclient/bitcoin_client.go b/zetaclient/bitcoin_client.go index 42a31c39dd..672bec4132 100644 --- a/zetaclient/bitcoin_client.go +++ b/zetaclient/bitcoin_client.go @@ -77,7 +77,6 @@ const ( minConfirmations = 0 maxHeightDiff = 10000 dustOffset = 2000 - bytesPerKB = 1000 btcBlocksPerDay = 144 ) @@ -490,9 +489,7 @@ func (ob *BitcoinChainClient) PostGasPrice() error { if *feeResult.FeeRate > math2.MaxInt64 { return fmt.Errorf("gas price is too large: %f", *feeResult.FeeRate) } - // #nosec G701 always in range - feeRate := new(big.Int).SetInt64(int64(*feeResult.FeeRate * 1e8)) - feeRatePerByte := new(big.Int).Div(feeRate, big.NewInt(bytesPerKB)) + feeRatePerByte := feeRateToSatPerByte(*feeResult.FeeRate) bn, err := ob.rpcClient.GetBlockCount() if err != nil { return err diff --git a/zetaclient/btc_signer.go b/zetaclient/btc_signer.go index f426fee681..8f131f5814 100644 --- a/zetaclient/btc_signer.go +++ b/zetaclient/btc_signer.go @@ -291,6 +291,14 @@ func (signer *BTCSigner) TryProcessOutTx(send *types.CrossChainTx, outTxMan *Out return } + // Add 1 satoshi/byte to gasPrice to avoid minRelayTxFee issue + networkInfo, err := signer.rpcClient.GetNetworkInfo() + if err != nil { + logger.Error().Err(err).Msgf("cannot get bitcoin network info") + } + satPerByte := feeRateToSatPerByte(networkInfo.RelayFee) + gasprice.Add(gasprice, satPerByte) + logger.Info().Msgf("SignWithdrawTx: to %s, value %d sats", addr.EncodeAddress(), params.Amount.Uint64()) logger.Info().Msgf("using utxos: %v", btcClient.utxos) tx, err := signer.SignWithdrawTx(to, float64(params.Amount.Uint64())/1e8, gasprice, sizelimit, btcClient, height, diff --git a/zetaclient/evm_client.go b/zetaclient/evm_client.go index eb0ed1341b..911c0ce9c4 100644 --- a/zetaclient/evm_client.go +++ b/zetaclient/evm_client.go @@ -462,9 +462,9 @@ func (ob *EVMChainClient) IsSendOutTxProcessed(sendHash string, nonce uint64, co // The lowest nonce we observe outTx for each chain var lowestOutTxNonceToObserve = map[int64]uint64{ - 5: 110900, // Goerli - 97: 102200, // BSC testnet - 80001: 153000, // Mumbai + 5: 113000, // Goerli + 97: 102600, // BSC testnet + 80001: 154500, // Mumbai } // FIXME: there's a chance that a txhash in OutTxChan may not deliver when Stop() is called diff --git a/zetaclient/utils.go b/zetaclient/utils.go index 56ba3000d9..4dda2e5e6b 100644 --- a/zetaclient/utils.go +++ b/zetaclient/utils.go @@ -3,6 +3,7 @@ package zetaclient import ( "errors" "math" + "math/big" "time" "github.com/btcsuite/btcd/txscript" @@ -11,8 +12,16 @@ import ( const ( satoshiPerBitcoin = 1e8 + bytesPerKB = 1000 ) +// feeRateToSatPerByte converts a fee rate in BTC/KB to sat/byte. +func feeRateToSatPerByte(rate float64) *big.Int { + // #nosec G701 always in range + satPerKB := new(big.Int).SetInt64(int64(rate * satoshiPerBitcoin)) + return new(big.Int).Div(satPerKB, big.NewInt(bytesPerKB)) +} + func getSatoshis(btc float64) (int64, error) { // The amount is only considered invalid if it cannot be represented // as an integer type. This may happen if f is NaN or +-Infinity. From bfa1cb88675d81ecef91aea90d18c4664749c98c Mon Sep 17 00:00:00 2001 From: charliec Date: Thu, 2 Nov 2023 16:07:49 -0500 Subject: [PATCH 3/6] skip mainnet addresses in cctxs --- zetaclient/bitcoin_client.go | 16 ++++++++++++++++ zetaclient/btc_signer.go | 8 +++++++- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/zetaclient/bitcoin_client.go b/zetaclient/bitcoin_client.go index 672bec4132..cd41a18f5e 100644 --- a/zetaclient/bitcoin_client.go +++ b/zetaclient/bitcoin_client.go @@ -1073,6 +1073,22 @@ func (ob *BitcoinChainClient) checkTSSVout(vouts []btcjson.Vout, params types.Ou } // 2nd vout: payment to recipient if vout.N == 1 { + // Re-encode address with the correct network HRP so we allow the incorrect addresses to pass in Athens3 + // TODO: remove this special handling after fixing the issue in zetacore + cctxAddress, err := btcutil.DecodeAddress(params.Receiver, config.BitconNetParams) + if err != nil { + return fmt.Errorf("checkTSSVout: error decoding receiver address %s", params.Receiver) + } + if !cctxAddress.IsForNet(config.BitconNetParams) { + ob.logger.ObserveOutTx.Error().Msgf("checkTSSVout: address %s is not intended for the network %s", params.Receiver, config.BitconNetParams.Name) + correctAddress, err := btcutil.NewAddressWitnessPubKeyHash(cctxAddress.ScriptAddress(), config.BitconNetParams) + if err != nil { + return errors.Wrapf(err, "checkTSSVout: error re-encoding address %s", params.Receiver) + } + params.Receiver = correctAddress.EncodeAddress() + ob.logger.ObserveOutTx.Info().Msgf("checkTSSVout: re-encoded address %s to %s", params.Receiver, correctAddress.EncodeAddress()) + } + if recvAddress != params.Receiver { return fmt.Errorf("checkTSSVout: output address %s not match params receiver %s", recvAddress, params.Receiver) } diff --git a/zetaclient/btc_signer.go b/zetaclient/btc_signer.go index 8f131f5814..e89f201362 100644 --- a/zetaclient/btc_signer.go +++ b/zetaclient/btc_signer.go @@ -279,12 +279,17 @@ func (signer *BTCSigner) TryProcessOutTx(send *types.CrossChainTx, outTxMan *Out return } - // FIXME: config chain params + // Check receiver P2WPKH address addr, err := btcutil.DecodeAddress(params.Receiver, config.BitconNetParams) if err != nil { logger.Error().Err(err).Msgf("cannot decode address %s ", params.Receiver) return } + // TODO: enable this check after fixing the issue in zetacore + // if !addr.IsForNet(config.BitconNetParams) { + // logger.Error().Msgf("address %s is not for network %s", params.Receiver, config.BitconNetParams.Name) + // return + // } to, ok := addr.(*btcutil.AddressWitnessPubKeyHash) if err != nil || !ok { logger.Error().Err(err).Msgf("cannot convert address %s to P2WPKH address", params.Receiver) @@ -295,6 +300,7 @@ func (signer *BTCSigner) TryProcessOutTx(send *types.CrossChainTx, outTxMan *Out networkInfo, err := signer.rpcClient.GetNetworkInfo() if err != nil { logger.Error().Err(err).Msgf("cannot get bitcoin network info") + return } satPerByte := feeRateToSatPerByte(networkInfo.RelayFee) gasprice.Add(gasprice, satPerByte) From ccb6b0c771bebfdcfcbd36d161052d5dc5d2e334 Mon Sep 17 00:00:00 2001 From: charliec Date: Fri, 3 Nov 2023 11:15:27 -0500 Subject: [PATCH 4/6] cherry picked minRelayTxFee hotfix and bitcoin testnet/mainnet address format fix --- zetaclient/bitcoin_client.go | 16 ---------------- zetaclient/btc_signer.go | 9 ++++----- 2 files changed, 4 insertions(+), 21 deletions(-) diff --git a/zetaclient/bitcoin_client.go b/zetaclient/bitcoin_client.go index cd41a18f5e..672bec4132 100644 --- a/zetaclient/bitcoin_client.go +++ b/zetaclient/bitcoin_client.go @@ -1073,22 +1073,6 @@ func (ob *BitcoinChainClient) checkTSSVout(vouts []btcjson.Vout, params types.Ou } // 2nd vout: payment to recipient if vout.N == 1 { - // Re-encode address with the correct network HRP so we allow the incorrect addresses to pass in Athens3 - // TODO: remove this special handling after fixing the issue in zetacore - cctxAddress, err := btcutil.DecodeAddress(params.Receiver, config.BitconNetParams) - if err != nil { - return fmt.Errorf("checkTSSVout: error decoding receiver address %s", params.Receiver) - } - if !cctxAddress.IsForNet(config.BitconNetParams) { - ob.logger.ObserveOutTx.Error().Msgf("checkTSSVout: address %s is not intended for the network %s", params.Receiver, config.BitconNetParams.Name) - correctAddress, err := btcutil.NewAddressWitnessPubKeyHash(cctxAddress.ScriptAddress(), config.BitconNetParams) - if err != nil { - return errors.Wrapf(err, "checkTSSVout: error re-encoding address %s", params.Receiver) - } - params.Receiver = correctAddress.EncodeAddress() - ob.logger.ObserveOutTx.Info().Msgf("checkTSSVout: re-encoded address %s to %s", params.Receiver, correctAddress.EncodeAddress()) - } - if recvAddress != params.Receiver { return fmt.Errorf("checkTSSVout: output address %s not match params receiver %s", recvAddress, params.Receiver) } diff --git a/zetaclient/btc_signer.go b/zetaclient/btc_signer.go index e89f201362..eb8830b960 100644 --- a/zetaclient/btc_signer.go +++ b/zetaclient/btc_signer.go @@ -285,11 +285,10 @@ func (signer *BTCSigner) TryProcessOutTx(send *types.CrossChainTx, outTxMan *Out logger.Error().Err(err).Msgf("cannot decode address %s ", params.Receiver) return } - // TODO: enable this check after fixing the issue in zetacore - // if !addr.IsForNet(config.BitconNetParams) { - // logger.Error().Msgf("address %s is not for network %s", params.Receiver, config.BitconNetParams.Name) - // return - // } + if !addr.IsForNet(config.BitconNetParams) { + logger.Error().Msgf("address %s is not for network %s", params.Receiver, config.BitconNetParams.Name) + return + } to, ok := addr.(*btcutil.AddressWitnessPubKeyHash) if err != nil || !ok { logger.Error().Err(err).Msgf("cannot convert address %s to P2WPKH address", params.Receiver) From fec6a799e6b78fe0818dbbaeedd2ca55269e5214 Mon Sep 17 00:00:00 2001 From: charliec Date: Mon, 6 Nov 2023 10:36:40 -0600 Subject: [PATCH 5/6] resolve conflict --- zetaclient/interfaces.go | 1 + 1 file changed, 1 insertion(+) diff --git a/zetaclient/interfaces.go b/zetaclient/interfaces.go index b2f17d9c90..f01fcc124c 100644 --- a/zetaclient/interfaces.go +++ b/zetaclient/interfaces.go @@ -91,6 +91,7 @@ type ZetaCoreBridger interface { // BTCRPCClient is the interface for BTC RPC client type BTCRPCClient interface { + GetNetworkInfo() (*btcjson.GetNetworkInfoResult, error) SendRawTransaction(tx *wire.MsgTx, allowHighFees bool) (*chainhash.Hash, error) ListUnspentMinMaxAddresses(minConf int, maxConf int, addrs []btcutil.Address) ([]btcjson.ListUnspentResult, error) EstimateSmartFee(confTarget int64, mode *btcjson.EstimateSmartFeeMode) (*btcjson.EstimateSmartFeeResult, error) From f794a0a614e4f014a10f476a4791fb309a9de769 Mon Sep 17 00:00:00 2001 From: charliec Date: Mon, 13 Nov 2023 10:47:21 -0600 Subject: [PATCH 6/6] update CHANGELOG.md for v10.1.x hotfix --- changelog.md | 1 + 1 file changed, 1 insertion(+) diff --git a/changelog.md b/changelog.md index 7347b78b58..fcf9816f5c 100644 --- a/changelog.md +++ b/changelog.md @@ -7,6 +7,7 @@ ### Fixes * [1372](https://github.com/zeta-chain/node/pull/1372) - Include Event Index as part for inbound tx digest +* [1367](https://github.com/zeta-chain/node/pull/1367) - fix minRelayTxFee issue and check misuse of bitcoin mainnet/testnet addresses * [1358](https://github.com/zeta-chain/node/pull/1358) - add a new thread to zetaclient which checks zeta supply in all connected chains in every block ### Refactoring