Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
33 changes: 21 additions & 12 deletions address.go
Original file line number Diff line number Diff line change
Expand Up @@ -100,16 +100,16 @@ func DecodeAddress(addr string, defaultNet *chaincfg.Params) (Address, error) {
switch len(decoded) {
case ripemd160.Size: // P2PKH or P2SH
switch typ {
case AddrTypePayToPubKeyHash:
case AddrTypePayToPubKeyHash, AddrTypeTokenPayToPubKeyHash:
return newAddressPubKeyHash(decoded, defaultNet)
case AddrTypePayToScriptHash:
case AddrTypePayToScriptHash, AddrTypeTokenPayToScriptHash:
return newAddressScriptHashFromHash(decoded, defaultNet)
default:
return nil, ErrUnknownAddressType
}
case sha256.Size: // P2SH32
switch typ {
case AddrTypePayToScriptHash32:
case AddrTypePayToScriptHash, AddrTypeTokenPayToScriptHash:
return newAddressScriptHash32FromHash(decoded, defaultNet)
default:
return nil, ErrUnknownAddressType
Expand Down Expand Up @@ -139,7 +139,7 @@ func DecodeAddress(addr string, defaultNet *chaincfg.Params) (Address, error) {
}
case sha256.Size: // P2SH32
switch typ {
case AddrTypePayToScriptHash32:
case AddrTypeTokenPayToScriptHash:
return NewSlpAddressScriptHash32FromHash(decoded, defaultNet)
default:
return nil, ErrUnknownAddressType
Expand Down Expand Up @@ -759,16 +759,21 @@ func checkDecodeCashAddress(input string) (result []byte, prefix string, t Addre
if err != nil {
return data, prefix, AddrTypePayToPubKeyHash, err
}
if len(data) != 21 {
if len(data) != 21 && len(data) != 33 { // version byte + ripemd160.Size or sha256.Size
return data, prefix, AddrTypePayToPubKeyHash, errors.New("incorrect data length")
}
switch data[0] {
case 0x00:

switch data[0] >> 3 { // bits 1 to 4 are the address type.
case 0:
t = AddrTypePayToPubKeyHash
case 0x08:
case 1:
t = AddrTypePayToScriptHash
case 2:
t = AddrTypeTokenPayToPubKeyHash
case 3:
t = AddrTypeTokenPayToScriptHash
}
return data[1:21], prefix, t, nil
return data[1:], prefix, t, nil
}

// AddressType represents the type of address and is used
Expand All @@ -784,9 +789,13 @@ const (
// a cashaddr PayToPubkeyHash address
AddrTypePayToScriptHash AddressType = 1

// AddrTypePayToScriptHash32 is the numeric identifier for
// a cashaddr PayToPubkeyHash address
AddrTypePayToScriptHash32 AddressType = 2
// AddrTypePayToScriptHash is the numeric identifier for
// a token aware cashaddr PayToPubkeyHash address
AddrTypeTokenPayToPubKeyHash AddressType = 2

// AddrTypeTokenPayToScriptHash is the numeric identifier for
// a token aware cashaddr PayToPubkeyHash address
AddrTypeTokenPayToScriptHash AddressType = 3
)

// Charset is the base32 character set for the cashaddr.
Expand Down
82 changes: 82 additions & 0 deletions address_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1017,3 +1017,85 @@ func TestConvertSlpToCashAddressP2sh(t *testing.T) {
t.Fatal("incorrect conversion")
}
}

// Source: https://github.com/cashtokens/cashtokens/blob/master/test-vectors/cashaddr.json
var p2SH32CashAddreTestVectors = []string{
"bitcoincash:qr6m7j9njldwwzlg9v7v53unlr4jkmx6eylep8ekg2",
"bitcoincash:zr6m7j9njldwwzlg9v7v53unlr4jkmx6eycnjehshe",
"bchtest:pr6m7j9njldwwzlg9v7v53unlr4jkmx6eyvwc0uz5t",
"pref:pr6m7j9njldwwzlg9v7v53unlr4jkmx6ey65nvtks5",
"bitcoincash:qr7fzmep8g7h7ymfxy74lgc0v950j3r2959lhtxxsl",
"bitcoincash:zr7fzmep8g7h7ymfxy74lgc0v950j3r295z4y4gq0v",
"bchtest:qr7fzmep8g7h7ymfxy74lgc0v950j3r295pdnvy3hr",
"bchtest:zr7fzmep8g7h7ymfxy74lgc0v950j3r295x8qj2hgs",
"bchreg:qr7fzmep8g7h7ymfxy74lgc0v950j3r295m39d8z59",
"bchreg:zr7fzmep8g7h7ymfxy74lgc0v950j3r295umknfytk",
"prefix:qr7fzmep8g7h7ymfxy74lgc0v950j3r295fu6e430r",
"prefix:zr7fzmep8g7h7ymfxy74lgc0v950j3r295wkf8mhss",
"bitcoincash:qpagr634w55t4wp56ftxx53xukhqgl24yse53qxdge",
"bitcoincash:zpagr634w55t4wp56ftxx53xukhqgl24ys77z7gth2",
"bitcoincash:qq9l9e2dgkx0hp43qm3c3h252e9euugrfc6vlt3r9e",
"bitcoincash:zq9l9e2dgkx0hp43qm3c3h252e9euugrfcaxv4l962",
"bitcoincash:qre24q38ghy6k3pegpyvtxahu8q8hqmxmqqn28z85p",
"bitcoincash:zre24q38ghy6k3pegpyvtxahu8q8hqmxmq8eeevptj",
"bitcoincash:qz7xc0vl85nck65ffrsx5wvewjznp9lflgktxc5878",
"bitcoincash:zz7xc0vl85nck65ffrsx5wvewjznp9lflg3p4x6pp5",
"bitcoincash:ppawqn2h74a4t50phuza84kdp3794pq3ccvm92p8sh",
"bitcoincash:rpawqn2h74a4t50phuza84kdp3794pq3cct3k50p0y",
"bitcoincash:pqv53dwyatxse2xh7nnlqhyr6ryjgfdtagkd4vc388",
"bitcoincash:rqv53dwyatxse2xh7nnlqhyr6ryjgfdtag38xjkhc5",
"bitcoincash:prseh0a4aejjcewhc665wjqhppgwrz2lw5txgn666a",
"bitcoincash:rrseh0a4aejjcewhc665wjqhppgwrz2lw5vvmd5u9w",
"bitcoincash:pzltaslh7xnrsxeqm7qtvh0v53n3gfk0v5wwf6d7j4",
"bitcoincash:rzltaslh7xnrsxeqm7qtvh0v53n3gfk0v5fy6yrcdx",
"bitcoincash:pvqqqqqqqqqqqqqqqqqqqqqqzg69v7ysqqqqqqqqqqqqqqqqqqqqqpkp7fqn0",
"bitcoincash:rvqqqqqqqqqqqqqqqqqqqqqqzg69v7ysqqqqqqqqqqqqqqqqqqqqqn9alsp2y",
"bitcoincash:pdzyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3jh2p5nn",
"bitcoincash:rdzyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygrpttc42c",
"bitcoincash:pwyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygsh3sujgcr",
"bitcoincash:rwyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zyg3zygs9zvatfpg",
"bitcoincash:p0xvenxvenxvenxvenxvenxvenxvenxvenxvenxvenxvenxvenxvcm6gz4t77",
"bitcoincash:r0xvenxvenxvenxvenxvenxvenxvenxvenxvenxvenxvenxvenxvcff5rv284",
"bitcoincash:p0llllllllllllllllllllllllllllllllllllllllllllllllll7x3vthu35",
"bitcoincash:r0llllllllllllllllllllllllllllllllllllllllllllllllll75zs2wagl",
"bchtest:pvch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxq7fqng6m6",
"pref:pvch8mmxy0rtfrlarg7ucrxxfzds5pamg73h7370aa87d80gyhqxq4k9m7qf9",
}

func TestP2SH32CashAddreTestVectors(t *testing.T) {
for _, s := range p2SH32CashAddreTestVectors {
result := strings.Split(s, ":")
params := &chaincfg.MainNetParams
switch result[0] {
case "bchtest":
params = &chaincfg.TestNet4Params
case "bchreg":
params = &chaincfg.RegressionNetParams
case "prefix", "pref":
continue

}
_, err := bchutil.DecodeAddress(s, params)
if err != nil {
t.Error(err)
}
}
}

var invalidAddreTestVectors = []string{
"bitcoincash:prseh0a4aejjcewhc665wjqhppgwrz2lw5txgn676a",
"bitcoincash:rrseh0a4aejjcewhc665wjqhppgwrz2lw5vVmd5u9w",
"bitcoincash:izltaslh7xnrsxeqm7qtvh0v53n3gfk0v5wwf6d7j4",
"bitcoincash:pvqqqqqqqqqqqqqqqqqqqqqqqqqqqqzg69v7ysqqqqqqqqqqqqqqqqqqqqqpkp7fqn0",
"bitcoincash:rv0qqqqqqqqqqqqqqqqqqqqqqzg69v7ysqqqqqqqqqqqqqqqqqqqqqn9alsp2y",
}

func TestInvalidCashAddressTestVectors(t *testing.T) {
for _, s := range invalidAddreTestVectors {
params := &chaincfg.MainNetParams
_, err := bchutil.DecodeAddress(s, params)
if err == nil {
t.Fatalf("Failed to error on invalid address string: %s", s)
}
}
}