diff --git a/cmd/geth/chaincmd.go b/cmd/geth/chaincmd.go
index 80f3777d6..868ee7db1 100644
--- a/cmd/geth/chaincmd.go
+++ b/cmd/geth/chaincmd.go
@@ -137,8 +137,7 @@ func upgradeDB(ctx *cli.Context) {
glog.Infoln("Upgrading blockchain database")
chain, chainDb := utils.MakeChain(ctx)
- v, _ := chainDb.Get([]byte("BlockchainVersion"))
- bcVersion := int(common.NewValue(v).Uint())
+ bcVersion := core.GetBlockChainVersion(chainDb)
if bcVersion == 0 {
bcVersion = core.BlockChainVersion
}
@@ -154,7 +153,7 @@ func upgradeDB(ctx *cli.Context) {
// Import the chain file.
chain, chainDb = utils.MakeChain(ctx)
- chainDb.Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes())
+ core.WriteBlockChainVersion(chainDb, core.BlockChainVersion)
err := utils.ImportChain(chain, exportFile)
chainDb.Close()
if err != nil {
diff --git a/common/package.go b/common/package.go
deleted file mode 100644
index 4e8780c08..000000000
--- a/common/package.go
+++ /dev/null
@@ -1,139 +0,0 @@
-// Copyright 2014 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-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/rlp.go b/common/rlp.go
deleted file mode 100644
index 481b451b1..000000000
--- a/common/rlp.go
+++ /dev/null
@@ -1,292 +0,0 @@
-// Copyright 2014 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-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.Val))
- 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
deleted file mode 100644
index 2320ffe3c..000000000
--- a/common/rlp_test.go
+++ /dev/null
@@ -1,176 +0,0 @@
-// Copyright 2014 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package common
-
-import (
- "bytes"
- "math/big"
- "reflect"
- "testing"
-
- "github.com/ethereum/go-ethereum/rlp"
-)
-
-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(byte(1)).Append(byte(2)).Append(byte(3))
- val.Append("4").AppendList().Append(byte(5))
-
- res, err := rlp.EncodeToBytes(val)
- if err != nil {
- t.Fatalf("encode error: %v", err)
- }
- exp := Encode([]interface{}{[]interface{}{1, 2, 3}, "4", []interface{}{5}})
- if bytes.Compare(res, exp) != 0 {
- t.Errorf("expected %x, got %x", exp, res)
- }
-}
-
-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 := NewValueFromBytes(enc)
- 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) {
- bv := NewValue([]interface{}{[]byte{1, 2, 3, 4, 5}, []byte{6}})
- b, _ := rlp.EncodeToBytes(bv)
- val := NewValueFromBytes(b)
- if !bv.Cmp(val) {
- t.Errorf("Expected %#v, got %#v", bv, val)
- }
-}
-
-func TestEncodeZero(t *testing.T) {
- b, _ := rlp.EncodeToBytes(NewValue(0))
- 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/value.go b/common/value.go
deleted file mode 100644
index 7abbf67b1..000000000
--- a/common/value.go
+++ /dev/null
@@ -1,428 +0,0 @@
-// Copyright 2014 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-package common
-
-import (
- "bytes"
- "fmt"
- "io"
- "math/big"
- "reflect"
- "strconv"
-
- "github.com/ethereum/go-ethereum/rlp"
-)
-
-// Value can hold values of certain basic types and provides ways to
-// convert between types without bothering to check whether the
-// conversion is actually meaningful.
-//
-// It currently supports the following types:
-//
-// - int{,8,16,32,64}
-// - uint{,8,16,32,64}
-// - *big.Int
-// - []byte, string
-// - []interface{}
-//
-// Value is useful whenever you feel that Go's types limit your
-// ability to express yourself. In these situations, use Value and
-// forget about this strong typing nonsense.
-type Value struct{ Val interface{} }
-
-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 {
- if data, ok := val.Val.([]interface{}); ok {
- return len(data)
- }
-
- return len(val.Bytes())
-}
-
-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 (self *Value) DecodeRLP(s *rlp.Stream) error {
- var v interface{}
- if err := s.Decode(&v); err != nil {
- return err
- }
- self.Val = v
- return nil
-}
-
-func (self *Value) EncodeRLP(w io.Writer) error {
- if self == nil {
- w.Write(rlp.EmptyList)
- return nil
- } else {
- return rlp.Encode(w, self.Val)
- }
-}
-
-// NewValueFromBytes decodes RLP data.
-// The contained value will be nil if data contains invalid RLP.
-func NewValueFromBytes(data []byte) *Value {
- v := new(Value)
- if len(data) != 0 {
- if err := rlp.DecodeBytes(data, v); err != nil {
- v.Val = nil
- }
- }
- return v
-}
-
-// 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
deleted file mode 100644
index ac2ef02a7..000000000
--- a/common/value_test.go
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright 2014 The go-ethereum Authors
-// This file is part of the go-ethereum library.
-//
-// The go-ethereum library is free software: you can redistribute it and/or modify
-// it under the terms of the GNU Lesser General Public License as published by
-// the Free Software Foundation, either version 3 of the License, or
-// (at your option) any later version.
-//
-// The go-ethereum library is distributed in the hope that it will be useful,
-// but WITHOUT ANY WARRANTY; without even the implied warranty of
-// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
-// GNU Lesser General Public License for more details.
-//
-// You should have received a copy of the GNU Lesser General Public License
-// along with the go-ethereum library. If not, see .
-
-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.Val).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)
-}
diff --git a/core/chain_makers.go b/core/chain_makers.go
index 4f6fa3989..5a8f380a3 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -104,6 +104,11 @@ func (b *BlockGen) AddTx(tx *types.Transaction) {
b.receipts = append(b.receipts, receipt)
}
+// Number returns the block number of the block being generated.
+func (b *BlockGen) Number() *big.Int {
+ return new(big.Int).Set(b.header.Number)
+}
+
// AddUncheckedReceipts forcefully adds a receipts to the block without a
// backing transaction.
//
diff --git a/core/database_util.go b/core/database_util.go
index fbcce3e8c..2dc113e29 100644
--- a/core/database_util.go
+++ b/core/database_util.go
@@ -582,3 +582,17 @@ func GetMipmapBloom(db ethdb.Database, number, level uint64) types.Bloom {
bloomDat, _ := db.Get(mipmapKey(number, level))
return types.BytesToBloom(bloomDat)
}
+
+// GetBlockChainVersion reads the version number from db.
+func GetBlockChainVersion(db ethdb.Database) int {
+ var vsn uint
+ enc, _ := db.Get([]byte("BlockchainVersion"))
+ rlp.DecodeBytes(enc, &vsn)
+ return int(vsn)
+}
+
+// WriteBlockChainVersion writes vsn as the version number to db.
+func WriteBlockChainVersion(db ethdb.Database, vsn int) {
+ enc, _ := rlp.EncodeToBytes(uint(vsn))
+ db.Put([]byte("BlockchainVersion"), enc)
+}
diff --git a/core/state/dump.go b/core/state/dump.go
index 9acb8a024..cff9c50aa 100644
--- a/core/state/dump.go
+++ b/core/state/dump.go
@@ -45,7 +45,7 @@ func (self *StateDB) RawDump() World {
it := self.trie.Iterator()
for it.Next() {
addr := self.trie.GetKey(it.Key)
- stateObject := NewStateObjectFromBytes(common.BytesToAddress(addr), it.Value, self.db)
+ stateObject, _ := DecodeObject(common.BytesToAddress(addr), self.db, it.Value)
account := Account{Balance: stateObject.balance.String(), Nonce: stateObject.nonce, Root: common.Bytes2Hex(stateObject.Root()), CodeHash: common.Bytes2Hex(stateObject.codeHash)}
account.Storage = make(map[string]string)
diff --git a/core/state/state_object.go b/core/state/state_object.go
index c06e3d227..47546112f 100644
--- a/core/state/state_object.go
+++ b/core/state/state_object.go
@@ -19,17 +19,19 @@ package state
import (
"bytes"
"fmt"
+ "io"
"math/big"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
+var emptyCodeHash = crypto.Sha3(nil)
+
type Code []byte
func (self Code) String() string {
@@ -56,8 +58,7 @@ func (self Storage) Copy() Storage {
}
type StateObject struct {
- // State database for storing state changes
- db ethdb.Database
+ db trie.Database // State database for storing state changes
trie *trie.SecureTrie
// Address belonging to this account
@@ -83,39 +84,16 @@ type StateObject struct {
dirty bool
}
-func NewStateObject(address common.Address, db ethdb.Database) *StateObject {
- object := &StateObject{db: db, address: address, balance: new(big.Int), dirty: true}
+func NewStateObject(address common.Address, db trie.Database) *StateObject {
+ object := &StateObject{
+ db: db,
+ address: address,
+ balance: new(big.Int),
+ dirty: true,
+ codeHash: emptyCodeHash,
+ storage: make(Storage),
+ }
object.trie, _ = trie.NewSecure(common.Hash{}, db)
- object.storage = make(Storage)
- return object
-}
-
-func NewStateObjectFromBytes(address common.Address, data []byte, db ethdb.Database) *StateObject {
- var extobject struct {
- Nonce uint64
- Balance *big.Int
- Root common.Hash
- CodeHash []byte
- }
- err := rlp.Decode(bytes.NewReader(data), &extobject)
- if err != nil {
- glog.Errorf("can't decode state object %x: %v", address, err)
- return nil
- }
- trie, err := trie.NewSecure(extobject.Root, db)
- if err != nil {
- // TODO: bubble this up or panic
- glog.Errorf("can't create account trie with root %x: %v", extobject.Root[:], err)
- return nil
- }
-
- object := &StateObject{address: address, db: db}
- object.nonce = extobject.Nonce
- object.balance = extobject.Balance
- object.codeHash = extobject.CodeHash
- object.trie = trie
- object.storage = make(map[string]common.Hash)
- object.code, _ = db.Get(extobject.CodeHash)
return object
}
@@ -172,7 +150,6 @@ func (self *StateObject) Update() {
self.trie.Delete([]byte(key))
continue
}
-
self.setAddr([]byte(key), value)
}
}
@@ -248,6 +225,7 @@ func (self *StateObject) Code() []byte {
func (self *StateObject) SetCode(code []byte) {
self.code = code
+ self.codeHash = crypto.Sha3(code)
self.dirty = true
}
@@ -276,23 +254,40 @@ func (self *StateObject) EachStorage(cb func(key, value []byte)) {
}
}
-//
// Encoding
-//
-// State object encoding methods
-func (c *StateObject) RlpEncode() []byte {
- return common.Encode([]interface{}{c.nonce, c.balance, c.Root(), c.CodeHash()})
+type extStateObject struct {
+ Nonce uint64
+ Balance *big.Int
+ Root common.Hash
+ CodeHash []byte
}
-func (c *StateObject) CodeHash() common.Bytes {
- return crypto.Sha3(c.code)
+// EncodeRLP implements rlp.Encoder.
+func (c *StateObject) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, []interface{}{c.nonce, c.balance, c.Root(), c.codeHash})
}
-// Storage change object. Used by the manifest for notifying changes to
-// the sub channels.
-type StorageState struct {
- StateAddress []byte
- Address []byte
- Value *big.Int
+// DecodeObject decodes an RLP-encoded state object.
+func DecodeObject(address common.Address, db trie.Database, data []byte) (*StateObject, error) {
+ var (
+ obj = &StateObject{address: address, db: db, storage: make(Storage)}
+ ext extStateObject
+ err error
+ )
+ if err = rlp.DecodeBytes(data, &ext); err != nil {
+ return nil, err
+ }
+ if obj.trie, err = trie.NewSecure(ext.Root, db); err != nil {
+ return nil, err
+ }
+ if !bytes.Equal(ext.CodeHash, emptyCodeHash) {
+ if obj.code, err = db.Get(ext.CodeHash); err != nil {
+ return nil, fmt.Errorf("can't find code for hash %x: %v", ext.CodeHash, err)
+ }
+ }
+ obj.nonce = ext.Nonce
+ obj.balance = ext.Balance
+ obj.codeHash = ext.CodeHash
+ return obj, nil
}
diff --git a/core/state/state_test.go b/core/state/state_test.go
index 7ddbe11a1..7ce341c36 100644
--- a/core/state/state_test.go
+++ b/core/state/state_test.go
@@ -138,8 +138,7 @@ func TestSnapshot2(t *testing.T) {
so0 := state.GetStateObject(stateobjaddr0)
so0.balance = big.NewInt(42)
so0.nonce = 43
- so0.code = []byte{'c', 'a', 'f', 'e'}
- so0.codeHash = so0.CodeHash()
+ so0.SetCode([]byte{'c', 'a', 'f', 'e'})
so0.remove = true
so0.deleted = false
so0.dirty = false
@@ -149,8 +148,7 @@ func TestSnapshot2(t *testing.T) {
so1 := state.GetStateObject(stateobjaddr1)
so1.balance = big.NewInt(52)
so1.nonce = 53
- so1.code = []byte{'c', 'a', 'f', 'e', '2'}
- so1.codeHash = so1.CodeHash()
+ so1.SetCode([]byte{'c', 'a', 'f', 'e', '2'})
so1.remove = true
so1.deleted = true
so1.dirty = true
diff --git a/core/state/statedb.go b/core/state/statedb.go
index a9de71409..ab93870bf 100644
--- a/core/state/statedb.go
+++ b/core/state/statedb.go
@@ -18,6 +18,7 @@
package state
import (
+ "fmt"
"math/big"
"github.com/ethereum/go-ethereum/common"
@@ -25,6 +26,7 @@ import (
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/logger/glog"
+ "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
@@ -205,13 +207,15 @@ func (self *StateDB) Delete(addr common.Address) bool {
// Update the given state object and apply it to state trie
func (self *StateDB) UpdateStateObject(stateObject *StateObject) {
- //addr := stateObject.Address()
-
- if len(stateObject.CodeHash()) > 0 {
- self.db.Put(stateObject.CodeHash(), stateObject.code)
+ if len(stateObject.code) > 0 {
+ self.db.Put(stateObject.codeHash, stateObject.code)
}
addr := stateObject.Address()
- self.trie.Update(addr[:], stateObject.RlpEncode())
+ data, err := rlp.EncodeToBytes(stateObject)
+ if err != nil {
+ panic(fmt.Errorf("can't encode object at %x: %v", addr[:], err))
+ }
+ self.trie.Update(addr[:], data)
}
// Delete the given state object and delete it from the state trie
@@ -238,10 +242,12 @@ func (self *StateDB) GetStateObject(addr common.Address) (stateObject *StateObje
if len(data) == 0 {
return nil
}
-
- stateObject = NewStateObjectFromBytes(addr, []byte(data), self.db)
+ stateObject, err := DecodeObject(addr, self.db, data)
+ if err != nil {
+ glog.Errorf("can't decode object at %x: %v", addr[:], err)
+ return nil
+ }
self.SetStateObject(stateObject)
-
return stateObject
}
diff --git a/core/types/receipt.go b/core/types/receipt.go
index e7d5203a3..5f847fc5c 100644
--- a/core/types/receipt.go
+++ b/core/types/receipt.go
@@ -125,17 +125,14 @@ func (r *ReceiptForStorage) DecodeRLP(s *rlp.Stream) error {
// Receipts is a wrapper around a Receipt array to implement types.DerivableList.
type Receipts []*Receipt
-// RlpEncode implements common.RlpEncode required for SHA3 derivation.
-func (r Receipts) RlpEncode() []byte {
- bytes, err := rlp.EncodeToBytes(r)
+// Len returns the number of receipts in this list.
+func (r Receipts) Len() int { return len(r) }
+
+// GetRlp returns the RLP encoding of one receipt from the list.
+func (r Receipts) GetRlp(i int) []byte {
+ bytes, err := rlp.EncodeToBytes(r[i])
if err != nil {
panic(err)
}
return bytes
}
-
-// Len returns the number of receipts in this list.
-func (r Receipts) Len() int { return len(r) }
-
-// GetRlp returns the RLP encoding of one receipt from the list.
-func (r Receipts) GetRlp(i int) []byte { return common.Rlp(r[i]) }
diff --git a/eth/backend.go b/eth/backend.go
index d51446d51..abd1214ca 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -180,12 +180,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
}
if !config.SkipBcVersionCheck {
- b, _ := chainDb.Get([]byte("BlockchainVersion"))
- bcVersion := int(common.NewValue(b).Uint())
+ bcVersion := core.GetBlockChainVersion(chainDb)
if bcVersion != config.BlockChainVersion && bcVersion != 0 {
return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d). Run geth upgradedb.\n", bcVersion, config.BlockChainVersion)
}
- saveBlockchainVersion(chainDb, config.BlockChainVersion)
+ core.WriteBlockChainVersion(chainDb, config.BlockChainVersion)
}
glog.V(logger.Info).Infof("Blockchain DB Version: %d", config.BlockChainVersion)
@@ -479,15 +478,6 @@ func dagFiles(epoch uint64) (string, string) {
return dag, "full-R" + dag
}
-func saveBlockchainVersion(db ethdb.Database, bcVersion int) {
- d, _ := db.Get([]byte("BlockchainVersion"))
- blockchainVersion := common.NewValue(d).Uint()
-
- if blockchainVersion == 0 {
- db.Put([]byte("BlockchainVersion"), common.NewValue(bcVersion).Bytes())
- }
-}
-
// upgradeChainDatabase ensures that the chain database stores block split into
// separate header and body entries.
func upgradeChainDatabase(db ethdb.Database) error {
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index cfcc8a2ef..f02418a2f 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -61,8 +61,11 @@ func makeChain(n int, seed byte, parent *types.Block, parentReceipts types.Recei
block.AddTx(tx)
}
// If the block number is a multiple of 5, add a bonus uncle to the block
- if i%5 == 0 {
- block.AddUncle(&types.Header{ParentHash: block.PrevBlock(i - 1).Hash(), Number: big.NewInt(int64(i - 1))})
+ if i > 0 && i%5 == 0 {
+ block.AddUncle(&types.Header{
+ ParentHash: block.PrevBlock(i - 1).Hash(),
+ Number: big.NewInt(block.Number().Int64() - 1),
+ })
}
})
// Convert the block-chain into a hash-chain and header/block maps
diff --git a/ethdb/memory_database.go b/ethdb/memory_database.go
index 01273b9db..45423ed73 100644
--- a/ethdb/memory_database.go
+++ b/ethdb/memory_database.go
@@ -18,7 +18,6 @@ package ethdb
import (
"errors"
- "fmt"
"sync"
"github.com/ethereum/go-ethereum/common"
@@ -90,27 +89,7 @@ func (db *MemDatabase) Delete(key []byte) error {
return nil
}
-func (db *MemDatabase) Print() {
- db.lock.RLock()
- defer db.lock.RUnlock()
-
- for key, val := range db.db {
- fmt.Printf("%x(%d): ", key, len(key))
- node := common.NewValueFromBytes(val)
- fmt.Printf("%q\n", node.Val)
- }
-}
-
-func (db *MemDatabase) Close() {
-}
-
-func (db *MemDatabase) LastKnownTD() []byte {
- data, _ := db.Get([]byte("LastKnownTotalDifficulty"))
- if len(data) == 0 || data == nil {
- data = []byte{0x0}
- }
- return data
-}
+func (db *MemDatabase) Close() {}
func (db *MemDatabase) NewBatch() Batch {
return &memBatch{db: db}
diff --git a/xeth/types.go b/xeth/types.go
index 218c8dc7c..090115b7e 100644
--- a/xeth/types.go
+++ b/xeth/types.go
@@ -47,10 +47,6 @@ func (self *Object) StorageString(str string) []byte {
}
}
-func (self *Object) StorageValue(addr *common.Value) []byte {
- return self.storage(addr.Bytes())
-}
-
func (self *Object) storage(addr []byte) []byte {
return self.StateObject.GetState(common.BytesToHash(addr)).Bytes()
}