forked from decred/dcraddrgen
-
Notifications
You must be signed in to change notification settings - Fork 0
/
address.go
142 lines (120 loc) · 5.14 KB
/
address.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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
// Copyright (c) 2013, 2014 The btcsuite developers
// Copyright (c) 2015 The Decred Developers
// Use of this source code is governed by an ISC
// license that can be found in the LICENSE file.
package address
import (
"errors"
"github.com/btcsuite/golangcrypto/ripemd160"
"github.com/decred/dcraddrgen/base58"
)
var PubKeyHashAddrIDMain = [2]byte{0x07, 0x3f}
var PubKeyHashAddrIDTest = [2]byte{0x0f, 0x21}
var PubKeyHashAddrIDSim = [2]byte{0x0e, 0x91}
var PubKeyHashAddrIDReg = [2]byte{0x0e, 0x01}
var (
// ErrChecksumMismatch describes an error where decoding failed due
// to a bad checksum.
ErrChecksumMismatch = errors.New("checksum mismatch")
// ErrUnknownAddressType describes an error where an address can not
// decoded as a specific address type due to the string encoding
// begining with an identifier byte unknown to any standard or
// registered (via chaincfg.Register) network.
ErrUnknownAddressType = errors.New("unknown address type")
// ErrAddressCollision describes an error where an address can not
// be uniquely determined as either a pay-to-pubkey-hash or
// pay-to-script-hash address since the leading identifier is used for
// describing both address kinds, but for different networks. Rather
// than assuming or defaulting to one or the other, this error is
// returned and the caller must decide how to decode the address.
ErrAddressCollision = errors.New("address collision")
)
// encodeAddress returns a human-readable payment address given a ripemd160 hash
// and netID which encodes the network and address type. It is used in both
// pay-to-pubkey-hash (P2PKH) and pay-to-script-hash (P2SH) address encoding.
func encodeAddress(hash160 []byte, netID [2]byte) string {
// Format is 2 bytes for a network and address class (i.e. P2PKH vs
// P2SH), 20 bytes for a RIPEMD160 hash, and 4 bytes of checksum.
return base58.CheckEncode(hash160[:ripemd160.Size], netID)
}
// Address is an interface type for any type of destination a transaction
// output may spend to. This includes pay-to-pubkey (P2PK), pay-to-pubkey-hash
// (P2PKH), and pay-to-script-hash (P2SH). Address is designed to be generic
// enough that other kinds of addresses may be added in the future without
// changing the decoding and encoding API.
type Address interface {
// String returns the string encoding of the transaction output
// destination.
//
// Please note that String differs subtly from EncodeAddress: String
// will return the value as a string without any conversion, while
// EncodeAddress may convert destination types (for example,
// converting pubkeys to P2PKH addresses) before encoding as a
// payment address string.
String() string
// EncodeAddress returns the string encoding of the payment address
// associated with the Address value. See the comment on String
// for how this method differs from String.
EncodeAddress() string
// ScriptAddress returns the raw bytes of the address to be used
// when inserting the address into a txout's script.
ScriptAddress() []byte
// Hash160 returns the Hash160(data) where data is the data normally
// hashed to 160 bits from the respective address type.
Hash160() *[ripemd160.Size]byte
}
// AddressPubKeyHash is an Address for a pay-to-pubkey-hash (P2PKH)
// transaction.
type AddressPubKeyHash struct {
hash [ripemd160.Size]byte
netID [2]byte
}
// NewAddressPubKeyHash returns a new AddressPubKeyHash. pkHash must
// be 20 bytes.
func NewAddressPubKeyHash(pkHash []byte,
pubKeyHashAddrId [2]byte) (*AddressPubKeyHash, error) {
var addrID [2]byte
addrID = pubKeyHashAddrId
apkh, err := newAddressPubKeyHash(pkHash, addrID)
if err != nil {
return nil, err
}
return apkh, nil
}
// newAddressPubKeyHash is the internal API to create a pubkey hash address
// with a known leading identifier byte for a network, rather than looking
// it up through its parameters. This is useful when creating a new address
// structure from a string encoding where the identifer byte is already
// known.
func newAddressPubKeyHash(pkHash []byte, netID [2]byte) (*AddressPubKeyHash,
error) {
// Check for a valid pubkey hash length.
if len(pkHash) != ripemd160.Size {
return nil, errors.New("pkHash must be 20 bytes")
}
addr := &AddressPubKeyHash{netID: netID}
copy(addr.hash[:], pkHash)
return addr, nil
}
// EncodeAddress returns the string encoding of a pay-to-pubkey-hash
// address. Part of the Address interface.
func (a *AddressPubKeyHash) EncodeAddress() string {
return encodeAddress(a.hash[:], a.netID)
}
// ScriptAddress returns the bytes to be included in a txout script to pay
// to a pubkey hash. Part of the Address interface.
func (a *AddressPubKeyHash) ScriptAddress() []byte {
return a.hash[:]
}
// String returns a human-readable string for the pay-to-pubkey-hash address.
// This is equivalent to calling EncodeAddress, but is provided so the type can
// be used as a fmt.Stringer.
func (a *AddressPubKeyHash) String() string {
return a.EncodeAddress()
}
// Hash160 returns the underlying array of the pubkey hash. This can be useful
// when an array is more appropiate than a slice (for example, when used as map
// keys).
func (a *AddressPubKeyHash) Hash160() *[ripemd160.Size]byte {
return &a.hash
}