common: remove old RLP implementation, Value and ExtPackage
In order to make this happen, kill all remaining trivial uses of common/{rlp,value}.go. The non-trivial ones have been updated earlier.
This commit is contained in:
parent
1b89bd5d26
commit
e6fb69296e
@ -137,8 +137,7 @@ func upgradeDB(ctx *cli.Context) {
|
|||||||
glog.Infoln("Upgrading blockchain database")
|
glog.Infoln("Upgrading blockchain database")
|
||||||
|
|
||||||
chain, chainDb := utils.MakeChain(ctx)
|
chain, chainDb := utils.MakeChain(ctx)
|
||||||
v, _ := chainDb.Get([]byte("BlockchainVersion"))
|
bcVersion := core.GetBlockChainVersion(chainDb)
|
||||||
bcVersion := int(common.NewValue(v).Uint())
|
|
||||||
if bcVersion == 0 {
|
if bcVersion == 0 {
|
||||||
bcVersion = core.BlockChainVersion
|
bcVersion = core.BlockChainVersion
|
||||||
}
|
}
|
||||||
@ -154,7 +153,7 @@ func upgradeDB(ctx *cli.Context) {
|
|||||||
|
|
||||||
// Import the chain file.
|
// Import the chain file.
|
||||||
chain, chainDb = utils.MakeChain(ctx)
|
chain, chainDb = utils.MakeChain(ctx)
|
||||||
chainDb.Put([]byte("BlockchainVersion"), common.NewValue(core.BlockChainVersion).Bytes())
|
core.WriteBlockChainVersion(chainDb, core.BlockChainVersion)
|
||||||
err := utils.ImportChain(chain, exportFile)
|
err := utils.ImportChain(chain, exportFile)
|
||||||
chainDb.Close()
|
chainDb.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
292
common/rlp.go
292
common/rlp.go
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
||||||
}
|
|
428
common/value.go
428
common/value.go
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
@ -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 <http://www.gnu.org/licenses/>.
|
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
|
@ -582,3 +582,17 @@ func GetMipmapBloom(db ethdb.Database, number, level uint64) types.Bloom {
|
|||||||
bloomDat, _ := db.Get(mipmapKey(number, level))
|
bloomDat, _ := db.Get(mipmapKey(number, level))
|
||||||
return types.BytesToBloom(bloomDat)
|
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)
|
||||||
|
}
|
||||||
|
@ -180,12 +180,11 @@ func New(ctx *node.ServiceContext, config *Config) (*Ethereum, error) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if !config.SkipBcVersionCheck {
|
if !config.SkipBcVersionCheck {
|
||||||
b, _ := chainDb.Get([]byte("BlockchainVersion"))
|
bcVersion := core.GetBlockChainVersion(chainDb)
|
||||||
bcVersion := int(common.NewValue(b).Uint())
|
|
||||||
if bcVersion != config.BlockChainVersion && bcVersion != 0 {
|
if bcVersion != config.BlockChainVersion && bcVersion != 0 {
|
||||||
return nil, fmt.Errorf("Blockchain DB version mismatch (%d / %d). Run geth upgradedb.\n", bcVersion, config.BlockChainVersion)
|
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)
|
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
|
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
|
// upgradeChainDatabase ensures that the chain database stores block split into
|
||||||
// separate header and body entries.
|
// separate header and body entries.
|
||||||
func upgradeChainDatabase(db ethdb.Database) error {
|
func upgradeChainDatabase(db ethdb.Database) error {
|
||||||
|
@ -18,7 +18,6 @@ package ethdb
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/ethereum/go-ethereum/common"
|
"github.com/ethereum/go-ethereum/common"
|
||||||
@ -90,27 +89,7 @@ func (db *MemDatabase) Delete(key []byte) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (db *MemDatabase) Print() {
|
func (db *MemDatabase) Close() {}
|
||||||
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) NewBatch() Batch {
|
func (db *MemDatabase) NewBatch() Batch {
|
||||||
return &memBatch{db: db}
|
return &memBatch{db: db}
|
||||||
|
@ -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 {
|
func (self *Object) storage(addr []byte) []byte {
|
||||||
return self.StateObject.GetState(common.BytesToHash(addr)).Bytes()
|
return self.StateObject.GetState(common.BytesToHash(addr)).Bytes()
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user