-
Notifications
You must be signed in to change notification settings - Fork 320
/
address_v1.go
87 lines (76 loc) · 2.74 KB
/
address_v1.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
// Copyright (c) 2018 IoTeX
// This is an alpha (internal) release and is not suitable for production. This source code is provided 'as is' and no
// warranties are given as to title or non-infringement, merchantability or fitness for purpose and, to the extent
// permitted by law, all liability for your use of the code is disclaimed. This source code is governed by Apache
// License 2.0 that can be found in the LICENSE file.
package address
import (
"github.com/pkg/errors"
"go.uber.org/zap"
"github.com/iotexproject/iotex-core/address/bech32"
"github.com/iotexproject/iotex-core/pkg/hash"
"github.com/iotexproject/iotex-core/pkg/log"
)
// _v1 is a singleton and defines V1 address metadata
var _v1 = v1{
AddressLength: 20,
}
type v1 struct {
// AddressLength indicates the byte length of an address
AddressLength int
}
// FromString decodes an encoded address string into an address struct
func (v *v1) FromString(encodedAddr string) (*AddrV1, error) {
payload, err := v.decodeBech32(encodedAddr)
if err != nil {
return nil, err
}
return v.FromBytes(payload)
}
// FromBytes converts a byte array into an address struct
func (v *v1) FromBytes(bytes []byte) (*AddrV1, error) {
if len(bytes) != v.AddressLength {
return nil, errors.Wrapf(ErrInvalidAddr, "invalid address length in bytes: %d", len(bytes))
}
return &AddrV1{
payload: hash.BytesToHash160(bytes),
}, nil
}
func (v *v1) decodeBech32(encodedAddr string) ([]byte, error) {
hrp, grouped, err := bech32.Decode(encodedAddr)
if hrp != prefix() {
return nil, errors.Wrapf(err, "hrp %s and address prefix %s don't match", hrp, prefix())
}
// Group the payload into 8 bit groups.
payload, err := bech32.ConvertBits(grouped, 5, 8, false)
if err != nil {
return nil, errors.Wrapf(err, "error when converting 5 bit groups into the payload")
}
return payload, nil
}
// AddrV1 is V1 address format to be used on IoTeX blockchain and subchains. It is composed of
// 20 bytes: hash derived from the the public key:
type AddrV1 struct {
payload hash.Hash160
}
// String encodes an address struct into a a String encoded address string
// The encoded address string will start with "io" for mainnet, and with "it" for testnet
func (addr *AddrV1) String() string {
payload := addr.payload[:]
// Group the payload into 5 bit groups.
grouped, err := bech32.ConvertBits(payload, 8, 5, true)
if err != nil {
log.L().Panic("Error when grouping the payload into 5 bit groups.", zap.Error(err))
return ""
}
encodedAddr, err := bech32.Encode(prefix(), grouped)
if err != nil {
log.L().Panic("Error when encoding bytes into a base32 string.", zap.Error(err))
return ""
}
return encodedAddr
}
// Bytes converts an address struct into a byte array
func (addr *AddrV1) Bytes() []byte {
return addr.payload[:]
}