Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: support Bitcoin P2TR, P2WSH, P2SH, P2PKH address types #1982

Merged
merged 29 commits into from
Apr 4, 2024
Merged
Changes from 1 commit
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
18c7196
backport/add a AddressTaproot type that satisfies btcutil.Address int…
brewmaster012 Mar 6, 2024
f78eb47
support taproot in DecodeBtcAddress
brewmaster012 Mar 6, 2024
0c167cd
minor tweak
brewmaster012 Mar 6, 2024
8252ca3
Merge branch 'develop' into feat-support-taproot
ws4charlie Mar 13, 2024
b0b2d74
Merge branch 'develop' into feat-support-taproot
ws4charlie Mar 21, 2024
a60375c
Merge branch 'develop' into feat-support-taproot
ws4charlie Mar 22, 2024
c2dfb7a
initial commit to support different types of BTC addresses
ws4charlie Mar 22, 2024
738d265
added decoding for more intx types
ws4charlie Mar 22, 2024
291322b
added btc intx address decoding and tests
ws4charlie Mar 24, 2024
18fc62f
fix compile error
ws4charlie Mar 25, 2024
50db809
Merge branch 'v16.0.0' of https://github.com/zeta-chain/node into fea…
ws4charlie Mar 25, 2024
76b6817
adjusted btc outtx size and withdrawer fee
ws4charlie Mar 26, 2024
c338d41
added changelog entry
ws4charlie Mar 26, 2024
31a0dfe
fix unit tests
ws4charlie Mar 26, 2024
82527b5
added e2e tests for different types of bitcoin addresses
ws4charlie Mar 26, 2024
d2935b9
try retriggering CI
lumtis Mar 27, 2024
bc02fb7
e2e tests all PR
lumtis Mar 27, 2024
2bcdfbc
resolved some PR review feedback
ws4charlie Mar 28, 2024
edc9be6
removed panic from test method LoadObjectFromJSONFile
ws4charlie Mar 28, 2024
f02cc52
improved function and added comments
ws4charlie Mar 28, 2024
e7c4c60
feat: add metric for concurrent key signs (#1960)
kevinssgh Mar 28, 2024
a341da9
Merge branch 'v16.0.0' into feat-support-taproot
ws4charlie Mar 29, 2024
e0f0196
merge develop branch into feat-support-taproot and resolve conflicts
ws4charlie Apr 3, 2024
11bd7ea
Merge branch 'develop' into feat-support-taproot
ws4charlie Apr 3, 2024
d911f67
added live test for intx sender address parsing
ws4charlie Apr 3, 2024
cea2885
fix CI unit test failure
ws4charlie Apr 3, 2024
268803c
updated changelog
ws4charlie Apr 3, 2024
1815f13
format testdata and clean up empty lines
ws4charlie Apr 3, 2024
b15de98
merge develop branch and resolve conflict
ws4charlie Apr 4, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Prev Previous commit
Next Next commit
added e2e tests for different types of bitcoin addresses
  • Loading branch information
ws4charlie committed Mar 26, 2024
commit 82527b5759aba15f869c43d418f559fc9067a602
6 changes: 5 additions & 1 deletion cmd/zetae2e/local/local.go
Original file line number Diff line number Diff line change
@@ -250,7 +250,11 @@ func localE2ETest(cmd *cobra.Command, _ []string) {
e2etests.TestZetaDepositRestrictedName,
}
bitcoinTests := []string{
e2etests.TestBitcoinWithdrawName,
e2etests.TestBitcoinWithdrawSegWitName,
e2etests.TestBitcoinWithdrawTaprootName,
e2etests.TestBitcoinWithdrawLegacyName,
e2etests.TestBitcoinWithdrawP2SHName,
e2etests.TestBitcoinWithdrawP2WSHName,
e2etests.TestBitcoinWithdrawInvalidAddressName,
e2etests.TestZetaWithdrawBTCRevertName,
e2etests.TestCrosschainSwapName,
53 changes: 47 additions & 6 deletions e2e/e2etests/e2etests.go
Original file line number Diff line number Diff line change
@@ -15,7 +15,11 @@ const (
TestZetaWithdrawBTCRevertName = "zeta_withdraw_btc_revert" // #nosec G101 - not a hardcoded password
TestMessagePassingName = "message_passing"
TestZRC20SwapName = "zrc20_swap"
TestBitcoinWithdrawName = "bitcoin_withdraw"
TestBitcoinWithdrawSegWitName = "bitcoin_withdraw_segwit"
TestBitcoinWithdrawTaprootName = "bitcoin_withdraw_taproot"
TestBitcoinWithdrawLegacyName = "bitcoin_withdraw_legacy"
TestBitcoinWithdrawP2WSHName = "bitcoin_withdraw_p2wsh"
TestBitcoinWithdrawP2SHName = "bitcoin_withdraw_p2sh"
TestBitcoinWithdrawInvalidAddressName = "bitcoin_withdraw_invalid"
TestBitcoinWithdrawRestrictedName = "bitcoin_withdraw_restricted"
TestCrosschainSwapName = "crosschain_swap"
@@ -130,12 +134,49 @@ var AllE2ETests = []runner.E2ETest{
TestZRC20Swap,
),
runner.NewE2ETest(
TestBitcoinWithdrawName,
"withdraw BTC from ZEVM",
TestBitcoinWithdrawSegWitName,
"withdraw BTC from ZEVM to a SegWit address",
[]runner.ArgDefinition{
runner.ArgDefinition{Description: "amount in btc", DefaultValue: "0.01"},
runner.ArgDefinition{Description: "receiver address", DefaultValue: ""},
runner.ArgDefinition{Description: "amount in btc", DefaultValue: "0.001"},
},
TestBitcoinWithdrawSegWit,
),
runner.NewE2ETest(
TestBitcoinWithdrawTaprootName,
"withdraw BTC from ZEVM to a Taproot address",
[]runner.ArgDefinition{
runner.ArgDefinition{Description: "receiver address", DefaultValue: ""},
runner.ArgDefinition{Description: "amount in btc", DefaultValue: "0.001"},
},
TestBitcoinWithdrawTaproot,
),
runner.NewE2ETest(
TestBitcoinWithdrawLegacyName,
"withdraw BTC from ZEVM to a legacy address",
[]runner.ArgDefinition{
runner.ArgDefinition{Description: "receiver address", DefaultValue: ""},
runner.ArgDefinition{Description: "amount in btc", DefaultValue: "0.001"},
},
TestBitcoinWithdraw,
TestBitcoinWithdrawLegacy,
),
runner.NewE2ETest(
TestBitcoinWithdrawP2WSHName,
"withdraw BTC from ZEVM to a P2WSH address",
[]runner.ArgDefinition{
runner.ArgDefinition{Description: "receiver address", DefaultValue: ""},
runner.ArgDefinition{Description: "amount in btc", DefaultValue: "0.001"},
},
TestBitcoinWithdrawP2WSH,
),
runner.NewE2ETest(
TestBitcoinWithdrawP2SHName,
"withdraw BTC from ZEVM to a P2SH address",
[]runner.ArgDefinition{
runner.ArgDefinition{Description: "receiver address", DefaultValue: ""},
runner.ArgDefinition{Description: "amount in btc", DefaultValue: "0.001"},
},
TestBitcoinWithdrawP2SH,
),
runner.NewE2ETest(
TestBitcoinWithdrawInvalidAddressName,
@@ -311,7 +352,7 @@ var AllE2ETests = []runner.E2ETest{
TestBitcoinWithdrawRestrictedName,
"withdraw Bitcoin from ZEVM to restricted address",
[]runner.ArgDefinition{
runner.ArgDefinition{Description: "amount in btc", DefaultValue: "0.01"},
runner.ArgDefinition{Description: "amount in btc", DefaultValue: "0.001"},
},
TestBitcoinWithdrawRestricted,
),
126 changes: 113 additions & 13 deletions e2e/e2etests/test_bitcoin_withdraw.go
Original file line number Diff line number Diff line change
@@ -9,30 +9,100 @@ import (
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcutil"
"github.com/zeta-chain/zetacore/common"
"github.com/zeta-chain/zetacore/common/bitcoin"
"github.com/zeta-chain/zetacore/e2e/runner"
"github.com/zeta-chain/zetacore/e2e/utils"
"github.com/zeta-chain/zetacore/zetaclient/testutils"
)

func TestBitcoinWithdraw(r *runner.E2ERunner, args []string) {
if len(args) != 1 {
panic("TestBitcoinWithdraw requires exactly one argument for the amount.")
func TestBitcoinWithdrawSegWit(r *runner.E2ERunner, args []string) {
// check length of arguments
if len(args) != 2 {
panic("TestBitcoinWithdrawSegWit requires two arguments: [receiver, amount]")
}
r.SetBtcAddress(r.Name, false)

withdrawalAmount, err := strconv.ParseFloat(args[0], 64)
if err != nil {
panic("Invalid withdrawal amount specified for TestBitcoinWithdraw.")
// parse arguments
defaultReceiver := r.BTCDeployerAddress.EncodeAddress()
receiver, amount := parseBitcoinWithdrawArgs(args, defaultReceiver)
_, ok := receiver.(*btcutil.AddressWitnessPubKeyHash)
if !ok {
panic("Invalid receiver address specified for TestBitcoinWithdrawSegWit.")
}

withdrawalAmountSat, err := btcutil.NewAmount(withdrawalAmount)
if err != nil {
panic(err)
WithdrawBitcoin(r, receiver, amount)
}

func TestBitcoinWithdrawTaproot(r *runner.E2ERunner, args []string) {
// check length of arguments
if len(args) != 2 {
panic("TestBitcoinWithdrawTaproot requires two arguments: [receiver, amount]")
}
amount := big.NewInt(int64(withdrawalAmountSat))
r.SetBtcAddress(r.Name, false)

// parse arguments and withdraw BTC
defaultReceiver := "bcrt1pqqqsyqcyq5rqwzqfpg9scrgwpugpzysnzs23v9ccrydpk8qarc0sj9hjuh"
receiver, amount := parseBitcoinWithdrawArgs(args, defaultReceiver)
_, ok := receiver.(*bitcoin.AddressTaproot)
if !ok {
panic("Invalid receiver address specified for TestBitcoinWithdrawTaproot.")
}

WithdrawBitcoin(r, receiver, amount)
}

func TestBitcoinWithdrawLegacy(r *runner.E2ERunner, args []string) {
// check length of arguments
if len(args) != 2 {
panic("TestBitcoinWithdrawLegacy requires two arguments: [receiver, amount]")
}
r.SetBtcAddress(r.Name, false)

WithdrawBitcoin(r, amount)
// parse arguments and withdraw BTC
defaultReceiver := "mxpYha3UJKUgSwsAz2qYRqaDSwAkKZ3YEY"
receiver, amount := parseBitcoinWithdrawArgs(args, defaultReceiver)
_, ok := receiver.(*btcutil.AddressPubKeyHash)
if !ok {
panic("Invalid receiver address specified for TestBitcoinWithdrawLegacy.")
}

WithdrawBitcoin(r, receiver, amount)
}

func TestBitcoinWithdrawP2WSH(r *runner.E2ERunner, args []string) {
// check length of arguments
if len(args) != 2 {
panic("TestBitcoinWithdrawP2WSH requires two arguments: [receiver, amount]")
}
r.SetBtcAddress(r.Name, false)

// parse arguments and withdraw BTC
defaultReceiver := "bcrt1qm9mzhyky4w853ft2ms6dtqdyyu3z2tmrq8jg8xglhyuv0dsxzmgs2f0sqy"
receiver, amount := parseBitcoinWithdrawArgs(args, defaultReceiver)
_, ok := receiver.(*btcutil.AddressWitnessScriptHash)
if !ok {
panic("Invalid receiver address specified for TestBitcoinWithdrawP2WSH.")
}

WithdrawBitcoin(r, receiver, amount)
}

func TestBitcoinWithdrawP2SH(r *runner.E2ERunner, args []string) {
// check length of arguments
if len(args) != 2 {
panic("TestBitcoinWithdrawP2SH requires two arguments: [receiver, amount]")
}
r.SetBtcAddress(r.Name, false)

// parse arguments and withdraw BTC
defaultReceiver := "2N6AoUj3KPS7wNGZXuCckh8YEWcSYNsGbqd"
receiver, amount := parseBitcoinWithdrawArgs(args, defaultReceiver)
_, ok := receiver.(*btcutil.AddressScriptHash)
if !ok {
panic("Invalid receiver address specified for TestBitcoinWithdrawP2SH.")
}

WithdrawBitcoin(r, receiver, amount)
}

func TestBitcoinWithdrawRestricted(r *runner.E2ERunner, args []string) {
@@ -56,6 +126,36 @@ func TestBitcoinWithdrawRestricted(r *runner.E2ERunner, args []string) {
WithdrawBitcoinRestricted(r, amount)
}

func parseBitcoinWithdrawArgs(args []string, defaultReceiver string) (btcutil.Address, *big.Int) {
// parse receiver address
var err error
var receiver btcutil.Address
if args[0] == "" {
// use the default receiver
receiver, err = common.DecodeBtcAddress(defaultReceiver, common.BtcRegtestChain().ChainId)
if err != nil {
panic("Invalid default receiver address specified for TestBitcoinWithdraw.")
}
} else {
receiver, err = common.DecodeBtcAddress(args[0], common.BtcRegtestChain().ChainId)
if err != nil {
panic("Invalid receiver address specified for TestBitcoinWithdraw.")
}
}
// parse the withdrawal amount
withdrawalAmount, err := strconv.ParseFloat(args[1], 64)
if err != nil {
panic("Invalid withdrawal amount specified for TestBitcoinWithdraw.")
}
withdrawalAmountSat, err := btcutil.NewAmount(withdrawalAmount)
if err != nil {
panic(err)
}
amount := big.NewInt(int64(withdrawalAmountSat))

return receiver, amount
}

func withdrawBTCZRC20(r *runner.E2ERunner, to btcutil.Address, amount *big.Int) *btcjson.TxRawResult {
tx, err := r.BTCZRC20.Approve(r.ZEVMAuth, r.BTCZRC20Addr, big.NewInt(amount.Int64()*2)) // approve more to cover withdraw fee
if err != nil {
@@ -116,8 +216,8 @@ func withdrawBTCZRC20(r *runner.E2ERunner, to btcutil.Address, amount *big.Int)
return rawTx
}

func WithdrawBitcoin(r *runner.E2ERunner, amount *big.Int) {
withdrawBTCZRC20(r, r.BTCDeployerAddress, amount)
func WithdrawBitcoin(r *runner.E2ERunner, receiver btcutil.Address, amount *big.Int) {
withdrawBTCZRC20(r, receiver, amount)
}

func WithdrawBitcoinRestricted(r *runner.E2ERunner, amount *big.Int) {
1 change: 1 addition & 0 deletions e2e/e2etests/test_bitcoin_withdraw_invalid.go
Original file line number Diff line number Diff line change
@@ -48,6 +48,7 @@ func WithdrawToInvalidAddress(r *runner.E2ERunner, amount *big.Int) {
stop := r.MineBlocks()

// withdraw amount provided as test arg BTC from ZRC20 to BTC legacy address
// the address "1EYVvXLusCxtVuEwoYvWRyN5EZTXwPVvo3" is for mainnet, not regtest
tx, err = r.BTCZRC20.Withdraw(r.ZEVMAuth, []byte("1EYVvXLusCxtVuEwoYvWRyN5EZTXwPVvo3"), amount)
if err != nil {
panic(err)