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.
27 log "github.com/sirupsen/logrus"
30 func ToHex(b []byte) string {
32 // Prefer output of "0x0" instead of "0x"
39 func FromHex(s string) []byte {
54 // Returns the number in bytes with the specified base
55 func NumberToBytes(num interface{}, bits int) []byte {
56 buf := new(bytes.Buffer)
57 err := binary.Write(buf, binary.BigEndian, num)
59 log.WithField("err", err).Error("NumberToBytes failed")
62 return buf.Bytes()[buf.Len()-(bits/8):]
67 // Attempts to cast a byte slice to a unsigned integer
68 func BytesToNumber(b []byte) uint64 {
71 // Make sure the buffer is 64bits
72 data := make([]byte, 8)
73 data = append(data[:len(b)], b...)
75 buf := bytes.NewReader(data)
76 err := binary.Read(buf, binary.BigEndian, &number)
78 log.WithField("err", err).Error("BytesToNumber failed")
86 // Read a variable length number in big endian byte order
87 func ReadVarInt(buff []byte) (ret uint64) {
88 switch l := len(buff); {
90 d := LeftPadBytes(buff, 8)
91 binary.Read(bytes.NewReader(d), binary.BigEndian, &ret)
94 d := LeftPadBytes(buff, 4)
95 binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
99 d := LeftPadBytes(buff, 2)
100 binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
104 binary.Read(bytes.NewReader(buff), binary.BigEndian, &num)
113 // Returns an exact copy of the provided bytes
114 func CopyBytes(b []byte) (copiedBytes []byte) {
115 copiedBytes = make([]byte, len(b))
121 func HasHexPrefix(str string) bool {
123 return l >= 2 && str[0:2] == "0x"
126 func IsHex(str string) bool {
128 return l >= 4 && l%2 == 0 && str[0:2] == "0x"
131 func Bytes2Hex(d []byte) string {
132 return hex.EncodeToString(d)
135 func Hex2Bytes(str string) []byte {
136 h, _ := hex.DecodeString(str)
141 func Hex2BytesFixed(str string, flen int) []byte {
142 h, _ := hex.DecodeString(str)
147 return h[len(h)-flen : len(h)]
149 hh := make([]byte, flen)
150 copy(hh[flen-len(h):flen], h[:])
156 func StringToByteFunc(str string, cb func(str string) []byte) (ret []byte) {
157 if len(str) > 1 && str[0:2] == "0x" && !strings.Contains(str, "\n") {
158 ret = Hex2Bytes(str[2:])
166 func FormatData(data string) []byte {
172 if data[0:1] == "\"" && data[len(data)-1:] == "\"" {
173 return RightPadBytes([]byte(data[1:len(data)-1]), 32)
174 } else if len(data) > 1 && data[:2] == "0x" {
175 d.SetBytes(Hex2Bytes(data[2:]))
180 return BigToBytes(d, 256)
183 func ParseData(data ...interface{}) (ret []byte) {
184 for _, item := range data {
185 switch t := item.(type) {
189 str = Hex2Bytes(t[2:])
194 ret = append(ret, RightPadBytes(str, 32)...)
196 ret = append(ret, LeftPadBytes(t, 32)...)
203 func RightPadBytes(slice []byte, l int) []byte {
208 padded := make([]byte, l)
209 copy(padded[0:len(slice)], slice)
214 func LeftPadBytes(slice []byte, l int) []byte {
219 padded := make([]byte, l)
220 copy(padded[l-len(slice):], slice)
225 func LeftPadString(str string, l int) string {
230 zeros := Bytes2Hex(make([]byte, (l-len(str))/2))
236 func RightPadString(str string, l int) string {
241 zeros := Bytes2Hex(make([]byte, (l-len(str))/2))
247 func ToAddress(slice []byte) (addr []byte) {
249 addr = LeftPadBytes(slice, 20)
250 } else if len(slice) > 20 {
251 addr = slice[len(slice)-20:]
256 addr = CopyBytes(addr)
261 func ByteSliceToInterface(slice [][]byte) (ret []interface{}) {
262 for _, i := range slice {
269 func Unit64ToBytes(n uint64) []byte {
270 buf := make([]byte, 8)
271 binary.LittleEndian.PutUint64(buf, n)
275 func BytesToUnit64(b []byte) uint64 {
276 return binary.LittleEndian.Uint64(b)