Skip to content

Commit

Permalink
Merge pull request #21 from renproject/hotfix/bch-legacy-addr
Browse files Browse the repository at this point in the history
Add legacy bitcoin address support
  • Loading branch information
Nadimpalli Susruth authored Nov 8, 2019
2 parents ddf1a69 + 209ac50 commit 6267e7e
Show file tree
Hide file tree
Showing 3 changed files with 93 additions and 0 deletions.
57 changes: 57 additions & 0 deletions testutil/btcaccount/btcaccount_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,63 @@ var _ = Describe("btc account", func() {
fmt.Println("txHash: ", txHash[:])
})

It("should be able to transfer funds to itself (legacy address)", func() {
// Get the account with actual balance
client := btcclient.NewClient(logger, btctypes.BchLocalnet)
wallet, err := testutil.LoadHdWalletFromEnv("BCH_TEST_MNEMONIC", "BCH_TEST_PASSPHRASE", client.Network())
Expect(err).NotTo(HaveOccurred())
key, err := wallet.EcdsaKey(44, 1, 0, 0, 2)
Expect(err).NotTo(HaveOccurred())
account, err := NewAccount(client, key)
Expect(err).NotTo(HaveOccurred())
fmt.Println("from address: ", account.Address().EncodeAddress())

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

utxos, err := account.UTXOs(ctx)
Expect(err).NotTo(HaveOccurred())
Expect(len(utxos)).Should(BeNumerically(">", 0))

// Build the transaction
toAddress, err := btctypes.AddressFromPubKey(key.PublicKey, btctypes.BtcLocalnet)
Expect(err).NotTo(HaveOccurred())
amount := 50000 * btctypes.SAT
fmt.Println("to address: ", toAddress.EncodeAddress())

txHash, err := account.Transfer(ctx, toAddress, amount, types.Standard, true)
Expect(err).NotTo(HaveOccurred())
fmt.Println("txHash: ", txHash[:])
})

It("should be able to transfer funds to itself (cash address)", func() {
// Get the account with actual balance
client := btcclient.NewClient(logger, btctypes.BchLocalnet)
wallet, err := testutil.LoadHdWalletFromEnv("BCH_TEST_MNEMONIC", "BCH_TEST_PASSPHRASE", client.Network())
Expect(err).NotTo(HaveOccurred())
key, err := wallet.EcdsaKey(44, 1, 0, 0, 2)
Expect(err).NotTo(HaveOccurred())
account, err := NewAccount(client, key)
Expect(err).NotTo(HaveOccurred())
fmt.Println("from address: ", account.Address().EncodeAddress())

ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
defer cancel()

utxos, err := account.UTXOs(ctx)
Expect(err).NotTo(HaveOccurred())
Expect(len(utxos)).Should(BeNumerically(">", 0))

// Build the transaction
toAddress := account.Address()
amount := 50000 * btctypes.SAT
fmt.Println("to address: ", toAddress.EncodeAddress())

txHash, err := account.Transfer(ctx, toAddress, amount, types.Standard, true)
Expect(err).NotTo(HaveOccurred())
fmt.Println("txHash: ", txHash[:])
})

It("should be able to transfer funds to itself", func() {
// Get the account with actual balance
client := btcclient.NewClient(logger, btctypes.ZecLocalnet)
Expand Down
14 changes: 14 additions & 0 deletions types/btctypes/bch/bch.go
Original file line number Diff line number Diff line change
Expand Up @@ -167,6 +167,18 @@ func AppendChecksum(prefix string, payload []byte) []byte {
}

func DecodeAddress(addr string, params *chaincfg.Params) (btcutil.Address, error) {
// Legacy address decoding
if address, err := btcutil.DecodeAddress(addr, params); err == nil {
switch address.(type) {
case *btcutil.AddressPubKeyHash, *btcutil.AddressScriptHash, *btcutil.AddressPubKey:
return address, nil
case *btcutil.AddressWitnessPubKeyHash, *btcutil.AddressWitnessScriptHash:
return nil, fmt.Errorf("bitcoin cash does not support SegWit addresses")
default:
return nil, fmt.Errorf("unsuported legacy bitcoin address type: %T", address)
}
}

if addrParts := strings.Split(addr, ":"); len(addrParts) != 1 {
addr = addrParts[1]
}
Expand Down Expand Up @@ -210,6 +222,8 @@ func PayToAddrScript(addr btcutil.Address) ([]byte, error) {
case *P2SHAddress:
return txscript.NewScriptBuilder().AddOp(txscript.OP_HASH160).AddData(addr.scriptHash).
AddOp(txscript.OP_EQUAL).Script()
case *btcutil.AddressPubKeyHash, *btcutil.AddressScriptHash, *btcutil.AddressPubKey:
return txscript.PayToAddrScript(addr)
default:
return nil, fmt.Errorf("unsupported address type %T", addr)
}
Expand Down
22 changes: 22 additions & 0 deletions types/btctypes/btctypes_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,28 @@ var _ = Describe("btc types", func() {
})
})

Context("bitcoin cash address", func() {
It("should decode the legacy addresses correctly", func() {
laddr, err := testutil.RandomAddress(BtcTestnet)
Expect(err).Should(BeNil())
addr, err := AddressFromBase58(laddr.EncodeAddress(), BchTestnet)
Expect(err).Should(BeNil())
Expect(addr.String()).Should(Equal(laddr.EncodeAddress()))
})

It("should decode the cash addresses (with prefix) correctly", func() {
addr, err := AddressFromBase58("bchtest:qrch9dvf9rc45p728n7d8p4r7n067jrdxgjyklgcg6", BchTestnet)
Expect(err).Should(BeNil())
Expect(addr.String()).Should(Equal("qrch9dvf9rc45p728n7d8p4r7n067jrdxgjyklgcg6"))
})

It("should decode the cash addresses (without prefix) correctly", func() {
addr, err := AddressFromBase58("qrch9dvf9rc45p728n7d8p4r7n067jrdxgjyklgcg6", BchTestnet)
Expect(err).Should(BeNil())
Expect(addr.String()).Should(Equal("qrch9dvf9rc45p728n7d8p4r7n067jrdxgjyklgcg6"))
})
})

Context("bitcoin networks", func() {
It("should be able to parse network from a string", func() {
testnet := "testnet"
Expand Down

0 comments on commit 6267e7e

Please sign in to comment.