-
Notifications
You must be signed in to change notification settings - Fork 2
/
hex.go
208 lines (178 loc) · 4.44 KB
/
hex.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
package utils
import (
"encoding/hex"
"fmt"
"github.com/consensys/gnark/frontend"
"math/big"
"strconv"
"github.com/ethereum/go-ethereum/common"
ec "github.com/ethereum/go-ethereum/common"
)
var (
// ZeroAddr is all 0s
ZeroAddr common.Address
// ZeroAddrHex is string of 20 0s
ZeroAddrHex = Addr2Hex(ZeroAddr)
// ZeroBigInt is big.NewInt(0)
ZeroBigInt = big.NewInt(0)
// ZeroHash is all 0s
ZeroHash common.Hash
// HashLength is the expected length of the hash
HashLength = 32
)
// ========== Hex/Bytes ==========
// IsValidTxHash verifies whether a string can represent a valid hash or not.
func IsValidTxHash(txHash string) bool {
if txHash == "" {
return false
}
if has0xPrefix(txHash) {
txHash = txHash[2:]
}
return len(txHash) == 2*HashLength && isHex(txHash)
}
// isHex validates whether each byte is valid hexadecimal string.
func isHex(str string) bool {
if len(str)%2 != 0 {
return false
}
for _, c := range []byte(str) {
if !isHexCharacter(c) {
return false
}
}
return true
}
// isHexCharacter returns bool of c being a valid hexadecimal.
func isHexCharacter(c byte) bool {
return ('0' <= c && c <= '9') || ('a' <= c && c <= 'f') || ('A' <= c && c <= 'F')
}
// has0xPrefix validates str begins with '0x' or '0X'.
func has0xPrefix(str string) bool {
return len(str) >= 2 && str[0] == '0' && (str[1] == 'x' || str[1] == 'X')
}
// Hex2Bytes supports hex string with or without 0x prefix
// Calls hex.DecodeString directly and ignore err
// similar to ec.FromHex but better
func Hex2Bytes(s string) (b []byte) {
if len(s) >= 2 && s[0] == '0' && (s[1] == 'x' || s[1] == 'X') {
s = s[2:]
}
// hex.DecodeString expects an even-length string
if len(s)%2 == 1 {
s = "0" + s
}
b, _ = hex.DecodeString(s)
return b
}
// Bytes2Hex returns hex string without 0x prefix
func Bytes2Hex(b []byte) string {
return hex.EncodeToString(b)
}
func Bytes2Hex0x(b []byte) string {
return "0x" + Bytes2Hex(b)
}
func ArrayHex2Hash(in []string) [][32]byte {
var ret [][32]byte
for _, e := range in {
ret = append(ret, Hex2Hash(e))
}
return ret
}
func ArrayBytes2Hex0x(in [][]byte) []string {
var ret []string
for _, e := range in {
ret = append(ret, Bytes2Hex0x(e[:]))
}
return ret
}
// ========== Address ==========
// Hex2Addr accepts hex string with or without 0x prefix and return Address
func Hex2Addr(s string) common.Address {
return ec.HexToAddress(s)
}
// Addr2Hex returns hex without 0x
func Addr2Hex(a common.Address) string {
return Bytes2Hex(a[:])
}
func Addr2Hex0x(a common.Address) string {
return "0x" + Addr2Hex(a)
}
// Bytes2Addr returns Address from b
// Addr.Bytes() does the reverse
func Bytes2Addr(b []byte) common.Address {
return ec.BytesToAddress(b)
}
// Bytes2AddrHex returns hex without 0x
func Bytes2AddrHex(b []byte) string {
return Addr2Hex(Bytes2Addr(b))
}
func Bytes2AddrHex0x(b []byte) string {
return "0x" + Bytes2AddrHex(b)
}
// FormatAddrHex formats a string into standard Addr string
func FormatAddrHex(s string) string {
return Addr2Hex(Hex2Addr(s))
}
// ========== Hash ==========
// Hex2Hash accepts hex string with or without 0x prefix and return Hash
func Hex2Hash(s string) common.Hash {
return ec.HexToHash(s)
}
// Bytes2Hash converts bytes to Hash
func Bytes2Hash(b []byte) common.Hash {
return ec.BytesToHash(b)
}
func Strings2bytes(rs []string) (ret [][]byte) {
for _, r := range rs {
ret = append(ret, Hex2Bytes(r))
}
return
}
func Hex2BigInt(s string) *big.Int {
b := Hex2Bytes(s)
return new(big.Int).SetBytes(b)
}
// if in is 20 bytes, return directly. otherwise return a new []byte w/ len 20, left pad 0x00..[in]
// if len(in)>20, panic
func Pad20Bytes(in []byte) []byte {
origLen := len(in)
if origLen == 20 {
return in
}
if origLen > 20 {
panic(fmt.Sprintf("%x len %d > 20", in, origLen))
}
ret := make([]byte, 20)
copy(ret[20-origLen:], in)
return ret
}
func Pad32Bytes(in []byte) []byte {
origLen := len(in)
if origLen == 32 {
return in
}
if origLen > 32 {
panic(fmt.Sprintf("%x len %d > 32", in, origLen))
}
ret := make([]byte, 32)
copy(ret[32-origLen:], in)
return ret
}
func Reverse[S ~[]E, E any](s S) S {
for i, j := 0, len(s)-1; i < j; i, j = i+1, j-1 {
s[i], s[j] = s[j], s[i]
}
return s
}
func GetHexArray(hexStr string, maxLen int) (res []frontend.Variable) {
for i := 0; i < maxLen; i++ {
if i < len(hexStr) {
intValue, _ := strconv.ParseInt(string(hexStr[i]), 16, 64)
res = append(res, intValue)
} else {
res = append(res, 0)
}
}
return
}