Skip to content

Commit

Permalink
support pubkey addresses. better clone config
Browse files Browse the repository at this point in the history
  • Loading branch information
buck54321 committed Jan 29, 2021
1 parent 59fe5cf commit b3a701d
Show file tree
Hide file tree
Showing 4 changed files with 93 additions and 44 deletions.
1 change: 1 addition & 0 deletions client/asset/btc/btc.go
Original file line number Diff line number Diff line change
Expand Up @@ -160,6 +160,7 @@ type RPCClient interface {
Disconnected() bool
}

// TxInSigner generates a signature for a transaction input.
type TxInSigner func(tx *wire.MsgTx, idx int, subScript []byte, hashType txscript.SigHashType, key *btcec.PrivateKey, val uint64) ([]byte, error)

// BTCCloneCFG holds clone specific parameters.
Expand Down
19 changes: 14 additions & 5 deletions dex/networks/bch/cashaddr.go
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,8 @@ func RecodeCashAddress(addr string, net *chaincfg.Params) (string, error) {
bchAddr, err = bchutil.NewAddressPubKeyHash(btcAddr.ScriptAddress(), convertParams(net))
case *btcutil.AddressScriptHash:
bchAddr, err = bchutil.NewAddressScriptHashFromHash(btcAddr.ScriptAddress(), convertParams(net))
// case *btcutil.AddressPubKey: // Do we need?
case *btcutil.AddressPubKey:
bchAddr, err = bchutil.NewAddressPubKey(btcAddr.ScriptAddress(), convertParams(net))
default:
return "", fmt.Errorf("unsupported address type %T", at)
}
Expand All @@ -47,11 +48,14 @@ func DecodeCashAddress(addr string, net *chaincfg.Params) (btcutil.Address, erro
}

