forked from iotaledger/iota.go
/
address.go
210 lines (177 loc) · 5.68 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
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
package iotago
import (
"encoding/hex"
"encoding/json"
"fmt"
"github.com/GalRogozinski/iota.go/v2/bech32"
"github.com/GalRogozinski/iota.go/v2/ed25519"
"golang.org/x/crypto/blake2b"
)
// Defines the type of addresses.
type AddressType = byte
const (
// Denotes an Ed25519 address.
AddressEd25519 AddressType = iota
)
// NetworkPrefix denotes the different network prefixes.
type NetworkPrefix string
// Network prefixes.
const (
PrefixMainnet NetworkPrefix = "iota"
PrefixTestnet NetworkPrefix = "atoi"
)
const (
// The length of an Ed25519 address
Ed25519AddressBytesLength = blake2b.Size256
// The size of a serialized Ed25519 address with its type denoting byte.
Ed25519AddressSerializedBytesSize = SmallTypeDenotationByteSize + Ed25519AddressBytesLength
)
// Address describes a general address.
type Address interface {
Serializable
fmt.Stringer
// Type returns the type of the address.
Type() AddressType
// Bech32 encodes the address as a bech32 string.
Bech32(hrp NetworkPrefix) string
}
// AddressSelector implements SerializableSelectorFunc for address types.
func AddressSelector(addressType uint32) (Serializable, error) {
return newAddress(byte(addressType))
}
func newAddress(addressType byte) (address Address, err error) {
switch addressType {
case AddressEd25519:
return &Ed25519Address{}, nil
default:
return nil, fmt.Errorf("%w: type %d", ErrUnknownAddrType, addressType)
}
}
func bech32String(hrp NetworkPrefix, addr Address) string {
bytes, _ := addr.Serialize(DeSeriModeNoValidation)
s, err := bech32.Encode(string(hrp), bytes)
if err != nil {
panic(err)
}
return s
}
// ParseBech32 decodes a bech32 encoded string.
func ParseBech32(s string) (NetworkPrefix, Address, error) {
hrp, addrData, err := bech32.Decode(s)
if err != nil {
return "", nil, fmt.Errorf("invalid bech32 encoding: %w", err)
}
if len(addrData) == 0 {
return "", nil, ErrDeserializationNotEnoughData
}
addr, err := newAddress(addrData[0])
if err != nil {
return "", nil, err
}
n, err := addr.Deserialize(addrData, DeSeriModePerformValidation)
if err != nil {
return "", nil, err
}
if n != len(addrData) {
return "", nil, ErrDeserializationNotAllConsumed
}
return NetworkPrefix(hrp), addr, nil
}
// ParseEd25519AddressFromHexString parses the given hex string into an Ed25519Address.
func ParseEd25519AddressFromHexString(hexAddr string) (*Ed25519Address, error) {
addrBytes, err := hex.DecodeString(hexAddr)
if err != nil {
return nil, err
}
addr := &Ed25519Address{}
copy(addr[:], addrBytes)
return addr, nil
}
// MustParseEd25519AddressFromHexString parses the given hex string into an Ed25519Address.
// It panics if the hex address is invalid.
func MustParseEd25519AddressFromHexString(hexAddr string) *Ed25519Address {
addr, err := ParseEd25519AddressFromHexString(hexAddr)
if err != nil {
panic(err)
}
return addr
}
// Defines an Ed25519 address.
type Ed25519Address [Ed25519AddressBytesLength]byte
func (edAddr *Ed25519Address) Type() AddressType {
return AddressEd25519
}
func (edAddr *Ed25519Address) Bech32(hrp NetworkPrefix) string {
return bech32String(hrp, edAddr)
}
func (edAddr *Ed25519Address) String() string {
return hex.EncodeToString(edAddr[:])
}
func (edAddr *Ed25519Address) Deserialize(data []byte, deSeriMode DeSerializationMode) (int, error) {
if deSeriMode.HasMode(DeSeriModePerformValidation) {
if err := checkMinByteLength(Ed25519AddressSerializedBytesSize, len(data)); err != nil {
return 0, fmt.Errorf("invalid Ed25519 address bytes: %w", err)
}
if err := checkTypeByte(data, AddressEd25519); err != nil {
return 0, fmt.Errorf("unable to deserialize Ed25519 address: %w", err)
}
}
copy(edAddr[:], data[SmallTypeDenotationByteSize:])
return Ed25519AddressSerializedBytesSize, nil
}
func (edAddr *Ed25519Address) Serialize(deSeriMode DeSerializationMode) (data []byte, err error) {
var b [Ed25519AddressSerializedBytesSize]byte
b[0] = AddressEd25519
copy(b[SmallTypeDenotationByteSize:], edAddr[:])
return b[:], nil
}
func (edAddr *Ed25519Address) MarshalJSON() ([]byte, error) {
jEd25519Address := &jsonEd25519Address{}
jEd25519Address.Address = hex.EncodeToString(edAddr[:])
jEd25519Address.Type = int(AddressEd25519)
return json.Marshal(jEd25519Address)
}
func (edAddr *Ed25519Address) UnmarshalJSON(bytes []byte) error {
jEd25519Address := &jsonEd25519Address{}
if err := json.Unmarshal(bytes, jEd25519Address); err != nil {
return err
}
seri, err := jEd25519Address.ToSerializable()
if err != nil {
return err
}
*edAddr = *seri.(*Ed25519Address)
return nil
}
// AddressFromEd25519PubKey returns the address belonging to the given Ed25519 public key.
func AddressFromEd25519PubKey(pubKey ed25519.PublicKey) Ed25519Address {
return blake2b.Sum256(pubKey[:])
}
// selects the json object for the given type.
func jsonAddressSelector(ty int) (JSONSerializable, error) {
var obj JSONSerializable
switch byte(ty) {
case AddressEd25519:
obj = &jsonEd25519Address{}
default:
return nil, fmt.Errorf("unable to decode address type from JSON: %w", ErrUnknownAddrType)
}
return obj, nil
}
// jsonEd25519Address defines the json representation of an Ed25519Address.
type jsonEd25519Address struct {
Type int `json:"type"`
Address string `json:"address"`
}
func (j *jsonEd25519Address) ToSerializable() (Serializable, error) {
addrBytes, err := hex.DecodeString(j.Address)
if err != nil {
return nil, fmt.Errorf("unable to decode address from JSON for Ed25519 address: %w", err)
}
if err := checkExactByteLength(len(addrBytes), Ed25519AddressBytesLength); err != nil {
return nil, fmt.Errorf("unable to decode address from JSON for Ed25519 address: %w", err)
}
addr := &Ed25519Address{}
copy(addr[:], addrBytes)
return addr, nil
}