1 // Copyright 2014 The go-ethereum Authors
2 // This file is part of the go-ethereum library.
4 // The go-ethereum library is free software: you can redistribute it and/or modify
5 // it under the terms of the GNU Lesser General Public License as published by
6 // the Free Software Foundation, either version 3 of the License, or
7 // (at your option) any later version.
9 // The go-ethereum library is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU Lesser General Public License for more details.
14 // You should have received a copy of the GNU Lesser General Public License
15 // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
17 // Package common contains various helper functions.
24 log "github.com/sirupsen/logrus"
29 func ToHex(b []byte) string {
31 // Prefer output of "0x0" instead of "0x"
38 func FromHex(s string) []byte {
53 // Returns the number in bytes with the specified base
54 func NumberToBytes(num interface{}, bits int) []byte {
55 buf := new(bytes.Buffer)
56 err := binary.Write(buf, binary.BigEndian, num)
58 log.WithField("err", err).Error("NumberToBytes failed")
61 return buf.Bytes()[buf.Len()-(bits/8):]
66 // Attempts to cast a byte slice to a unsigned integer
67 func BytesToNumber(b []byte) uint64 {
70 // Make sure the buffer is 64bits
71 data := make([]byte, 8)
72 data = append(data[:len(b)], b...)
74 buf := bytes.NewReader(data)
75 err := binary.Read(buf, binary.BigEndian, &number)
77 log.WithField("err", err).Error("BytesToNumber failed")
85 // Read a variable length number in big endian byte order
86 func ReadVarInt(buff []byte) (ret uint64) {
87 switch l := len(buff); {
89 d := LeftPadBytes(buff, 8)
90 binary.Read(bytes.NewReader(d), binary.BigEndian, &ret)
93 d := LeftPadBytes(buff, 4)
94 binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
98 d := LeftPadBytes(buff, 2)
99 binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
103 binary.Read(bytes.NewReader(buff), binary.BigEndian, &num)
112 // Returns an exact copy of the provided bytes
113 func CopyBytes(b []byte) (copiedBytes []byte) {
114 copiedBytes = make([]byte, len(b))
120 func HasHexPrefix(str string) bool {
122 return l >= 2 && str[0:2] == "0x"
125 func IsHex(str string) bool {
127 return l >= 4 && l%2 == 0 && str[0:2] == "0x"
130 func Bytes2Hex(d []byte) string {
131 return hex.EncodeToString(d)
134 func Hex2Bytes(str string) []byte {
135 h, _ := hex.DecodeString(str)
140 func Hex2BytesFixed(str string, flen int) []byte {
141 h, _ := hex.DecodeString(str)
146 return h[len(h)-flen : len(h)]
148 hh := make([]byte, flen)
149 copy(hh[flen-len(h):flen], h[:])
155 func StringToByteFunc(str string, cb func(str string) []byte) (ret []byte) {
156 if len(str) > 1 && str[0:2] == "0x" && !strings.Contains(str, "\n") {
157 ret = Hex2Bytes(str[2:])
165 func FormatData(data string) []byte {
171 if data[0:1] == "\"" && data[len(data)-1:] == "\"" {
172 return RightPadBytes([]byte(data[1:len(data)-1]), 32)
173 } else if len(data) > 1 && data[:2] == "0x" {
174 d.SetBytes(Hex2Bytes(data[2:]))
179 return BigToBytes(d, 256)
182 func ParseData(data ...interface{}) (ret []byte) {
183 for _, item := range data {
184 switch t := item.(type) {
188 str = Hex2Bytes(t[2:])
193 ret = append(ret, RightPadBytes(str, 32)...)
195 ret = append(ret, LeftPadBytes(t, 32)...)
202 func RightPadBytes(slice []byte, l int) []byte {
207 padded := make([]byte, l)
208 copy(padded[0:len(slice)], slice)
213 func LeftPadBytes(slice []byte, l int) []byte {
218 padded := make([]byte, l)
219 copy(padded[l-len(slice):], slice)
224 func LeftPadString(str string, l int) string {
229 zeros := Bytes2Hex(make([]byte, (l-len(str))/2))
235 func RightPadString(str string, l int) string {
240 zeros := Bytes2Hex(make([]byte, (l-len(str))/2))
246 func ToAddress(slice []byte) (addr []byte) {
248 addr = LeftPadBytes(slice, 20)
249 } else if len(slice) > 20 {
250 addr = slice[len(slice)-20:]
255 addr = CopyBytes(addr)
260 func ByteSliceToInterface(slice [][]byte) (ret []interface{}) {
261 for _, i := range slice {