diff options
author | zelig <viktor.tron@gmail.com> | 2014-07-31 00:03:20 +0800 |
---|---|---|
committer | zelig <viktor.tron@gmail.com> | 2014-07-31 00:03:20 +0800 |
commit | 9831619881c5264c2449ce1b906108d892b6e1e1 (patch) | |
tree | f8775b1196fe6b31081a553945377f40bdc8d550 /ethutil | |
parent | 194c58858cd230a9a08b0eb14650720341a5580e (diff) | |
parent | 42d47ecfb09ac0b419db5722602d9b02e21f2457 (diff) | |
download | go-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.go | 19 | ||||
-rw-r--r-- | ethutil/bytes.go | 27 | ||||
-rw-r--r-- | ethutil/common.go | 12 | ||||
-rw-r--r-- | ethutil/config.go | 6 | ||||
-rw-r--r-- | ethutil/path.go | 40 | ||||
-rw-r--r-- | ethutil/rlp.go | 139 | ||||
-rw-r--r-- | ethutil/rlp_test.go | 11 | ||||
-rw-r--r-- | ethutil/value.go | 61 | ||||
-rw-r--r-- | ethutil/value_test.go | 15 |
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) + } +} |