aboutsummaryrefslogtreecommitdiffstats
path: root/ethutil
diff options
context:
space:
mode:
authorzelig <viktor.tron@gmail.com>2014-07-31 00:03:20 +0800
committerzelig <viktor.tron@gmail.com>2014-07-31 00:03:20 +0800
commit9831619881c5264c2449ce1b906108d892b6e1e1 (patch)
treef8775b1196fe6b31081a553945377f40bdc8d550 /ethutil
parent194c58858cd230a9a08b0eb14650720341a5580e (diff)
parent42d47ecfb09ac0b419db5722602d9b02e21f2457 (diff)
downloadgo-tangerine-9831619881c5264c2449ce1b906108d892b6e1e1.tar
go-tangerine-9831619881c5264c2449ce1b906108d892b6e1e1.tar.gz
go-tangerine-9831619881c5264c2449ce1b906108d892b6e1e1.tar.bz2
go-tangerine-9831619881c5264c2449ce1b906108d892b6e1e1.tar.lz
go-tangerine-9831619881c5264c2449ce1b906108d892b6e1e1.tar.xz
go-tangerine-9831619881c5264c2449ce1b906108d892b6e1e1.tar.zst
go-tangerine-9831619881c5264c2449ce1b906108d892b6e1e1.zip
merge upstream
Diffstat (limited to 'ethutil')
-rw-r--r--ethutil/big.go19
-rw-r--r--ethutil/bytes.go27
-rw-r--r--ethutil/common.go12
-rw-r--r--ethutil/config.go6
-rw-r--r--ethutil/path.go40
-rw-r--r--ethutil/rlp.go139
-rw-r--r--ethutil/rlp_test.go11
-rw-r--r--ethutil/value.go61
-rw-r--r--ethutil/value_test.go15
9 files changed, 235 insertions, 95 deletions
diff --git a/ethutil/big.go b/ethutil/big.go
index 7af6f7414..ec263b818 100644
--- a/ethutil/big.go
+++ b/ethutil/big.go
@@ -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
+}
diff --git a/ethutil/bytes.go b/ethutil/bytes.go
index 34fff7d42..4027e3986 100644
--- a/ethutil/bytes.go
+++ b/ethutil/bytes.go
@@ -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
}
diff --git a/ethutil/common.go b/ethutil/common.go
index 2fd031a20..cbd94e7ad 100644
--- a/ethutil/common.go
+++ b/ethutil/common.go
@@ -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)
)
diff --git a/ethutil/config.go b/ethutil/config.go
index 41bece21d..81052318e 100644
--- a/ethutil/config.go
+++ b/ethutil/config.go
@@ -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)
}
diff --git a/ethutil/path.go b/ethutil/path.go
index 97f58ab7e..27022bcfa 100644
--- a/ethutil/path.go
+++ b/ethutil/path.go
@@ -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
+}
diff --git a/ethutil/rlp.go b/ethutil/rlp.go
index 195ef0efb..333a84927 100644
--- a/ethutil/rlp.go
+++ b/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,74 +71,20 @@ func DecodeWithReader(reader *bytes.Buffer) interface{} {
}
return slice
-
- }
-
- 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
+ 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
+ }
}
- return slice, pos
-
default:
- panic(fmt.Sprintf("byte not supported: %q", char))
}
- return slice, 0
+ return slice
}
var (
@@ -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
+}
diff --git a/ethutil/rlp_test.go b/ethutil/rlp_test.go
index 095c01ecc..90057ab42 100644
--- a/ethutil/rlp_test.go
+++ b/ethutil/rlp_test.go
@@ -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" {
diff --git a/ethutil/value.go b/ethutil/value.go
index fba7426d1..85dc44ed6 100644
--- a/ethutil/value.go
+++ b/ethutil/value.go
@@ -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
diff --git a/ethutil/value_test.go b/ethutil/value_test.go
index a100f44bc..710cbd887 100644
--- a/ethutil/value_test.go
+++ b/ethutil/value_test.go
@@ -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)
+ }
+}