Skip to content

Commit

Permalink
fix: btc decode address (#1528)
Browse files Browse the repository at this point in the history
* add checks for params

* add wrapper function for btc decode address

* remove checks fro prefixes

* add check to see if address belongs to a network

* fix unit tests

* add changelog

* remove unnecessary print statements

* Update common/address.go

Co-authored-by: Lucas Bertrand <[email protected]>

* Update common/address.go

Co-authored-by: Lucas Bertrand <[email protected]>

* Update common/address.go

Co-authored-by: Lucas Bertrand <[email protected]>

* fix lint

* Update common/address.go

Co-authored-by: Lucas Bertrand <[email protected]>

---------

Co-authored-by: Lucas Bertrand <[email protected]>
  • Loading branch information
kingpinXD and lumtis authored Jan 9, 2024
1 parent e6ccc5b commit 0642dbb
Show file tree
Hide file tree
Showing 8 changed files with 64 additions and 15 deletions.
1 change: 1 addition & 0 deletions changelog.md
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
* fix docker build issues with version: golang:1.20-alpine3.18
* [1525](https://github.com/zeta-chain/node/pull/1525) - relax EVM chain block header length check 1024->4096
* [1522](https://github.com/zeta-chain/node/pull/1522/files) - block `distribution` module account from receiving zeta
* [1528](https://github.com/zeta-chain/node/pull/1528) - fix panic caused on decoding malformed BTC addresses

### Refactoring

Expand Down
37 changes: 37 additions & 0 deletions common/address.go
Original file line number Diff line number Diff line change
@@ -1,8 +1,11 @@
package common

import (
"errors"
"fmt"
"strings"

"github.com/btcsuite/btcutil"
eth "github.com/ethereum/go-ethereum/common"
"github.com/zeta-chain/zetacore/common/cosmos"
)
Expand Down Expand Up @@ -41,3 +44,37 @@ func (addr Address) IsEmpty() bool {
func (addr Address) String() string {
return string(addr)
}

func ConvertRecoverToError(r interface{}) error {
switch x := r.(type) {
case string:
return errors.New(x)
case error:
return x
default:
return fmt.Errorf("%v", x)
}
}

func DecodeBtcAddress(inputAddress string, chainID int64) (address btcutil.Address, err error) {
defer func() {
if r := recover(); r != nil {
err = ConvertRecoverToError(r)
err = fmt.Errorf("input address:%s, chainId:%d, err:%s", inputAddress, chainID, err.Error())
return
}
}()
chainParams, err := GetBTCChainParams(chainID)
if err != nil {
return nil, err
}
if chainParams == nil {
return nil, fmt.Errorf("chain params not found")
}
address, err = btcutil.DecodeAddress(inputAddress, chainParams)
ok := address.IsForNet(chainParams)
if !ok {
return nil, fmt.Errorf("address is not for network %s", chainParams.Name)
}
return
}
20 changes: 20 additions & 0 deletions common/address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,23 @@ func TestAddress(t *testing.T) {
addr = NewAddress("0x90f2b1ae50e6018230e90a33f98c7844a0ab635a")
require.EqualValuesf(t, "0x90f2b1ae50e6018230e90a33f98c7844a0ab635a", addr.String(), "address string should be equal")
}

func TestDecodeBtcAddress(t *testing.T) {
t.Run("invalid string", func(t *testing.T) {
_, err := DecodeBtcAddress("�U�ڷ���i߭����꿚�l", 18332)
require.ErrorContains(t, err, "runtime error: index out of range")
})
t.Run("invalid chain", func(t *testing.T) {
_, err := DecodeBtcAddress("14CEjTd5ci3228J45GdnGeUKLSSeCWUQxK", 0)
require.ErrorContains(t, err, "is not a Bitcoin chain")
})
t.Run("nil pointer dereference", func(t *testing.T) {
_, err := DecodeBtcAddress("tb1qy9pqmk2pd9sv63g27jt8r657wy0d9uee4x2dt2", 18332)
require.ErrorContains(t, err, "runtime error: invalid memory address or nil pointer dereference")
})
t.Run("valid address", func(t *testing.T) {
_, err := DecodeBtcAddress("bcrt1qy9pqmk2pd9sv63g27jt8r657wy0d9uee4x2dt2", 18444)
require.NoError(t, err)
})

}
2 changes: 1 addition & 1 deletion common/chain.go
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ func (chain Chain) EncodeAddress(b []byte) (string, error) {
if err != nil {
return "", err
}
addr, err := btcutil.DecodeAddress(addrStr, chainParams)
addr, err := DecodeBtcAddress(addrStr, chain.ChainId)
if err != nil {
return "", err
}
Expand Down
4 changes: 2 additions & 2 deletions contrib/localnet/orchestrator/smoketest/runner/setup_zeta.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ import (

"github.com/ethereum/go-ethereum/accounts/abi/bind"

"github.com/btcsuite/btcutil"
ethcommon "github.com/ethereum/go-ethereum/common"
"github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/systemcontract.sol"
"github.com/zeta-chain/protocol-contracts/pkg/contracts/zevm/zrc20.sol"
Expand Down Expand Up @@ -38,7 +37,8 @@ func (sm *SmokeTestRunner) SetTSSAddresses() {
}

tssAddress := ethcommon.HexToAddress(res.Eth)
btcTSSAddress, err := btcutil.DecodeAddress(res.Btc, common.BitcoinRegnetParams)

btcTSSAddress, err := common.DecodeBtcAddress(res.Btc, common.BtcRegtestChain().ChainId)
if err != nil {
panic(err)
}
Expand Down
6 changes: 1 addition & 5 deletions x/crosschain/keeper/evm_hooks.go
Original file line number Diff line number Diff line change
Expand Up @@ -289,11 +289,7 @@ func (k Keeper) ParseZRC20WithdrawalEvent(ctx sdk.Context, log ethtypes.Log) (*z
if event.Value.Cmp(big.NewInt(0)) <= 0 {
return nil, fmt.Errorf("ParseZRC20WithdrawalEvent: invalid amount %s", event.Value.String())
}
btcChainParams, err := common.GetBTCChainParams(chainID)
if err != nil {
return nil, err
}
addr, err := btcutil.DecodeAddress(string(event.To), btcChainParams)
addr, err := common.DecodeBtcAddress(string(event.To), chainID)
if err != nil {
return nil, fmt.Errorf("ParseZRC20WithdrawalEvent: invalid address %s: %s", event.To, err)
}
Expand Down
6 changes: 1 addition & 5 deletions zetaclient/bitcoin_client.go
Original file line number Diff line number Diff line change
Expand Up @@ -758,11 +758,7 @@ func (ob *BitcoinChainClient) FetchUTXOS() error {

// List unspent.
tssAddr := ob.Tss.BTCAddress()
bitcoinNetParams, err := common.BitcoinNetParamsFromChainID(ob.chain.ChainId)
if err != nil {
return fmt.Errorf("btc: error getting bitcoin net params : %v", err)
}
address, err := btcutil.DecodeAddress(tssAddr, bitcoinNetParams)
address, err := common.DecodeBtcAddress(tssAddr, ob.chain.ChainId)
if err != nil {
return fmt.Errorf("btc: error decoding wallet address (%s) : %s", tssAddr, err.Error())
}
Expand Down
3 changes: 1 addition & 2 deletions zetaclient/btc_signer.go
Original file line number Diff line number Diff line change
Expand Up @@ -301,8 +301,7 @@ func (signer *BTCSigner) TryProcessOutTx(
logger.Error().Err(err).Msgf("cannot get bitcoin net params%v", err)
return
}

addr, err := btcutil.DecodeAddress(params.Receiver, bitcoinNetParams)
addr, err := common.DecodeBtcAddress(params.Receiver, params.ReceiverChainId)
if err != nil {
logger.Error().Err(err).Msgf("cannot decode address %s ", params.Receiver)
return
Expand Down

0 comments on commit 0642dbb

Please sign in to comment.