diff --git a/common/big.go b/common/big.go
index 4ce87ee0c6..5e95224ef0 100644
--- a/common/big.go
+++ b/common/big.go
@@ -116,14 +116,19 @@ func FirstBitSet(v *big.Int) int {
//
// Returns the bytes of a big integer with the size specified by **base**
// 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 {
- ret := make([]byte, base/8)
+ bytes := num.Bytes()
+ blen := len(bytes)
+ bpb := base / 8
- if len(num.Bytes()) > base/8 {
- return num.Bytes()
+ if blen > bpb {
+ return bytes
}
-
- return append(ret[:len(ret)-len(num.Bytes())], num.Bytes()...)
+ padBuf := make([]byte, bpb)
+ return append(padBuf[:bpb-blen], bytes...)
}
// Big copy
diff --git a/common/bytes.go b/common/bytes.go
index b9fb3b2da6..68ccbd37d9 100644
--- a/common/bytes.go
+++ b/common/bytes.go
@@ -14,7 +14,6 @@
// You should have received a copy of the GNU Lesser General Public License
// along with the go-ethereum library. If not, see .
-// Package common contains various helper functions.
package common
import (
@@ -61,60 +60,29 @@ func NumberToBytes(num interface{}, bits int) []byte {
return buf.Bytes()[buf.Len()-(bits/8):]
}
-// Bytes to number
-//
-// Attempts to cast a byte slice to a unsigned integer
+// Converts byte slice to a unsigned integer. Bytes are
+// interpreted as big-endian image of unsigned 64bit 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 {
- var number uint64
+ var data = LeftPadBytes(b, 8)
- // Make sure the buffer is 64bits
- data := make([]byte, 8)
- data = append(data[:len(b)], b...)
+ var n uint64
+ n |= uint64(data[0]) << 56
+ 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)
- err := binary.Read(buf, binary.BigEndian, &number)
- if err != nil {
- fmt.Println("BytesToNumber failed:", err)
- }
-
- return number
+ return n
}
-// 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
func CopyBytes(b []byte) (copiedBytes []byte) {
- copiedBytes = make([]byte, len(b))
- copy(copiedBytes, b)
-
- return
+ return append([]byte{}, b...)
}
func HasHexPrefix(str string) bool {
@@ -137,7 +105,7 @@ func Hex2Bytes(str string) []byte {
return h
}
-func Hex2BytesFixed(str string, flen int) []byte {
+func HexToBytesFixed(str string, flen int) []byte {
h, _ := hex.DecodeString(str)
if len(h) == flen {
return h
diff --git a/common/bytes_test.go b/common/bytes_test.go
index 2e52084777..49b4796a56 100644
--- a/common/bytes_test.go
+++ b/common/bytes_test.go
@@ -39,47 +39,59 @@ func (s *BytesSuite) TestNumberToBytes(c *checker.C) {
}
func (s *BytesSuite) TestBytesToNumber(c *checker.C) {
- datasmall := []byte{0xe9, 0x38, 0xe9, 0x38}
- datalarge := []byte{0xe9, 0x38, 0xe9, 0x38, 0xe9, 0x38, 0xe9, 0x38}
+ data := [][]byte{
+ // check for zero-len
+ []byte{},
+ // check for len < 8
+ []byte{0xfe},
+ []byte{0xca, 0xfe},
+ []byte{0xca, 0xfe, 0xba, 0xbe},
+ // check case len < 8
+ []byte{0x7f, 0x6f, 0x5f, 0x4f, 0x3f, 0x2f, 0x1f, 0x0f},
+ // check case len = 8
+ []byte{0x7f, 0x6f, 0x5f, 0x4f, 0x3f, 0x2f, 0x1f, 0x0f, 0xba, 0xdc, 0x0d},
+ }
+ expected := []uint64{
+ 0x0,
+ 0xfe,
+ 0xcafe,
+ 0xcafebabe,
+ 0x7f6f5f4f3f2f1f0f,
+ 0x7f6f5f4f3f2f1f0f,
+ }
- var expsmall uint64 = 0xe938e938
- var explarge uint64 = 0x0
+ // assert-test-invariants:
+ c.Assert(len(data[0]), checker.Equals, 0)
+ c.Assert(len(data[1]), checker.Equals, 1)
+ c.Assert(len(data[2]), checker.Equals, 2)
+ c.Assert(len(data[3]), checker.Equals, 4)
+ c.Assert(len(data[4]), checker.Equals, 8)
+ c.Assert(len(data[5]), checker.Equals, 11)
- ressmall := BytesToNumber(datasmall)
- reslarge := BytesToNumber(datalarge)
+ c.Assert(len(expected), checker.Equals, len(data))
- c.Assert(ressmall, checker.Equals, expsmall)
- c.Assert(reslarge, checker.Equals, explarge)
-
-}
-
-func (s *BytesSuite) TestReadVarInt(c *checker.C) {
- data8 := []byte{1, 2, 3, 4, 5, 6, 7, 8}
- data4 := []byte{1, 2, 3, 4}
- data2 := []byte{1, 2}
- data1 := []byte{1}
-
- exp8 := uint64(72623859790382856)
- exp4 := uint64(16909060)
- exp2 := uint64(258)
- exp1 := uint64(1)
-
- res8 := ReadVarInt(data8)
- res4 := ReadVarInt(data4)
- res2 := ReadVarInt(data2)
- 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)
+ for i := 0; i < len(data); i++ {
+ have := BytesToNumber(data[i])
+ c.Assert(have, checker.Equals, expected[i])
+ }
}
func (s *BytesSuite) TestCopyBytes(c *checker.C) {
- data1 := []byte{1, 2, 3, 4}
- exp1 := []byte{1, 2, 3, 4}
- res1 := CopyBytes(data1)
- c.Assert(res1, checker.DeepEquals, exp1)
+ data := [][]byte{
+ []byte{0x00, 0x7f, 0x80, 0xff}, // interesting bytes
+ []byte{}, // empty case
+ }
+
+ // 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) {
diff --git a/common/pkgdoc.go b/common/pkgdoc.go
new file mode 100644
index 0000000000..72d08f8159
--- /dev/null
+++ b/common/pkgdoc.go
@@ -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 .
+
+// Package common contains various helper functions.
+package common