merge upstream
This commit is contained in:
@ -4,14 +4,6 @@ import (
|
||||
"math/big"
|
||||
)
|
||||
|
||||
var BigInt0 *big.Int = big.NewInt(0)
|
||||
|
||||
// True
|
||||
var BigTrue *big.Int = big.NewInt(1)
|
||||
|
||||
// False
|
||||
var BigFalse *big.Int = big.NewInt(0)
|
||||
|
||||
// Big pow
|
||||
//
|
||||
// Returns the power of two big integers
|
||||
@ -73,3 +65,14 @@ func BigMax(x, y *big.Int) *big.Int {
|
||||
|
||||
return x
|
||||
}
|
||||
|
||||
// Big min
|
||||
//
|
||||
// Returns the minimum size big integer
|
||||
func BigMin(x, y *big.Int) *big.Int {
|
||||
if x.Cmp(y) >= 0 {
|
||||
return y
|
||||
}
|
||||
|
||||
return x
|
||||
}
|
||||
|
@ -44,26 +44,28 @@ func BytesToNumber(b []byte) uint64 {
|
||||
// Read variable int
|
||||
//
|
||||
// Read a variable length number in big endian byte order
|
||||
func ReadVarint(reader *bytes.Reader) (ret uint64) {
|
||||
if reader.Len() == 8 {
|
||||
var num uint64
|
||||
binary.Read(reader, binary.BigEndian, &num)
|
||||
ret = uint64(num)
|
||||
} else if reader.Len() == 4 {
|
||||
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
|
||||
binary.Read(reader, binary.BigEndian, &num)
|
||||
d := LeftPadBytes(buff, 4)
|
||||
binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
|
||||
ret = uint64(num)
|
||||
} else if reader.Len() == 2 {
|
||||
case l > 1:
|
||||
var num uint16
|
||||
binary.Read(reader, binary.BigEndian, &num)
|
||||
d := LeftPadBytes(buff, 2)
|
||||
binary.Read(bytes.NewReader(d), binary.BigEndian, &num)
|
||||
ret = uint64(num)
|
||||
} else {
|
||||
default:
|
||||
var num uint8
|
||||
binary.Read(reader, binary.BigEndian, &num)
|
||||
binary.Read(bytes.NewReader(buff), binary.BigEndian, &num)
|
||||
ret = uint64(num)
|
||||
}
|
||||
|
||||
return ret
|
||||
return
|
||||
}
|
||||
|
||||
// Binary length
|
||||
@ -98,6 +100,7 @@ func Bytes2Hex(d []byte) string {
|
||||
|
||||
func Hex2Bytes(str string) []byte {
|
||||
h, _ := hex.DecodeString(str)
|
||||
|
||||
return h
|
||||
}
|
||||
|
||||
|
@ -58,9 +58,11 @@ func CurrencyToString(num *big.Int) string {
|
||||
|
||||
// Common big integers often used
|
||||
var (
|
||||
Big1 = big.NewInt(1)
|
||||
Big2 = big.NewInt(2)
|
||||
Big0 = big.NewInt(0)
|
||||
Big32 = big.NewInt(32)
|
||||
Big256 = big.NewInt(0xff)
|
||||
Big1 = big.NewInt(1)
|
||||
Big2 = big.NewInt(2)
|
||||
Big0 = big.NewInt(0)
|
||||
BigTrue = Big1
|
||||
BigFalse = Big0
|
||||
Big32 = big.NewInt(32)
|
||||
Big256 = big.NewInt(0xff)
|
||||
)
|
||||
|
@ -3,8 +3,9 @@ package ethutil
|
||||
import (
|
||||
"flag"
|
||||
"fmt"
|
||||
"github.com/rakyll/globalconf"
|
||||
"os"
|
||||
|
||||
"github.com/rakyll/globalconf"
|
||||
)
|
||||
|
||||
// Config struct
|
||||
@ -28,8 +29,7 @@ var Config *ConfigManager
|
||||
func ReadConfig(ConfigFile string, Datadir string, EnvPrefix string) *ConfigManager {
|
||||
if Config == nil {
|
||||
// create ConfigFile if does not exist, otherwise globalconf panic when trying to persist flags
|
||||
_, err := os.Stat(ConfigFile)
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
if !FileExist(ConfigFile) {
|
||||
fmt.Printf("config file '%s' doesn't exist, creating it\n", ConfigFile)
|
||||
os.Create(ConfigFile)
|
||||
}
|
||||
|
@ -1,6 +1,8 @@
|
||||
package ethutil
|
||||
|
||||
import (
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/user"
|
||||
"strings"
|
||||
)
|
||||
@ -18,3 +20,41 @@ func ExpandHomePath(p string) (path string) {
|
||||
|
||||
return
|
||||
}
|
||||
|
||||
func FileExist(filePath string) bool {
|
||||
_, err := os.Stat(filePath)
|
||||
if err != nil && os.IsNotExist(err) {
|
||||
return false
|
||||
}
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
func ReadAllFile(filePath string) (string, error) {
|
||||
file, err := os.Open(filePath)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
data, err := ioutil.ReadAll(file)
|
||||
if err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return string(data), nil
|
||||
}
|
||||
|
||||
func WriteFile(filePath string, content []byte) error {
|
||||
fh, err := os.OpenFile(filePath, os.O_RDWR|os.O_CREATE, os.ModePerm)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
defer fh.Close()
|
||||
|
||||
_, err = fh.Write(content)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
143
ethutil/rlp.go
143
ethutil/rlp.go
@ -55,8 +55,7 @@ func DecodeWithReader(reader *bytes.Buffer) interface{} {
|
||||
return reader.Next(int(char - 0x80))
|
||||
|
||||
case char <= 0xbf:
|
||||
buff := bytes.NewReader(reader.Next(int(char - 0xb8)))
|
||||
length := ReadVarint(buff)
|
||||
length := ReadVarInt(reader.Next(int(char - 0xb7)))
|
||||
|
||||
return reader.Next(int(length))
|
||||
|
||||
@ -72,76 +71,22 @@ func DecodeWithReader(reader *bytes.Buffer) interface{} {
|
||||
}
|
||||
|
||||
return slice
|
||||
|
||||
case char <= 0xff:
|
||||
length := ReadVarInt(reader.Next(int(char - 0xf7)))
|
||||
for i := uint64(0); i < length; i++ {
|
||||
obj := DecodeWithReader(reader)
|
||||
if obj != nil {
|
||||
slice = append(slice, obj)
|
||||
} else {
|
||||
break
|
||||
}
|
||||
}
|
||||
default:
|
||||
}
|
||||
|
||||
return slice
|
||||
}
|
||||
|
||||
// TODO Use a bytes.Buffer instead of a raw byte slice.
|
||||
// Cleaner code, and use draining instead of seeking the next bytes to read
|
||||
func Decode(data []byte, pos uint64) (interface{}, uint64) {
|
||||
var slice []interface{}
|
||||
char := int(data[pos])
|
||||
switch {
|
||||
case char <= 0x7f:
|
||||
return data[pos], pos + 1
|
||||
|
||||
case char <= 0xb7:
|
||||
b := uint64(data[pos]) - 0x80
|
||||
|
||||
return data[pos+1 : pos+1+b], pos + 1 + b
|
||||
|
||||
case char <= 0xbf:
|
||||
b := uint64(data[pos]) - 0xb7
|
||||
|
||||
b2 := ReadVarint(bytes.NewReader(data[pos+1 : pos+1+b]))
|
||||
|
||||
return data[pos+1+b : pos+1+b+b2], pos + 1 + b + b2
|
||||
|
||||
case char <= 0xf7:
|
||||
b := uint64(data[pos]) - 0xc0
|
||||
prevPos := pos
|
||||
pos++
|
||||
for i := uint64(0); i < b; {
|
||||
var obj interface{}
|
||||
|
||||
// Get the next item in the data list and append it
|
||||
obj, prevPos = Decode(data, pos)
|
||||
slice = append(slice, obj)
|
||||
|
||||
// Increment i by the amount bytes read in the previous
|
||||
// read
|
||||
i += (prevPos - pos)
|
||||
pos = prevPos
|
||||
}
|
||||
return slice, pos
|
||||
|
||||
case char <= 0xff:
|
||||
l := uint64(data[pos]) - 0xf7
|
||||
b := ReadVarint(bytes.NewReader(data[pos+1 : pos+1+l]))
|
||||
|
||||
pos = pos + l + 1
|
||||
|
||||
prevPos := b
|
||||
for i := uint64(0); i < uint64(b); {
|
||||
var obj interface{}
|
||||
|
||||
obj, prevPos = Decode(data, pos)
|
||||
slice = append(slice, obj)
|
||||
|
||||
i += (prevPos - pos)
|
||||
pos = prevPos
|
||||
}
|
||||
return slice, pos
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("byte not supported: %q", char))
|
||||
}
|
||||
|
||||
return slice, 0
|
||||
}
|
||||
|
||||
var (
|
||||
directRlp = big.NewInt(0x7f)
|
||||
numberRlp = big.NewInt(0xb7)
|
||||
@ -223,3 +168,67 @@ func Encode(object interface{}) []byte {
|
||||
|
||||
return buff.Bytes()
|
||||
}
|
||||
|
||||
// TODO Use a bytes.Buffer instead of a raw byte slice.
|
||||
// Cleaner code, and use draining instead of seeking the next bytes to read
|
||||
func Decode(data []byte, pos uint64) (interface{}, uint64) {
|
||||
var slice []interface{}
|
||||
char := int(data[pos])
|
||||
switch {
|
||||
case char <= 0x7f:
|
||||
return data[pos], pos + 1
|
||||
|
||||
case char <= 0xb7:
|
||||
b := uint64(data[pos]) - 0x80
|
||||
|
||||
return data[pos+1 : pos+1+b], pos + 1 + b
|
||||
|
||||
case char <= 0xbf:
|
||||
b := uint64(data[pos]) - 0xb7
|
||||
|
||||
b2 := ReadVarInt(data[pos+1 : pos+1+b])
|
||||
|
||||
return data[pos+1+b : pos+1+b+b2], pos + 1 + b + b2
|
||||
|
||||
case char <= 0xf7:
|
||||
b := uint64(data[pos]) - 0xc0
|
||||
prevPos := pos
|
||||
pos++
|
||||
for i := uint64(0); i < b; {
|
||||
var obj interface{}
|
||||
|
||||
// Get the next item in the data list and append it
|
||||
obj, prevPos = Decode(data, pos)
|
||||
slice = append(slice, obj)
|
||||
|
||||
// Increment i by the amount bytes read in the previous
|
||||
// read
|
||||
i += (prevPos - pos)
|
||||
pos = prevPos
|
||||
}
|
||||
return slice, pos
|
||||
|
||||
case char <= 0xff:
|
||||
l := uint64(data[pos]) - 0xf7
|
||||
b := ReadVarInt(data[pos+1 : pos+1+l])
|
||||
|
||||
pos = pos + l + 1
|
||||
|
||||
prevPos := b
|
||||
for i := uint64(0); i < uint64(b); {
|
||||
var obj interface{}
|
||||
|
||||
obj, prevPos = Decode(data, pos)
|
||||
slice = append(slice, obj)
|
||||
|
||||
i += (prevPos - pos)
|
||||
pos = prevPos
|
||||
}
|
||||
return slice, pos
|
||||
|
||||
default:
|
||||
panic(fmt.Sprintf("byte not supported: %q", char))
|
||||
}
|
||||
|
||||
return slice, 0
|
||||
}
|
||||
|
@ -44,6 +44,17 @@ func TestValueSlice(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestLargeData(t *testing.T) {
|
||||
data := make([]byte, 100000)
|
||||
enc := Encode(data)
|
||||
value := NewValue(enc)
|
||||
value.Decode()
|
||||
|
||||
if value.Len() != len(data) {
|
||||
t.Error("Expected data to be", len(data), "got", value.Len())
|
||||
}
|
||||
}
|
||||
|
||||
func TestValue(t *testing.T) {
|
||||
value := NewValueFromBytes([]byte("\xcd\x83dog\x83god\x83cat\x01"))
|
||||
if value.Get(0).Str() != "dog" {
|
||||
|
@ -1,7 +1,6 @@
|
||||
package ethutil
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"math/big"
|
||||
"reflect"
|
||||
@ -67,7 +66,9 @@ func (val *Value) Uint() uint64 {
|
||||
} else if Val, ok := val.Val.(uint); ok {
|
||||
return uint64(Val)
|
||||
} else if Val, ok := val.Val.([]byte); ok {
|
||||
return ReadVarint(bytes.NewReader(Val))
|
||||
return new(big.Int).SetBytes(Val).Uint64()
|
||||
} else if Val, ok := val.Val.(*big.Int); ok {
|
||||
return Val.Uint64()
|
||||
}
|
||||
|
||||
return 0
|
||||
@ -205,6 +206,13 @@ func (val *Value) Cmp(o *Value) bool {
|
||||
return reflect.DeepEqual(val.Val, o.Val)
|
||||
}
|
||||
|
||||
func (self *Value) DeepCmp(o *Value) bool {
|
||||
a := NewValue(self.BigInt())
|
||||
b := NewValue(o.BigInt())
|
||||
|
||||
return a.Cmp(b)
|
||||
}
|
||||
|
||||
func (val *Value) Encode() []byte {
|
||||
return Encode(val.Val)
|
||||
}
|
||||
@ -260,6 +268,55 @@ func (val *Value) Append(v interface{}) *Value {
|
||||
return val
|
||||
}
|
||||
|
||||
const (
|
||||
valOpAdd = iota
|
||||
valOpDiv
|
||||
valOpMul
|
||||
valOpPow
|
||||
valOpSub
|
||||
)
|
||||
|
||||
// Math stuff
|
||||
func (self *Value) doOp(op int, other interface{}) *Value {
|
||||
left := self.BigInt()
|
||||
right := NewValue(other).BigInt()
|
||||
|
||||
switch op {
|
||||
case valOpAdd:
|
||||
self.Val = left.Add(left, right)
|
||||
case valOpDiv:
|
||||
self.Val = left.Div(left, right)
|
||||
case valOpMul:
|
||||
self.Val = left.Mul(left, right)
|
||||
case valOpPow:
|
||||
self.Val = left.Exp(left, right, Big0)
|
||||
case valOpSub:
|
||||
self.Val = left.Sub(left, right)
|
||||
}
|
||||
|
||||
return self
|
||||
}
|
||||
|
||||
func (self *Value) Add(other interface{}) *Value {
|
||||
return self.doOp(valOpAdd, other)
|
||||
}
|
||||
|
||||
func (self *Value) Sub(other interface{}) *Value {
|
||||
return self.doOp(valOpSub, other)
|
||||
}
|
||||
|
||||
func (self *Value) Div(other interface{}) *Value {
|
||||
return self.doOp(valOpDiv, other)
|
||||
}
|
||||
|
||||
func (self *Value) Mul(other interface{}) *Value {
|
||||
return self.doOp(valOpMul, other)
|
||||
}
|
||||
|
||||
func (self *Value) Pow(other interface{}) *Value {
|
||||
return self.doOp(valOpPow, other)
|
||||
}
|
||||
|
||||
type ValueIterator struct {
|
||||
value *Value
|
||||
currentValue *Value
|
||||
|
@ -63,3 +63,18 @@ func TestIterator(t *testing.T) {
|
||||
i++
|
||||
}
|
||||
}
|
||||
|
||||
func TestMath(t *testing.T) {
|
||||
a := NewValue(1)
|
||||
a.Add(1).Add(1)
|
||||
|
||||
if !a.DeepCmp(NewValue(3)) {
|
||||
t.Error("Expected 3, got", a)
|
||||
}
|
||||
|
||||
a = NewValue(2)
|
||||
a.Sub(1).Sub(1)
|
||||
if !a.DeepCmp(NewValue(0)) {
|
||||
t.Error("Expected 0, got", a)
|
||||
}
|
||||
}
|
||||
|
Reference in New Issue
Block a user