This commit is contained in:
Joubin Houshyar 2017-01-17 11:05:16 +00:00 committed by GitHub
commit 6ece9cec44
4 changed files with 92 additions and 89 deletions

View file

@ -116,14 +116,19 @@ func FirstBitSet(v *big.Int) int {
// //
// Returns the bytes of a big integer with the size specified by **base** // Returns the bytes of a big integer with the size specified by **base**
// Attempts to pad the byte array with zeros. // Attempts to pad the byte array with zeros.
//
// Note that input arg **num** is expected to be non-nil;
// nil argument will result in runtime panic.
func BigToBytes(num *big.Int, base int) []byte { func BigToBytes(num *big.Int, base int) []byte {
ret := make([]byte, base/8) bytes := num.Bytes()
blen := len(bytes)
bpb := base / 8
if len(num.Bytes()) > base/8 { if blen > bpb {
return num.Bytes() return bytes
} }
padBuf := make([]byte, bpb)
return append(ret[:len(ret)-len(num.Bytes())], num.Bytes()...) return append(padBuf[:bpb-blen], bytes...)
} }
// Big copy // Big copy

View file

@ -14,7 +14,6 @@
// You should have received a copy of the GNU Lesser General Public License // You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package common contains various helper functions.
package common package common
import ( import (
@ -61,60 +60,29 @@ func NumberToBytes(num interface{}, bits int) []byte {
return buf.Bytes()[buf.Len()-(bits/8):] return buf.Bytes()[buf.Len()-(bits/8):]
} }
// Bytes to number // Converts byte slice to a unsigned integer. Bytes are
// // interpreted as big-endian image of unsigned 64bit integer.
// Attempts to cast a byte slice to a unsigned integer // Slices less than 8 bytes are left padded before conversion;
// For slices larger than 8 bytes the trailing bytes are ignored.
func BytesToNumber(b []byte) uint64 { func BytesToNumber(b []byte) uint64 {
var number uint64 var data = LeftPadBytes(b, 8)
// Make sure the buffer is 64bits var n uint64
data := make([]byte, 8) n |= uint64(data[0]) << 56
data = append(data[:len(b)], b...) n |= uint64(data[1]) << 48
n |= uint64(data[2]) << 40
n |= uint64(data[3]) << 32
n |= uint64(data[4]) << 24
n |= uint64(data[5]) << 16
n |= uint64(data[6]) << 8
n |= uint64(data[7])
buf := bytes.NewReader(data) return n
err := binary.Read(buf, binary.BigEndian, &number)
if err != nil {
fmt.Println("BytesToNumber failed:", err)
} }
return number
}
// Read variable int
//
// Read a variable length number in big endian byte order
func ReadVarInt(buff []byte) (ret uint64) {
switch l := len(buff); {
case l > 4:
d := LeftPadBytes(buff, 8)
binary.Read(bytes.NewReader(d), binary.BigEndian, &ret)
case l > 2:
var num uint32
d := LeftPadBytes(buff, 4)
binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
ret = uint64(num)
case l > 1:
var num uint16
d := LeftPadBytes(buff, 2)
binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
ret = uint64(num)
default:
var num uint8
binary.Read(bytes.NewReader(buff), binary.BigEndian, &num)
ret = uint64(num)
}
return
}
// Copy bytes
//
// Returns an exact copy of the provided bytes // Returns an exact copy of the provided bytes
func CopyBytes(b []byte) (copiedBytes []byte) { func CopyBytes(b []byte) (copiedBytes []byte) {
copiedBytes = make([]byte, len(b)) return append([]byte{}, b...)
copy(copiedBytes, b)
return
} }
func HasHexPrefix(str string) bool { func HasHexPrefix(str string) bool {
@ -137,7 +105,7 @@ func Hex2Bytes(str string) []byte {
return h return h
} }
func Hex2BytesFixed(str string, flen int) []byte { func HexToBytesFixed(str string, flen int) []byte {
h, _ := hex.DecodeString(str) h, _ := hex.DecodeString(str)
if len(h) == flen { if len(h) == flen {
return h return h

View file

@ -39,47 +39,59 @@ func (s *BytesSuite) TestNumberToBytes(c *checker.C) {
} }
func (s *BytesSuite) TestBytesToNumber(c *checker.C) { func (s *BytesSuite) TestBytesToNumber(c *checker.C) {
datasmall := []byte{0xe9, 0x38, 0xe9, 0x38} data := [][]byte{
datalarge := []byte{0xe9, 0x38, 0xe9, 0x38, 0xe9, 0x38, 0xe9, 0x38} // check for zero-len
[]byte{},
var expsmall uint64 = 0xe938e938 // check for len < 8
var explarge uint64 = 0x0 []byte{0xfe},
[]byte{0xca, 0xfe},
ressmall := BytesToNumber(datasmall) []byte{0xca, 0xfe, 0xba, 0xbe},
reslarge := BytesToNumber(datalarge) // check case len < 8
[]byte{0x7f, 0x6f, 0x5f, 0x4f, 0x3f, 0x2f, 0x1f, 0x0f},
c.Assert(ressmall, checker.Equals, expsmall) // check case len = 8
c.Assert(reslarge, checker.Equals, explarge) []byte{0x7f, 0x6f, 0x5f, 0x4f, 0x3f, 0x2f, 0x1f, 0x0f, 0xba, 0xdc, 0x0d},
}
expected := []uint64{
0x0,
0xfe,
0xcafe,
0xcafebabe,
0x7f6f5f4f3f2f1f0f,
0x7f6f5f4f3f2f1f0f,
} }
func (s *BytesSuite) TestReadVarInt(c *checker.C) { // assert-test-invariants:
data8 := []byte{1, 2, 3, 4, 5, 6, 7, 8} c.Assert(len(data[0]), checker.Equals, 0)
data4 := []byte{1, 2, 3, 4} c.Assert(len(data[1]), checker.Equals, 1)
data2 := []byte{1, 2} c.Assert(len(data[2]), checker.Equals, 2)
data1 := []byte{1} c.Assert(len(data[3]), checker.Equals, 4)
c.Assert(len(data[4]), checker.Equals, 8)
c.Assert(len(data[5]), checker.Equals, 11)
exp8 := uint64(72623859790382856) c.Assert(len(expected), checker.Equals, len(data))
exp4 := uint64(16909060)
exp2 := uint64(258)
exp1 := uint64(1)
res8 := ReadVarInt(data8) for i := 0; i < len(data); i++ {
res4 := ReadVarInt(data4) have := BytesToNumber(data[i])
res2 := ReadVarInt(data2) c.Assert(have, checker.Equals, expected[i])
res1 := ReadVarInt(data1) }
c.Assert(res8, checker.Equals, exp8)
c.Assert(res4, checker.Equals, exp4)
c.Assert(res2, checker.Equals, exp2)
c.Assert(res1, checker.Equals, exp1)
} }
func (s *BytesSuite) TestCopyBytes(c *checker.C) { func (s *BytesSuite) TestCopyBytes(c *checker.C) {
data1 := []byte{1, 2, 3, 4} data := [][]byte{
exp1 := []byte{1, 2, 3, 4} []byte{0x00, 0x7f, 0x80, 0xff}, // interesting bytes
res1 := CopyBytes(data1) []byte{}, // empty case
c.Assert(res1, checker.DeepEquals, exp1) }
// test
for i := 0; i < len(data); i++ {
have := CopyBytes(data[i])
if data[i] != nil {
// make sure we're not just returning the input arg
c.Assert(&have, checker.Not(checker.Equals), &data[i])
}
// verify deep copy
c.Assert(have, checker.DeepEquals, data[i])
}
} }
func (s *BytesSuite) TestIsHex(c *checker.C) { func (s *BytesSuite) TestIsHex(c *checker.C) {

18
common/pkgdoc.go Normal file
View file

@ -0,0 +1,18 @@
// Copyright 2014 The go-ethereum Authors
// This file is part of the go-ethereum library.
//
// The go-ethereum library is free software: you can redistribute it and/or modify
// it under the terms of the GNU Lesser General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// The go-ethereum library is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU Lesser General Public License for more details.
//
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
// Package common contains various helper functions.
package common