switch at := bchAddr.(type) {
case *bchutil.AddressPubKeyHash:
// From what I can tell, the legacy address formats are probably
// unnecessary, but I'd hate to be wrong.
case *bchutil.AddressPubKeyHash, *bchutil.LegacyAddressPubKeyHash:
return btcutil.NewAddressPubKeyHash(bchAddr.ScriptAddress(), net)
case *bchutil.AddressScriptHash:
case *bchutil.AddressScriptHash, *bchutil.LegacyAddressScriptHash:
return btcutil.NewAddressScriptHashFromHash(bchAddr.ScriptAddress(), net)
// case *btcutil.AddressPubKey: // Do we need?
case *bchutil.AddressPubKey:
return btcutil.NewAddressPubKey(bchAddr.ScriptAddress(), net)
default:
return nil, fmt.Errorf("unsupported address type %T", at)
}
Expand All @@ -73,5 +77,10 @@ func convertParams(btcParams *chaincfg.Params) *bchchaincfg.Params {
// withPrefix adds the Bech32 prefix to the bchutil.Address, since the stringers
// don't, for some reason.
func withPrefix(bchAddr bchutil.Address, net *chaincfg.Params) string {
return net.Bech32HRPSegwit + ":" + bchAddr.String()
switch bchAddr.(type) {
case *bchutil.AddressPubKeyHash, *bchutil.AddressScriptHash:
return net.Bech32HRPSegwit + ":" + bchAddr.String()
}
// Must be a pubkey address, which gets no prefix.
return bchAddr.String()
}
90 changes: 64 additions & 26 deletions dex/networks/bch/cashaddr_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ import (
"testing"

"decred.org/dcrdex/dex/encode"
"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil"
"github.com/gcash/bchutil"
Expand All @@ -19,46 +20,83 @@ func TestCashAddr(t *testing.T) {
highB[i] = 255
}

lowPubKey := make([]byte, 33)
lowPubKey[0] = 2
lowPubKey[32] = 1

checkHash := func(net *chaincfg.Params, h []byte) {
t.Helper()
var bchAddr bchutil.Address
bchAddr, err := bchutil.NewAddressPubKeyHash(h, convertParams(net))
if err != nil {
t.Fatalf("bchutil.AddressScriptHash error: %v", err)
}
testRoundTripFromBCH(t, withPrefix(bchAddr, net), net)

bchAddr, err = bchutil.NewAddressScriptHashFromHash(h, convertParams(net))
if err != nil {
t.Fatalf("bchutil.AddressScriptHash error: %v", err)
switch len(h) {
case 20:
var bchAddr bchutil.Address
bchAddr, err := bchutil.NewAddressPubKeyHash(h, convertParams(net))
if err != nil {
t.Fatalf("bchutil.AddressScriptHash error: %v", err)
}
testRoundTripFromBCH(t, withPrefix(bchAddr, net), net)

bchAddr, err = bchutil.NewAddressScriptHashFromHash(h, convertParams(net))
if err != nil {
t.Fatalf("bchutil.AddressScriptHash error: %v", err)
}
testRoundTripFromBCH(t, withPrefix(bchAddr, net), net)

var btcAddr btcutil.Address
btcAddr, err = btcutil.NewAddressPubKeyHash(h, net)
if err != nil {
t.Fatalf("btcutil.NewAddressPubkeyHash error: %v", err)
}

testRoundTripFromBTC(t, btcAddr.String(), net)

btcAddr, err = btcutil.NewAddressScriptHashFromHash(h, net)
if err != nil {
t.Fatalf("btcutil.NewAddressPubkeyHash error: %v", err)
}
testRoundTripFromBTC(t, btcAddr.String(), net)

case 33, 65: // See btcec.PubKeyBytesLen(Un)Compressed
var bchAddr bchutil.Address
bchAddr, err := bchutil.NewAddressPubKey(h, convertParams(net))
if err != nil {
t.Fatalf("bchutil.NewAddressPubKey error: %v", err)
}
testRoundTripFromBCH(t, withPrefix(bchAddr, net), net)

var btcAddr btcutil.Address
btcAddr, err = btcutil.NewAddressPubKey(h, net)
if err != nil {
t.Fatalf("btcutil.NewAddressPubKey error: %v", err)
}

testRoundTripFromBTC(t, btcAddr.String(), net)

default:
t.Fatalf("unknown address data length %d", len(h))
}
testRoundTripFromBCH(t, withPrefix(bchAddr, net), net)

var btcAddr btcutil.Address
btcAddr, err = btcutil.NewAddressPubKeyHash(h, net)
if err != nil {
t.Fatalf("btcutil.NewAddressPubkeyHash error: %v", err)
}

testRoundTripFromBTC(t, btcAddr.String(), net)

btcAddr, err = btcutil.NewAddressScriptHashFromHash(h, net)
if err != nil {
t.Fatalf("btcutil.NewAddressPubkeyHash error: %v", err)
}
testRoundTripFromBTC(t, btcAddr.String(), net)
}

nets := []*chaincfg.Params{MainNetParams, TestNet3Params, RegressionNetParams}
for _, net := range nets {
// Check the lowest and highest possible hashes.
for _, h := range [][]byte{lowB, highB} {
checkHash(net, h)
}
checkHash(net, lowB)
checkHash(net, highB)
// Check a bunch of random addresses.
for i := 0; i < 1000; i++ {
checkHash(net, encode.RandomBytes(20))
}
// Check Pubkey addresses. These just encode to the hex encoding of the
// serialized pubkey for both bch and btc, so there's little that can go
// wrong.
checkHash(net, lowPubKey)
for i := 0; i < 100; i++ {
_, pubKey := btcec.PrivKeyFromBytes(btcec.S256(), encode.RandomBytes(33))
checkHash(net, pubKey.SerializeUncompressed())
checkHash(net, pubKey.SerializeCompressed())
}

}
}

Expand Down
27 changes: 14 additions & 13 deletions dex/networks/bch/params.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,37 +6,38 @@ package bch
import (
"decred.org/dcrdex/dex/networks/btc"
"github.com/btcsuite/btcd/chaincfg"
bchchaincfg "github.com/gcash/bchd/chaincfg"
)

var (
// MainNetParams are the clone parameters for mainnet.
MainNetParams = btc.ReadCloneParams(&btc.CloneParams{
PubKeyHashAddrID: 0x00,
ScriptHashAddrID: 0x05,
PubKeyHashAddrID: bchchaincfg.MainNetParams.LegacyPubKeyHashAddrID,
ScriptHashAddrID: bchchaincfg.MainNetParams.LegacyScriptHashAddrID,
Bech32HRPSegwit: "bitcoincash",
CoinbaseMaturity: 100,
Net: 0xe8f3e1e3,
// BitcoinCash didn't change any of these net identifiers, so these are
// all spoofed. The only place we currently use Net is in
// btcd/chaincfg.Register, where it is checked to prevent duplicate
// registration, so our only requirement is that it is unique. This one
// was just generated with a prng.
Net: 0xe8f3e1e3,
})
// TestNet3Params are the clone parameters for testnet.
TestNet3Params = btc.ReadCloneParams(&btc.CloneParams{
PubKeyHashAddrID: 0x6f,
ScriptHashAddrID: 0xc4,
PubKeyHashAddrID: bchchaincfg.TestNet3Params.LegacyPubKeyHashAddrID,
ScriptHashAddrID: bchchaincfg.TestNet3Params.LegacyScriptHashAddrID,
Bech32HRPSegwit: "bchtest",
CoinbaseMaturity: 100,
Net: 0xf4f3e5f4,
})
// RegressionNetParams are the clone parameters for simnet.
RegressionNetParams = btc.ReadCloneParams(&btc.CloneParams{
PubKeyHashAddrID: 0x6f,
ScriptHashAddrID: 0xc4,
PubKeyHashAddrID: bchchaincfg.RegressionNetParams.LegacyPubKeyHashAddrID,
ScriptHashAddrID: bchchaincfg.RegressionNetParams.LegacyScriptHashAddrID,
Bech32HRPSegwit: "bchreg",
CoinbaseMaturity: 100,
// Net is not the standard for BCH simnet, since they never changed it
// from the BTC value. The only place we currently use Net is in
// btcd/chaincfg.Register, where it is checked to prevent duplicate
// registration, so our only requirement is that it is unique. This one
// was just generated with a prng.
Net: 0xee87f733,
Net: 0xee87f733,
})
)

Expand Down

0 comments on commit b3a701d

Please sign in to comment.