-
Notifications
You must be signed in to change notification settings - Fork 0
/
bech32PubkeyConverter.go
executable file
·134 lines (112 loc) · 3.7 KB
/
bech32PubkeyConverter.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
package pubkeyConverter
import (
"encoding/hex"
"fmt"
"runtime/debug"
"github.com/ThotaGopichandThota/gn-core/core"
"github.com/ThotaGopichandThota/gn-core/core/check"
"github.com/btcsuite/btcd/btcutil/bech32"
)
type config struct {
prefix string
fromBits byte
toBits byte
pad bool
}
var bech32Config = config{
fromBits: byte(8),
toBits: byte(5),
pad: true,
}
// bech32PubkeyConverter encodes or decodes provided public key as/from bech32 format
type bech32PubkeyConverter struct {
prefix string
len int
}
// NewBech32PubkeyConverter returns a bech32PubkeyConverter instance
func NewBech32PubkeyConverter(addressLen int, prefix string) (*bech32PubkeyConverter, error) {
if addressLen < 1 {
return nil, fmt.Errorf("%w when creating address converter, addressLen should have been greater than 0",
ErrInvalidAddressLength)
}
if addressLen%2 == 1 {
return nil, fmt.Errorf("%w when creating address converter, addressLen should have been an even number",
ErrInvalidAddressLength)
}
if !check.IfHrp(prefix) {
return nil, fmt.Errorf("%w when creating address converter, prefix should have been human readable",
ErrInvalidHrpPrefix)
}
return &bech32PubkeyConverter{
prefix: prefix,
len: addressLen,
}, nil
}
// Len returns the decoded address length
func (bpc *bech32PubkeyConverter) Len() int {
return bpc.len
}
// Decode converts the provided public key string as bech32 decoded bytes
func (bpc *bech32PubkeyConverter) Decode(humanReadable string) ([]byte, error) {
decodedPrefix, buff, err := bech32.Decode(humanReadable)
if err != nil {
return nil, err
}
if decodedPrefix != bpc.prefix {
return nil, ErrInvalidMoaAddress
}
// warning: mind the order of the parameters, those should be inverted
decodedBytes, err := bech32.ConvertBits(buff, bech32Config.toBits, bech32Config.fromBits, !bech32Config.pad)
if err != nil {
return nil, ErrBech32ConvertError
}
if len(decodedBytes) != bpc.len {
return nil, fmt.Errorf("%w when decoding address, expected length %d, received %d",
ErrWrongSize, bpc.len, len(decodedBytes))
}
return decodedBytes, nil
}
// Encode converts the provided bytes in a bech32 form
func (bpc *bech32PubkeyConverter) Encode(pkBytes []byte) (string, error) {
if len(pkBytes) != bpc.len {
return "", fmt.Errorf("%w when encoding address, expected length %d, received %d",
ErrWrongSize, bpc.len, len(pkBytes))
}
conv, err := bech32.ConvertBits(pkBytes, bech32Config.fromBits, bech32Config.toBits, bech32Config.pad)
if err != nil {
return "", fmt.Errorf("%w: %s", ErrConvertBits, err.Error())
}
encodedBytes, err := bech32.Encode(bpc.prefix, conv)
if err != nil {
return "", fmt.Errorf("%w: %s", ErrBech32ConvertError, err.Error())
}
return encodedBytes, nil
}
// SilentEncode converts the provided bytes in a bech32 form without returning any error
func (bpc *bech32PubkeyConverter) SilentEncode(pkBytes []byte, log core.Logger) string {
encodedBytes, err := bpc.Encode(pkBytes)
if err != nil {
log.Warn("bech32PubkeyConverter.SilentEncode",
"hex buff", hex.EncodeToString(pkBytes),
"error", err,
"stack trace", string(debug.Stack()))
return ""
}
return encodedBytes
}
// EncodeSlice converts the provided bytes slice into a slice of bech32 addresses
func (bpc *bech32PubkeyConverter) EncodeSlice(pkBytesSlice [][]byte) ([]string, error) {
encodedSlice := make([]string, 0, len(pkBytesSlice))
for _, item := range pkBytesSlice {
encoded, err := bpc.Encode(item)
if err != nil {
return nil, err
}
encodedSlice = append(encodedSlice, encoded)
}
return encodedSlice, nil
}
// IsInterfaceNil returns true if there is no value under the interface
func (bpc *bech32PubkeyConverter) IsInterfaceNil() bool {
return bpc == nil
}