-
Notifications
You must be signed in to change notification settings - Fork 0
/
btcaddr.go
127 lines (104 loc) · 2.89 KB
/
btcaddr.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
package addrutils
import (
"github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcutil"
"github.com/btcsuite/btcutil/base58"
"golang.org/x/crypto/ripemd160"
)
func BtcAddressFromCheckBytes(bCheckAddr []byte) (btcutil.Address, error) {
decoded, netID, err := DecodeCheckAddrBytes(bCheckAddr)
if err != nil {
return nil, err
}
switch len(decoded) {
case ripemd160.Size:
isP2PKH := chaincfg.IsPubKeyHashAddrID(netID)
isP2SH := chaincfg.IsScriptHashAddrID(netID)
switch hash160 := decoded; {
case isP2PKH && isP2SH:
return nil, btcutil.ErrAddressCollision
case isP2PKH:
return newAddressPubKeyHash(hash160, netID)
case isP2SH:
return newAddressScriptHashFromHash(hash160, netID)
default:
return nil, btcutil.ErrUnknownAddressType
}
default:
return nil, ErrHash160Size
}
}
func StrBtcAddrToCheckBytes(addr string) (checkBytes []byte, err error) {
decoded := base58.Decode(addr)
if len(decoded) < 5 {
return nil, base58.ErrInvalidFormat
}
var cksum [4]byte
copy(cksum[:], decoded[len(decoded)-4:])
if checksum(decoded[:len(decoded)-4]) != cksum {
return nil, base58.ErrChecksum
}
checkBytes = append(checkBytes, decoded...)
return
}
func BtcAddressFromStr(addr string) (btcutil.Address, error) {
checkBytes, err := StrBtcAddrToCheckBytes(addr)
if err != nil {
return nil, err
}
return BtcAddressFromCheckBytes(checkBytes)
}
type AddressPubKeyHash struct {
hash [ripemd160.Size]byte
netID byte
}
func (a *AddressPubKeyHash) EncodeAddress() string {
return base58.CheckEncode(a.hash[:ripemd160.Size], a.netID)
}
func (a *AddressPubKeyHash) ScriptAddress() []byte {
return a.hash[:]
}
func (a *AddressPubKeyHash) IsForNet(net *chaincfg.Params) bool {
return a.netID == net.PubKeyHashAddrID
}
func (a *AddressPubKeyHash) String() string {
return a.EncodeAddress()
}
func (a *AddressPubKeyHash) Hash160() *[ripemd160.Size]byte {
return &a.hash
}
func newAddressPubKeyHash(pkHash []byte, netID byte) (*AddressPubKeyHash, error) {
if len(pkHash) != ripemd160.Size {
return nil, ErrHash160Size
}
addr := &AddressPubKeyHash{netID: netID}
copy(addr.hash[:], pkHash)
return addr, nil
}
type AddressScriptHash struct {
hash [ripemd160.Size]byte
netID byte
}
func (a *AddressScriptHash) EncodeAddress() string {
return base58.CheckEncode(a.hash[:ripemd160.Size], a.netID)
}
func (a *AddressScriptHash) ScriptAddress() []byte {
return a.hash[:]
}
func (a *AddressScriptHash) IsForNet(net *chaincfg.Params) bool {
return a.netID == net.ScriptHashAddrID
}
func (a *AddressScriptHash) String() string {
return a.EncodeAddress()
}
func (a *AddressScriptHash) Hash160() *[ripemd160.Size]byte {
return &a.hash
}
func newAddressScriptHashFromHash(scriptHash []byte, netID byte) (*AddressScriptHash, error) {
if len(scriptHash) != ripemd160.Size {
return nil, ErrHash160Size
}
addr := &AddressScriptHash{netID: netID}
copy(addr.hash[:], scriptHash)
return addr, nil
}