aboutsummaryrefslogtreecommitdiffstats
path: root/common
diff options
context:
space:
mode:
authorobscuren <geffobscura@gmail.com>2015-03-16 18:27:38 +0800
committerobscuren <geffobscura@gmail.com>2015-03-16 18:27:38 +0800
commitb5234413611ce5984292f85a01de1f56c045b490 (patch)
treee6e0c6f7fe8358a2dc63cdea11ac66b4f59397f5 /common
parent0b8f66ed9ef177dc72442dd7ba337c6733e30344 (diff)
downloadgo-tangerine-b5234413611ce5984292f85a01de1f56c045b490.tar
go-tangerine-b5234413611ce5984292f85a01de1f56c045b490.tar.gz
go-tangerine-b5234413611ce5984292f85a01de1f56c045b490.tar.bz2
go-tangerine-b5234413611ce5984292f85a01de1f56c045b490.tar.lz
go-tangerine-b5234413611ce5984292f85a01de1f56c045b490.tar.xz
go-tangerine-b5234413611ce5984292f85a01de1f56c045b490.tar.zst
go-tangerine-b5234413611ce5984292f85a01de1f56c045b490.zip
Moved ethutil => common
Diffstat (limited to 'common')
-rw-r--r--common/.gitignore12
-rw-r--r--common/.travis.yml3
-rw-r--r--common/README.md139
-rw-r--r--common/big.go123
-rw-r--r--common/big_test.go73
-rw-r--r--common/bytes.go234
-rw-r--r--common/bytes_test.go193
-rw-r--r--common/common.go165
-rw-r--r--common/common_test.go89
-rw-r--r--common/config.go67
-rw-r--r--common/db.go12
-rw-r--r--common/list.go81
-rw-r--r--common/main_test.go9
-rw-r--r--common/math/dist.go80
-rw-r--r--common/math/dist_test.go66
-rw-r--r--common/natspec/natspec.go63
-rw-r--r--common/natspec/natspec_js.go4
-rw-r--r--common/natspec/natspec_test.go97
-rw-r--r--common/number/int.go181
-rw-r--r--common/number/uint_test.go92
-rw-r--r--common/package.go123
-rw-r--r--common/path.go68
-rw-r--r--common/path_test.go51
-rw-r--r--common/rlp.go276
-rw-r--r--common/rlp_test.go156
-rw-r--r--common/size.go15
-rw-r--r--common/size_test.go23
-rw-r--r--common/types.go6
-rw-r--r--common/value.go401
-rw-r--r--common/value_test.go70
30 files changed, 2972 insertions, 0 deletions
diff --git a/common/.gitignore b/common/.gitignore
new file mode 100644
index 000000000..f725d58d1
--- /dev/null
+++ b/common/.gitignore
@@ -0,0 +1,12 @@
+# See http://help.github.com/ignore-files/ for more about ignoring files.
+#
+# If you find yourself ignoring temporary files generated by your text editor
+# or operating system, you probably want to add a global ignore instead:
+# git config --global core.excludesfile ~/.gitignore_global
+
+/tmp
+*/**/*un~
+*un~
+.DS_Store
+*/**/.DS_Store
+
diff --git a/common/.travis.yml b/common/.travis.yml
new file mode 100644
index 000000000..69359072d
--- /dev/null
+++ b/common/.travis.yml
@@ -0,0 +1,3 @@
+language: go
+go:
+ - 1.2
diff --git a/common/README.md b/common/README.md
new file mode 100644
index 000000000..1ed56b71b
--- /dev/null
+++ b/common/README.md
@@ -0,0 +1,139 @@
+# ethutil
+
+[![Build
+Status](https://travis-ci.org/ethereum/go-ethereum.png?branch=master)](https://travis-ci.org/ethereum/go-ethereum)
+
+The ethutil package contains the ethereum utility library.
+
+# Installation
+
+`go get github.com/ethereum/ethutil-go`
+
+# Usage
+
+## RLP (Recursive Linear Prefix) Encoding
+
+RLP Encoding is an encoding scheme utilized by the Ethereum project. It
+encodes any native value or list to string.
+
+More in depth information about the Encoding scheme see the [Wiki](http://wiki.ethereum.org/index.php/RLP)
+article.
+
+```go
+rlp := ethutil.Encode("doge")
+fmt.Printf("%q\n", rlp) // => "\0x83dog"
+
+rlp = ethutil.Encode([]interface{}{"dog", "cat"})
+fmt.Printf("%q\n", rlp) // => "\0xc8\0x83dog\0x83cat"
+decoded := ethutil.Decode(rlp)
+fmt.Println(decoded) // => ["dog" "cat"]
+```
+
+## Patricia Trie
+
+Patricie Tree is a merkle trie utilized by the Ethereum project.
+
+More in depth information about the (modified) Patricia Trie can be
+found on the [Wiki](http://wiki.ethereum.org/index.php/Patricia_Tree).
+
+The patricia trie uses a db as backend and could be anything as long as
+it satisfies the Database interface found in `ethutil/db.go`.
+
+```go
+db := NewDatabase()
+
+// db, root
+trie := ethutil.NewTrie(db, "")
+
+trie.Put("puppy", "dog")
+trie.Put("horse", "stallion")
+trie.Put("do", "verb")
+trie.Put("doge", "coin")
+
+// Look up the key "do" in the trie
+out := trie.Get("do")
+fmt.Println(out) // => verb
+
+trie.Delete("puppy")
+```
+
+The patricia trie, in combination with RLP, provides a robust,
+cryptographically authenticated data structure that can be used to store
+all (key, value) bindings.
+
+```go
+// ... Create db/trie
+
+// Note that RLP uses interface slices as list
+value := ethutil.Encode([]interface{}{"one", 2, "three", []interface{}{42}})
+// Store the RLP encoded value of the list
+trie.Put("mykey", value)
+```
+
+## Value
+
+Value is a Generic Value which is used in combination with RLP data or
+`([])interface{}` structures. It may serve as a bridge between RLP data
+and actual real values and takes care of all the type checking and
+casting. Unlike Go's `reflect.Value` it does not panic if it's unable to
+cast to the requested value. It simple returns the base value of that
+type (e.g. `Slice()` returns []interface{}, `Uint()` return 0, etc).
+
+### Creating a new Value
+
+`NewEmptyValue()` returns a new \*Value with it's initial value set to a
+`[]interface{}`
+
+`AppendList()` appends a list to the current value.
+
+`Append(v)` appends the value (v) to the current value/list.
+
+```go
+val := ethutil.NewEmptyValue().Append(1).Append("2")
+val.AppendList().Append(3)
+```
+
+### Retrieving values
+
+`Get(i)` returns the `i` item in the list.
+
+`Uint()` returns the value as an unsigned int64.
+
+`Slice()` returns the value as a interface slice.
+
+`Str()` returns the value as a string.
+
+`Bytes()` returns the value as a byte slice.
+
+`Len()` assumes current to be a slice and returns its length.
+
+`Byte()` returns the value as a single byte.
+
+```go
+val := ethutil.NewValue([]interface{}{1,"2",[]interface{}{3}})
+val.Get(0).Uint() // => 1
+val.Get(1).Str() // => "2"
+s := val.Get(2) // => Value([]interface{}{3})
+s.Get(0).Uint() // => 3
+```
+
+## Decoding
+
+Decoding streams of RLP data is simplified
+
+```go
+val := ethutil.NewValueFromBytes(rlpData)
+val.Get(0).Uint()
+```
+
+## Encoding
+
+Encoding from Value to RLP is done with the `Encode` method. The
+underlying value can be anything RLP can encode (int, str, lists, bytes)
+
+```go
+val := ethutil.NewValue([]interface{}{1,"2",[]interface{}{3}})
+rlp := val.Encode()
+// Store the rlp data
+Store(rlp)
+```
diff --git a/common/big.go b/common/big.go
new file mode 100644
index 000000000..750b28f85
--- /dev/null
+++ b/common/big.go
@@ -0,0 +1,123 @@
+package common
+
+import "math/big"
+
+// Big pow
+//
+// Returns the power of two big integers
+func BigPow(a, b int) *big.Int {
+ c := new(big.Int)
+ c.Exp(big.NewInt(int64(a)), big.NewInt(int64(b)), big.NewInt(0))
+
+ return c
+}
+
+// Big
+//
+// Shortcut for new(big.Int).SetString(..., 0)
+func Big(num string) *big.Int {
+ n := new(big.Int)
+ n.SetString(num, 0)
+
+ return n
+}
+
+// BigD
+//
+// Shortcut for new(big.Int).SetBytes(...)
+func Bytes2Big(data []byte) *big.Int {
+ n := new(big.Int)
+ n.SetBytes(data)
+
+ return n
+}
+func BigD(data []byte) *big.Int { return Bytes2Big(data) }
+
+func String2Big(num string) *big.Int {
+ n := new(big.Int)
+ n.SetString(num, 0)
+ return n
+}
+
+func BitTest(num *big.Int, i int) bool {
+ return num.Bit(i) > 0
+}
+
+// To256
+//
+// "cast" the big int to a 256 big int (i.e., limit to)
+var tt256 = new(big.Int).Lsh(big.NewInt(1), 256)
+var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1))
+var tt255 = new(big.Int).Lsh(big.NewInt(1), 255)
+
+func U256(x *big.Int) *big.Int {
+ //if x.Cmp(Big0) < 0 {
+ // return new(big.Int).Add(tt256, x)
+ // }
+
+ x.And(x, tt256m1)
+
+ return x
+}
+
+func S256(x *big.Int) *big.Int {
+ if x.Cmp(tt255) < 0 {
+ return x
+ } else {
+ // We don't want to modify x, ever
+ return new(big.Int).Sub(x, tt256)
+ }
+}
+
+func FirstBitSet(v *big.Int) int {
+ for i := 0; i < v.BitLen(); i++ {
+ if v.Bit(i) > 0 {
+ return i
+ }
+ }
+
+ return v.BitLen()
+}
+
+// Big to bytes
+//
+// Returns the bytes of a big integer with the size specified by **base**
+// Attempts to pad the byte array with zeros.
+func BigToBytes(num *big.Int, base int) []byte {
+ ret := make([]byte, base/8)
+
+ if len(num.Bytes()) > base/8 {
+ return num.Bytes()
+ }
+
+ return append(ret[:len(ret)-len(num.Bytes())], num.Bytes()...)
+}
+
+// Big copy
+//
+// Creates a copy of the given big integer
+func BigCopy(src *big.Int) *big.Int {
+ return new(big.Int).Set(src)
+}
+
+// Big max
+//
+// Returns the maximum size big integer
+func BigMax(x, y *big.Int) *big.Int {
+ if x.Cmp(y) <= 0 {
+ return y
+ }
+
+ 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/common/big_test.go b/common/big_test.go
new file mode 100644
index 000000000..cedbaf144
--- /dev/null
+++ b/common/big_test.go
@@ -0,0 +1,73 @@
+package common
+
+import (
+ "bytes"
+ "testing"
+)
+
+func TestMisc(t *testing.T) {
+ a := Big("10")
+ b := Big("57896044618658097711785492504343953926634992332820282019728792003956564819968")
+ c := []byte{1, 2, 3, 4}
+ z := BitTest(a, 1)
+
+ if z != true {
+ t.Error("Expected true got", z)
+ }
+
+ U256(a)
+ S256(a)
+
+ U256(b)
+ S256(b)
+
+ BigD(c)
+}
+
+func TestBigMax(t *testing.T) {
+ a := Big("10")
+ b := Big("5")
+
+ max1 := BigMax(a, b)
+ if max1 != a {
+ t.Errorf("Expected %d got %d", a, max1)
+ }
+
+ max2 := BigMax(b, a)
+ if max2 != a {
+ t.Errorf("Expected %d got %d", a, max2)
+ }
+}
+
+func TestBigMin(t *testing.T) {
+ a := Big("10")
+ b := Big("5")
+
+ min1 := BigMin(a, b)
+ if min1 != b {
+ t.Errorf("Expected %d got %d", b, min1)
+ }
+
+ min2 := BigMin(b, a)
+ if min2 != b {
+ t.Errorf("Expected %d got %d", b, min2)
+ }
+}
+
+func TestBigCopy(t *testing.T) {
+ a := Big("10")
+ b := BigCopy(a)
+ c := Big("1000000000000")
+ y := BigToBytes(b, 16)
+ ybytes := []byte{0, 10}
+ z := BigToBytes(c, 16)
+ zbytes := []byte{232, 212, 165, 16, 0}
+
+ if bytes.Compare(y, ybytes) != 0 {
+ t.Error("Got", ybytes)
+ }
+
+ if bytes.Compare(z, zbytes) != 0 {
+ t.Error("Got", zbytes)
+ }
+}
diff --git a/common/bytes.go b/common/bytes.go
new file mode 100644
index 000000000..4aef9a223
--- /dev/null
+++ b/common/bytes.go
@@ -0,0 +1,234 @@
+package common
+
+import (
+ "bytes"
+ "encoding/binary"
+ "encoding/hex"
+ "fmt"
+ "math/big"
+ "strings"
+)
+
+type Bytes []byte
+
+func (self Bytes) String() string {
+ return string(self)
+}
+
+func DeleteFromByteSlice(s [][]byte, hash []byte) [][]byte {
+ for i, h := range s {
+ if bytes.Compare(h, hash) == 0 {
+ return append(s[:i:i], s[i+1:]...)
+ }
+ }
+
+ return s
+}
+
+// Number to bytes
+//
+// Returns the number in bytes with the specified base
+func NumberToBytes(num interface{}, bits int) []byte {
+ buf := new(bytes.Buffer)
+ err := binary.Write(buf, binary.BigEndian, num)
+ if err != nil {
+ fmt.Println("NumberToBytes failed:", err)
+ }
+
+ return buf.Bytes()[buf.Len()-(bits/8):]
+}
+
+// Bytes to number
+//
+// Attempts to cast a byte slice to a unsigned integer
+func BytesToNumber(b []byte) uint64 {
+ var number uint64
+
+ // Make sure the buffer is 64bits
+ data := make([]byte, 8)
+ data = append(data[:len(b)], b...)
+
+ buf := bytes.NewReader(data)
+ err := binary.Read(buf, binary.BigEndian, &number)
+ if err != nil {
+ fmt.Println("BytesToNumber failed:", err)
+ }
+
+ return number
+}
+
+// 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
+}
+
+// Binary length
+//
+// Returns the true binary length of the given number
+func BinaryLength(num int) int {
+ if num == 0 {
+ return 0
+ }
+
+ return 1 + BinaryLength(num>>8)
+}
+
+// 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
+}
+
+func IsHex(str string) bool {
+ l := len(str)
+ return l >= 4 && l%2 == 0 && str[0:2] == "0x"
+}
+
+func Bytes2Hex(d []byte) string {
+ return hex.EncodeToString(d)
+}
+
+func Hex2Bytes(str string) []byte {
+ h, _ := hex.DecodeString(str)
+
+ return h
+}
+
+func StringToByteFunc(str string, cb func(str string) []byte) (ret []byte) {
+ if len(str) > 1 && str[0:2] == "0x" && !strings.Contains(str, "\n") {
+ ret = Hex2Bytes(str[2:])
+ } else {
+ ret = cb(str)
+ }
+
+ return
+}
+
+func FormatData(data string) []byte {
+ if len(data) == 0 {
+ return nil
+ }
+ // Simple stupid
+ d := new(big.Int)
+ if data[0:1] == "\"" && data[len(data)-1:] == "\"" {
+ return RightPadBytes([]byte(data[1:len(data)-1]), 32)
+ } else if len(data) > 1 && data[:2] == "0x" {
+ d.SetBytes(Hex2Bytes(data[2:]))
+ } else {
+ d.SetString(data, 0)
+ }
+
+ return BigToBytes(d, 256)
+}
+
+func ParseData(data ...interface{}) (ret []byte) {
+ for _, item := range data {
+ switch t := item.(type) {
+ case string:
+ var str []byte
+ if IsHex(t) {
+ str = Hex2Bytes(t[2:])
+ } else {
+ str = []byte(t)
+ }
+
+ ret = append(ret, RightPadBytes(str, 32)...)
+ case []byte:
+ ret = append(ret, LeftPadBytes(t, 32)...)
+ }
+ }
+
+ return
+}
+
+func RightPadBytes(slice []byte, l int) []byte {
+ if l < len(slice) {
+ return slice
+ }
+
+ padded := make([]byte, l)
+ copy(padded[0:len(slice)], slice)
+
+ return padded
+}
+
+func LeftPadBytes(slice []byte, l int) []byte {
+ if l < len(slice) {
+ return slice
+ }
+
+ padded := make([]byte, l)
+ copy(padded[l-len(slice):], slice)
+
+ return padded
+}
+
+func LeftPadString(str string, l int) string {
+ if l < len(str) {
+ return str
+ }
+
+ zeros := Bytes2Hex(make([]byte, (l-len(str))/2))
+
+ return zeros + str
+
+}
+
+func RightPadString(str string, l int) string {
+ if l < len(str) {
+ return str
+ }
+
+ zeros := Bytes2Hex(make([]byte, (l-len(str))/2))
+
+ return str + zeros
+
+}
+
+func Address(slice []byte) (addr []byte) {
+ if len(slice) < 20 {
+ addr = LeftPadBytes(slice, 20)
+ } else if len(slice) > 20 {
+ addr = slice[len(slice)-20:]
+ } else {
+ addr = slice
+ }
+
+ addr = CopyBytes(addr)
+
+ return
+}
+
+func ByteSliceToInterface(slice [][]byte) (ret []interface{}) {
+ for _, i := range slice {
+ ret = append(ret, i)
+ }
+
+ return
+}
diff --git a/common/bytes_test.go b/common/bytes_test.go
new file mode 100644
index 000000000..ec106bf4b
--- /dev/null
+++ b/common/bytes_test.go
@@ -0,0 +1,193 @@
+package common
+
+import (
+ checker "gopkg.in/check.v1"
+)
+
+type BytesSuite struct{}
+
+var _ = checker.Suite(&BytesSuite{})
+
+func (s *BytesSuite) TestByteString(c *checker.C) {
+ var data Bytes
+ data = []byte{102, 111, 111}
+ exp := "foo"
+ res := data.String()
+
+ c.Assert(res, checker.Equals, exp)
+}
+
+/*
+func (s *BytesSuite) TestDeleteFromByteSlice(c *checker.C) {
+ data := []byte{1, 2, 3, 4}
+ slice := []byte{1, 2, 3, 4}
+ exp := []byte{1, 4}
+ res := DeleteFromByteSlice(data, slice)
+
+ c.Assert(res, checker.DeepEquals, exp)
+}
+
+*/
+func (s *BytesSuite) TestNumberToBytes(c *checker.C) {
+ // data1 := int(1)
+ // res1 := NumberToBytes(data1, 16)
+ // c.Check(res1, checker.Panics)
+
+ var data2 float64 = 3.141592653
+ exp2 := []byte{0xe9, 0x38}
+ res2 := NumberToBytes(data2, 16)
+ c.Assert(res2, checker.DeepEquals, exp2)
+}
+
+func (s *BytesSuite) TestBytesToNumber(c *checker.C) {
+ datasmall := []byte{0xe9, 0x38, 0xe9, 0x38}
+ datalarge := []byte{0xe9, 0x38, 0xe9, 0x38, 0xe9, 0x38, 0xe9, 0x38}
+
+ var expsmall uint64 = 0xe938e938
+ var explarge uint64 = 0x0
+
+ ressmall := BytesToNumber(datasmall)
+ reslarge := BytesToNumber(datalarge)
+
+ 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)
+}
+
+func (s *BytesSuite) TestBinaryLength(c *checker.C) {
+ data1 := 0
+ data2 := 920987656789
+
+ exp1 := 0
+ exp2 := 5
+
+ res1 := BinaryLength(data1)
+ res2 := BinaryLength(data2)
+
+ c.Assert(res1, checker.Equals, exp1)
+ c.Assert(res2, checker.Equals, exp2)
+}
+
+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)
+}
+
+func (s *BytesSuite) TestIsHex(c *checker.C) {
+ data1 := "a9e67e"
+ exp1 := false
+ res1 := IsHex(data1)
+ c.Assert(res1, checker.DeepEquals, exp1)
+
+ data2 := "0xa9e67e00"
+ exp2 := true
+ res2 := IsHex(data2)
+ c.Assert(res2, checker.DeepEquals, exp2)
+
+}
+
+func (s *BytesSuite) TestParseDataString(c *checker.C) {
+ res1 := ParseData("hello", "world", "0x0106")
+ data := "68656c6c6f000000000000000000000000000000000000000000000000000000776f726c640000000000000000000000000000000000000000000000000000000106000000000000000000000000000000000000000000000000000000000000"
+ exp1 := Hex2Bytes(data)
+ c.Assert(res1, checker.DeepEquals, exp1)
+}
+
+func (s *BytesSuite) TestParseDataBytes(c *checker.C) {
+ data1 := []byte{232, 212, 165, 16, 0}
+ exp1 := []byte{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 232, 212, 165, 16, 0}
+
+ res1 := ParseData(data1)
+ c.Assert(res1, checker.DeepEquals, exp1)
+
+}
+
+func (s *BytesSuite) TestLeftPadBytes(c *checker.C) {
+ val1 := []byte{1, 2, 3, 4}
+ exp1 := []byte{0, 0, 0, 0, 1, 2, 3, 4}
+
+ res1 := LeftPadBytes(val1, 8)
+ res2 := LeftPadBytes(val1, 2)
+
+ c.Assert(res1, checker.DeepEquals, exp1)
+ c.Assert(res2, checker.DeepEquals, val1)
+}
+
+func (s *BytesSuite) TestFormatData(c *checker.C) {
+ data1 := ""
+ data2 := "0xa9e67e00"
+ data3 := "a9e67e"
+ data4 := "\"a9e67e00\""
+
+ // exp1 := []byte{}
+ exp2 := []byte{00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 0xa9, 0xe6, 0x7e, 00}
+ exp3 := []byte{00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00}
+ exp4 := []byte{0x61, 0x39, 0x65, 0x36, 0x37, 0x65, 0x30, 0x30, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00, 00}
+
+ res1 := FormatData(data1)
+ res2 := FormatData(data2)
+ res3 := FormatData(data3)
+ res4 := FormatData(data4)
+
+ c.Assert(res1, checker.IsNil)
+ c.Assert(res2, checker.DeepEquals, exp2)
+ c.Assert(res3, checker.DeepEquals, exp3)
+ c.Assert(res4, checker.DeepEquals, exp4)
+}
+
+func (s *BytesSuite) TestRightPadBytes(c *checker.C) {
+ val := []byte{1, 2, 3, 4}
+ exp := []byte{1, 2, 3, 4, 0, 0, 0, 0}
+
+ resstd := RightPadBytes(val, 8)
+ resshrt := RightPadBytes(val, 2)
+
+ c.Assert(resstd, checker.DeepEquals, exp)
+ c.Assert(resshrt, checker.DeepEquals, val)
+}
+
+func (s *BytesSuite) TestLeftPadString(c *checker.C) {
+ val := "test"
+ exp := "\x30\x30\x30\x30" + val
+
+ resstd := LeftPadString(val, 8)
+ resshrt := LeftPadString(val, 2)
+
+ c.Assert(resstd, checker.Equals, exp)
+ c.Assert(resshrt, checker.Equals, val)
+}
+
+func (s *BytesSuite) TestRightPadString(c *checker.C) {
+ val := "test"
+ exp := val + "\x30\x30\x30\x30"
+
+ resstd := RightPadString(val, 8)
+ resshrt := RightPadString(val, 2)
+
+ c.Assert(resstd, checker.Equals, exp)
+ c.Assert(resshrt, checker.Equals, val)
+}
diff --git a/common/common.go b/common/common.go
new file mode 100644
index 000000000..1371d18d4
--- /dev/null
+++ b/common/common.go
@@ -0,0 +1,165 @@
+package common
+
+import (
+ "fmt"
+ "math/big"
+ "os"
+ "os/user"
+ "path"
+ "path/filepath"
+ "runtime"
+ "time"
+
+ "github.com/kardianos/osext"
+)
+
+// MakeName creates a node name that follows the ethereum convention
+// for such names. It adds the operation system name and Go runtime version
+// the name.
+func MakeName(name, version string) string {
+ return fmt.Sprintf("%s/v%s/%s/%s", name, version, runtime.GOOS, runtime.Version())
+}
+
+func DefaultAssetPath() string {
+ var assetPath string
+ pwd, _ := os.Getwd()
+ srcdir := path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "cmd", "mist")
+
+ // If the current working directory is the go-ethereum dir
+ // assume a debug build and use the source directory as
+ // asset directory.
+ if pwd == srcdir {
+ assetPath = path.Join(pwd, "assets")
+ } else {
+ switch runtime.GOOS {
+ case "darwin":
+ // Get Binary Directory
+ exedir, _ := osext.ExecutableFolder()
+ assetPath = filepath.Join(exedir, "../Resources")
+ case "linux":
+ assetPath = "/usr/share/mist"
+ case "windows":
+ assetPath = "./assets"
+ default:
+ assetPath = "."
+ }
+ }
+
+ // Check if the assetPath exists. If not, try the source directory
+ // This happens when binary is run from outside cmd/mist directory
+ if _, err := os.Stat(assetPath); os.IsNotExist(err) {
+ assetPath = path.Join(srcdir, "assets")
+ }
+
+ return assetPath
+}
+
+func DefaultDataDir() string {
+ usr, _ := user.Current()
+ if runtime.GOOS == "darwin" {
+ return path.Join(usr.HomeDir, "Library/Ethereum")
+ } else if runtime.GOOS == "windows" {
+ return path.Join(usr.HomeDir, "AppData/Roaming/Ethereum")
+ } else {
+ return path.Join(usr.HomeDir, ".ethereum")
+ }
+}
+
+func FromHex(s string) []byte {
+ if len(s) > 1 {
+ if s[0:2] == "0x" {
+ s = s[2:]
+ }
+ if len(s)%2 == 1 {
+ s = "0" + s
+ }
+ return Hex2Bytes(s)
+ }
+ return nil
+}
+func IsWindows() bool {
+ return runtime.GOOS == "windows"
+}
+
+func WindonizePath(path string) string {
+ if string(path[0]) == "/" && IsWindows() {
+ path = path[1:]
+ }
+ return path
+}
+
+// The different number of units
+var (
+ Douglas = BigPow(10, 42)
+ Einstein = BigPow(10, 21)
+ Ether = BigPow(10, 18)
+ Finney = BigPow(10, 15)
+ Szabo = BigPow(10, 12)
+ Shannon = BigPow(10, 9)
+ Babbage = BigPow(10, 6)
+ Ada = BigPow(10, 3)
+ Wei = big.NewInt(1)
+)
+
+//
+// Currency to string
+// Returns a string representing a human readable format
+func CurrencyToString(num *big.Int) string {
+ var (
+ fin *big.Int = num
+ denom string = "Wei"
+ )
+
+ switch {
+ case num.Cmp(Douglas) >= 0:
+ fin = new(big.Int).Div(num, Douglas)
+ denom = "Douglas"
+ case num.Cmp(Einstein) >= 0:
+ fin = new(big.Int).Div(num, Einstein)
+ denom = "Einstein"
+ case num.Cmp(Ether) >= 0:
+ fin = new(big.Int).Div(num, Ether)
+ denom = "Ether"
+ case num.Cmp(Finney) >= 0:
+ fin = new(big.Int).Div(num, Finney)
+ denom = "Finney"
+ case num.Cmp(Szabo) >= 0:
+ fin = new(big.Int).Div(num, Szabo)
+ denom = "Szabo"
+ case num.Cmp(Shannon) >= 0:
+ fin = new(big.Int).Div(num, Shannon)
+ denom = "Shannon"
+ case num.Cmp(Babbage) >= 0:
+ fin = new(big.Int).Div(num, Babbage)
+ denom = "Babbage"
+ case num.Cmp(Ada) >= 0:
+ fin = new(big.Int).Div(num, Ada)
+ denom = "Ada"
+ }
+
+ // TODO add comment clarifying expected behavior
+ if len(fin.String()) > 5 {
+ return fmt.Sprintf("%sE%d %s", fin.String()[0:5], len(fin.String())-5, denom)
+ }
+
+ return fmt.Sprintf("%v %s", fin, denom)
+}
+
+// Common big integers often used
+var (
+ Big1 = big.NewInt(1)
+ Big2 = big.NewInt(2)
+ Big3 = big.NewInt(3)
+ Big0 = big.NewInt(0)
+ BigTrue = Big1
+ BigFalse = Big0
+ Big32 = big.NewInt(32)
+ Big256 = big.NewInt(0xff)
+ Big257 = big.NewInt(257)
+)
+
+func Bench(pre string, cb func()) {
+ start := time.Now()
+ cb()
+ fmt.Println(pre, ": took:", time.Since(start))
+}
diff --git a/common/common_test.go b/common/common_test.go
new file mode 100644
index 000000000..c7ba87f90
--- /dev/null
+++ b/common/common_test.go
@@ -0,0 +1,89 @@
+package common
+
+import (
+ "bytes"
+ "math/big"
+ "os"
+ "testing"
+
+ checker "gopkg.in/check.v1"
+)
+
+type CommonSuite struct{}
+
+var _ = checker.Suite(&CommonSuite{})
+
+func (s *CommonSuite) TestOS(c *checker.C) {
+ expwin := (os.PathSeparator == '\\' && os.PathListSeparator == ';')
+ res := IsWindows()
+
+ if !expwin {
+ c.Assert(res, checker.Equals, expwin, checker.Commentf("IsWindows is", res, "but path is", os.PathSeparator))
+ } else {
+ c.Assert(res, checker.Not(checker.Equals), expwin, checker.Commentf("IsWindows is", res, "but path is", os.PathSeparator))
+ }
+}
+
+func (s *CommonSuite) TestWindonziePath(c *checker.C) {
+ iswindowspath := os.PathSeparator == '\\'
+ path := "/opt/eth/test/file.ext"
+ res := WindonizePath(path)
+ ressep := string(res[0])
+
+ if !iswindowspath {
+ c.Assert(ressep, checker.Equals, "/")
+ } else {
+ c.Assert(ressep, checker.Not(checker.Equals), "/")
+ }
+}
+
+func (s *CommonSuite) TestCommon(c *checker.C) {
+ douglas := CurrencyToString(BigPow(10, 43))
+ einstein := CurrencyToString(BigPow(10, 22))
+ ether := CurrencyToString(BigPow(10, 19))
+ finney := CurrencyToString(BigPow(10, 16))
+ szabo := CurrencyToString(BigPow(10, 13))
+ shannon := CurrencyToString(BigPow(10, 10))
+ babbage := CurrencyToString(BigPow(10, 7))
+ ada := CurrencyToString(BigPow(10, 4))
+ wei := CurrencyToString(big.NewInt(10))
+
+ c.Assert(douglas, checker.Equals, "10 Douglas")
+ c.Assert(einstein, checker.Equals, "10 Einstein")
+ c.Assert(ether, checker.Equals, "10 Ether")
+ c.Assert(finney, checker.Equals, "10 Finney")
+ c.Assert(szabo, checker.Equals, "10 Szabo")
+ c.Assert(shannon, checker.Equals, "10 Shannon")
+ c.Assert(babbage, checker.Equals, "10 Babbage")
+ c.Assert(ada, checker.Equals, "10 Ada")
+ c.Assert(wei, checker.Equals, "10 Wei")
+}
+
+func (s *CommonSuite) TestLarge(c *checker.C) {
+ douglaslarge := CurrencyToString(BigPow(100000000, 43))
+ adalarge := CurrencyToString(BigPow(100000000, 4))
+ weilarge := CurrencyToString(big.NewInt(100000000))
+
+ c.Assert(douglaslarge, checker.Equals, "10000E298 Douglas")
+ c.Assert(adalarge, checker.Equals, "10000E7 Einstein")
+ c.Assert(weilarge, checker.Equals, "100 Babbage")
+}
+
+//fromHex
+func TestFromHex(t *testing.T) {
+ input := "0x01"
+ expected := []byte{1}
+ result := FromHex(input)
+ if bytes.Compare(expected, result) != 0 {
+ t.Errorf("Expected % x got % x", expected, result)
+ }
+}
+
+func TestFromHexOddLength(t *testing.T) {
+ input := "0x1"
+ expected := []byte{1}
+ result := FromHex(input)
+ if bytes.Compare(expected, result) != 0 {
+ t.Errorf("Expected % x got % x", expected, result)
+ }
+}
diff --git a/common/config.go b/common/config.go
new file mode 100644
index 000000000..23a902bc1
--- /dev/null
+++ b/common/config.go
@@ -0,0 +1,67 @@
+package common
+
+import (
+ "flag"
+ "fmt"
+ "os"
+
+ "github.com/rakyll/globalconf"
+)
+
+// Config struct
+type ConfigManager struct {
+ ExecPath string
+ Debug bool
+ Diff bool
+ DiffType string
+ Paranoia bool
+ VmType int
+
+ conf *globalconf.GlobalConf
+}
+
+// Read config
+//
+// Initialize Config from Config File
+func ReadConfig(ConfigFile string, Datadir string, EnvPrefix string) *ConfigManager {
+ if !FileExist(ConfigFile) {
+ // create ConfigFile if it does not exist, otherwise
+ // globalconf will panic when trying to persist flags.
+ fmt.Printf("config file '%s' doesn't exist, creating it\n", ConfigFile)
+ os.Create(ConfigFile)
+ }
+ g, err := globalconf.NewWithOptions(&globalconf.Options{
+ Filename: ConfigFile,
+ EnvPrefix: EnvPrefix,
+ })
+ if err != nil {
+ fmt.Println(err)
+ } else {
+ g.ParseAll()
+ }
+ cfg := &ConfigManager{ExecPath: Datadir, Debug: true, conf: g, Paranoia: true}
+ return cfg
+}
+
+// provides persistence for flags
+func (c *ConfigManager) Save(key string, value interface{}) {
+ f := &flag.Flag{Name: key, Value: newConfValue(value)}
+ c.conf.Set("", f)
+}
+
+func (c *ConfigManager) Delete(key string) {
+ c.conf.Delete("", key)
+}
+
+// private type implementing flag.Value
+type confValue struct {
+ value string
+}
+
+// generic constructor to allow persising non-string values directly
+func newConfValue(value interface{}) *confValue {
+ return &confValue{fmt.Sprintf("%v", value)}
+}
+
+func (self confValue) String() string { return self.value }
+func (self confValue) Set(s string) error { self.value = s; return nil }
diff --git a/common/db.go b/common/db.go
new file mode 100644
index 000000000..6505e61c6
--- /dev/null
+++ b/common/db.go
@@ -0,0 +1,12 @@
+package common
+
+// Database interface
+type Database interface {
+ Put(key []byte, value []byte)
+ Get(key []byte) ([]byte, error)
+ //GetKeys() []*Key
+ Delete(key []byte) error
+ LastKnownTD() []byte
+ Close()
+ Print()
+}
diff --git a/common/list.go b/common/list.go
new file mode 100644
index 000000000..594a8a24b
--- /dev/null
+++ b/common/list.go
@@ -0,0 +1,81 @@
+package common
+
+import (
+ "encoding/json"
+ "reflect"
+ "sync"
+)
+
+// The list type is an anonymous slice handler which can be used
+// for containing any slice type to use in an environment which
+// does not support slice types (e.g., JavaScript, QML)
+type List struct {
+ mut sync.Mutex
+ val interface{}
+ list reflect.Value
+ Length int
+}
+
+// Initialise a new list. Panics if non-slice type is given.
+func NewList(t interface{}) *List {
+ list := reflect.ValueOf(t)
+ if list.Kind() != reflect.Slice {
+ panic("list container initialized with a non-slice type")
+ }
+
+ return &List{sync.Mutex{}, t, list, list.Len()}
+}
+
+func EmptyList() *List {
+ return NewList([]interface{}{})
+}
+
+// Get N element from the embedded slice. Returns nil if OOB.
+func (self *List) Get(i int) interface{} {
+ if self.list.Len() > i {
+ self.mut.Lock()
+ defer self.mut.Unlock()
+
+ i := self.list.Index(i).Interface()
+
+ return i
+ }
+
+ return nil
+}
+
+func (self *List) GetAsJson(i int) interface{} {
+ e := self.Get(i)
+
+ r, _ := json.Marshal(e)
+
+ return string(r)
+}
+
+// Appends value at the end of the slice. Panics when incompatible value
+// is given.
+func (self *List) Append(v interface{}) {
+ self.mut.Lock()
+ defer self.mut.Unlock()
+
+ self.list = reflect.Append(self.list, reflect.ValueOf(v))
+ self.Length = self.list.Len()
+}
+
+// Returns the underlying slice as interface.
+func (self *List) Interface() interface{} {
+ return self.list.Interface()
+}
+
+// For JavaScript <3
+func (self *List) ToJSON() string {
+ // make(T, 0) != nil
+ list := make([]interface{}, 0)
+ for i := 0; i < self.Length; i++ {
+ list = append(list, self.Get(i))
+ }
+
+ data, _ := json.Marshal(list)
+
+ return string(data)
+}
diff --git a/common/main_test.go b/common/main_test.go
new file mode 100644
index 000000000..2bed278e6
--- /dev/null
+++ b/common/main_test.go
@@ -0,0 +1,9 @@
+package common
+
+import (
+ "testing"
+
+ checker "gopkg.in/check.v1"
+)
+
+func Test(t *testing.T) { checker.TestingT(t) }
diff --git a/common/math/dist.go b/common/math/dist.go
new file mode 100644
index 000000000..0a0731971
--- /dev/null
+++ b/common/math/dist.go
@@ -0,0 +1,80 @@
+package math
+
+import (
+ "math/big"
+ "sort"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+type Summer interface {
+ Sum(i int) *big.Int
+ Len() int
+}
+
+func Sum(slice Summer) (sum *big.Int) {
+ sum = new(big.Int)
+
+ for i := 0; i < slice.Len(); i++ {
+ sum.Add(sum, slice.Sum(i))
+ }
+ return
+}
+
+type Vector struct {
+ Gas, Price *big.Int
+}
+
+type VectorsBy func(v1, v2 Vector) bool
+
+func (self VectorsBy) Sort(vectors []Vector) {
+ bs := vectorSorter{
+ vectors: vectors,
+ by: self,
+ }
+ sort.Sort(bs)
+}
+
+type vectorSorter struct {
+ vectors []Vector
+ by func(v1, v2 Vector) bool
+}
+
+func (v vectorSorter) Len() int { return len(v.vectors) }
+func (v vectorSorter) Less(i, j int) bool { return v.by(v.vectors[i], v.vectors[j]) }
+func (v vectorSorter) Swap(i, j int) { v.vectors[i], v.vectors[j] = v.vectors[j], v.vectors[i] }
+
+func PriceSort(v1, v2 Vector) bool { return v1.Price.Cmp(v2.Price) < 0 }
+func GasSort(v1, v2 Vector) bool { return v1.Gas.Cmp(v2.Gas) < 0 }
+
+type vectorSummer struct {
+ vectors []Vector
+ by func(v Vector) *big.Int
+}
+
+type VectorSum func(v Vector) *big.Int
+
+func (v VectorSum) Sum(vectors []Vector) *big.Int {
+ vs := vectorSummer{
+ vectors: vectors,
+ by: v,
+ }
+ return Sum(vs)
+}
+
+func (v vectorSummer) Len() int { return len(v.vectors) }
+func (v vectorSummer) Sum(i int) *big.Int { return v.by(v.vectors[i]) }
+
+func GasSum(v Vector) *big.Int { return v.Gas }
+
+var etherInWei = new(big.Rat).SetInt(common.String2Big("1000000000000000000"))
+
+func GasPrice(bp, gl, ep *big.Int) *big.Int {
+ BP := new(big.Rat).SetInt(bp)
+ GL := new(big.Rat).SetInt(gl)
+ EP := new(big.Rat).SetInt(ep)
+ GP := new(big.Rat).Quo(BP, GL)
+ GP = GP.Quo(GP, EP)
+
+ return GP.Mul(GP, etherInWei).Num()
+}
diff --git a/common/math/dist_test.go b/common/math/dist_test.go
new file mode 100644
index 000000000..90e302f44
--- /dev/null
+++ b/common/math/dist_test.go
@@ -0,0 +1,66 @@
+package math
+
+import (
+ "fmt"
+ "math/big"
+ "testing"
+)
+
+type summer struct {
+ numbers []*big.Int
+}
+
+func (s summer) Len() int { return len(s.numbers) }
+func (s summer) Sum(i int) *big.Int {
+ return s.numbers[i]
+}
+
+func TestSum(t *testing.T) {
+ summer := summer{numbers: []*big.Int{big.NewInt(1), big.NewInt(2), big.NewInt(3)}}
+ sum := Sum(summer)
+ if sum.Cmp(big.NewInt(6)) != 0 {
+ t.Errorf("not 6", sum)
+ }
+}
+
+func TestDist(t *testing.T) {
+ var vectors = []Vector{
+ Vector{big.NewInt(1000), big.NewInt(1234)},
+ Vector{big.NewInt(500), big.NewInt(10023)},
+ Vector{big.NewInt(1034), big.NewInt(1987)},
+ Vector{big.NewInt(1034), big.NewInt(1987)},
+ Vector{big.NewInt(8983), big.NewInt(1977)},
+ Vector{big.NewInt(98382), big.NewInt(1887)},
+ Vector{big.NewInt(12398), big.NewInt(1287)},
+ Vector{big.NewInt(12398), big.NewInt(1487)},
+ Vector{big.NewInt(12398), big.NewInt(1987)},
+ Vector{big.NewInt(12398), big.NewInt(128)},
+ Vector{big.NewInt(12398), big.NewInt(1987)},
+ Vector{big.NewInt(1398), big.NewInt(187)},
+ Vector{big.NewInt(12328), big.NewInt(1927)},
+ Vector{big.NewInt(12398), big.NewInt(1987)},
+ Vector{big.NewInt(22398), big.NewInt(1287)},
+ Vector{big.NewInt(1370), big.NewInt(1981)},
+ Vector{big.NewInt(12398), big.NewInt(1957)},
+ Vector{big.NewInt(42198), big.NewInt(1987)},
+ }
+
+ VectorsBy(GasSort).Sort(vectors)
+ fmt.Println(vectors)
+
+ BP := big.NewInt(15)
+ GL := big.NewInt(1000000)
+ EP := big.NewInt(100)
+ fmt.Println("BP", BP, "GL", GL, "EP", EP)
+ GP := GasPrice(BP, GL, EP)
+ fmt.Println("GP =", GP, "Wei per GU")
+
+ S := len(vectors) / 4
+ fmt.Println("L", len(vectors), "S", S)
+ for i := 1; i <= S*4; i += S {
+ fmt.Printf("T%d = %v\n", i, vectors[i])
+ }
+
+ g := VectorSum(GasSum).Sum(vectors)
+ fmt.Printf("G = ∑g* (%v)\n", g)
+}
diff --git a/common/natspec/natspec.go b/common/natspec/natspec.go
new file mode 100644
index 000000000..793bf59ae
--- /dev/null
+++ b/common/natspec/natspec.go
@@ -0,0 +1,63 @@
+package natspec
+
+import (
+ "fmt"
+ "github.com/obscuren/otto"
+)
+
+type NatSpec struct {
+ jsvm *otto.Otto
+}
+
+// TODO: should initialise with abi and userdoc jsons
+func New() (self *NatSpec, err error) {
+
+ self = new(NatSpec)
+ self.jsvm = otto.New()
+
+ _, err = self.jsvm.Run(natspecJS)
+ if err != nil {
+ return
+ }
+ _, err = self.jsvm.Run("var natspec = require('natspec');")
+ if err != nil {
+ return
+ }
+
+ return
+}
+
+func (self *NatSpec) Notice(transaction, abi, method, expression string) (string, error) {
+ var err error
+ if _, err = self.jsvm.Run("var transaction = " + transaction + ";"); err != nil {
+ return "", fmt.Errorf("natspec.js error setting transaction: %v", err)
+ }
+
+ if _, err = self.jsvm.Run("var abi = " + abi + ";"); err != nil {
+ return "", fmt.Errorf("natspec.js error setting abi: %v", err)
+ }
+
+ if _, err = self.jsvm.Run("var method = '" + method + "';"); err != nil {
+ return "", fmt.Errorf("natspec.js error setting method: %v", err)
+ }
+
+ if _, err = self.jsvm.Run("var expression = \"" + expression + "\";"); err != nil {
+ return "", fmt.Errorf("natspec.js error setting expression: %v", err)
+ }
+
+ self.jsvm.Run("var call = {method: method,abi: abi,transaction: transaction};")
+ value, err := self.jsvm.Run("natspec.evaluateExpression(expression, call);")
+ if err != nil {
+ return "", fmt.Errorf("natspec.js error evaluating expression: %v", err)
+ }
+ evalError := "Natspec evaluation failed, wrong input params"
+ if value.String() == evalError {
+ return "", fmt.Errorf("natspec.js error evaluating expression: wrong input params in expression '%s'", expression)
+ }
+ if len(value.String()) == 0 {
+ return "", fmt.Errorf("natspec.js error evaluating expression")
+ }
+
+ return value.String(), nil
+
+}
diff --git a/common/natspec/natspec_js.go b/common/natspec/natspec_js.go
new file mode 100644
index 000000000..96d8204fb
--- /dev/null
+++ b/common/natspec/natspec_js.go
@@ -0,0 +1,4 @@
+package natspec
+
+const natspecJS = `require=function t(e,n,r){function i(f,u){if(!n[f]){if(!e[f]){var s="function"==typeof require&&require;if(!u&&s)return s(f,!0);if(o)return o(f,!0);var c=new Error("Cannot find module '"+f+"'");throw c.code="MODULE_NOT_FOUND",c}var a=n[f]={exports:{}};e[f][0].call(a.exports,function(t){var n=e[f][1][t];return i(n?n:t)},a,a.exports,t,e,n,r)}return n[f].exports}for(var o="function"==typeof require&&require,f=0;f<r.length;f++)i(r[f]);return i}({1:[function(){},{}],2:[function(t,e){function n(){if(!f){f=!0;for(var t,e=o.length;e;){t=o,o=[];for(var n=-1;++n<e;)t[n]();e=o.length}f=!1}}function r(){}var i=e.exports={},o=[],f=!1;i.nextTick=function(t){o.push(t),f||setTimeout(n,0)},i.title="browser",i.browser=!0,i.env={},i.argv=[],i.version="",i.on=r,i.addListener=r,i.once=r,i.off=r,i.removeListener=r,i.removeAllListeners=r,i.emit=r,i.binding=function(){throw new Error("process.binding is not supported")},i.cwd=function(){return"/"},i.chdir=function(){throw new Error("process.chdir is not supported")},i.umask=function(){return 0}},{}],3:[function(t,e){var n=t("./utils"),r=t("./types"),i=t("./const"),o=t("./formatters"),f=function(t){console.error("parser does not support type: "+t)},u=function(t){return"[]"===t.slice(-2)},s=function(t,e){return u(t)||"string"===t?o.formatInputInt(e.length):""},c=r.inputTypes(),a=function(t,e){var n="",r="",i="";return t.forEach(function(t,r){n+=s(t.type,e[r])}),t.forEach(function(n,o){for(var s=!1,a=0;a<c.length&&!s;a++)s=c[a].type(t[o].type,e[o]);s||f(t[o].type);var l=c[a-1].format;u(t[o].type)?i+=e[o].reduce(function(t,e){return t+l(e)},""):"string"===t[o].type?i+=l(e[o]):r+=l(e[o])}),n+=r+i},l=function(t){return u(t)||"string"===t?2*i.ETH_PADDING:0},p=r.outputTypes(),h=function(t,e){e=e.slice(2);var n=[],s=2*i.ETH_PADDING,c=t.reduce(function(t,e){return t+l(e.type)},0),a=e.slice(0,c);return e=e.slice(c),t.forEach(function(i,c){for(var l=!1,h=0;h<p.length&&!l;h++)l=p[h].type(t[c].type);l||f(t[c].type);var g=p[h-1].format;if(u(t[c].type)){var m=o.formatOutputUInt(a.slice(0,s));a=a.slice(s);for(var d=[],v=0;m>v;v++)d.push(g(e.slice(0,s))),e=e.slice(s);n.push(d)}else r.prefixedType("string")(t[c].type)?(a=a.slice(s),n.push(g(e.slice(0,s))),e=e.slice(s)):(n.push(g(e.slice(0,s))),e=e.slice(s))}),n},g=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),i=n.extractTypeName(t.name),o=function(){var e=Array.prototype.slice.call(arguments);return a(t.inputs,e)};void 0===e[r]&&(e[r]=o),e[r][i]=o}),e},m=function(t){var e={};return t.forEach(function(t){var r=n.extractDisplayName(t.name),i=n.extractTypeName(t.name),o=function(e){return h(t.outputs,e)};void 0===e[r]&&(e[r]=o),e[r][i]=o}),e};e.exports={inputParser:g,outputParser:m,formatInput:a,formatOutput:h}},{"./const":4,"./formatters":5,"./types":6,"./utils":7}],4:[function(t,e){(function(n){if("build"!==n.env.NODE_ENV)var r=t("bignumber.js");var i=["wei","Kwei","Mwei","Gwei","szabo","finney","ether","grand","Mether","Gether","Tether","Pether","Eether","Zether","Yether","Nether","Dether","Vether","Uether"];e.exports={ETH_PADDING:32,ETH_SIGNATURE_LENGTH:4,ETH_UNITS:i,ETH_BIGNUMBER_ROUNDING_MODE:{ROUNDING_MODE:r.ROUND_DOWN},ETH_POLLING_TIMEOUT:1e3}}).call(this,t("_process"))},{_process:2,"bignumber.js":8}],5:[function(t,e){(function(n){if("build"!==n.env.NODE_ENV)var r=t("bignumber.js");var i=t("./utils"),o=t("./const"),f=function(t,e,n){return new Array(e-t.length+1).join(n?n:"0")+t},u=function(t){var e=2*o.ETH_PADDING;return t instanceof r||"number"==typeof t?("number"==typeof t&&(t=new r(t)),r.config(o.ETH_BIGNUMBER_ROUNDING_MODE),t=t.round(),t.lessThan(0)&&(t=new r("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16).plus(t).plus(1)),t=t.toString(16)):t=0===t.indexOf("0x")?t.substr(2):"string"==typeof t?u(new r(t)):(+t).toString(16),f(t,e)},s=function(t){return i.fromAscii(t,o.ETH_PADDING).substr(2)},c=function(t){return"000000000000000000000000000000000000000000000000000000000000000"+(t?"1":"0")},a=function(t){return u(new r(t).times(new r(2).pow(128)))},l=function(t){return"1"===new r(t.substr(0,1),16).toString(2).substr(0,1)},p=function(t){return t=t||"0",l(t)?new r(t,16).minus(new r("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff",16)).minus(1):new r(t,16)},h=function(t){return t=t||"0",new r(t,16)},g=function(t){return p(t).dividedBy(new r(2).pow(128))},m=function(t){return h(t).dividedBy(new r(2).pow(128))},d=function(t){return"0x"+t},v=function(t){return"0000000000000000000000000000000000000000000000000000000000000001"===t?!0:!1},w=function(t){return i.toAscii(t)},y=function(t){return"0x"+t.slice(t.length-40,t.length)};e.exports={formatInputInt:u,formatInputString:s,formatInputBool:c,formatInputReal:a,formatOutputInt:p,formatOutputUInt:h,formatOutputReal:g,formatOutputUReal:m,formatOutputHash:d,formatOutputBool:v,formatOutputString:w,formatOutputAddress:y}}).call(this,t("_process"))},{"./const":4,"./utils":7,_process:2,"bignumber.js":8}],6:[function(t,e){var n=t("./formatters"),r=function(t){return function(e){return 0===e.indexOf(t)}},i=function(t){return function(e){return t===e}},o=function(){return[{type:r("uint"),format:n.formatInputInt},{type:r("int"),format:n.formatInputInt},{type:r("hash"),format:n.formatInputInt},{type:r("string"),format:n.formatInputString},{type:r("real"),format:n.formatInputReal},{type:r("ureal"),format:n.formatInputReal},{type:i("address"),format:n.formatInputInt},{type:i("bool"),format:n.formatInputBool}]},f=function(){return[{type:r("uint"),format:n.formatOutputUInt},{type:r("int"),format:n.formatOutputInt},{type:r("hash"),format:n.formatOutputHash},{type:r("string"),format:n.formatOutputString},{type:r("real"),format:n.formatOutputReal},{type:r("ureal"),format:n.formatOutputUReal},{type:i("address"),format:n.formatOutputAddress},{type:i("bool"),format:n.formatOutputBool}]};e.exports={prefixedType:r,namedType:i,inputTypes:o,outputTypes:f}},{"./formatters":5}],7:[function(t,e){var n=t("./const"),r=function(t,e){for(var n=!1,r=0;r<t.length&&!n;r++)n=e(t[r]);return n?r-1:-1},i=function(t){var e="",n=0,r=t.length;for("0x"===t.substring(0,2)&&(n=2);r>n;n+=2){var i=parseInt(t.substr(n,2),16);if(0===i)break;e+=String.fromCharCode(i)}return e},o=function(t){for(var e="",n=0;n<t.length;n++){var r=t.charCodeAt(n).toString(16);e+=r.length<2?"0"+r:r}return e},f=function(t,e){e=void 0===e?0:e;for(var n=o(t);n.length<2*e;)n+="00";return"0x"+n},u=function(t){var e=t.indexOf("(");return-1!==e?t.substr(0,e):t},s=function(t){var e=t.indexOf("(");return-1!==e?t.substr(e+1,t.length-1-(e+1)).replace(" ",""):""},c=function(t){return t.filter(function(t){return"function"===t.type})},a=function(t){return t.filter(function(t){return"event"===t.type})},l=function(t){for(var e="string"==typeof t?0===t.indexOf("0x")?parseInt(t.substr(2),16):parseInt(t):t,r=0,i=n.ETH_UNITS;e>3e3&&r<i.length-1;)e/=1e3,r++;for(var o=e.toString().length<e.toFixed(2).length?e.toString():e.toFixed(2),f=function(t,e,n){return e+","+n};;){var u=o;if(o=o.replace(/(\d)(\d\d\d[\.\,])/,f),u===o)break}return o+" "+i[r]};e.exports={findIndex:r,toAscii:i,fromAscii:f,extractDisplayName:u,extractTypeName:s,filterFunctions:c,filterEvents:a,toEth:l}},{"./const":4}],8:[function(t,e){!function(n){"use strict";function r(t){function e(t,r){var i,o,f,u,s,c,a=this;if(!(a instanceof e))return $&&U(26,"constructor call without new",t),new e(t,r);if(null!=r&&z(r,2,64,L,"base")){if(r=0|r,c=t+"",10==r)return a=new e(t instanceof e?t:c),F(a,B+a.e+1,H);if((u="number"==typeof t)&&0*t!=0||!new RegExp("^-?"+(i="["+N.slice(0,r)+"]+")+"(?:\\."+i+")?$",37>r?"i":"").test(c))return m(a,c,u,r);u?(a.s=0>1/t?(c=c.slice(1),-1):1,$&&c.replace(/^0\.0*|\./,"").length>15&&U(L,O,t),u=!1):a.s=45===c.charCodeAt(0)?(c=c.slice(1),-1):1,c=n(c,10,r,a.s)}else{if(t instanceof e)return a.s=t.s,a.e=t.e,a.c=(t=t.c)?t.slice():t,void(L=0);if((u="number"==typeof t)&&0*t==0){if(a.s=0>1/t?(t=-t,-1):1,t===~~t){for(o=0,f=t;f>=10;f/=10,o++);return a.e=o,a.c=[t],void(L=0)}c=t+""}else{if(!d.test(c=t+""))return m(a,c,u);a.s=45===c.charCodeAt(0)?(c=c.slice(1),-1):1}}for((o=c.indexOf("."))>-1&&(c=c.replace(".","")),(f=c.search(/e/i))>0?(0>o&&(o=f),o+=+c.slice(f+1),c=c.substring(0,f)):0>o&&(o=c.length),f=0;48===c.charCodeAt(f);f++);for(s=c.length;48===c.charCodeAt(--s););if(c=c.slice(f,s+1))if(s=c.length,u&&$&&s>15&&U(L,O,a.s*t),o=o-f-1,o>q)a.c=a.e=null;else if(k>o)a.c=[a.e=0];else{if(a.e=o,a.c=[],f=(o+1)%I,0>o&&(f+=I),s>f){for(f&&a.c.push(+c.slice(0,f)),s-=I;s>f;)a.c.push(+c.slice(f,f+=I));c=c.slice(f),f=I-c.length}else f-=s;for(;f--;c+="0");a.c.push(+c)}else a.c=[a.e=0];L=0}function n(t,n,r,i){var f,u,s,a,p,h,g,m=t.indexOf("."),d=B,v=H;for(37>r&&(t=t.toLowerCase()),m>=0&&(s=Y,Y=0,t=t.replace(".",""),g=new e(r),p=g.pow(t.length-m),Y=s,g.c=c(l(o(p.c),p.e),10,n),g.e=g.c.length),h=c(t,r,n),u=s=h.length;0==h[--s];h.pop());if(!h[0])return"0";if(0>m?--u:(p.c=h,p.e=u,p.s=i,p=G(p,g,d,v,n),h=p.c,a=p.r,u=p.e),f=u+d+1,m=h[f],s=n/2,a=a||0>f||null!=h[f+1],a=4>v?(null!=m||a)&&(0==v||v==(p.s<0?3:2)):m>s||m==s&&(4==v||a||6==v&&1&h[f-1]||v==(p.s<0?8:7)),1>f||!h[0])t=a?l("1",-d):"0";else{if(h.length=f,a)for(--n;++h[--f]>n;)h[f]=0,f||(++u,h.unshift(1));for(s=h.length;!h[--s];);for(m=0,t="";s>=m;t+=N.charAt(h[m++]));t=l(t,u)}return t}function h(t,n,r,i){var f,u,s,c,p;if(r=null!=r&&z(r,0,8,i,b)?0|r:H,!t.c)return t.toString();if(f=t.c[0],s=t.e,null==n)p=o(t.c),p=19==i||24==i&&C>=s?a(p,s):l(p,s);else if(t=F(new e(t),n,r),u=t.e,p=o(t.c),c=p.length,19==i||24==i&&(u>=n||C>=u)){for(;n>c;p+="0",c++);p=a(p,u)}else if(n-=s,p=l(p,u),u+1>c){if(--n>0)for(p+=".";n--;p+="0");}else if(n+=u-c,n>0)for(u+1==c&&(p+=".");n--;p+="0");return t.s<0&&f?"-"+p:p}function S(t,n){var r,i,o=0;for(s(t[0])&&(t=t[0]),r=new e(t[0]);++o<t.length;){if(i=new e(t[o]),!i.s){r=i;break}n.call(r,i)&&(r=i)}return r}function A(t,e,n,r,i){return(e>t||t>n||t!=p(t))&&U(r,(i||"decimal places")+(e>t||t>n?" out of range":" not an integer"),t),!0}function R(t,e,n){for(var r=1,i=e.length;!e[--i];e.pop());for(i=e[0];i>=10;i/=10,r++);return(n=r+n*I-1)>q?t.c=t.e=null:k>n?t.c=[t.e=0]:(t.e=n,t.c=e),t}function U(t,e,n){var r=new Error(["new BigNumber","cmp","config","div","divToInt","eq","gt","gte","lt","lte","minus","mod","plus","precision","random","round","shift","times","toDigits","toExponential","toFixed","toFormat","toFraction","pow","toPrecision","toString","BigNumber"][t]+"() "+e+": "+n);throw r.name="BigNumber Error",L=0,r}function F(t,e,n,r){var i,o,f,u,s,c,a,l=t.c,p=_;if(l){t:{for(i=1,u=l[0];u>=10;u/=10,i++);if(o=e-i,0>o)o+=I,f=e,s=l[c=0],a=s/p[i-f-1]%10|0;else if(c=v((o+1)/I),c>=l.length){if(!r)break t;for(;l.length<=c;l.push(0));s=a=0,i=1,o%=I,f=o-I+1}else{for(s=u=l[c],i=1;u>=10;u/=10,i++);o%=I,f=o-I+i,a=0>f?0:s/p[i-f-1]%10|0}if(r=r||0>e||null!=l[c+1]||(0>f?s:s%p[i-f-1]),r=4>n?(a||r)&&(0==n||n==(t.s<0?3:2)):a>5||5==a&&(4==n||r||6==n&&(o>0?f>0?s/p[i-f]:0:l[c-1])%10&1||n==(t.s<0?8:7)),1>e||!l[0])return l.length=0,r?(e-=t.e+1,l[0]=p[e%I],t.e=-e||0):l[0]=t.e=0,t;if(0==o?(l.length=c,u=1,c--):(l.length=c+1,u=p[I-o],l[c]=f>0?w(s/p[i-f]%p[f])*u:0),r)for(;;){if(0==c){for(o=1,f=l[0];f>=10;f/=10,o++);for(f=l[0]+=u,u=1;f>=10;f/=10,u++);o!=u&&(t.e++,l[0]==E&&(l[0]=1));break}if(l[c]+=u,l[c]!=E)break;l[c--]=0,u=1}for(o=l.length;0===l[--o];l.pop());}t.e>q?t.c=t.e=null:t.e<k&&(t.c=[t.e=0])}return t}var G,L=0,M=e.prototype,P=new e(1),B=20,H=4,C=-7,j=21,k=-1e7,q=1e7,$=!0,z=A,V=!1,W=1,Y=100,Z={decimalSeparator:".",groupSeparator:",",groupSize:3,secondaryGroupSize:0,fractionGroupSeparator:" ",fractionGroupSize:0};return e.another=r,e.ROUND_UP=0,e.ROUND_DOWN=1,e.ROUND_CEIL=2,e.ROUND_FLOOR=3,e.ROUND_HALF_UP=4,e.ROUND_HALF_DOWN=5,e.ROUND_HALF_EVEN=6,e.ROUND_HALF_CEIL=7,e.ROUND_HALF_FLOOR=8,e.EUCLID=9,e.config=function(){var t,e,n=0,r={},i=arguments,o=i[0],f=o&&"object"==typeof o?function(){return o.hasOwnProperty(e)?null!=(t=o[e]):void 0}:function(){return i.length>n?null!=(t=i[n++]):void 0};return f(e="DECIMAL_PLACES")&&z(t,0,D,2,e)&&(B=0|t),r[e]=B,f(e="ROUNDING_MODE")&&z(t,0,8,2,e)&&(H=0|t),r[e]=H,f(e="EXPONENTIAL_AT")&&(s(t)?z(t[0],-D,0,2,e)&&z(t[1],0,D,2,e)&&(C=0|t[0],j=0|t[1]):z(t,-D,D,2,e)&&(C=-(j=0|(0>t?-t:t)))),r[e]=[C,j],f(e="RANGE")&&(s(t)?z(t[0],-D,-1,2,e)&&z(t[1],1,D,2,e)&&(k=0|t[0],q=0|t[1]):z(t,-D,D,2,e)&&(0|t?k=-(q=0|(0>t?-t:t)):$&&U(2,e+" cannot be zero",t))),r[e]=[k,q],f(e="ERRORS")&&(t===!!t||1===t||0===t?(L=0,z=($=!!t)?A:u):$&&U(2,e+y,t)),r[e]=$,f(e="CRYPTO")&&(t===!!t||1===t||0===t?(V=!(!t||!g||"object"!=typeof g),t&&!V&&$&&U(2,"crypto unavailable",g)):$&&U(2,e+y,t)),r[e]=V,f(e="MODULO_MODE")&&z(t,0,9,2,e)&&(W=0|t),r[e]=W,f(e="POW_PRECISION")&&z(t,0,D,2,e)&&(Y=0|t),r[e]=Y,f(e="FORMAT")&&("object"==typeof t?Z=t:$&&U(2,e+" not an object",t)),r[e]=Z,r},e.max=function(){return S(arguments,M.lt)},e.min=function(){return S(arguments,M.gt)},e.random=function(){var t=9007199254740992,n=Math.random()*t&2097151?function(){return w(Math.random()*t)}:function(){return 8388608*(1073741824*Math.random()|0)+(8388608*Math.random()|0)};return function(t){var r,i,o,f,u,s=0,c=[],a=new e(P);if(t=null!=t&&z(t,0,D,14)?0|t:B,f=v(t/I),V)if(g&&g.getRandomValues){for(r=g.getRandomValues(new Uint32Array(f*=2));f>s;)u=131072*r[s]+(r[s+1]>>>11),u>=9e15?(i=g.getRandomValues(new Uint32Array(2)),r[s]=i[0],r[s+1]=i[1]):(c.push(u%1e14),s+=2);s=f/2}else if(g&&g.randomBytes){for(r=g.randomBytes(f*=7);f>s;)u=281474976710656*(31&r[s])+1099511627776*r[s+1]+4294967296*r[s+2]+16777216*r[s+3]+(r[s+4]<<16)+(r[s+5]<<8)+r[s+6],u>=9e15?g.randomBytes(7).copy(r,s):(c.push(u%1e14),s+=7);s=f/7}else $&&U(14,"crypto unavailable",g);if(!s)for(;f>s;)u=n(),9e15>u&&(c[s++]=u%1e14);for(f=c[--s],t%=I,f&&t&&(u=_[I-t],c[s]=w(f/u)*u);0===c[s];c.pop(),s--);if(0>s)c=[o=0];else{for(o=-1;0===c[0];c.shift(),o-=I);for(s=1,u=c[0];u>=10;u/=10,s++);I>s&&(o-=I-s)}return a.e=o,a.c=c,a}}(),G=function(){function t(t,e,n){var r,i,o,f,u=0,s=t.length,c=e%T,a=e/T|0;for(t=t.slice();s--;)o=t[s]%T,f=t[s]/T|0,r=a*o+f*c,i=c*o+r%T*T+u,u=(i/n|0)+(r/T|0)+a*f,t[s]=i%n;return u&&t.unshift(u),t}function n(t,e,n,r){var i,o;if(n!=r)o=n>r?1:-1;else for(i=o=0;n>i;i++)if(t[i]!=e[i]){o=t[i]>e[i]?1:-1;break}return o}function r(t,e,n,r){for(var i=0;n--;)t[n]-=i,i=t[n]<e[n]?1:0,t[n]=i*r+t[n]-e[n];for(;!t[0]&&t.length>1;t.shift());}return function(o,f,u,s,c){var a,l,p,h,g,m,d,v,y,b,O,N,x,_,T,D,S,A=o.s==f.s?1:-1,R=o.c,U=f.c;if(!(R&&R[0]&&U&&U[0]))return new e(o.s&&f.s&&(R?!U||R[0]!=U[0]:U)?R&&0==R[0]||!U?0*A:A/0:0/0);for(v=new e(A),y=v.c=[],l=o.e-f.e,A=u+l+1,c||(c=E,l=i(o.e/I)-i(f.e/I),A=A/I|0),p=0;U[p]==(R[p]||0);p++);if(U[p]>(R[p]||0)&&l--,0>A)y.push(1),h=!0;else{for(_=R.length,D=U.length,p=0,A+=2,g=w(c/(U[0]+1)),g>1&&(U=t(U,g,c),R=t(R,g,c),D=U.length,_=R.length),x=D,b=R.slice(0,D),O=b.length;D>O;b[O++]=0);S=U.slice(),S.unshift(0),T=U[0],U[1]>=c/2&&T++;do g=0,a=n(U,b,D,O),0>a?(N=b[0],D!=O&&(N=N*c+(b[1]||0)),g=w(N/T),g>1?(g>=c&&(g=c-1),m=t(U,g,c),d=m.length,O=b.length,a=n(m,b,d,O),1==a&&(g--,r(m,d>D?S:U,d,c))):(0==g&&(a=g=1),m=U.slice()),d=m.length,O>d&&m.unshift(0),r(b,m,O,c),-1==a&&(O=b.length,a=n(U,b,D,O),1>a&&(g++,r(b,O>D?S:U,O,c))),O=b.length):0===a&&(g++,b=[0]),y[p++]=g,a&&b[0]?b[O++]=R[x]||0:(b=[R[x]],O=1);while((x++<_||null!=b[0])&&A--);h=null!=b[0],y[0]||y.shift()}if(c==E){for(p=1,A=y[0];A>=10;A/=10,p++);F(v,u+(v.e=p+l*I-1)+1,s,h)}else v.e=l,v.r=+h;return v}}(),m==function(){var t=/^(-?)0([xbo])(\w[\w.]*$)/i,n=/^([^.]+)\.$/,r=/^\.([^.]+)$/,i=/^-?(Infinity|NaN)$/,o=/^\s*\+([\w.])|^\s+|\s+$/g;return function(f,u,s,c){var a,l=s?u:u.replace(o,"$1");if(i.test(l))f.s=isNaN(l)?null:0>l?-1:1;else{if(!s&&(l=l.replace(t,function(t,e,n){return a="x"==(n=n.toLowerCase())?16:"b"==n?2:8,c&&c!=a?t:e}),c&&(a=c,l=l.replace(n,"$1").replace(r,"0.$1")),u!=l))return new e(l,a);$&&U(L,"not a"+(c?" base "+c:"")+" number",u),f.s=null}f.c=f.e=null,L=0}}(),M.absoluteValue=M.abs=function(){var t=new e(this);return t.s<0&&(t.s=1),t},M.ceil=function(){return F(new e(this),this.e+1,2)},M.comparedTo=M.cmp=function(t,n){return L=1,f(this,new e(t,n))},M.decimalPlaces=M.dp=function(){var t,e,n=this.c;if(!n)return null;if(t=((e=n.length-1)-i(this.e/I))*I,e=n[e])for(;e%10==0;e/=10,t--);return 0>t&&(t=0),t},M.dividedBy=M.div=function(t,n){return L=3,G(this,new e(t,n),B,H)},M.dividedToIntegerBy=M.divToInt=function(t,n){return L=4,G(this,new e(t,n),0,1)},M.equals=M.eq=function(t,n){return L=5,0===f(this,new e(t,n))},M.floor=function(){return F(new e(this),this.e+1,3)},M.greaterThan=M.gt=function(t,n){return L=6,f(this,new e(t,n))>0},M.greaterThanOrEqualTo=M.gte=function(t,n){return L=7,1===(n=f(this,new e(t,n)))||0===n},M.isFinite=function(){return!!this.c},M.isInteger=M.isInt=function(){return!!this.c&&i(this.e/I)>this.c.length-2},M.isNaN=function(){return!this.s},M.isNegative=M.isNeg=function(){return this.s<0},M.isZero=function(){return!!this.c&&0==this.c[0]},M.lessThan=M.lt=function(t,n){return L=8,f(this,new e(t,n))<0},M.lessThanOrEqualTo=M.lte=function(t,n){return L=9,-1===(n=f(this,new e(t,n)))||0===n},M.minus=M.sub=function(t,n){var r,o,f,u,s=this,c=s.s;if(L=10,t=new e(t,n),n=t.s,!c||!n)return new e(0/0);if(c!=n)return t.s=-n,s.plus(t);var a=s.e/I,l=t.e/I,p=s.c,h=t.c;if(!a||!l){if(!p||!h)return p?(t.s=-n,t):new e(h?s:0/0);if(!p[0]||!h[0])return h[0]?(t.s=-n,t):new e(p[0]?s:3==H?-0:0)}if(a=i(a),l=i(l),p=p.slice(),c=a-l){for((u=0>c)?(c=-c,f=p):(l=a,f=h),f.reverse(),n=c;n--;f.push(0));f.reverse()}else for(o=(u=(c=p.length)<(n=h.length))?c:n,c=n=0;o>n;n++)if(p[n]!=h[n]){u=p[n]<h[n];break}if(u&&(f=p,p=h,h=f,t.s=-t.s),n=(o=h.length)-(r=p.length),n>0)for(;n--;p[r++]=0);for(n=E-1;o>c;){if(p[--o]<h[o]){for(r=o;r&&!p[--r];p[r]=n);--p[r],p[o]+=E}p[o]-=h[o]}for(;0==p[0];p.shift(),--l);return p[0]?R(t,p,l):(t.s=3==H?-1:1,t.c=[t.e=0],t)},M.modulo=M.mod=function(t,n){var r,i,o=this;return L=11,t=new e(t,n),!o.c||!t.s||t.c&&!t.c[0]?new e(0/0):!t.c||o.c&&!o.c[0]?new e(o):(9==W?(i=t.s,t.s=1,r=G(o,t,0,3),t.s=i,r.s*=i):r=G(o,t,0,W),o.minus(r.times(t)))},M.negated=M.neg=function(){var t=new e(this);return t.s=-t.s||null,t},M.plus=M.add=function(t,n){var r,o=this,f=o.s;if(L=12,t=new e(t,n),n=t.s,!f||!n)return new e(0/0);if(f!=n)return t.s=-n,o.minus(t);var u=o.e/I,s=t.e/I,c=o.c,a=t.c;if(!u||!s){if(!c||!a)return new e(f/0);if(!c[0]||!a[0])return a[0]?t:new e(c[0]?o:0*f)}if(u=i(u),s=i(s),c=c.slice(),f=u-s){for(f>0?(s=u,r=a):(f=-f,r=c),r.reverse();f--;r.push(0));r.reverse()}for(f=c.length,n=a.length,0>f-n&&(r=a,a=c,c=r,n=f),f=0;n;)f=(c[--n]=c[n]+a[n]+f)/E|0,c[n]%=E;return f&&(c.unshift(f),++s),R(t,c,s)},M.precision=M.sd=function(t){var e,n,r=this,i=r.c;if(null!=t&&t!==!!t&&1!==t&&0!==t&&($&&U(13,"argument"+y,t),t!=!!t&&(t=null)),!i)return null;if(n=i.length-1,e=n*I+1,n=i[n]){for(;n%10==0;n/=10,e--);for(n=i[0];n>=10;n/=10,e++);}return t&&r.e+1>e&&(e=r.e+1),e},M.round=function(t,n){var r=new e(this);return(null==t||z(t,0,D,15))&&F(r,~~t+this.e+1,null!=n&&z(n,0,8,15,b)?0|n:H),r},M.shift=function(t){var n=this;return z(t,-x,x,16,"argument")?n.times("1e"+p(t)):new e(n.c&&n.c[0]&&(-x>t||t>x)?n.s*(0>t?0:1/0):n)},M.squareRoot=M.sqrt=function(){var t,n,r,f,u,s=this,c=s.c,a=s.s,l=s.e,p=B+4,h=new e("0.5");if(1!==a||!c||!c[0])return new e(!a||0>a&&(!c||c[0])?0/0:c?s:1/0);if(a=Math.sqrt(+s),0==a||a==1/0?(n=o(c),(n.length+l)%2==0&&(n+="0"),a=Math.sqrt(n),l=i((l+1)/2)-(0>l||l%2),a==1/0?n="1e"+l:(n=a.toExponential(),n=n.slice(0,n.indexOf("e")+1)+l),r=new e(n)):r=new e(a+""),r.c[0])for(l=r.e,a=l+p,3>a&&(a=0);;)if(u=r,r=h.times(u.plus(G(s,u,p,1))),o(u.c).slice(0,a)===(n=o(r.c)).slice(0,a)){if(r.e<l&&--a,n=n.slice(a-3,a+1),"9999"!=n&&(f||"4999"!=n)){(!+n||!+n.slice(1)&&"5"==n.charAt(0))&&(F(r,r.e+B+2,1),t=!r.times(r).eq(s));break}if(!f&&(F(u,u.e+B+2,0),u.times(u).eq(s))){r=u;break}p+=4,a+=4,f=1}return F(r,r.e+B+1,H,t)},M.times=M.mul=function(t,n){var r,o,f,u,s,c,a,l,p,h,g,m,d,v,w,y=this,b=y.c,O=(L=17,t=new e(t,n)).c;if(!(b&&O&&b[0]&&O[0]))return!y.s||!t.s||b&&!b[0]&&!O||O&&!O[0]&&!b?t.c=t.e=t.s=null:(t.s*=y.s,b&&O?(t.c=[0],t.e=0):t.c=t.e=null),t;for(o=i(y.e/I)+i(t.e/I),t.s*=y.s,a=b.length,h=O.length,h>a&&(d=b,b=O,O=d,f=a,a=h,h=f),f=a+h,d=[];f--;d.push(0));for(v=E,w=T,f=h;--f>=0;){for(r=0,g=O[f]%w,m=O[f]/w|0,s=a,u=f+s;u>f;)l=b[--s]%w,p=b[s]/w|0,c=m*l+p*g,l=g*l+c%w*w+d[u]+r,r=(l/v|0)+(c/w|0)+m*p,d[u--]=l%v;d[u]=r}return r?++o:d.shift(),R(t,d,o)},M.toDigits=function(t,n){var r=new e(this);return t=null!=t&&z(t,1,D,18,"precision")?0|t:null,n=null!=n&&z(n,0,8,18,b)?0|n:H,t?F(r,t,n):r},M.toExponential=function(t,e){return h(this,null!=t&&z(t,0,D,19)?~~t+1:null,e,19)},M.toFixed=function(t,e){return h(this,null!=t&&z(t,0,D,20)?~~t+this.e+1:null,e,20)},M.toFormat=function(t,e){var n=h(this,null!=t&&z(t,0,D,21)?~~t+this.e+1:null,e,21);if(this.c){var r,i=n.split("."),o=+Z.groupSize,f=+Z.secondaryGroupSize,u=Z.groupSeparator,s=i[0],c=i[1],a=this.s<0,l=a?s.slice(1):s,p=l.length;if(f&&(r=o,o=f,f=r,p-=r),o>0&&p>0){for(r=p%o||o,s=l.substr(0,r);p>r;r+=o)s+=u+l.substr(r,o);f>0&&(s+=u+l.slice(r)),a&&(s="-"+s)}n=c?s+Z.decimalSeparator+((f=+Z.fractionGroupSize)?c.replace(new RegExp("\\d{"+f+"}\\B","g"),"$&"+Z.fractionGroupSeparator):c):s}return n},M.toFraction=function(t){var n,r,i,f,u,s,c,a,l,p=$,h=this,g=h.c,m=new e(P),d=r=new e(P),v=c=new e(P);if(null!=t&&($=!1,s=new e(t),$=p,(!(p=s.isInt())||s.lt(P))&&($&&U(22,"max denominator "+(p?"out of range":"not an integer"),t),t=!p&&s.c&&F(s,s.e+1,1).gte(P)?s:null)),!g)return h.toString();for(l=o(g),f=m.e=l.length-h.e-1,m.c[0]=_[(u=f%I)<0?I+u:u],t=!t||s.cmp(m)>0?f>0?m:d:s,u=q,q=1/0,s=new e(l),c.c[0]=0;a=G(s,m,0,1),i=r.plus(a.times(v)),1!=i.cmp(t);)r=v,v=i,d=c.plus(a.times(i=d)),c=i,m=s.minus(a.times(i=m)),s=i;return i=G(t.minus(r),v,0,1),c=c.plus(i.times(d)),r=r.plus(i.times(v)),c.s=d.s=h.s,f*=2,n=G(d,v,f,H).minus(h).abs().cmp(G(c,r,f,H).minus(h).abs())<1?[d.toString(),v.toString()]:[c.toString(),r.toString()],q=u,n},M.toNumber=function(){var t=this;return+t||(t.s?0*t.s:0/0)},M.toPower=M.pow=function(t){var n,r,i=w(0>t?-t:+t),o=this;if(!z(t,-x,x,23,"exponent")&&(!isFinite(t)||i>x&&(t/=0)||parseFloat(t)!=t&&!(t=0/0)))return new e(Math.pow(+o,t));for(n=Y?v(Y/I+2):0,r=new e(P);;){if(i%2){if(r=r.times(o),!r.c)break;n&&r.c.length>n&&(r.c.length=n)}if(i=w(i/2),!i)break;o=o.times(o),n&&o.c&&o.c.length>n&&(o.c.length=n)}return 0>t&&(r=P.div(r)),n?F(r,Y,H):r},M.toPrecision=function(t,e){return h(this,null!=t&&z(t,1,D,24,"precision")?0|t:null,e,24)},M.toString=function(t){var e,r=this,i=r.s,f=r.e;return null===f?i?(e="Infinity",0>i&&(e="-"+e)):e="NaN":(e=o(r.c),e=null!=t&&z(t,2,64,25,"base")?n(l(e,f),0|t,10,i):C>=f||f>=j?a(e,f):l(e,f),0>i&&r.c[0]&&(e="-"+e)),e},M.truncated=M.trunc=function(){return F(new e(this),this.e+1,1)},M.valueOf=M.toJSON=function(){return this.toString()},null!=t&&e.config(t),e}function i(t){var e=0|t;return t>0||t===e?e:e-1}function o(t){for(var e,n,r=1,i=t.length,o=t[0]+"";i>r;){for(e=t[r++]+"",n=I-e.length;n--;e="0"+e);o+=e}for(i=o.length;48===o.charCodeAt(--i););return o.slice(0,i+1||1)}function f(t,e){var n,r,i=t.c,o=e.c,f=t.s,u=e.s,s=t.e,c=e.e;if(!f||!u)return null;if(n=i&&!i[0],r=o&&!o[0],n||r)return n?r?0:-u:f;if(f!=u)return f;if(n=0>f,r=s==c,!i||!o)return r?0:!i^n?1:-1;if(!r)return s>c^n?1:-1;for(u=(s=i.length)<(c=o.length)?s:c,f=0;u>f;f++)if(i[f]!=o[f])return i[f]>o[f]^n?1:-1;return s==c?0:s>c^n?1:-1}function u(t,e,n){return(t=p(t))>=e&&n>=t}function s(t){return"[object Array]"==Object.prototype.toString.call(t)}function c(t,e,n){for(var r,i,o=[0],f=0,u=t.length;u>f;){for(i=o.length;i--;o[i]*=e);for(o[r=0]+=N.indexOf(t.charAt(f++));r<o.length;r++)o[r]>n-1&&(null==o[r+1]&&(o[r+1]=0),o[r+1]+=o[r]/n|0,o[r]%=n)}return o.reverse()}function a(t,e){return(t.length>1?t.charAt(0)+"."+t.slice(1):t)+(0>e?"e":"e+")+e}function l(t,e){var n,r;if(0>e){for(r="0.";++e;r+="0");t=r+t}else if(n=t.length,++e>n){for(r="0",e-=n;--e;r+="0");t+=r}else n>e&&(t=t.slice(0,e)+"."+t.slice(e));return t}function p(t){return t=parseFloat(t),0>t?v(t):w(t)}var h,g,m,d=/^-?(\d+(\.\d*)?|\.\d+)(e[+-]?\d+)?$/i,v=Math.ceil,w=Math.floor,y=" not a boolean or binary digit",b="rounding mode",O="number type has more than 15 significant digits",N="0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ$_",E=1e14,I=14,x=9007199254740991,_=[1,10,100,1e3,1e4,1e5,1e6,1e7,1e8,1e9,1e10,1e11,1e12,1e13],T=1e7,D=1e9;if(h=r(),"function"==typeof define&&define.amd)define(function(){return h});else if("undefined"!=typeof e&&e.exports){if(e.exports=h,!g)try{g=t("crypto")}catch(S){}}else n.BigNumber=h}(this)},{crypto:1}],natspec:[function(t,e){var n=t("./node_modules/ethereum.js/lib/abi.js"),r=function(){var t=function(t,e){Object.keys(t).forEach(function(n){e[n]=t[n]})},e=function(t){return Object.keys(t).reduce(function(t,e){return t+"var "+e+" = context['"+e+"'];\n"},"")},r=function(t,e){return t.filter(function(t){return t.name===e})[0]},i=function(t,e){var r=n.formatOutput(t.inputs,"0x"+e.params[0].data.slice(10));return t.inputs.reduce(function(t,e,n){return t[e.name]=r[n],t},{})},o=function(t,e){var n,r="",i=/\` + "`" + `(?:\\.|[^` + "`" + `\\])*\` + "`" + `/gim,o=0;try{for(;null!==(n=i.exec(t));){var f=i.lastIndex-n[0].length,u=n[0].slice(1,n[0].length-1);r+=t.slice(o,f);var s=e(u);r+=s,o=i.lastIndex}r+=t.slice(o)}catch(c){throw new Error("Natspec evaluation failed, wrong input params")}return r},f=function(n,f){var u={};if(f)try{var s=r(f.abi,f.method),c=i(s,f.transaction);t(c,u)}catch(a){throw new Error("Natspec evaluation failed, method does not exist")}var l=e(u),p=o(n,function(t){var e=new Function("context",l+"return "+t+";");return e(u).toString()});return p},u=function(t,e){try{return f(t,e)}catch(n){return n.message}};return{evaluateExpression:f,evaluateExpressionSafe:u}}();e.exports=r},{"./node_modules/ethereum.js/lib/abi.js":3}]},{},[]);
+//# sourceMappingURL=natspec.js.map`
diff --git a/common/natspec/natspec_test.go b/common/natspec/natspec_test.go
new file mode 100644
index 000000000..330dc831d
--- /dev/null
+++ b/common/natspec/natspec_test.go
@@ -0,0 +1,97 @@
+package natspec
+
+import (
+ "testing"
+)
+
+func TestNotice(t *testing.T) {
+
+ tx := `
+ {
+ "jsonrpc": "2.0",
+ "method": "eth_call",
+ "params": [{
+ "to": "0x8521742d3f456bd237e312d6e30724960f72517a",
+ "data": "0xc6888fa1000000000000000000000000000000000000000000000000000000000000007a"
+ }],
+ "id": 6
+ }
+ `
+
+ abi := `
+ [{
+ "name": "multiply",
+ "constant": false,
+ "type": "function",
+ "inputs": [{
+ "name": "a",
+ "type": "uint256"
+ }],
+ "outputs": [{
+ "name": "d",
+ "type": "uint256"
+ }]
+ }]
+ `
+
+ desc := "Will multiply `a` by 7 and return `a * 7`."
+
+ method := "multiply"
+
+ ns, err := New()
+ if err != nil {
+ t.Errorf("NewNATSpec error %v", err)
+ }
+
+ notice, err := ns.Notice(tx, abi, method, desc)
+
+ if err != nil {
+ t.Errorf("expected no error got %v", err)
+ }
+
+ expected := "Will multiply 122 by 7 and return 854."
+ if notice != expected {
+ t.Errorf("incorrect notice. expected %v, got %v", expected, notice)
+ } else {
+ t.Logf("returned notice \"%v\"", notice)
+ }
+
+ notice, err = ns.Notice(tx, abi, method, "Will multiply 122 by \"7\" and return 854.")
+
+ expected = "natspec.js error setting expression: (anonymous): Line 1:41 Unexpected number"
+
+ if err == nil {
+ t.Errorf("expected error, got nothing (notice: '%v')", err, notice)
+ } else {
+ if err.Error() != expected {
+ t.Errorf("expected error '%s' got '%v' (notice: '%v')", expected, err, notice)
+ }
+ }
+
+ // https://github.com/ethereum/natspec.js/issues/1
+ badDesc := "Will multiply `e` by 7 and return `a * 7`."
+ notice, err = ns.Notice(tx, abi, method, badDesc)
+
+ expected = "natspec.js error evaluating expression: Error: Natspec evaluation failed, wrong input params"
+
+ if err == nil {
+ t.Errorf("expected error, got nothing (notice: '%v')", notice)
+ } else {
+ if err.Error() != expected {
+ t.Errorf("expected error '%s' got '%v' (notice: '%v')", expected, err, notice)
+ }
+ }
+
+ notice, err = ns.Notice(tx, abi, "missing_method", desc)
+
+ expected = "natspec.js error evaluating expression: Error: Natspec evaluation failed, method does not exist"
+
+ if err == nil {
+ t.Errorf("expected error, got nothing (notice: '%v')", notice)
+ } else {
+ if err.Error() != expected {
+ t.Errorf("expected error '%s' got '%v' (notice: '%v')", expected, err, notice)
+ }
+ }
+
+}
diff --git a/common/number/int.go b/common/number/int.go
new file mode 100644
index 000000000..6cc5e68b4
--- /dev/null
+++ b/common/number/int.go
@@ -0,0 +1,181 @@
+package number
+
+import (
+ "math/big"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+var tt256 = new(big.Int).Lsh(big.NewInt(1), 256)
+var tt256m1 = new(big.Int).Sub(new(big.Int).Lsh(big.NewInt(1), 256), big.NewInt(1))
+var tt255 = new(big.Int).Lsh(big.NewInt(1), 255)
+
+func limitUnsigned256(x *Number) *Number {
+ x.num.And(x.num, tt256m1)
+ return x
+}
+
+func limitSigned256(x *Number) *Number {
+ if x.num.Cmp(tt255) < 0 {
+ return x
+ } else {
+ x.num.Sub(x.num, tt256)
+ return x
+ }
+}
+
+// Number function
+type Initialiser func(n int64) *Number
+
+// A Number represents a generic integer with a bounding function limiter. Limit is called after each operations
+// to give "fake" bounded integers. New types of Number can be created through NewInitialiser returning a lambda
+// with the new Initialiser.
+type Number struct {
+ num *big.Int
+ limit func(n *Number) *Number
+}
+
+// Returns a new initialiser for a new *Number without having to expose certain fields
+func NewInitialiser(limiter func(*Number) *Number) Initialiser {
+ return func(n int64) *Number {
+ return &Number{big.NewInt(n), limiter}
+ }
+}
+
+// Return a Number with a UNSIGNED limiter up to 256 bits
+func Uint256(n int64) *Number {
+ return &Number{big.NewInt(n), limitUnsigned256}
+}
+
+// Return a Number with a SIGNED limiter up to 256 bits
+func Int256(n int64) *Number {
+ return &Number{big.NewInt(n), limitSigned256}
+}
+
+// Returns a Number with a SIGNED unlimited size
+func Big(n int64) *Number {
+ return &Number{big.NewInt(n), func(x *Number) *Number { return x }}
+}
+
+// Sets i to sum of x+y
+func (i *Number) Add(x, y *Number) *Number {
+ i.num.Add(x.num, y.num)
+ return i.limit(i)
+}
+
+// Sets i to difference of x-y
+func (i *Number) Sub(x, y *Number) *Number {
+ i.num.Sub(x.num, y.num)
+ return i.limit(i)
+}
+
+// Sets i to product of x*y
+func (i *Number) Mul(x, y *Number) *Number {
+ i.num.Mul(x.num, y.num)
+ return i.limit(i)
+}
+
+// Sets i to the quotient prodject of x/y
+func (i *Number) Div(x, y *Number) *Number {
+ i.num.Div(x.num, y.num)
+ return i.limit(i)
+}
+
+// Sets i to x % y
+func (i *Number) Mod(x, y *Number) *Number {
+ i.num.Mod(x.num, y.num)
+ return i.limit(i)
+}
+
+// Sets i to x << s
+func (i *Number) Lsh(x *Number, s uint) *Number {
+ i.num.Lsh(x.num, s)
+ return i.limit(i)
+}
+
+// Sets i to x^y
+func (i *Number) Pow(x, y *Number) *Number {
+ i.num.Exp(x.num, y.num, big.NewInt(0))
+ return i.limit(i)
+}
+
+// Setters
+
+// Set x to i
+func (i *Number) Set(x *Number) *Number {
+ i.num.Set(x.num)
+ return i.limit(i)
+}
+
+// Set x bytes to i
+func (i *Number) SetBytes(x []byte) *Number {
+ i.num.SetBytes(x)
+ return i.limit(i)
+}
+
+// Cmp compares x and y and returns:
+//
+// -1 if x < y
+// 0 if x == y
+// +1 if x > y
+func (i *Number) Cmp(x *Number) int {
+ return i.num.Cmp(x.num)
+}
+
+// Getters
+
+// Returns the string representation of i
+func (i *Number) String() string {
+ return i.num.String()
+}
+
+// Returns the byte representation of i
+func (i *Number) Bytes() []byte {
+ return i.num.Bytes()
+}
+
+// Uint64 returns the Uint64 representation of x. If x cannot be represented in an int64, the result is undefined.
+func (i *Number) Uint64() uint64 {
+ return i.num.Uint64()
+}
+
+// Int64 returns the int64 representation of x. If x cannot be represented in an int64, the result is undefined.
+func (i *Number) Int64() int64 {
+ return i.num.Int64()
+}
+
+// Returns the signed version of i
+func (i *Number) Int256() *Number {
+ return Int(0).Set(i)
+}
+
+// Returns the unsigned version of i
+func (i *Number) Uint256() *Number {
+ return Uint(0).Set(i)
+}
+
+// Returns the index of the first bit that's set to 1
+func (i *Number) FirstBitSet() int {
+ for j := 0; j < i.num.BitLen(); j++ {
+ if i.num.Bit(j) > 0 {
+ return j
+ }
+ }
+
+ return i.num.BitLen()
+}
+
+// Variables
+
+var (
+ Zero = Uint(0)
+ One = Uint(1)
+ Two = Uint(2)
+ MaxUint256 = Uint(0).SetBytes(common.Hex2Bytes("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"))
+
+ MinOne = Int(-1)
+
+ // "typedefs"
+ Uint = Uint256
+ Int = Int256
+)
diff --git a/common/number/uint_test.go b/common/number/uint_test.go
new file mode 100644
index 000000000..262d584ed
--- /dev/null
+++ b/common/number/uint_test.go
@@ -0,0 +1,92 @@
+package number
+
+import (
+ "math/big"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+)
+
+func TestSet(t *testing.T) {
+ a := Uint(0)
+ b := Uint(10)
+ a.Set(b)
+ if a.num.Cmp(b.num) != 0 {
+ t.Error("didn't compare", a, b)
+ }
+
+ c := Uint(0).SetBytes(common.Hex2Bytes("0a"))
+ if c.num.Cmp(big.NewInt(10)) != 0 {
+ t.Error("c set bytes failed.")
+ }
+}
+
+func TestInitialiser(t *testing.T) {
+ check := false
+ init := NewInitialiser(func(x *Number) *Number {
+ check = true
+ return x
+ })
+ a := init(0).Add(init(1), init(2))
+ if a.Cmp(init(3)) != 0 {
+ t.Error("expected 3. got", a)
+ }
+ if !check {
+ t.Error("expected limiter to be called")
+ }
+}
+
+func TestGet(t *testing.T) {
+ a := Uint(10)
+ if a.Uint64() != 10 {
+ t.Error("expected to get 10. got", a.Uint64())
+ }
+
+ a = Uint(10)
+ if a.Int64() != 10 {
+ t.Error("expected to get 10. got", a.Int64())
+ }
+}
+
+func TestCmp(t *testing.T) {
+ a := Uint(10)
+ b := Uint(10)
+ c := Uint(11)
+
+ if a.Cmp(b) != 0 {
+ t.Error("a b == 0 failed", a, b)
+ }
+
+ if a.Cmp(c) >= 0 {
+ t.Error("a c < 0 failed", a, c)
+ }
+
+ if c.Cmp(b) <= 0 {
+ t.Error("c b > 0 failed", c, b)
+ }
+}
+
+func TestMaxArith(t *testing.T) {
+ a := Uint(0).Add(MaxUint256, One)
+ if a.Cmp(Zero) != 0 {
+ t.Error("expected max256 + 1 = 0 got", a)
+ }
+
+ a = Uint(0).Sub(Uint(0), One)
+ if a.Cmp(MaxUint256) != 0 {
+ t.Error("expected 0 - 1 = max256 got", a)
+ }
+
+ a = Int(0).Sub(Int(0), One)
+ if a.Cmp(MinOne) != 0 {
+ t.Error("expected 0 - 1 = -1 got", a)
+ }
+}
+
+func TestConversion(t *testing.T) {
+ a := Int(-1)
+ b := a.Uint256()
+ if b.Cmp(MaxUint256) != 0 {
+ t.Error("expected -1 => unsigned to return max. got", b)
+ }
+}
diff --git a/common/package.go b/common/package.go
new file mode 100644
index 000000000..7f38d8e4d
--- /dev/null
+++ b/common/package.go
@@ -0,0 +1,123 @@
+package common
+
+import (
+ "archive/zip"
+ "encoding/json"
+ "fmt"
+ "io"
+ "io/ioutil"
+ "strings"
+)
+
+// Manifest object
+//
+// The manifest object holds all the relevant information supplied with the
+// the manifest specified in the package
+type Manifest struct {
+ Entry string
+ Height, Width int
+}
+
+// External package
+//
+// External package contains the main html file and manifest
+type ExtPackage struct {
+ EntryHtml string
+ Manifest *Manifest
+}
+
+// Read file
+//
+// Read a given compressed file and returns the read bytes.
+// Returns an error otherwise
+func ReadFile(f *zip.File) ([]byte, error) {
+ rc, err := f.Open()
+ if err != nil {
+ return nil, err
+ }
+ defer rc.Close()
+
+ content, err := ioutil.ReadAll(rc)
+ if err != nil {
+ return nil, err
+ }
+
+ return content, nil
+}
+
+// Reads manifest
+//
+// Reads and returns a manifest object. Returns error otherwise
+func ReadManifest(m []byte) (*Manifest, error) {
+ var manifest Manifest
+
+ dec := json.NewDecoder(strings.NewReader(string(m)))
+ if err := dec.Decode(&manifest); err == io.EOF {
+ } else if err != nil {
+ return nil, err
+ }
+
+ return &manifest, nil
+}
+
+// Find file in archive
+//
+// Returns the index of the given file name if it exists. -1 if file not found
+func FindFileInArchive(fn string, files []*zip.File) (index int) {
+ index = -1
+ // Find the manifest first
+ for i, f := range files {
+ if f.Name == fn {
+ index = i
+ }
+ }
+
+ return
+}
+
+// Open package
+//
+// Opens a prepared ethereum package
+// Reads the manifest file and determines file contents and returns and
+// the external package.
+func OpenPackage(fn string) (*ExtPackage, error) {
+ r, err := zip.OpenReader(fn)
+ if err != nil {
+ return nil, err
+ }
+ defer r.Close()
+
+ manifestIndex := FindFileInArchive("manifest.json", r.File)
+
+ if manifestIndex < 0 {
+ return nil, fmt.Errorf("No manifest file found in archive")
+ }
+
+ f, err := ReadFile(r.File[manifestIndex])
+ if err != nil {
+ return nil, err
+ }
+
+ manifest, err := ReadManifest(f)
+ if err != nil {
+ return nil, err
+ }
+
+ if manifest.Entry == "" {
+ return nil, fmt.Errorf("Entry file specified but appears to be empty: %s", manifest.Entry)
+ }
+
+ entryIndex := FindFileInArchive(manifest.Entry, r.File)
+ if entryIndex < 0 {
+ return nil, fmt.Errorf("Entry file not found: '%s'", manifest.Entry)
+ }
+
+ f, err = ReadFile(r.File[entryIndex])
+ if err != nil {
+ return nil, err
+ }
+
+ extPackage := &ExtPackage{string(f), manifest}
+
+ return extPackage, nil
+}
diff --git a/common/path.go b/common/path.go
new file mode 100644
index 000000000..680c8366c
--- /dev/null
+++ b/common/path.go
@@ -0,0 +1,68 @@
+package common
+
+import (
+ "io/ioutil"
+ "os"
+ "os/user"
+ "path"
+ "strings"
+)
+
+func ExpandHomePath(p string) (path string) {
+ path = p
+
+ // Check in case of paths like "/something/~/something/"
+ if len(path) > 1 && path[:2] == "~/" {
+ usr, _ := user.Current()
+ dir := usr.HomeDir
+
+ path = strings.Replace(p, "~", dir, 1)
+ }
+
+ 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_TRUNC|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
+}
+
+func AbsolutePath(Datadir string, filename string) string {
+ if path.IsAbs(filename) {
+ return filename
+ }
+ return path.Join(Datadir, filename)
+}
diff --git a/common/path_test.go b/common/path_test.go
new file mode 100644
index 000000000..4af1bd7af
--- /dev/null
+++ b/common/path_test.go
@@ -0,0 +1,51 @@
+package common
+
+import (
+ // "os"
+ "testing"
+)
+
+func TestGoodFile(t *testing.T) {
+ goodpath := "~/goethereumtest.pass"
+ path := ExpandHomePath(goodpath)
+ contentstring := "3.14159265358979323846"
+
+ err := WriteFile(path, []byte(contentstring))
+ if err != nil {
+ t.Error("Could not write file")
+ }
+
+ if !FileExist(path) {
+ t.Error("File not found at", path)
+ }
+
+ v, err := ReadAllFile(path)
+ if err != nil {
+ t.Error("Could not read file", path)
+ }
+ if v != contentstring {
+ t.Error("Expected", contentstring, "Got", v)
+ }
+
+}
+
+func TestBadFile(t *testing.T) {
+ badpath := "/this/path/should/not/exist/goethereumtest.fail"
+ path := ExpandHomePath(badpath)
+ contentstring := "3.14159265358979323846"
+
+ err := WriteFile(path, []byte(contentstring))
+ if err == nil {
+ t.Error("Wrote file, but should not be able to", path)
+ }
+
+ if FileExist(path) {
+ t.Error("Found file, but should not be able to", path)
+ }
+
+ v, err := ReadAllFile(path)
+ if err == nil {
+ t.Error("Read file, but should not be able to", v)
+ }
+
+}
diff --git a/common/rlp.go b/common/rlp.go
new file mode 100644
index 000000000..602f13202
--- /dev/null
+++ b/common/rlp.go
@@ -0,0 +1,276 @@
+package common
+
+import (
+ "bytes"
+ "fmt"
+ "math/big"
+ "reflect"
+)
+
+type RlpEncode interface {
+ RlpEncode() []byte
+}
+
+type RlpEncodeDecode interface {
+ RlpEncode
+ RlpValue() []interface{}
+}
+
+type RlpEncodable interface {
+ RlpData() interface{}
+}
+
+func Rlp(encoder RlpEncode) []byte {
+ return encoder.RlpEncode()
+}
+
+type RlpEncoder struct {
+ rlpData []byte
+}
+
+func NewRlpEncoder() *RlpEncoder {
+ encoder := &RlpEncoder{}
+
+ return encoder
+}
+func (coder *RlpEncoder) EncodeData(rlpData interface{}) []byte {
+ return Encode(rlpData)
+}
+
+const (
+ RlpEmptyList = 0x80
+ RlpEmptyStr = 0x40
+)
+
+const rlpEof = -1
+
+func Char(c []byte) int {
+ if len(c) > 0 {
+ return int(c[0])
+ }
+
+ return rlpEof
+}
+
+func DecodeWithReader(reader *bytes.Buffer) interface{} {
+ var slice []interface{}
+
+ // Read the next byte
+ char := Char(reader.Next(1))
+ switch {
+ case char <= 0x7f:
+ return char
+
+ case char <= 0xb7:
+ return reader.Next(int(char - 0x80))
+
+ case char <= 0xbf:
+ length := ReadVarInt(reader.Next(int(char - 0xb7)))
+
+ return reader.Next(int(length))
+
+ case char <= 0xf7:
+ length := int(char - 0xc0)
+ for i := 0; i < length; i++ {
+ obj := DecodeWithReader(reader)
+ slice = append(slice, obj)
+ }
+
+ return slice
+ case char <= 0xff:
+ length := ReadVarInt(reader.Next(int(char - 0xf7)))
+ for i := uint64(0); i < length; i++ {
+ obj := DecodeWithReader(reader)
+ slice = append(slice, obj)
+ }
+
+ return slice
+ default:
+ panic(fmt.Sprintf("byte not supported: %q", char))
+ }
+
+ return slice
+}
+
+var (
+ directRlp = big.NewInt(0x7f)
+ numberRlp = big.NewInt(0xb7)
+ zeroRlp = big.NewInt(0x0)
+)
+
+func intlen(i int64) (length int) {
+ for i > 0 {
+ i = i >> 8
+ length++
+ }
+ return
+}
+
+func Encode(object interface{}) []byte {
+ var buff bytes.Buffer
+
+ if object != nil {
+ switch t := object.(type) {
+ case *Value:
+ buff.Write(Encode(t.Raw()))
+ case RlpEncodable:
+ buff.Write(Encode(t.RlpData()))
+ // Code dup :-/
+ case int:
+ buff.Write(Encode(big.NewInt(int64(t))))
+ case uint:
+ buff.Write(Encode(big.NewInt(int64(t))))
+ case int8:
+ buff.Write(Encode(big.NewInt(int64(t))))
+ case int16:
+ buff.Write(Encode(big.NewInt(int64(t))))
+ case int32:
+ buff.Write(Encode(big.NewInt(int64(t))))
+ case int64:
+ buff.Write(Encode(big.NewInt(t)))
+ case uint16:
+ buff.Write(Encode(big.NewInt(int64(t))))
+ case uint32:
+ buff.Write(Encode(big.NewInt(int64(t))))
+ case uint64:
+ buff.Write(Encode(big.NewInt(int64(t))))
+ case byte:
+ buff.Write(Encode(big.NewInt(int64(t))))
+ case *big.Int:
+ // Not sure how this is possible while we check for nil
+ if t == nil {
+ buff.WriteByte(0xc0)
+ } else {
+ buff.Write(Encode(t.Bytes()))
+ }
+ case Bytes:
+ buff.Write(Encode([]byte(t)))
+ case []byte:
+ if len(t) == 1 && t[0] <= 0x7f {
+ buff.Write(t)
+ } else if len(t) < 56 {
+ buff.WriteByte(byte(len(t) + 0x80))
+ buff.Write(t)
+ } else {
+ b := big.NewInt(int64(len(t)))
+ buff.WriteByte(byte(len(b.Bytes()) + 0xb7))
+ buff.Write(b.Bytes())
+ buff.Write(t)
+ }
+ case string:
+ buff.Write(Encode([]byte(t)))
+ case []interface{}:
+ // Inline function for writing the slice header
+ WriteSliceHeader := func(length int) {
+ if length < 56 {
+ buff.WriteByte(byte(length + 0xc0))
+ } else {
+ b := big.NewInt(int64(length))
+ buff.WriteByte(byte(len(b.Bytes()) + 0xf7))
+ buff.Write(b.Bytes())
+ }
+ }
+
+ var b bytes.Buffer
+ for _, val := range t {
+ b.Write(Encode(val))
+ }
+ WriteSliceHeader(len(b.Bytes()))
+ buff.Write(b.Bytes())
+ default:
+ // This is how it should have been from the start
+ // needs refactoring (@fjl)
+ v := reflect.ValueOf(t)
+ switch v.Kind() {
+ case reflect.Slice:
+ var b bytes.Buffer
+ for i := 0; i < v.Len(); i++ {
+ b.Write(Encode(v.Index(i).Interface()))
+ }
+
+ blen := b.Len()
+ if blen < 56 {
+ buff.WriteByte(byte(blen) + 0xc0)
+ } else {
+ ilen := byte(intlen(int64(blen)))
+ buff.WriteByte(ilen + 0xf7)
+ t := make([]byte, ilen)
+ for i := byte(0); i < ilen; i++ {
+ t[ilen-i-1] = byte(blen >> (i * 8))
+ }
+ buff.Write(t)
+ }
+ buff.ReadFrom(&b)
+ }
+ }
+ } else {
+ // Empty list for nil
+ buff.WriteByte(0xc0)
+ }
+
+ 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/common/rlp_test.go b/common/rlp_test.go
new file mode 100644
index 000000000..16a3553d7
--- /dev/null
+++ b/common/rlp_test.go
@@ -0,0 +1,156 @@
+package common
+
+import (
+ "bytes"
+ "math/big"
+ "reflect"
+ "testing"
+)
+
+func TestNonInterfaceSlice(t *testing.T) {
+ vala := []string{"value1", "value2", "value3"}
+ valb := []interface{}{"value1", "value2", "value3"}
+ resa := Encode(vala)
+ resb := Encode(valb)
+ if !bytes.Equal(resa, resb) {
+ t.Errorf("expected []string & []interface{} to be equal")
+ }
+}
+
+func TestRlpValueEncoding(t *testing.T) {
+ val := EmptyValue()
+ val.AppendList().Append(1).Append(2).Append(3)
+ val.Append("4").AppendList().Append(5)
+
+ res := val.Encode()
+ exp := Encode([]interface{}{[]interface{}{1, 2, 3}, "4", []interface{}{5}})
+ if bytes.Compare(res, exp) != 0 {
+ t.Errorf("expected %q, got %q", res, exp)
+ }
+}
+
+func TestValueSlice(t *testing.T) {
+ val := []interface{}{
+ "value1",
+ "valeu2",
+ "value3",
+ }
+
+ value := NewValue(val)
+ splitVal := value.SliceFrom(1)
+
+ if splitVal.Len() != 2 {
+ t.Error("SliceFrom: Expected len", 2, "got", splitVal.Len())
+ }
+
+ splitVal = value.SliceTo(2)
+ if splitVal.Len() != 2 {
+ t.Error("SliceTo: Expected len", 2, "got", splitVal.Len())
+ }
+
+ splitVal = value.SliceFromTo(1, 3)
+ if splitVal.Len() != 2 {
+ t.Error("SliceFromTo: Expected len", 2, "got", splitVal.Len())
+ }
+}
+
+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" {
+ t.Errorf("expected '%v', got '%v'", value.Get(0).Str(), "dog")
+ }
+
+ if value.Get(3).Uint() != 1 {
+ t.Errorf("expected '%v', got '%v'", value.Get(3).Uint(), 1)
+ }
+}
+
+func TestEncode(t *testing.T) {
+ strRes := "\x83dog"
+ bytes := Encode("dog")
+
+ str := string(bytes)
+ if str != strRes {
+ t.Errorf("Expected %q, got %q", strRes, str)
+ }
+
+ sliceRes := "\xcc\x83dog\x83god\x83cat"
+ strs := []interface{}{"dog", "god", "cat"}
+ bytes = Encode(strs)
+ slice := string(bytes)
+ if slice != sliceRes {
+ t.Error("Expected %q, got %q", sliceRes, slice)
+ }
+
+ intRes := "\x82\x04\x00"
+ bytes = Encode(1024)
+ if string(bytes) != intRes {
+ t.Errorf("Expected %q, got %q", intRes, bytes)
+ }
+}
+
+func TestDecode(t *testing.T) {
+ single := []byte("\x01")
+ b, _ := Decode(single, 0)
+
+ if b.(uint8) != 1 {
+ t.Errorf("Expected 1, got %q", b)
+ }
+
+ str := []byte("\x83dog")
+ b, _ = Decode(str, 0)
+ if bytes.Compare(b.([]byte), []byte("dog")) != 0 {
+ t.Errorf("Expected dog, got %q", b)
+ }
+
+ slice := []byte("\xcc\x83dog\x83god\x83cat")
+ res := []interface{}{"dog", "god", "cat"}
+ b, _ = Decode(slice, 0)
+ if reflect.DeepEqual(b, res) {
+ t.Errorf("Expected %q, got %q", res, b)
+ }
+}
+
+func TestEncodeDecodeBigInt(t *testing.T) {
+ bigInt := big.NewInt(1391787038)
+ encoded := Encode(bigInt)
+
+ value := NewValueFromBytes(encoded)
+ if value.BigInt().Cmp(bigInt) != 0 {
+ t.Errorf("Expected %v, got %v", bigInt, value.BigInt())
+ }
+}
+
+func TestEncodeDecodeBytes(t *testing.T) {
+ b := NewValue([]interface{}{[]byte{1, 2, 3, 4, 5}, byte(6)})
+ val := NewValueFromBytes(b.Encode())
+ if !b.Cmp(val) {
+ t.Errorf("Expected %v, got %v", val, b)
+ }
+}
+
+func TestEncodeZero(t *testing.T) {
+ b := NewValue(0).Encode()
+ exp := []byte{0xc0}
+ if bytes.Compare(b, exp) == 0 {
+ t.Error("Expected", exp, "got", b)
+ }
+}
+
+func BenchmarkEncodeDecode(b *testing.B) {
+ for i := 0; i < b.N; i++ {
+ bytes := Encode([]interface{}{"dog", "god", "cat"})
+ Decode(bytes, 0)
+ }
+}
diff --git a/common/size.go b/common/size.go
new file mode 100644
index 000000000..80a17279b
--- /dev/null
+++ b/common/size.go
@@ -0,0 +1,15 @@
+package common
+
+import "fmt"
+
+type StorageSize float64
+
+func (self StorageSize) String() string {
+ if self > 1000000 {
+ return fmt.Sprintf("%.2f mB", self/1000000)
+ } else if self > 1000 {
+ return fmt.Sprintf("%.2f kB", self/1000)
+ } else {
+ return fmt.Sprintf("%.2f B", self)
+ }
+}
diff --git a/common/size_test.go b/common/size_test.go
new file mode 100644
index 000000000..c90eabc26
--- /dev/null
+++ b/common/size_test.go
@@ -0,0 +1,23 @@
+package common
+
+import (
+ checker "gopkg.in/check.v1"
+)
+
+type SizeSuite struct{}
+
+var _ = checker.Suite(&SizeSuite{})
+
+func (s *SizeSuite) TestStorageSizeString(c *checker.C) {
+ data1 := 2381273
+ data2 := 2192
+ data3 := 12
+
+ exp1 := "2.38 mB"
+ exp2 := "2.19 kB"
+ exp3 := "12.00 B"
+
+ c.Assert(StorageSize(data1).String(), checker.Equals, exp1)
+ c.Assert(StorageSize(data2).String(), checker.Equals, exp2)
+ c.Assert(StorageSize(data3).String(), checker.Equals, exp3)
+}
diff --git a/common/types.go b/common/types.go
new file mode 100644
index 000000000..7646b2c34
--- /dev/null
+++ b/common/types.go
@@ -0,0 +1,6 @@
+package common
+
+type (
+ Hash [32]byte
+ Address [20]byte
+)
diff --git a/common/value.go b/common/value.go
new file mode 100644
index 000000000..72a123772
--- /dev/null
+++ b/common/value.go
@@ -0,0 +1,401 @@
+package common
+
+import (
+ "bytes"
+ "fmt"
+ "math/big"
+ "reflect"
+ "strconv"
+)
+
+// Data values are returned by the rlp decoder. The data values represents
+// one item within the rlp data structure. It's responsible for all the casting
+// It always returns something valid
+type Value struct {
+ Val interface{}
+ kind reflect.Value
+}
+
+func (val *Value) String() string {
+ return fmt.Sprintf("%x", val.Val)
+}
+
+func NewValue(val interface{}) *Value {
+ t := val
+ if v, ok := val.(*Value); ok {
+ t = v.Val
+ }
+
+ return &Value{Val: t}
+}
+
+func (val *Value) Type() reflect.Kind {
+ return reflect.TypeOf(val.Val).Kind()
+}
+
+func (val *Value) IsNil() bool {
+ return val.Val == nil
+}
+
+func (val *Value) Len() int {
+ //return val.kind.Len()
+ if data, ok := val.Val.([]interface{}); ok {
+ return len(data)
+ }
+
+ return len(val.Bytes())
+}
+
+func (val *Value) Raw() interface{} {
+ return val.Val
+}
+
+func (val *Value) Interface() interface{} {
+ return val.Val
+}
+
+func (val *Value) Uint() uint64 {
+ if Val, ok := val.Val.(uint8); ok {
+ return uint64(Val)
+ } else if Val, ok := val.Val.(uint16); ok {
+ return uint64(Val)
+ } else if Val, ok := val.Val.(uint32); ok {
+ return uint64(Val)
+ } else if Val, ok := val.Val.(uint64); ok {
+ return Val
+ } else if Val, ok := val.Val.(float32); ok {
+ return uint64(Val)
+ } else if Val, ok := val.Val.(float64); ok {
+ return uint64(Val)
+ } else if Val, ok := val.Val.(int); ok {
+ return uint64(Val)
+ } else if Val, ok := val.Val.(uint); ok {
+ return uint64(Val)
+ } else if Val, ok := val.Val.([]byte); ok {
+ return new(big.Int).SetBytes(Val).Uint64()
+ } else if Val, ok := val.Val.(*big.Int); ok {
+ return Val.Uint64()
+ }
+
+ return 0
+}
+
+func (val *Value) Int() int64 {
+ if Val, ok := val.Val.(int8); ok {
+ return int64(Val)
+ } else if Val, ok := val.Val.(int16); ok {
+ return int64(Val)
+ } else if Val, ok := val.Val.(int32); ok {
+ return int64(Val)
+ } else if Val, ok := val.Val.(int64); ok {
+ return Val
+ } else if Val, ok := val.Val.(int); ok {
+ return int64(Val)
+ } else if Val, ok := val.Val.(float32); ok {
+ return int64(Val)
+ } else if Val, ok := val.Val.(float64); ok {
+ return int64(Val)
+ } else if Val, ok := val.Val.([]byte); ok {
+ return new(big.Int).SetBytes(Val).Int64()
+ } else if Val, ok := val.Val.(*big.Int); ok {
+ return Val.Int64()
+ } else if Val, ok := val.Val.(string); ok {
+ n, _ := strconv.Atoi(Val)
+ return int64(n)
+ }
+
+ return 0
+}
+
+func (val *Value) Byte() byte {
+ if Val, ok := val.Val.(byte); ok {
+ return Val
+ }
+
+ return 0x0
+}
+
+func (val *Value) BigInt() *big.Int {
+ if a, ok := val.Val.([]byte); ok {
+ b := new(big.Int).SetBytes(a)
+
+ return b
+ } else if a, ok := val.Val.(*big.Int); ok {
+ return a
+ } else if a, ok := val.Val.(string); ok {
+ return Big(a)
+ } else {
+ return big.NewInt(int64(val.Uint()))
+ }
+
+ return big.NewInt(0)
+}
+
+func (val *Value) Str() string {
+ if a, ok := val.Val.([]byte); ok {
+ return string(a)
+ } else if a, ok := val.Val.(string); ok {
+ return a
+ } else if a, ok := val.Val.(byte); ok {
+ return string(a)
+ }
+
+ return ""
+}
+
+func (val *Value) Bytes() []byte {
+ if a, ok := val.Val.([]byte); ok {
+ return a
+ } else if s, ok := val.Val.(byte); ok {
+ return []byte{s}
+ } else if s, ok := val.Val.(string); ok {
+ return []byte(s)
+ } else if s, ok := val.Val.(*big.Int); ok {
+ return s.Bytes()
+ } else {
+ return big.NewInt(val.Int()).Bytes()
+ }
+
+ return []byte{}
+}
+
+func (val *Value) Err() error {
+ if err, ok := val.Val.(error); ok {
+ return err
+ }
+
+ return nil
+}
+
+func (val *Value) Slice() []interface{} {
+ if d, ok := val.Val.([]interface{}); ok {
+ return d
+ }
+
+ return []interface{}{}
+}
+
+func (val *Value) SliceFrom(from int) *Value {
+ slice := val.Slice()
+
+ return NewValue(slice[from:])
+}
+
+func (val *Value) SliceTo(to int) *Value {
+ slice := val.Slice()
+
+ return NewValue(slice[:to])
+}
+
+func (val *Value) SliceFromTo(from, to int) *Value {
+ slice := val.Slice()
+
+ return NewValue(slice[from:to])
+}
+
+// TODO More type checking methods
+func (val *Value) IsSlice() bool {
+ return val.Type() == reflect.Slice
+}
+
+func (val *Value) IsStr() bool {
+ return val.Type() == reflect.String
+}
+
+func (self *Value) IsErr() bool {
+ _, ok := self.Val.(error)
+ return ok
+}
+
+// Special list checking function. Something is considered
+// a list if it's of type []interface{}. The list is usually
+// used in conjunction with rlp decoded streams.
+func (val *Value) IsList() bool {
+ _, ok := val.Val.([]interface{})
+
+ return ok
+}
+
+func (val *Value) IsEmpty() bool {
+ return val.Val == nil || ((val.IsSlice() || val.IsStr()) && val.Len() == 0)
+}
+
+// Threat the value as a slice
+func (val *Value) Get(idx int) *Value {
+ if d, ok := val.Val.([]interface{}); ok {
+ // Guard for oob
+ if len(d) <= idx {
+ return NewValue(nil)
+ }
+
+ if idx < 0 {
+ return NewValue(nil)
+ }
+
+ return NewValue(d[idx])
+ }
+
+ // If this wasn't a slice you probably shouldn't be using this function
+ return NewValue(nil)
+}
+
+func (self *Value) Copy() *Value {
+ switch val := self.Val.(type) {
+ case *big.Int:
+ return NewValue(new(big.Int).Set(val))
+ case []byte:
+ return NewValue(CopyBytes(val))
+ default:
+ return NewValue(self.Val)
+ }
+
+ return nil
+}
+
+func (val *Value) Cmp(o *Value) bool {
+ return reflect.DeepEqual(val.Val, o.Val)
+}
+
+func (self *Value) DeepCmp(o *Value) bool {
+ return bytes.Compare(self.Bytes(), o.Bytes()) == 0
+}
+
+func (val *Value) Encode() []byte {
+ return Encode(val.Val)
+}
+
+// Assume that the data we have is encoded
+func (self *Value) Decode() {
+ v, _ := Decode(self.Bytes(), 0)
+ self.Val = v
+ //self.Val = DecodeWithReader(bytes.NewBuffer(self.Bytes()))
+}
+
+func NewValueFromBytes(data []byte) *Value {
+ if len(data) != 0 {
+ value := NewValue(data)
+ value.Decode()
+
+ return value
+ }
+
+ return NewValue(nil)
+}
+
+// Value setters
+func NewSliceValue(s interface{}) *Value {
+ list := EmptyValue()
+
+ if s != nil {
+ if slice, ok := s.([]interface{}); ok {
+ for _, val := range slice {
+ list.Append(val)
+ }
+ } else if slice, ok := s.([]string); ok {
+ for _, val := range slice {
+ list.Append(val)
+ }
+ }
+ }
+
+ return list
+}
+
+func EmptyValue() *Value {
+ return NewValue([]interface{}{})
+}
+
+func (val *Value) AppendList() *Value {
+ list := EmptyValue()
+ val.Val = append(val.Slice(), list)
+
+ return list
+}
+
+func (val *Value) Append(v interface{}) *Value {
+ val.Val = append(val.Slice(), v)
+
+ 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
+ idx int
+}
+
+func (val *Value) NewIterator() *ValueIterator {
+ return &ValueIterator{value: val}
+}
+
+func (it *ValueIterator) Len() int {
+ return it.value.Len()
+}
+
+func (it *ValueIterator) Next() bool {
+ if it.idx >= it.value.Len() {
+ return false
+ }
+
+ it.currentValue = it.value.Get(it.idx)
+ it.idx++
+
+ return true
+}
+
+func (it *ValueIterator) Value() *Value {
+ return it.currentValue
+}
+
+func (it *ValueIterator) Idx() int {
+ return it.idx - 1
+}
diff --git a/common/value_test.go b/common/value_test.go
new file mode 100644
index 000000000..09d37802d
--- /dev/null
+++ b/common/value_test.go
@@ -0,0 +1,70 @@
+package common
+
+import (
+ "math/big"
+
+ checker "gopkg.in/check.v1"
+)
+
+type ValueSuite struct{}
+
+var _ = checker.Suite(&ValueSuite{})
+
+func (s *ValueSuite) TestValueCmp(c *checker.C) {
+ val1 := NewValue("hello")
+ val2 := NewValue("world")
+ c.Assert(val1.Cmp(val2), checker.Equals, false)
+
+ val3 := NewValue("hello")
+ val4 := NewValue("hello")
+ c.Assert(val3.Cmp(val4), checker.Equals, true)
+}
+
+func (s *ValueSuite) TestValueTypes(c *checker.C) {
+ str := NewValue("str")
+ num := NewValue(1)
+ inter := NewValue([]interface{}{1})
+ byt := NewValue([]byte{1, 2, 3, 4})
+ bigInt := NewValue(big.NewInt(10))
+
+ strExp := "str"
+ numExp := uint64(1)
+ interExp := []interface{}{1}
+ bytExp := []byte{1, 2, 3, 4}
+ bigExp := big.NewInt(10)
+
+ c.Assert(str.Str(), checker.Equals, strExp)
+ c.Assert(num.Uint(), checker.Equals, numExp)
+ c.Assert(NewValue(inter.Interface()).Cmp(NewValue(interExp)), checker.Equals, true)
+ c.Assert(byt.Bytes(), checker.DeepEquals, bytExp)
+ c.Assert(bigInt.BigInt(), checker.DeepEquals, bigExp)
+}
+
+func (s *ValueSuite) TestIterator(c *checker.C) {
+ value := NewValue([]interface{}{1, 2, 3})
+ iter := value.NewIterator()
+ values := []uint64{1, 2, 3}
+ i := 0
+ for iter.Next() {
+ c.Assert(values[i], checker.Equals, iter.Value().Uint())
+ i++
+ }
+}
+
+func (s *ValueSuite) TestMath(c *checker.C) {
+ data1 := NewValue(1)
+ data1.Add(1).Add(1)
+ exp1 := NewValue(3)
+ data2 := NewValue(2)
+ data2.Sub(1).Sub(1)
+ exp2 := NewValue(0)
+
+ c.Assert(data1.DeepCmp(exp1), checker.Equals, true)
+ c.Assert(data2.DeepCmp(exp2), checker.Equals, true)
+}
+
+func (s *ValueSuite) TestString(c *checker.C) {
+ data := "10"
+ exp := int64(10)
+ c.Assert(NewValue(data).Int(), checker.DeepEquals, exp)
+}