merge upstream

This commit is contained in:
zelig
2014-07-30 18:03:20 +02:00
37 changed files with 1323 additions and 868 deletions

View File

@ -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
}

View File

@ -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
}

View File

@ -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)
)

View File

@ -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)
}

View File

@ -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
}

View File

@ -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
}

View File

@ -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" {

View File

@ -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

View File

@ -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)
}
}