aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--blockpool/blockpool.go51
-rw-r--r--blockpool/peers.go49
-rw-r--r--blockpool/section.go15
-rw-r--r--cmd/ethereum/admin.go9
-rw-r--r--cmd/ethereum/main.go2
-rw-r--r--cmd/ethtest/main.go69
-rw-r--r--cmd/utils/cmd.go36
-rw-r--r--common/bytes.go2
-rw-r--r--common/types.go89
-rw-r--r--common/types_template.go48
-rw-r--r--common/types_test.go15
-rw-r--r--core/block_processor.go39
-rw-r--r--core/block_processor_test.go5
-rw-r--r--core/chain_makers.go8
-rw-r--r--core/chain_manager.go84
-rw-r--r--core/chain_manager_test.go9
-rw-r--r--core/error.go6
-rw-r--r--core/execution.go27
-rw-r--r--core/filter.go24
-rw-r--r--core/genesis.go11
-rw-r--r--core/state_transition.go39
-rw-r--r--core/transaction_pool.go65
-rw-r--r--core/transaction_pool_test.go12
-rw-r--r--core/types/block.go183
-rw-r--r--core/types/block_test.go59
-rw-r--r--core/types/bloom9.go28
-rw-r--r--core/types/common.go32
-rw-r--r--core/types/derive_sha.go10
-rw-r--r--core/types/receipt.go38
-rw-r--r--core/types/transaction.go154
-rw-r--r--core/types/transaction_test.go57
-rw-r--r--core/vm_env.go42
-rw-r--r--crypto/crypto.go18
-rw-r--r--crypto/crypto_test.go8
-rw-r--r--eth/backend.go6
-rw-r--r--eth/protocol.go144
-rw-r--r--eth/protocol_test.go189
-rw-r--r--miner/miner.go3
-rw-r--r--miner/worker.go27
-rw-r--r--p2p/handshake.go8
-rw-r--r--p2p/message.go77
-rw-r--r--p2p/message_test.go24
-rw-r--r--p2p/peer.go7
-rw-r--r--p2p/peer_test.go73
-rw-r--r--p2p/rlpx_test.go4
-rw-r--r--p2p/server.go11
-rw-r--r--p2p/server_test.go2
-rw-r--r--pow/block.go5
-rw-r--r--pow/ezp/pow.go11
-rw-r--r--rlp/decode.go7
-rw-r--r--rlp/encode.go28
-rw-r--r--rlp/encode_test.go7
-rw-r--r--rpc/api.go19
-rw-r--r--rpc/responses.go76
-rw-r--r--rpc/util.go4
-rw-r--r--state/dump.go2
-rw-r--r--state/log.go32
-rw-r--r--state/managed_state.go25
-rw-r--r--state/managed_state_test.go12
-rw-r--r--state/state_object.go38
-rw-r--r--state/state_test.go11
-rw-r--r--state/statedb.go69
-rw-r--r--tests/blocktest.go56
-rw-r--r--tests/helper/vm.go88
-rw-r--r--tests/vm/gh_test.go50
-rw-r--r--vm/common.go78
-rw-r--r--vm/context.go8
-rw-r--r--vm/environment.go32
-rw-r--r--vm/gas.go49
-rw-r--r--vm/vm.go61
-rw-r--r--whisper/envelope.go2
-rw-r--r--whisper/peer.go9
-rw-r--r--xeth/state.go6
-rw-r--r--xeth/types.go20
-rw-r--r--xeth/xeth.go48
75 files changed, 1601 insertions, 1170 deletions
diff --git a/blockpool/blockpool.go b/blockpool/blockpool.go
index bc998cd7b..c5af481a7 100644
--- a/blockpool/blockpool.go
+++ b/blockpool/blockpool.go
@@ -1,12 +1,12 @@
package blockpool
import (
- "bytes"
"fmt"
"math/big"
"sync"
"time"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/errs"
ethlogger "github.com/ethereum/go-ethereum/logger"
@@ -101,7 +101,7 @@ func (self *Config) init() {
// node is the basic unit of the internal model of block chain/tree in the blockpool
type node struct {
lock sync.RWMutex
- hash []byte
+ hash common.Hash
block *types.Block
hashBy string
blockBy string
@@ -123,7 +123,7 @@ type BlockPool struct {
Config *Config
// the minimal interface with blockchain
- hasBlock func(hash []byte) bool
+ hasBlock func(hash common.Hash) bool
insertChain func(types.Blocks) error
verifyPoW func(pow.Block) bool
@@ -133,7 +133,7 @@ type BlockPool struct {
lock sync.RWMutex
chainLock sync.RWMutex
// alloc-easy pool of hash slices
- hashSlicePool chan [][]byte
+ hashSlicePool chan []common.Hash
status *status
@@ -144,7 +144,7 @@ type BlockPool struct {
// public constructor
func New(
- hasBlock func(hash []byte) bool,
+ hasBlock func(hash common.Hash) bool,
insertChain func(types.Blocks) error,
verifyPoW func(pow.Block) bool,
) *BlockPool {
@@ -176,7 +176,7 @@ func (self *BlockPool) Start() {
}
self.Config.init()
- self.hashSlicePool = make(chan [][]byte, 150)
+ self.hashSlicePool = make(chan []common.Hash, 150)
self.status = newStatus()
self.quit = make(chan bool)
self.pool = make(map[string]*entry)
@@ -261,14 +261,13 @@ Peer info is currently not persisted across disconnects (or sessions)
*/
func (self *BlockPool) AddPeer(
- td *big.Int, currentBlockHash []byte,
+ td *big.Int, currentBlockHash common.Hash,
peerId string,
- requestBlockHashes func([]byte) error,
- requestBlocks func([][]byte) error,
+ requestBlockHashes func(common.Hash) error,
+ requestBlocks func([]common.Hash) error,
peerError func(*errs.Error),
) (best bool) {
-
return self.peers.addPeer(td, currentBlockHash, peerId, requestBlockHashes, requestBlocks, peerError)
}
@@ -289,7 +288,7 @@ launches all block request processes on each chain section
the first argument is an iterator function. Using this block hashes are decoded from the rlp message payload on demand. As a result, AddBlockHashes needs to run synchronously for one peer since the message is discarded if the caller thread returns.
*/
-func (self *BlockPool) AddBlockHashes(next func() ([]byte, bool), peerId string) {
+func (self *BlockPool) AddBlockHashes(next func() (common.Hash, bool), peerId string) {
bestpeer, best := self.peers.getPeer(peerId)
if !best {
@@ -306,7 +305,7 @@ func (self *BlockPool) AddBlockHashes(next func() ([]byte, bool), peerId string)
self.status.lock.Unlock()
var n int
- var hash []byte
+ var hash common.Hash
var ok, headSection, peerswitch bool
var sec, child, parent *section
var entry *entry
@@ -318,7 +317,7 @@ func (self *BlockPool) AddBlockHashes(next func() ([]byte, bool), peerId string)
plog.Debugf("AddBlockHashes: peer <%s> starting from [%s] (peer head: %s)", peerId, hex(bestpeer.parentHash), hex(bestpeer.currentBlockHash))
// first check if we are building the head section of a peer's chain
- if bytes.Equal(bestpeer.parentHash, hash) {
+ if bestpeer.parentHash == hash {
if self.hasBlock(bestpeer.currentBlockHash) {
return
}
@@ -561,7 +560,7 @@ func (self *BlockPool) AddBlock(block *types.Block, peerId string) {
entry := self.get(hash)
// a peer's current head block is appearing the first time
- if bytes.Equal(hash, sender.currentBlockHash) {
+ if hash == sender.currentBlockHash {
if sender.currentBlock == nil {
plog.Debugf("AddBlock: add head block %s for peer <%s> (head: %s)", hex(hash), peerId, hex(sender.currentBlockHash))
sender.setChainInfoFromBlock(block)
@@ -664,7 +663,7 @@ LOOP:
plog.DebugDetailf("activateChain: section [%s] activated by peer <%s>", sectionhex(sec), p.id)
sec.activate(p)
if i > 0 && connected != nil {
- connected[string(sec.top.hash)] = sec
+ connected[sec.top.hash.Str()] = sec
}
/*
we need to relink both complete and incomplete sections
@@ -696,7 +695,7 @@ LOOP:
// must run in separate go routine, otherwise
// switchpeer -> activateChain -> activate deadlocks on section process select and peers.lock
-func (self *BlockPool) requestBlocks(attempts int, hashes [][]byte) {
+func (self *BlockPool) requestBlocks(attempts int, hashes []common.Hash) {
self.wg.Add(1)
go func() {
self.peers.requestBlocks(attempts, hashes)
@@ -718,16 +717,16 @@ func (self *BlockPool) getChild(sec *section) *section {
}
// accessor and setter for entries in the pool
-func (self *BlockPool) get(hash []byte) *entry {
+func (self *BlockPool) get(hash common.Hash) *entry {
self.lock.RLock()
defer self.lock.RUnlock()
- return self.pool[string(hash)]
+ return self.pool[hash.Str()]
}
-func (self *BlockPool) set(hash []byte, e *entry) {
+func (self *BlockPool) set(hash common.Hash, e *entry) {
self.lock.Lock()
defer self.lock.Unlock()
- self.pool[string(hash)] = e
+ self.pool[hash.Str()] = e
}
func (self *BlockPool) remove(sec *section) {
@@ -736,7 +735,7 @@ func (self *BlockPool) remove(sec *section) {
defer self.lock.Unlock()
for _, node := range sec.nodes {
- delete(self.pool, string(node.hash))
+ delete(self.pool, node.hash.Str())
}
if sec.initialised && sec.poolRootIndex != 0 {
self.status.lock.Lock()
@@ -745,17 +744,17 @@ func (self *BlockPool) remove(sec *section) {
}
}
-func (self *BlockPool) getHashSlice() (s [][]byte) {
+func (self *BlockPool) getHashSlice() (s []common.Hash) {
select {
case s = <-self.hashSlicePool:
default:
- s = make([][]byte, self.Config.BlockBatchSize)
+ s = make([]common.Hash, self.Config.BlockBatchSize)
}
return
}
// Return returns a Client to the pool.
-func (self *BlockPool) putHashSlice(s [][]byte) {
+func (self *BlockPool) putHashSlice(s []common.Hash) {
if len(s) == self.Config.BlockBatchSize {
select {
case self.hashSlicePool <- s:
@@ -765,8 +764,8 @@ func (self *BlockPool) putHashSlice(s [][]byte) {
}
// pretty prints hash (byte array) with first 4 bytes in hex
-func hex(hash []byte) (name string) {
- if hash == nil {
+func hex(hash common.Hash) (name string) {
+ if (hash == common.Hash{}) {
name = ""
} else {
name = fmt.Sprintf("%x", hash[:4])
diff --git a/blockpool/peers.go b/blockpool/peers.go
index 5f4889792..d94d6ac46 100644
--- a/blockpool/peers.go
+++ b/blockpool/peers.go
@@ -1,16 +1,15 @@
package blockpool
import (
- "bytes"
"math/big"
"math/rand"
"sort"
"sync"
"time"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/errs"
- "github.com/ethereum/go-ethereum/common"
)
type peer struct {
@@ -18,20 +17,20 @@ type peer struct {
// last known blockchain status
td *big.Int
- currentBlockHash []byte
+ currentBlockHash common.Hash
currentBlock *types.Block
- parentHash []byte
+ parentHash common.Hash
headSection *section
id string
// peer callbacks
- requestBlockHashes func([]byte) error
- requestBlocks func([][]byte) error
+ requestBlockHashes func(common.Hash) error
+ requestBlocks func([]common.Hash) error
peerError func(*errs.Error)
errors *errs.Errors
- sections [][]byte
+ sections []common.Hash
// channels to push new head block and head section for peer a
currentBlockC chan *types.Block
@@ -66,10 +65,10 @@ type peers struct {
// peer constructor
func (self *peers) newPeer(
td *big.Int,
- currentBlockHash []byte,
+ currentBlockHash common.Hash,
id string,
- requestBlockHashes func([]byte) error,
- requestBlocks func([][]byte) error,
+ requestBlockHashes func(common.Hash) error,
+ requestBlocks func([]common.Hash) error,
peerError func(*errs.Error),
) (p *peer) {
@@ -107,7 +106,7 @@ func (self *peer) addError(code int, format string, params ...interface{}) {
self.peerError(err)
}
-func (self *peer) setChainInfo(td *big.Int, c []byte) {
+func (self *peer) setChainInfo(td *big.Int, c common.Hash) {
self.lock.Lock()
defer self.lock.Unlock()
@@ -115,7 +114,7 @@ func (self *peer) setChainInfo(td *big.Int, c []byte) {
self.currentBlockHash = c
self.currentBlock = nil
- self.parentHash = nil
+ self.parentHash = common.Hash{}
self.headSection = nil
}
@@ -139,7 +138,7 @@ func (self *peer) setChainInfoFromBlock(block *types.Block) {
}()
}
-func (self *peers) requestBlocks(attempts int, hashes [][]byte) {
+func (self *peers) requestBlocks(attempts int, hashes []common.Hash) {
// distribute block request among known peers
self.lock.RLock()
defer self.lock.RUnlock()
@@ -178,18 +177,18 @@ func (self *peers) requestBlocks(attempts int, hashes [][]byte) {
// returns true iff peer is promoted as best peer in the pool
func (self *peers) addPeer(
td *big.Int,
- currentBlockHash []byte,
+ currentBlockHash common.Hash,
id string,
- requestBlockHashes func([]byte) error,
- requestBlocks func([][]byte) error,
+ requestBlockHashes func(common.Hash) error,
+ requestBlocks func([]common.Hash) error,
peerError func(*errs.Error),
) (best bool) {
- var previousBlockHash []byte
+ var previousBlockHash common.Hash
self.lock.Lock()
p, found := self.peers[id]
if found {
- if !bytes.Equal(p.currentBlockHash, currentBlockHash) {
+ if p.currentBlockHash != currentBlockHash {
previousBlockHash = p.currentBlockHash
plog.Debugf("addPeer: Update peer <%s> with td %v and current block %s (was %v)", id, td, hex(currentBlockHash), hex(previousBlockHash))
p.setChainInfo(td, currentBlockHash)
@@ -221,7 +220,7 @@ func (self *peers) addPeer(
// new block update for active current best peer -> request hashes
plog.Debugf("addPeer: <%s> already the best peer. Request new head section info from %s", id, hex(currentBlockHash))
- if previousBlockHash != nil {
+ if (previousBlockHash != common.Hash{}) {
if entry := self.bp.get(previousBlockHash); entry != nil {
p.headSectionC <- nil
self.bp.activateChain(entry.section, p, nil)
@@ -318,15 +317,15 @@ func (self *BlockPool) switchPeer(oldp, newp *peer) {
}
var connected = make(map[string]*section)
- var sections [][]byte
+ var sections []common.Hash
for _, hash := range newp.sections {
plog.DebugDetailf("activate chain starting from section [%s]", hex(hash))
// if section not connected (ie, top of a contiguous sequence of sections)
- if connected[string(hash)] == nil {
+ if connected[hash.Str()] == nil {
// if not deleted, then reread from pool (it can be orphaned top half of a split section)
if entry := self.get(hash); entry != nil {
self.activateChain(entry.section, newp, connected)
- connected[string(hash)] = entry.section
+ connected[hash.Str()] = entry.section
sections = append(sections, hash)
}
}
@@ -396,7 +395,7 @@ func (self *peer) getCurrentBlock(currentBlock *types.Block) {
plog.DebugDetailf("HeadSection: <%s> head block %s found in blockpool", self.id, hex(self.currentBlockHash))
} else {
plog.DebugDetailf("HeadSection: <%s> head block %s not found... requesting it", self.id, hex(self.currentBlockHash))
- self.requestBlocks([][]byte{self.currentBlockHash})
+ self.requestBlocks([]common.Hash{self.currentBlockHash})
self.blocksRequestTimer = time.After(self.bp.Config.BlocksRequestInterval)
return
}
@@ -427,9 +426,9 @@ func (self *peer) getBlockHashes() {
self.addError(ErrInvalidBlock, "%v", err)
self.bp.status.badPeers[self.id]++
} else {
- headKey := string(self.parentHash)
+ headKey := self.parentHash.Str()
height := self.bp.status.chain[headKey] + 1
- self.bp.status.chain[string(self.currentBlockHash)] = height
+ self.bp.status.chain[self.currentBlockHash.Str()] = height
if height > self.bp.status.values.LongestChain {
self.bp.status.values.LongestChain = height
}
diff --git a/blockpool/section.go b/blockpool/section.go
index 03c4f5cc6..c73aaa6df 100644
--- a/blockpool/section.go
+++ b/blockpool/section.go
@@ -4,6 +4,7 @@ import (
"sync"
"time"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
@@ -27,9 +28,9 @@ type section struct {
nodes []*node
peer *peer
- parentHash []byte
+ parentHash common.Hash
- blockHashes [][]byte
+ blockHashes []common.Hash
poolRootIndex int
@@ -115,7 +116,7 @@ func (self *section) addSectionToBlockChain(p *peer) {
break
}
self.poolRootIndex--
- keys = append(keys, string(node.hash))
+ keys = append(keys, node.hash.Str())
blocks = append(blocks, block)
}
@@ -166,9 +167,9 @@ func (self *section) addSectionToBlockChain(p *peer) {
self.bp.status.lock.Lock()
if err == nil {
- headKey := string(blocks[0].ParentHash())
+ headKey := blocks[0].ParentHash().Str()
height := self.bp.status.chain[headKey] + len(blocks)
- self.bp.status.chain[string(blocks[len(blocks)-1].Hash())] = height
+ self.bp.status.chain[blocks[len(blocks)-1].Hash().Str()] = height
if height > self.bp.status.values.LongestChain {
self.bp.status.values.LongestChain = height
}
@@ -316,7 +317,7 @@ LOOP:
self.addSectionToBlockChain(self.peer)
}
} else {
- if self.parentHash == nil && n == self.bottom {
+ if (self.parentHash == common.Hash{}) && n == self.bottom {
self.parentHash = block.ParentHash()
plog.DebugDetailf("[%s] got parent head block hash %s...checking", sectionhex(self), hex(self.parentHash))
self.blockHashesRequest()
@@ -456,7 +457,7 @@ func (self *section) blockHashesRequest() {
// a demoted peer's fork will be chosen over the best peer's chain
// because relinking the correct chain (activateChain) is overwritten here in
// demoted peer's section process just before the section is put to idle mode
- if self.parentHash != nil {
+ if (self.parentHash != common.Hash{}) {
if parent := self.bp.get(self.parentHash); parent != nil {
parentSection = parent.section
plog.DebugDetailf("[%s] blockHashesRequest: parent section [%s] linked\n", sectionhex(self), sectionhex(parentSection))
diff --git a/cmd/ethereum/admin.go b/cmd/ethereum/admin.go
index 880a22c22..41aaf46d8 100644
--- a/cmd/ethereum/admin.go
+++ b/cmd/ethereum/admin.go
@@ -8,8 +8,8 @@ import (
"time"
"github.com/ethereum/go-ethereum/cmd/utils"
- "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/rpc"
"github.com/ethereum/go-ethereum/state"
@@ -221,13 +221,10 @@ func (js *jsre) exportChain(call otto.FunctionCall) otto.Value {
fmt.Println(err)
return otto.FalseValue()
}
-
- data := js.ethereum.ChainManager().Export()
- if err := common.WriteFile(fn, data); err != nil {
+ if err := utils.ExportChain(js.ethereum.ChainManager(), fn); err != nil {
fmt.Println(err)
return otto.FalseValue()
}
-
return otto.TrueValue()
}
@@ -239,7 +236,7 @@ func (js *jsre) dumpBlock(call otto.FunctionCall) otto.Value {
block = js.ethereum.ChainManager().GetBlockByNumber(uint64(num))
} else if call.Argument(0).IsString() {
hash, _ := call.Argument(0).ToString()
- block = js.ethereum.ChainManager().GetBlock(common.Hex2Bytes(hash))
+ block = js.ethereum.ChainManager().GetBlock(common.HexToHash(hash))
} else {
fmt.Println("invalid argument for dump. Either hex string or number")
}
diff --git a/cmd/ethereum/main.go b/cmd/ethereum/main.go
index 38c04ec9d..afaf06948 100644
--- a/cmd/ethereum/main.go
+++ b/cmd/ethereum/main.go
@@ -314,7 +314,7 @@ func dump(ctx *cli.Context) {
for _, arg := range ctx.Args() {
var block *types.Block
if hashish(arg) {
- block = chainmgr.GetBlock(common.Hex2Bytes(arg))
+ block = chainmgr.GetBlock(common.HexToHash(arg))
} else {
num, _ := strconv.Atoi(arg)
block = chainmgr.GetBlockByNumber(uint64(num))
diff --git a/cmd/ethtest/main.go b/cmd/ethtest/main.go
index cf1ec6dfa..ee6bcc540 100644
--- a/cmd/ethtest/main.go
+++ b/cmd/ethtest/main.go
@@ -24,6 +24,7 @@ package main
import (
"bytes"
"encoding/json"
+ "fmt"
"io"
"io/ioutil"
"log"
@@ -33,6 +34,7 @@ import (
"strings"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state"
@@ -66,7 +68,7 @@ type Account struct {
}
func StateObjectFromAccount(db common.Database, addr string, account Account) *state.StateObject {
- obj := state.NewStateObject(common.Hex2Bytes(addr), db)
+ obj := state.NewStateObject(common.HexToAddress(addr), db)
obj.SetBalance(common.Big(account.Balance))
if common.IsHex(account.Code) {
@@ -112,7 +114,7 @@ func RunVmTest(r io.Reader) (failed int) {
for name, test := range tests {
db, _ := ethdb.NewMemDatabase()
- statedb := state.New(nil, db)
+ statedb := state.New(common.Hash{}, db)
for addr, account := range test.Pre {
obj := StateObjectFromAccount(db, addr, account)
statedb.SetStateObject(obj)
@@ -135,63 +137,82 @@ func RunVmTest(r io.Reader) (failed int) {
rexp := helper.FromHex(test.Out)
if bytes.Compare(rexp, ret) != 0 {
- helper.Log.Infof("FAIL: %s's return failed. Expected %x, got %x\n", name, rexp, ret)
+ helper.Log.Infof("%s's return failed. Expected %x, got %x\n", name, rexp, ret)
failed = 1
}
for addr, account := range test.Post {
- obj := statedb.GetStateObject(helper.FromHex(addr))
+ obj := statedb.GetStateObject(common.HexToAddress(addr))
if obj == nil {
continue
}
if len(test.Exec) == 0 {
if obj.Balance().Cmp(common.Big(account.Balance)) != 0 {
- helper.Log.Infof("FAIL: %s's : (%x) balance failed. Expected %v, got %v => %v\n",
- name,
- obj.Address()[:4],
- account.Balance,
- obj.Balance(),
- new(big.Int).Sub(common.Big(account.Balance), obj.Balance()),
- )
+ helper.Log.Infof("%s's : (%x) balance failed. Expected %v, got %v => %v\n", name, obj.Address().Bytes()[:4], account.Balance, obj.Balance(), new(big.Int).Sub(common.Big(account.Balance), obj.Balance()))
failed = 1
}
}
for addr, value := range account.Storage {
- v := obj.GetState(helper.FromHex(addr)).Bytes()
+ v := obj.GetState(common.HexToHash(addr)).Bytes()
vexp := helper.FromHex(value)
if bytes.Compare(v, vexp) != 0 {
- helper.Log.Infof("FAIL: %s's : (%x: %s) storage failed. Expected %x, got %x (%v %v)\n", name, obj.Address()[0:4], addr, vexp, v, common.BigD(vexp), common.BigD(v))
+ helper.Log.Infof("%s's : (%x: %s) storage failed. Expected %x, got %x (%v %v)\n", name, obj.Address().Bytes()[0:4], addr, vexp, v, common.BigD(vexp), common.BigD(v))
failed = 1
}
}
}
- if !bytes.Equal(common.Hex2Bytes(test.PostStateRoot), statedb.Root()) {
- helper.Log.Infof("FAIL: %s's : Post state root error. Expected %s, got %x\n", name, test.PostStateRoot, statedb.Root())
+ statedb.Sync()
+ //if !bytes.Equal(common.Hex2Bytes(test.PostStateRoot), statedb.Root()) {
+ if common.HexToHash(test.PostStateRoot) != statedb.Root() {
+ helper.Log.Infof("%s's : Post state root failed. Expected %s, got %x", name, test.PostStateRoot, statedb.Root())
failed = 1
}
if len(test.Logs) > 0 {
if len(test.Logs) != len(logs) {
- helper.Log.Infof("FAIL: log length mismatch. Expected %d, got %d", len(test.Logs), len(logs))
+ helper.Log.Infof("log length failed. Expected %d, got %d", len(test.Logs), len(logs))
failed = 1
} else {
- /*
- fmt.Println("A", test.Logs)
- fmt.Println("B", logs)
- for i, log := range test.Logs {
- genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256)
- if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) {
- t.Errorf("bloom mismatch")
+ for i, log := range test.Logs {
+ if common.HexToAddress(log.AddressF) != logs[i].Address() {
+ helper.Log.Infof("'%s' log address failed. Expected %v got %x", name, log.AddressF, logs[i].Address())
+ failed = 1
+ }
+
+ if !bytes.Equal(logs[i].Data(), helper.FromHex(log.DataF)) {
+ helper.Log.Infof("'%s' log data failed. Expected %v got %x", name, log.DataF, logs[i].Data())
+ failed = 1
+ }
+
+ if len(log.TopicsF) != len(logs[i].Topics()) {
+ helper.Log.Infof("'%s' log topics length failed. Expected %d got %d", name, len(log.TopicsF), logs[i].Topics())
+ failed = 1
+ } else {
+ for j, topic := range log.TopicsF {
+ if common.HexToHash(topic) != logs[i].Topics()[j] {
+ helper.Log.Infof("'%s' log topic[%d] failed. Expected %v got %x", name, j, topic, logs[i].Topics()[j])
+ failed = 1
}
}
- */
+ }
+ genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256)
+
+ if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) {
+ helper.Log.Infof("'%s' bloom failed.", name)
+ failed = 1
+ }
+ }
}
}
+ if failed == 1 {
+ fmt.Println(string(statedb.Dump()))
+ }
+
logger.Flush()
}
diff --git a/cmd/utils/cmd.go b/cmd/utils/cmd.go
index 74fd5334e..feea29d64 100644
--- a/cmd/utils/cmd.go
+++ b/cmd/utils/cmd.go
@@ -23,14 +23,15 @@ package utils
import (
"fmt"
+ "io"
"os"
"os/signal"
"regexp"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/eth"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -152,29 +153,34 @@ func ImportChain(chainmgr *core.ChainManager, fn string) error {
}
defer fh.Close()
- var blocks types.Blocks
- if err := rlp.Decode(fh, &blocks); err != nil {
- return err
- }
-
chainmgr.Reset()
- if err := chainmgr.InsertChain(blocks); err != nil {
- return err
+ stream := rlp.NewStream(fh)
+ var i int
+ for ; ; i++ {
+ var b types.Block
+ if err := stream.Decode(&b); err == io.EOF {
+ break
+ } else if err != nil {
+ return fmt.Errorf("at block %d: %v", i, err)
+ }
+ if err := chainmgr.InsertChain(types.Blocks{&b}); err != nil {
+ return fmt.Errorf("invalid block %d: %v", i, err)
+ }
}
- fmt.Printf("imported %d blocks\n", len(blocks))
-
+ fmt.Printf("imported %d blocks\n", i)
return nil
}
func ExportChain(chainmgr *core.ChainManager, fn string) error {
fmt.Printf("exporting blockchain '%s'\n", fn)
-
- data := chainmgr.Export()
-
- if err := common.WriteFile(fn, data); err != nil {
+ fh, err := os.OpenFile(fn, os.O_CREATE|os.O_WRONLY|os.O_TRUNC, os.ModePerm)
+ if err != nil {
+ return err
+ }
+ defer fh.Close()
+ if err := chainmgr.Export(fh); err != nil {
return err
}
fmt.Printf("exported blockchain\n")
-
return nil
}
diff --git a/common/bytes.go b/common/bytes.go
index 4aef9a223..5e553d23c 100644
--- a/common/bytes.go
+++ b/common/bytes.go
@@ -211,7 +211,7 @@ func RightPadString(str string, l int) string {
}
-func Address(slice []byte) (addr []byte) {
+func ToAddress(slice []byte) (addr []byte) {
if len(slice) < 20 {
addr = LeftPadBytes(slice, 20)
} else if len(slice) > 20 {
diff --git a/common/types.go b/common/types.go
index 6a9abdf18..38044d5c8 100644
--- a/common/types.go
+++ b/common/types.go
@@ -1,6 +1,91 @@
package common
+import "math/big"
+
+const (
+ hashLength = 32
+ addressLength = 20
+)
+
type (
- uHash [32]byte
- uAddress [20]byte
+ Hash [hashLength]byte
+ Address [addressLength]byte
)
+
+func BytesToHash(b []byte) Hash {
+ var h Hash
+ h.SetBytes(b)
+ return h
+}
+func StringToHash(s string) Hash { return BytesToHash([]byte(s)) }
+func BigToHash(b *big.Int) Hash { return BytesToHash(b.Bytes()) }
+func HexToHash(s string) Hash { return BytesToHash(FromHex(s)) }
+
+// Don't use the default 'String' method in case we want to overwrite
+
+// Get the string representation of the underlying hash
+func (h Hash) Str() string { return string(h[:]) }
+func (h Hash) Bytes() []byte { return h[:] }
+func (h Hash) Big() *big.Int { return Bytes2Big(h[:]) }
+func (h Hash) Hex() string { return "0x" + Bytes2Hex(h[:]) }
+
+// Sets the hash to the value of b. If b is larger than len(h) it will panic
+func (h *Hash) SetBytes(b []byte) {
+ if len(b) > len(h) {
+ b = b[len(b)-hashLength:]
+ }
+
+ // reverse loop
+ for i := len(b) - 1; i >= 0; i-- {
+ h[hashLength-len(b)+i] = b[i]
+ }
+}
+
+// Set string `s` to h. If s is larger than len(h) it will panic
+func (h *Hash) SetString(s string) { h.SetBytes([]byte(s)) }
+
+// Sets h to other
+func (h *Hash) Set(other Hash) {
+ for i, v := range other {
+ h[i] = v
+ }
+}
+
+/////////// Address
+func BytesToAddress(b []byte) Address {
+ var a Address
+ a.SetBytes(b)
+ return a
+}
+func StringToAddress(s string) Address { return BytesToAddress([]byte(s)) }
+func BigToAddress(b *big.Int) Address { return BytesToAddress(b.Bytes()) }
+func HexToAddress(s string) Address { return BytesToAddress(FromHex(s)) }
+
+// Get the string representation of the underlying address
+func (a Address) Str() string { return string(a[:]) }
+func (a Address) Bytes() []byte { return a[:] }
+func (a Address) Big() *big.Int { return Bytes2Big(a[:]) }
+func (a Address) Hash() Hash { return BytesToHash(a[:]) }
+func (a Address) Hex() string { return "0x" + Bytes2Hex(a[:]) }
+
+// Sets the address to the value of b. If b is larger than len(a) it will panic
+func (a *Address) SetBytes(b []byte) {
+ if len(b) > len(a) {
+ b = b[len(b)-addressLength:]
+ }
+
+ // reverse loop
+ for i := len(b) - 1; i >= 0; i-- {
+ a[addressLength-len(b)+i] = b[i]
+ }
+}
+
+// Set string `s` to a. If s is larger than len(a) it will panic
+func (a *Address) SetString(s string) { a.SetBytes([]byte(s)) }
+
+// Sets a to other
+func (a *Address) Set(other Address) {
+ for i, v := range other {
+ a[i] = v
+ }
+}
diff --git a/common/types_template.go b/common/types_template.go
new file mode 100644
index 000000000..1c82a36dc
--- /dev/null
+++ b/common/types_template.go
@@ -0,0 +1,48 @@
+// +build none
+//sed -e 's/_N_/Hash/g' -e 's/_S_/32/g' -e '1d' types_template.go | gofmt -w hash.go
+
+package common
+
+import "math/big"
+
+type _N_ [_S_]byte
+
+func BytesTo_N_(b []byte) _N_ {
+ var h _N_
+ h.SetBytes(b)
+ return h
+}
+func StringTo_N_(s string) _N_ { return BytesTo_N_([]byte(s)) }
+func BigTo_N_(b *big.Int) _N_ { return BytesTo_N_(b.Bytes()) }
+func HexTo_N_(s string) _N_ { return BytesTo_N_(FromHex(s)) }
+
+// Don't use the default 'String' method in case we want to overwrite
+
+// Get the string representation of the underlying hash
+func (h _N_) Str() string { return string(h[:]) }
+func (h _N_) Bytes() []byte { return h[:] }
+func (h _N_) Big() *big.Int { return Bytes2Big(h[:]) }
+func (h _N_) Hex() string { return "0x" + Bytes2Hex(h[:]) }
+
+// Sets the hash to the value of b. If b is larger than len(h) it will panic
+func (h *_N_) SetBytes(b []byte) {
+ // Use the right most bytes
+ if len(b) > len(h) {
+ b = b[len(b)-_S_:]
+ }
+
+ // Reverse the loop
+ for i := len(b) - 1; i >= 0; i-- {
+ h[_S_-len(b)+i] = b[i]
+ }
+}
+
+// Set string `s` to h. If s is larger than len(h) it will panic
+func (h *_N_) SetString(s string) { h.SetBytes([]byte(s)) }
+
+// Sets h to other
+func (h *_N_) Set(other _N_) {
+ for i, v := range other {
+ h[i] = v
+ }
+}
diff --git a/common/types_test.go b/common/types_test.go
new file mode 100644
index 000000000..9f303152c
--- /dev/null
+++ b/common/types_test.go
@@ -0,0 +1,15 @@
+package common
+
+import "testing"
+
+func TestBytesConversion(t *testing.T) {
+ bytes := []byte{5}
+ hash := BytesToHash(bytes)
+
+ var exp Hash
+ exp[31] = 5
+
+ if hash != exp {
+ t.Errorf("expected %x got %x", exp, hash)
+ }
+}
diff --git a/core/block_processor.go b/core/block_processor.go
index 62c9c92a6..99c5fea05 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -1,7 +1,6 @@
package core
import (
- "bytes"
"fmt"
"math/big"
"sync"
@@ -78,7 +77,8 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
_, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, block), tx, cb)
if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) {
// If the account is managed, remove the invalid nonce.
- self.bc.TxState().RemoveNonce(tx.From(), tx.Nonce())
+ from, _ := tx.From()
+ self.bc.TxState().RemoveNonce(from, tx.Nonce())
return nil, nil, err
}
@@ -86,7 +86,7 @@ func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, stated
statedb.Update(nil)
cumulative := new(big.Int).Set(usedGas.Add(usedGas, gas))
- receipt := types.NewReceipt(statedb.Root(), cumulative)
+ receipt := types.NewReceipt(statedb.Root().Bytes(), cumulative)
receipt.SetLogs(statedb.Logs())
receipt.Bloom = types.CreateBloom(types.Receipts{receipt})
chainlogger.Debugln(receipt)
@@ -186,7 +186,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
// Validate the received block's bloom with the one derived from the generated receipts.
// For valid blocks this should always validate to true.
rbloom := types.CreateBloom(receipts)
- if bytes.Compare(rbloom, header.Bloom) != 0 {
+ if rbloom != header.Bloom {
err = fmt.Errorf("unable to replicate block's bloom=%x", rbloom)
return
}
@@ -194,14 +194,14 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
// The transactions Trie's root (R = (Tr [[H1, T1], [H2, T2], ... [Hn, Tn]]))
// can be used by light clients to make sure they've received the correct Txs
txSha := types.DeriveSha(block.Transactions())
- if bytes.Compare(txSha, header.TxHash) != 0 {
+ if txSha != header.TxHash {
err = fmt.Errorf("validating transaction root. received=%x got=%x", header.TxHash, txSha)
return
}
// Tre receipt Trie's root (R = (Tr [[H1, R1], ... [Hn, R1]]))
receiptSha := types.DeriveSha(receipts)
- if bytes.Compare(receiptSha, header.ReceiptHash) != 0 {
+ if receiptSha != header.ReceiptHash {
err = fmt.Errorf("validating receipt root. received=%x got=%x", header.ReceiptHash, receiptSha)
return
}
@@ -214,7 +214,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
// Commit state objects/accounts to a temporary trie (does not save)
// used to calculate the state root.
state.Update(common.Big0)
- if !bytes.Equal(header.Root, state.Root()) {
+ if header.Root != state.Root() {
err = fmt.Errorf("invalid merkle root. received=%x got=%x", header.Root, state.Root())
return
}
@@ -230,7 +230,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (td *big
putTx(sm.extraDb, tx)
}
- chainlogger.Infof("processed block #%d (%x...)\n", header.Number, block.Hash()[0:4])
+ chainlogger.Infof("processed block #%d (%x...)\n", header.Number, block.Hash().Bytes()[0:4])
return td, state.Logs(), nil
}
@@ -280,35 +280,34 @@ func (sm *BlockProcessor) AccumulateRewards(statedb *state.StateDB, block, paren
ancestors := set.New()
uncles := set.New()
- ancestorHeaders := make(map[string]*types.Header)
+ ancestorHeaders := make(map[common.Hash]*types.Header)
for _, ancestor := range sm.bc.GetAncestors(block, 7) {
- hash := string(ancestor.Hash())
- ancestorHeaders[hash] = ancestor.Header()
- ancestors.Add(hash)
+ ancestorHeaders[ancestor.Hash()] = ancestor.Header()
+ ancestors.Add(ancestor.Hash())
// Include ancestors uncles in the uncle set. Uncles must be unique.
for _, uncle := range ancestor.Uncles() {
- uncles.Add(string(uncle.Hash()))
+ uncles.Add(uncle.Hash())
}
}
- uncles.Add(string(block.Hash()))
+ uncles.Add(block.Hash())
for _, uncle := range block.Uncles() {
- if uncles.Has(string(uncle.Hash())) {
+ if uncles.Has(uncle.Hash()) {
// Error not unique
return UncleError("Uncle not unique")
}
- uncles.Add(string(uncle.Hash()))
+ uncles.Add(uncle.Hash())
- if ancestors.Has(string(uncle.Hash())) {
+ if ancestors.Has(uncle.Hash()) {
return UncleError("Uncle is ancestor")
}
- if !ancestors.Has(string(uncle.ParentHash)) {
+ if !ancestors.Has(uncle.ParentHash) {
return UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
}
- if err := sm.ValidateHeader(uncle, ancestorHeaders[string(uncle.ParentHash)]); err != nil {
+ if err := sm.ValidateHeader(uncle, ancestorHeaders[uncle.ParentHash]); err != nil {
return ValidationError(fmt.Sprintf("%v", err))
}
@@ -354,5 +353,5 @@ func putTx(db common.Database, tx *types.Transaction) {
statelogger.Infoln("Failed encoding tx", err)
return
}
- db.Put(tx.Hash(), rlpEnc)
+ db.Put(tx.Hash().Bytes(), rlpEnc)
}
diff --git a/core/block_processor_test.go b/core/block_processor_test.go
index ad29404e1..64add7e8b 100644
--- a/core/block_processor_test.go
+++ b/core/block_processor_test.go
@@ -4,6 +4,7 @@ import (
"math/big"
"testing"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/pow/ezp"
@@ -19,7 +20,7 @@ func proc() (*BlockProcessor, *ChainManager) {
func TestNumber(t *testing.T) {
bp, chain := proc()
- block1 := chain.NewBlock(nil)
+ block1 := chain.NewBlock(common.Address{})
block1.Header().Number = big.NewInt(3)
err := bp.ValidateHeader(block1.Header(), chain.Genesis().Header())
@@ -27,7 +28,7 @@ func TestNumber(t *testing.T) {
t.Errorf("expected block number error")
}
- block1 = chain.NewBlock(nil)
+ block1 = chain.NewBlock(common.Address{})
err = bp.ValidateHeader(block1.Header(), chain.Genesis().Header())
if err == BlockNumberErr {
t.Errorf("didn't expect block number error")
diff --git a/core/chain_makers.go b/core/chain_makers.go
index d800dee34..e3001331c 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -29,7 +29,7 @@ var (
// Utility functions for making chains on the fly
// Exposed for sake of testing from other packages (eg. go-ethash)
-func NewBlockFromParent(addr []byte, parent *types.Block) *types.Block {
+func NewBlockFromParent(addr common.Address, parent *types.Block) *types.Block {
return newBlockFromParent(addr, parent)
}
@@ -54,7 +54,7 @@ func NewCanonical(n int, db common.Database) (*BlockProcessor, error) {
}
// block time is fixed at 10 seconds
-func newBlockFromParent(addr []byte, parent *types.Block) *types.Block {
+func newBlockFromParent(addr common.Address, parent *types.Block) *types.Block {
block := types.NewBlock(parent.Hash(), addr, parent.Root(), common.BigPow(2, 32), 0, "")
block.SetUncles(nil)
block.SetTransactions(nil)
@@ -74,8 +74,8 @@ func newBlockFromParent(addr []byte, parent *types.Block) *types.Block {
// Actually make a block by simulating what miner would do
// we seed chains by the first byte of the coinbase
func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db common.Database, seed int) *types.Block {
- addr := common.LeftPadBytes([]byte{byte(i)}, 20)
- addr[0] = byte(seed)
+ var addr common.Address
+ addr[0], addr[19] = byte(seed), byte(i)
block := newBlockFromParent(addr, parent)
state := state.New(block.Root(), db)
cbase := state.GetOrNewStateObject(addr)
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 64ea8957d..915fa704f 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -3,6 +3,7 @@ package core
import (
"bytes"
"fmt"
+ "io"
"math/big"
"sync"
@@ -37,8 +38,8 @@ func CalcDifficulty(block, parent *types.Header) *big.Int {
diff.Sub(parent.Difficulty, adjust)
}
- if diff.Cmp(GenesisDiff) < 0 {
- return GenesisDiff
+ if diff.Cmp(min) < 0 {
+ return min
}
return diff
@@ -86,7 +87,7 @@ type ChainManager struct {
tsmu sync.RWMutex
td *big.Int
currentBlock *types.Block
- lastBlockHash []byte
+ lastBlockHash common.Hash
transState *state.StateDB
txState *state.ManagedState
@@ -112,7 +113,7 @@ func (self *ChainManager) Td() *big.Int {
return self.td
}
-func (self *ChainManager) LastBlockHash() []byte {
+func (self *ChainManager) LastBlockHash() common.Hash {
self.mu.RLock()
defer self.mu.RUnlock()
@@ -126,7 +127,7 @@ func (self *ChainManager) CurrentBlock() *types.Block {
return self.currentBlock
}
-func (self *ChainManager) Status() (td *big.Int, currentBlock []byte, genesisBlock []byte) {
+func (self *ChainManager) Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash) {
self.mu.RLock()
defer self.mu.RUnlock()
@@ -168,7 +169,7 @@ func (self *ChainManager) setTransState(statedb *state.StateDB) {
func (bc *ChainManager) setLastBlock() {
data, _ := bc.blockDb.Get([]byte("LastBlock"))
if len(data) != 0 {
- block := bc.GetBlock(data)
+ block := bc.GetBlock(common.BytesToHash(data))
bc.currentBlock = block
bc.lastBlockHash = block.Hash()
@@ -182,12 +183,14 @@ func (bc *ChainManager) setLastBlock() {
}
// Block creation & chain handling
-func (bc *ChainManager) NewBlock(coinbase []byte) *types.Block {
+func (bc *ChainManager) NewBlock(coinbase common.Address) *types.Block {
bc.mu.RLock()
defer bc.mu.RUnlock()
- var root []byte
- parentHash := ZeroHash256
+ var (
+ root common.Hash
+ parentHash common.Hash
+ )
if bc.currentBlock != nil {
root = bc.currentBlock.Header().Root
@@ -234,7 +237,7 @@ func (bc *ChainManager) Reset() {
}
func (bc *ChainManager) removeBlock(block *types.Block) {
- bc.blockDb.Delete(append(blockHashPre, block.Hash()...))
+ bc.blockDb.Delete(append(blockHashPre, block.Hash().Bytes()...))
}
func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) {
@@ -252,35 +255,32 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) {
bc.currentBlock = bc.genesisBlock
}
-func (self *ChainManager) Export() []byte {
+// Export writes the active chain to the given writer.
+func (self *ChainManager) Export(w io.Writer) error {
self.mu.RLock()
defer self.mu.RUnlock()
-
chainlogger.Infof("exporting %v blocks...\n", self.currentBlock.Header().Number)
-
- blocks := make([]*types.Block, int(self.currentBlock.NumberU64())+1)
for block := self.currentBlock; block != nil; block = self.GetBlock(block.Header().ParentHash) {
- blocks[block.NumberU64()] = block
+ if err := block.EncodeRLP(w); err != nil {
+ return err
+ }
}
-
- return common.Encode(blocks)
+ return nil
}
func (bc *ChainManager) insert(block *types.Block) {
- //encodedBlock := common.Encode(block)
- bc.blockDb.Put([]byte("LastBlock"), block.Hash())
+ bc.blockDb.Put([]byte("LastBlock"), block.Hash().Bytes())
bc.currentBlock = block
bc.lastBlockHash = block.Hash()
key := append(blockNumPre, block.Number().Bytes()...)
- bc.blockDb.Put(key, bc.lastBlockHash)
+ bc.blockDb.Put(key, bc.lastBlockHash.Bytes())
}
func (bc *ChainManager) write(block *types.Block) {
- encodedBlock := common.Encode(block.RlpDataForStorage())
-
- key := append(blockHashPre, block.Hash()...)
- bc.blockDb.Put(key, encodedBlock)
+ enc, _ := rlp.EncodeToBytes((*types.StorageBlock)(block))
+ key := append(blockHashPre, block.Hash().Bytes()...)
+ bc.blockDb.Put(key, enc)
}
// Accessors
@@ -289,12 +289,12 @@ func (bc *ChainManager) Genesis() *types.Block {
}
// Block fetching methods
-func (bc *ChainManager) HasBlock(hash []byte) bool {
- data, _ := bc.blockDb.Get(append(blockHashPre, hash...))
+func (bc *ChainManager) HasBlock(hash common.Hash) bool {
+ data, _ := bc.blockDb.Get(append(blockHashPre, hash[:]...))
return len(data) != 0
}
-func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain [][]byte) {
+func (self *ChainManager) GetBlockHashesFromHash(hash common.Hash, max uint64) (chain []common.Hash) {
block := self.GetBlock(hash)
if block == nil {
return
@@ -317,18 +317,17 @@ func (self *ChainManager) GetBlockHashesFromHash(hash []byte, max uint64) (chain
return
}
-func (self *ChainManager) GetBlock(hash []byte) *types.Block {
- data, _ := self.blockDb.Get(append(blockHashPre, hash...))
+func (self *ChainManager) GetBlock(hash common.Hash) *types.Block {
+ data, _ := self.blockDb.Get(append(blockHashPre, hash[:]...))
if len(data) == 0 {
return nil
}
- var block types.Block
+ var block types.StorageBlock
if err := rlp.Decode(bytes.NewReader(data), &block); err != nil {
- fmt.Println(err)
+ chainlogger.Errorf("invalid block RLP for hash %x: %v", hash, err)
return nil
}
-
- return &block
+ return (*types.Block)(&block)
}
func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {
@@ -340,7 +339,7 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {
return nil
}
- return self.GetBlock(key)
+ return self.GetBlock(common.BytesToHash(key))
}
func (self *ChainManager) GetUnclesInChain(block *types.Block, length int) (uncles []*types.Header) {
@@ -418,7 +417,7 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
}
h := block.Header()
- chainlogger.Infof("INVALID block #%v (%x)\n", h.Number, h.Hash()[:4])
+ chainlogger.Infof("INVALID block #%v (%x)\n", h.Number, h.Hash().Bytes()[:4])
chainlogger.Infoln(err)
chainlogger.Debugln(block)
return err
@@ -435,7 +434,9 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
// At this point it's possible that a different chain (fork) becomes the new canonical chain.
if td.Cmp(self.td) > 0 {
if block.Header().Number.Cmp(new(big.Int).Add(cblock.Header().Number, common.Big1)) < 0 {
- chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, block.Hash()[:4], td, cblock.Header().Number, cblock.Hash()[:4], self.td)
+ chash := cblock.Hash()
+ hash := block.Hash()
+ chainlogger.Infof("Split detected. New head #%v (%x) TD=%v, was #%v (%x) TD=%v\n", block.Header().Number, hash[:4], td, cblock.Header().Number, chash[:4], self.td)
queue[i] = ChainSplitEvent{block, logs}
queueEvent.splitCount++
@@ -445,10 +446,10 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
self.insert(block)
jsonlogger.LogJson(&logger.EthChainNewHead{
- BlockHash: common.Bytes2Hex(block.Hash()),
+ BlockHash: block.Hash().Hex(),
BlockNumber: block.Number(),
- ChainHeadHash: common.Bytes2Hex(cblock.Hash()),
- BlockPrevHash: common.Bytes2Hex(block.ParentHash()),
+ ChainHeadHash: cblock.Hash().Hex(),
+ BlockPrevHash: block.ParentHash().Hex(),
})
self.setTransState(state.New(block.Root(), self.stateDb))
@@ -465,7 +466,6 @@ func (self *ChainManager) InsertChain(chain types.Blocks) error {
}
- // XXX put this in a goroutine?
go self.eventMux.Post(queueEvent)
return nil
@@ -505,7 +505,9 @@ out:
}
}
+/*
// Satisfy state query interface
-func (self *ChainManager) GetAccount(addr []byte) *state.StateObject {
+func (self *ChainManager) GetAccount(addr common.Hash) *state.StateObject {
return self.State().GetAccount(addr)
}
+*/
diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go
index 898d37f9c..e49e594a3 100644
--- a/core/chain_manager_test.go
+++ b/core/chain_manager_test.go
@@ -1,7 +1,6 @@
package core
import (
- "bytes"
"fmt"
"math/big"
"os"
@@ -35,7 +34,7 @@ func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big
// asert the bmans have the same block at i
bi1 := bman.bc.GetBlockByNumber(uint64(i)).Hash()
bi2 := bman2.bc.GetBlockByNumber(uint64(i)).Hash()
- if bytes.Compare(bi1, bi2) != 0 {
+ if bi1 != bi2 {
t.Fatal("chains do not have the same hash at height", i)
}
@@ -270,11 +269,11 @@ func TestChainInsertions(t *testing.T) {
<-done
}
- if bytes.Equal(chain2[len(chain2)-1].Hash(), chainMan.CurrentBlock().Hash()) {
+ if chain2[len(chain2)-1].Hash() != chainMan.CurrentBlock().Hash() {
t.Error("chain2 is canonical and shouldn't be")
}
- if !bytes.Equal(chain1[len(chain1)-1].Hash(), chainMan.CurrentBlock().Hash()) {
+ if chain1[len(chain1)-1].Hash() != chainMan.CurrentBlock().Hash() {
t.Error("chain1 isn't canonical and should be")
}
}
@@ -320,7 +319,7 @@ func TestChainMultipleInsertions(t *testing.T) {
<-done
}
- if !bytes.Equal(chains[longest][len(chains[longest])-1].Hash(), chainMan.CurrentBlock().Hash()) {
+ if chains[longest][len(chains[longest])-1].Hash() != chainMan.CurrentBlock().Hash() {
t.Error("Invalid canonical chain")
}
}
diff --git a/core/error.go b/core/error.go
index 69e320eb0..f6ac26cff 100644
--- a/core/error.go
+++ b/core/error.go
@@ -4,6 +4,8 @@ import (
"errors"
"fmt"
"math/big"
+
+ "github.com/ethereum/go-ethereum/common"
)
var (
@@ -21,7 +23,7 @@ func (err *ParentErr) Error() string {
return err.Message
}
-func ParentError(hash []byte) error {
+func ParentError(hash common.Hash) error {
return &ParentErr{Message: fmt.Sprintf("Block's parent unknown %x", hash)}
}
@@ -136,7 +138,7 @@ func IsTDError(e error) bool {
type KnownBlockError struct {
number *big.Int
- hash []byte
+ hash common.Hash
}
func (self *KnownBlockError) Error() string {
diff --git a/core/execution.go b/core/execution.go
index be45eeeb4..4f15fb42a 100644
--- a/core/execution.go
+++ b/core/execution.go
@@ -4,6 +4,7 @@ import (
"math/big"
"time"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/vm"
@@ -11,26 +12,23 @@ import (
type Execution struct {
env vm.Environment
- address, input []byte
+ address *common.Address
+ input []byte
Gas, price, value *big.Int
}
-func NewExecution(env vm.Environment, address, input []byte, gas, gasPrice, value *big.Int) *Execution {
+func NewExecution(env vm.Environment, address *common.Address, input []byte, gas, gasPrice, value *big.Int) *Execution {
return &Execution{env: env, address: address, input: input, Gas: gas, price: gasPrice, value: value}
}
-func (self *Execution) Addr() []byte {
- return self.address
-}
-
-func (self *Execution) Call(codeAddr []byte, caller vm.ContextRef) ([]byte, error) {
+func (self *Execution) Call(codeAddr common.Address, caller vm.ContextRef) ([]byte, error) {
// Retrieve the executing code
code := self.env.State().GetCode(codeAddr)
- return self.exec(code, codeAddr, caller)
+ return self.exec(&codeAddr, code, caller)
}
-func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret []byte, err error) {
+func (self *Execution) exec(contextAddr *common.Address, code []byte, caller vm.ContextRef) (ret []byte, err error) {
env := self.env
evm := vm.NewVm(env)
if env.Depth() == vm.MaxCallDepth {
@@ -40,14 +38,15 @@ func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret
}
vsnapshot := env.State().Copy()
- if len(self.address) == 0 {
+ if self.address == nil {
// Generate a new address
nonce := env.State().GetNonce(caller.Address())
- self.address = crypto.CreateAddress(caller.Address(), nonce)
+ addr := crypto.CreateAddress(caller.Address(), nonce)
+ self.address = &addr
env.State().SetNonce(caller.Address(), nonce+1)
}
- from, to := env.State().GetStateObject(caller.Address()), env.State().GetOrNewStateObject(self.address)
+ from, to := env.State().GetStateObject(caller.Address()), env.State().GetOrNewStateObject(*self.address)
err = env.Transfer(from, to, self.value)
if err != nil {
env.State().Set(vsnapshot)
@@ -73,8 +72,8 @@ func (self *Execution) exec(code, contextAddr []byte, caller vm.ContextRef) (ret
}
func (self *Execution) Create(caller vm.ContextRef) (ret []byte, err error, account *state.StateObject) {
- ret, err = self.exec(self.input, nil, caller)
- account = self.env.State().GetStateObject(self.address)
+ ret, err = self.exec(nil, self.input, caller)
+ account = self.env.State().GetStateObject(*self.address)
return
}
diff --git a/core/filter.go b/core/filter.go
index 487e82902..f1627636f 100644
--- a/core/filter.go
+++ b/core/filter.go
@@ -1,9 +1,9 @@
package core
import (
- "bytes"
"math"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/state"
)
@@ -16,8 +16,8 @@ type FilterOptions struct {
Earliest int64
Latest int64
- Address [][]byte
- Topics [][][]byte
+ Address []common.Address
+ Topics [][]common.Hash
Skip int
Max int
@@ -29,9 +29,9 @@ type Filter struct {
earliest int64
latest int64
skip int
- address [][]byte
+ address []common.Address
max int
- topics [][][]byte
+ topics [][]common.Hash
BlockCallback func(*types.Block, state.Logs)
PendingCallback func(*types.Block, state.Logs)
@@ -67,11 +67,11 @@ func (self *Filter) SetLatestBlock(latest int64) {
self.latest = latest
}
-func (self *Filter) SetAddress(addr [][]byte) {
+func (self *Filter) SetAddress(addr []common.Address) {
self.address = addr
}
-func (self *Filter) SetTopics(topics [][][]byte) {
+func (self *Filter) SetTopics(topics [][]common.Hash) {
self.topics = topics
}
@@ -131,9 +131,9 @@ func (self *Filter) Find() state.Logs {
return logs[skip:]
}
-func includes(addresses [][]byte, a []byte) bool {
+func includes(addresses []common.Address, a common.Address) bool {
for _, addr := range addresses {
- if !bytes.Equal(addr, a) {
+ if addr != a {
return false
}
}
@@ -151,13 +151,13 @@ Logs:
continue
}
- logTopics := make([][]byte, len(self.topics))
+ logTopics := make([]common.Hash, len(self.topics))
copy(logTopics, log.Topics())
for i, topics := range self.topics {
for _, topic := range topics {
var match bool
- if bytes.Equal(log.Topics()[i], topic) {
+ if log.Topics()[i] == topic {
match = true
}
if !match {
@@ -176,7 +176,7 @@ func (self *Filter) bloomFilter(block *types.Block) bool {
if len(self.address) > 0 {
var included bool
for _, addr := range self.address {
- if types.BloomLookup(block.Bloom(), addr) {
+ if types.BloomLookup(block.Bloom(), addr.Hash()) {
included = true
break
}
diff --git a/core/genesis.go b/core/genesis.go
index bfd51f196..3e00533ae 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -6,9 +6,8 @@ import (
"math/big"
"os"
- "github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/state"
)
@@ -19,19 +18,15 @@ import (
var ZeroHash256 = make([]byte, 32)
var ZeroHash160 = make([]byte, 20)
var ZeroHash512 = make([]byte, 64)
-var EmptyShaList = crypto.Sha3(common.Encode([]interface{}{}))
-var EmptyListRoot = crypto.Sha3(common.Encode(""))
-
var GenesisDiff = big.NewInt(131072)
var GenesisGasLimit = big.NewInt(3141592)
func GenesisBlock(db common.Database) *types.Block {
- genesis := types.NewBlock(ZeroHash256, ZeroHash160, nil, GenesisDiff, 42, "")
+ genesis := types.NewBlock(common.Hash{}, common.Address{}, common.Hash{}, GenesisDiff, 42, "")
genesis.Header().Number = common.Big0
genesis.Header().GasLimit = GenesisGasLimit
genesis.Header().GasUsed = common.Big0
genesis.Header().Time = 0
- genesis.Header().MixDigest = make([]byte, 32)
genesis.Td = common.Big0
@@ -49,7 +44,7 @@ func GenesisBlock(db common.Database) *types.Block {
statedb := state.New(genesis.Root(), db)
for addr, account := range accounts {
codedAddr := common.Hex2Bytes(addr)
- accountState := statedb.GetAccount(codedAddr)
+ accountState := statedb.GetAccount(common.BytesToAddress(codedAddr))
accountState.SetBalance(common.Big(account.Balance))
statedb.UpdateStateObject(accountState)
}
diff --git a/core/state_transition.go b/core/state_transition.go
index 279abee62..d0b2c5d7c 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -4,8 +4,8 @@ import (
"fmt"
"math/big"
- "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/vm"
)
@@ -31,7 +31,7 @@ var ()
* 6) Derive new state root
*/
type StateTransition struct {
- coinbase []byte
+ coinbase common.Address
msg Message
gas, gasPrice *big.Int
initialGas *big.Int
@@ -44,9 +44,10 @@ type StateTransition struct {
env vm.Environment
}
+// Message represents a message sent to a contract.
type Message interface {
- From() []byte
- To() []byte
+ From() (common.Address, error)
+ To() *common.Address
GasPrice() *big.Int
Gas() *big.Int
@@ -56,13 +57,14 @@ type Message interface {
Data() []byte
}
-func AddressFromMessage(msg Message) []byte {
- // Generate a new address
- return crypto.Sha3(common.NewValue([]interface{}{msg.From(), msg.Nonce()}).Encode())[12:]
+func AddressFromMessage(msg Message) common.Address {
+ from, _ := msg.From()
+
+ return crypto.CreateAddress(from, msg.Nonce())
}
func MessageCreatesContract(msg Message) bool {
- return len(msg.To()) == 0
+ return msg.To() == nil
}
func MessageGasValue(msg Message) *big.Int {
@@ -92,13 +94,18 @@ func (self *StateTransition) Coinbase() *state.StateObject {
return self.state.GetOrNewStateObject(self.coinbase)
}
func (self *StateTransition) From() *state.StateObject {
- return self.state.GetOrNewStateObject(self.msg.From())
+ f, _ := self.msg.From()
+ return self.state.GetOrNewStateObject(f)
}
func (self *StateTransition) To() *state.StateObject {
- if self.msg != nil && MessageCreatesContract(self.msg) {
+ if self.msg == nil {
return nil
}
- return self.state.GetOrNewStateObject(self.msg.To())
+ to := self.msg.To()
+ if to == nil {
+ return nil // contract creation
+ }
+ return self.state.GetOrNewStateObject(*to)
}
func (self *StateTransition) UseGas(amount *big.Int) error {
@@ -119,7 +126,7 @@ func (self *StateTransition) BuyGas() error {
sender := self.From()
if sender.Balance().Cmp(MessageGasValue(self.msg)) < 0 {
- return fmt.Errorf("insufficient ETH for gas (%x). Req %v, has %v", sender.Address()[:4], MessageGasValue(self.msg), sender.Balance())
+ return fmt.Errorf("insufficient ETH for gas (%x). Req %v, has %v", sender.Address().Bytes()[:4], MessageGasValue(self.msg), sender.Balance())
}
coinbase := self.Coinbase()
@@ -196,7 +203,8 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
var ref vm.ContextRef
if MessageCreatesContract(msg) {
contract := makeContract(msg, self.state)
- ret, err, ref = vmenv.Create(sender, contract.Address(), self.msg.Data(), self.gas, self.gasPrice, self.value)
+ addr := contract.Address()
+ ret, err, ref = vmenv.Create(sender, &addr, self.msg.Data(), self.gas, self.gasPrice, self.value)
if err == nil {
dataGas := big.NewInt(int64(len(ret)))
dataGas.Mul(dataGas, vm.GasCreateByte)
@@ -230,7 +238,7 @@ func (self *StateTransition) refundGas() {
for addr, ref := range self.state.Refunds() {
refund := common.BigMin(uhalf, ref)
self.gas.Add(self.gas, refund)
- self.state.AddBalance([]byte(addr), refund.Mul(refund, self.msg.GasPrice()))
+ self.state.AddBalance(common.StringToAddress(addr), refund.Mul(refund, self.msg.GasPrice()))
}
coinbase.RefundGas(self.gas, self.msg.GasPrice())
@@ -242,7 +250,8 @@ func (self *StateTransition) gasUsed() *big.Int {
// Converts an message in to a state object
func makeContract(msg Message, state *state.StateDB) *state.StateObject {
- addr := AddressFromMessage(msg)
+ faddr, _ := msg.From()
+ addr := crypto.CreateAddress(faddr, msg.Nonce())
contract := state.GetOrNewStateObject(addr)
contract.SetInitCode(msg.Data())
diff --git a/core/transaction_pool.go b/core/transaction_pool.go
index 515cc2040..f2fe5c748 100644
--- a/core/transaction_pool.go
+++ b/core/transaction_pool.go
@@ -5,8 +5,8 @@ import (
"fmt"
"sync"
- "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
)
@@ -20,9 +20,7 @@ var (
const txPoolQueueSize = 50
type TxPoolHook chan *types.Transaction
-type TxMsg struct {
- Tx *types.Transaction
-}
+type TxMsg struct{ Tx *types.Transaction }
const (
minGasPrice = 1000000
@@ -44,7 +42,7 @@ type TxPool struct {
quit chan bool
// The actual pool
//pool *list.List
- txs map[string]*types.Transaction
+ txs map[common.Hash]*types.Transaction
SecondaryProcessor TxProcessor
@@ -55,7 +53,7 @@ type TxPool struct {
func NewTxPool(eventMux *event.TypeMux) *TxPool {
return &TxPool{
- txs: make(map[string]*types.Transaction),
+ txs: make(map[common.Hash]*types.Transaction),
queueChan: make(chan *types.Transaction, txPoolQueueSize),
quit: make(chan bool),
eventMux: eventMux,
@@ -63,21 +61,16 @@ func NewTxPool(eventMux *event.TypeMux) *TxPool {
}
func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error {
- if len(tx.To()) != 0 && len(tx.To()) != 20 {
- return fmt.Errorf("Invalid recipient. len = %d", len(tx.To()))
+ // Validate sender
+ if _, err := tx.From(); err != nil {
+ return ErrInvalidSender
}
-
// Validate curve param
v, _, _ := tx.Curve()
if v > 28 || v < 27 {
return fmt.Errorf("tx.v != (28 || 27) => %v", v)
}
-
- // Validate sender address
- senderAddr := tx.From()
- if senderAddr == nil || len(senderAddr) != 20 {
- return ErrInvalidSender
- }
+ return nil
/* XXX this kind of validation needs to happen elsewhere in the gui when sending txs.
Other clients should do their own validation. Value transfer could throw error
@@ -91,19 +84,17 @@ func (pool *TxPool) ValidateTransaction(tx *types.Transaction) error {
return fmt.Errorf("Insufficient amount in sender's (%x) account", tx.From())
}
*/
-
- return nil
}
func (self *TxPool) addTx(tx *types.Transaction) {
- self.txs[string(tx.Hash())] = tx
+ self.txs[tx.Hash()] = tx
}
func (self *TxPool) add(tx *types.Transaction) error {
- if self.txs[string(tx.Hash())] != nil {
- return fmt.Errorf("Known transaction (%x)", tx.Hash()[0:4])
+ hash := tx.Hash()
+ if self.txs[hash] != nil {
+ return fmt.Errorf("Known transaction (%x)", hash[0:4])
}
-
err := self.ValidateTransaction(tx)
if err != nil {
return err
@@ -111,19 +102,17 @@ func (self *TxPool) add(tx *types.Transaction) error {
self.addTx(tx)
- var to string
- if len(tx.To()) > 0 {
- to = common.Bytes2Hex(tx.To()[:4])
+ var toname string
+ if to := tx.To(); to != nil {
+ toname = common.Bytes2Hex(to[:4])
} else {
- to = "[NEW_CONTRACT]"
+ toname = "[NEW_CONTRACT]"
}
- var from string
- if len(tx.From()) > 0 {
- from = common.Bytes2Hex(tx.From()[:4])
- } else {
- return errors.New(fmt.Sprintf("FROM ADDRESS MUST BE POSITIVE (was %v)", tx.From()))
- }
- txplogger.Debugf("(t) %x => %s (%v) %x\n", from, to, tx.Value, tx.Hash())
+ // we can ignore the error here because From is
+ // verified in ValidateTransaction.
+ f, _ := tx.From()
+ from := common.Bytes2Hex(f[:4])
+ txplogger.Debugf("(t) %x => %s (%v) %x\n", from, toname, tx.Value, tx.Hash())
// Notify the subscribers
go self.eventMux.Post(TxPreEvent{tx})
@@ -140,6 +129,7 @@ func (self *TxPool) Add(tx *types.Transaction) error {
defer self.mu.Unlock()
return self.add(tx)
}
+
func (self *TxPool) AddTransactions(txs []*types.Transaction) {
self.mu.Lock()
defer self.mu.Unlock()
@@ -148,7 +138,8 @@ func (self *TxPool) AddTransactions(txs []*types.Transaction) {
if err := self.add(tx); err != nil {
txplogger.Debugln(err)
} else {
- txplogger.Debugf("tx %x\n", tx.Hash()[0:4])
+ h := tx.Hash()
+ txplogger.Debugf("tx %x\n", h[:4])
}
}
}
@@ -172,7 +163,8 @@ func (pool *TxPool) RemoveInvalid(query StateQuery) {
var removedTxs types.Transactions
for _, tx := range pool.txs {
- sender := query.GetAccount(tx.From())
+ from, _ := tx.From()
+ sender := query.GetAccount(from[:])
err := pool.ValidateTransaction(tx)
if err != nil || sender.Nonce() >= tx.Nonce() {
removedTxs = append(removedTxs, tx)
@@ -186,14 +178,13 @@ func (pool *TxPool) RemoveInvalid(query StateQuery) {
func (self *TxPool) RemoveSet(txs types.Transactions) {
self.mu.Lock()
defer self.mu.Unlock()
-
for _, tx := range txs {
- delete(self.txs, string(tx.Hash()))
+ delete(self.txs, tx.Hash())
}
}
func (pool *TxPool) Flush() {
- pool.txs = make(map[string]*types.Transaction)
+ pool.txs = make(map[common.Hash]*types.Transaction)
}
func (pool *TxPool) Start() {
diff --git a/core/transaction_pool_test.go b/core/transaction_pool_test.go
index 418cb0415..bf9012573 100644
--- a/core/transaction_pool_test.go
+++ b/core/transaction_pool_test.go
@@ -4,10 +4,10 @@ import (
"crypto/ecdsa"
"testing"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/ethdb"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/state"
)
@@ -21,11 +21,11 @@ func SQ() stateQuery {
}
func (self stateQuery) GetAccount(addr []byte) *state.StateObject {
- return state.NewStateObject(addr, self.db)
+ return state.NewStateObject(common.BytesToAddress(addr), self.db)
}
func transaction() *types.Transaction {
- return types.NewTransactionMessage(make([]byte, 20), common.Big0, common.Big0, common.Big0, nil)
+ return types.NewTransactionMessage(common.Address{}, common.Big0, common.Big0, common.Big0, nil)
}
func setup() (*TxPool, *ecdsa.PrivateKey) {
@@ -88,10 +88,8 @@ func TestRemoveInvalid(t *testing.T) {
func TestInvalidSender(t *testing.T) {
pool, _ := setup()
- tx := new(types.Transaction)
- tx.V = 28
- err := pool.ValidateTransaction(tx)
+ err := pool.ValidateTransaction(new(types.Transaction))
if err != ErrInvalidSender {
- t.Error("expected %v, got %v", ErrInvalidSender, err)
+ t.Errorf("expected %v, got %v", ErrInvalidSender, err)
}
}
diff --git a/core/types/block.go b/core/types/block.go
index 2d65cdca6..6f26358fb 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -1,33 +1,33 @@
package types
import (
- "bytes"
"encoding/binary"
"fmt"
+ "io"
"math/big"
"sort"
"time"
- "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/rlp"
)
type Header struct {
// Hash to the previous block
- ParentHash []byte
+ ParentHash common.Hash
// Uncles of this block
- UncleHash []byte
+ UncleHash common.Hash
// The coin base address
- Coinbase []byte
+ Coinbase common.Address
// Block Trie state
- Root []byte
+ Root common.Hash
// Tx sha
- TxHash []byte
+ TxHash common.Hash
// Receipt sha
- ReceiptHash []byte
+ ReceiptHash common.Hash
// Bloom
- Bloom []byte
+ Bloom Bloom
// Difficulty for the current block
Difficulty *big.Int
// The block number
@@ -41,9 +41,17 @@ type Header struct {
// Extra data
Extra string
// Mix digest for quick checking to prevent DOS
- MixDigest []byte
+ MixDigest common.Hash
// Nonce
- Nonce []byte
+ Nonce [8]byte
+}
+
+func (self *Header) Hash() common.Hash {
+ return rlpHash(self.rlpData(true))
+}
+
+func (self *Header) HashNoNonce() common.Hash {
+ return rlpHash(self.rlpData(false))
}
func (self *Header) rlpData(withNonce bool) []interface{} {
@@ -65,7 +73,6 @@ func (self *Header) rlpData(withNonce bool) []interface{} {
if withNonce {
fields = append(fields, self.MixDigest, self.Nonce)
}
-
return fields
}
@@ -73,28 +80,49 @@ func (self *Header) RlpData() interface{} {
return self.rlpData(true)
}
-func (self *Header) Hash() []byte {
- return crypto.Sha3(common.Encode(self.rlpData(true)))
-}
-
-func (self *Header) HashNoNonce() []byte {
- return crypto.Sha3(common.Encode(self.rlpData(false)))
+func rlpHash(x interface{}) (h common.Hash) {
+ hw := sha3.NewKeccak256()
+ rlp.Encode(hw, x)
+ hw.Sum(h[:0])
+ return h
}
type Block struct {
- // Preset Hash for mock
- HeaderHash []byte
- ParentHeaderHash []byte
- header *Header
- uncles []*Header
- transactions Transactions
- Td *big.Int
+ // Preset Hash for mock (Tests)
+ HeaderHash common.Hash
+ ParentHeaderHash common.Hash
+ // ^^^^ ignore ^^^^
+
+ header *Header
+ uncles []*Header
+ transactions Transactions
+ Td *big.Int
receipts Receipts
Reward *big.Int
}
-func NewBlock(parentHash []byte, coinbase []byte, root []byte, difficulty *big.Int, nonce uint64, extra string) *Block {
+// StorageBlock defines the RLP encoding of a Block stored in the
+// state database. The StorageBlock encoding contains fields that
+// would otherwise need to be recomputed.
+type StorageBlock Block
+
+// "external" block encoding. used for eth protocol, etc.
+type extblock struct {
+ Header *Header
+ Txs []*Transaction
+ Uncles []*Header
+}
+
+// "storage" block encoding. used for database.
+type storageblock struct {
+ Header *Header
+ Txs []*Transaction
+ Uncles []*Header
+ TD *big.Int
+}
+
+func NewBlock(parentHash common.Hash, coinbase common.Address, root common.Hash, difficulty *big.Int, nonce uint64, extra string) *Block {
header := &Header{
Root: root,
ParentHash: parentHash,
@@ -105,16 +133,13 @@ func NewBlock(parentHash []byte, coinbase []byte, root []byte, difficulty *big.I
GasUsed: new(big.Int),
GasLimit: new(big.Int),
}
- header.setNonce(nonce)
-
+ header.SetNonce(nonce)
block := &Block{header: header, Reward: new(big.Int)}
-
return block
}
-func (self *Header) setNonce(nonce uint64) {
- self.Nonce = make([]byte, 8)
- binary.BigEndian.PutUint64(self.Nonce, nonce)
+func (self *Header) SetNonce(nonce uint64) {
+ binary.BigEndian.PutUint64(self.Nonce[:], nonce)
}
func NewBlockWithHeader(header *Header) *Block {
@@ -122,22 +147,40 @@ func NewBlockWithHeader(header *Header) *Block {
}
func (self *Block) DecodeRLP(s *rlp.Stream) error {
- var extblock struct {
- Header *Header
- Txs []*Transaction
- Uncles []*Header
- TD *big.Int // optional
+ var eb extblock
+ if err := s.Decode(&eb); err != nil {
+ return err
}
- if err := s.Decode(&extblock); err != nil {
+ self.header, self.uncles, self.transactions = eb.Header, eb.Uncles, eb.Txs
+ return nil
+}
+
+func (self Block) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, extblock{
+ Header: self.header,
+ Txs: self.transactions,
+ Uncles: self.uncles,
+ })
+}
+
+func (self *StorageBlock) DecodeRLP(s *rlp.Stream) error {
+ var sb storageblock
+ if err := s.Decode(&sb); err != nil {
return err
}
- self.header = extblock.Header
- self.uncles = extblock.Uncles
- self.transactions = extblock.Txs
- self.Td = extblock.TD
+ self.header, self.uncles, self.transactions, self.Td = sb.Header, sb.Uncles, sb.Txs, sb.TD
return nil
}
+func (self StorageBlock) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, storageblock{
+ Header: self.header,
+ Txs: self.transactions,
+ Uncles: self.uncles,
+ TD: self.Td,
+ })
+}
+
func (self *Block) Header() *Header {
return self.header
}
@@ -148,16 +191,16 @@ func (self *Block) Uncles() []*Header {
func (self *Block) SetUncles(uncleHeaders []*Header) {
self.uncles = uncleHeaders
- self.header.UncleHash = crypto.Sha3(common.Encode(uncleHeaders))
+ self.header.UncleHash = rlpHash(uncleHeaders)
}
func (self *Block) Transactions() Transactions {
return self.transactions
}
-func (self *Block) Transaction(hash []byte) *Transaction {
+func (self *Block) Transaction(hash common.Hash) *Transaction {
for _, transaction := range self.transactions {
- if bytes.Equal(hash, transaction.Hash()) {
+ if transaction.Hash() == hash {
return transaction
}
}
@@ -196,24 +239,23 @@ func (self *Block) RlpDataForStorage() interface{} {
}
// Header accessors (add as you need them)
-func (self *Block) Number() *big.Int { return self.header.Number }
-func (self *Block) NumberU64() uint64 { return self.header.Number.Uint64() }
-func (self *Block) MixDigest() []byte { return self.header.MixDigest }
+func (self *Block) Number() *big.Int { return self.header.Number }
+func (self *Block) NumberU64() uint64 { return self.header.Number.Uint64() }
+func (self *Block) MixDigest() common.Hash { return self.header.MixDigest }
func (self *Block) Nonce() uint64 {
- return binary.BigEndian.Uint64(self.header.Nonce)
+ return binary.BigEndian.Uint64(self.header.Nonce[:])
}
func (self *Block) SetNonce(nonce uint64) {
- self.header.setNonce(nonce)
+ self.header.SetNonce(nonce)
}
-func (self *Block) Bloom() []byte { return self.header.Bloom }
-func (self *Block) Coinbase() []byte { return self.header.Coinbase }
-func (self *Block) Time() int64 { return int64(self.header.Time) }
-func (self *Block) GasLimit() *big.Int { return self.header.GasLimit }
-func (self *Block) GasUsed() *big.Int { return self.header.GasUsed }
-func (self *Block) Root() []byte { return self.header.Root }
-func (self *Block) SetRoot(root []byte) { self.header.Root = root }
-func (self *Block) Size() common.StorageSize { return common.StorageSize(len(common.Encode(self))) }
+func (self *Block) Bloom() Bloom { return self.header.Bloom }
+func (self *Block) Coinbase() common.Address { return self.header.Coinbase }
+func (self *Block) Time() int64 { return int64(self.header.Time) }
+func (self *Block) GasLimit() *big.Int { return self.header.GasLimit }
+func (self *Block) GasUsed() *big.Int { return self.header.GasUsed }
+func (self *Block) Root() common.Hash { return self.header.Root }
+func (self *Block) SetRoot(root common.Hash) { self.header.Root = root }
func (self *Block) GetTransaction(i int) *Transaction {
if len(self.transactions) > i {
return self.transactions[i]
@@ -227,20 +269,33 @@ func (self *Block) GetUncle(i int) *Header {
return nil
}
+func (self *Block) Size() common.StorageSize {
+ c := writeCounter(0)
+ rlp.Encode(&c, self)
+ return common.StorageSize(c)
+}
+
+type writeCounter common.StorageSize
+
+func (c *writeCounter) Write(b []byte) (int, error) {
+ *c += writeCounter(len(b))
+ return len(b), nil
+}
+
// Implement pow.Block
-func (self *Block) Difficulty() *big.Int { return self.header.Difficulty }
-func (self *Block) HashNoNonce() []byte { return self.header.HashNoNonce() }
+func (self *Block) Difficulty() *big.Int { return self.header.Difficulty }
+func (self *Block) HashNoNonce() common.Hash { return self.header.HashNoNonce() }
-func (self *Block) Hash() []byte {
- if self.HeaderHash != nil {
+func (self *Block) Hash() common.Hash {
+ if (self.HeaderHash != common.Hash{}) {
return self.HeaderHash
} else {
return self.header.Hash()
}
}
-func (self *Block) ParentHash() []byte {
- if self.ParentHeaderHash != nil {
+func (self *Block) ParentHash() common.Hash {
+ if (self.ParentHeaderHash != common.Hash{}) {
return self.ParentHeaderHash
} else {
return self.header.ParentHash
diff --git a/core/types/block_test.go b/core/types/block_test.go
index ab1254f4c..e4f6c38a5 100644
--- a/core/types/block_test.go
+++ b/core/types/block_test.go
@@ -1 +1,60 @@
package types
+
+import (
+ "bytes"
+ "math/big"
+ "reflect"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// from bcValidBlockTest.json, "SimpleTx"
+func TestBlockEncoding(t *testing.T) {
+ blockEnc := common.FromHex("f90260f901f9a083cafc574e1f51ba9dc0568fc617a08ea2429fb384059c972f13b19fa1c8dd55a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017a05fe50b260da6308036625b850b5d6ced6d0a9f814c0688bc91ffb7b7a3a54b67a0bc37d79753ad738a6dac4921e57392f145d8887476de3f783dfa7edae9283e52b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefd8825208845506eb0780a0bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff49888a13a5a8c8f2bb1c4f861f85f800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d870a801ba09bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094fa08a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1c0")
+
+ var block Block
+ if err := rlp.DecodeBytes(blockEnc, &block); err != nil {
+ t.Fatal("decode error: ", err)
+ }
+
+ check := func(f string, got, want interface{}) {
+ if !reflect.DeepEqual(got, want) {
+ t.Errorf("%s mismatch: got %v, want %v", f, got, want)
+ }
+ }
+ check("Difficulty", block.Difficulty(), big.NewInt(131072))
+ check("GasLimit", block.GasLimit(), big.NewInt(3141592))
+ check("GasUsed", block.GasUsed(), big.NewInt(21000))
+ check("Coinbase", block.Coinbase(), common.HexToAddress("8888f1f195afa192cfee860698584c030f4c9db1"))
+ check("MixDigest", block.MixDigest(), common.HexToHash("bd4472abb6659ebe3ee06ee4d7b72a00a9f4d001caca51342001075469aff498"))
+ check("Root", block.Root(), common.HexToHash("ef1552a40b7165c3cd773806b9e0c165b75356e0314bf0706f279c729f51e017"))
+ check("Hash", block.Hash(), common.HexToHash("0a5843ac1cb04865017cb35a57b50b07084e5fcee39b5acadade33149f4fff9e"))
+ check("Nonce", block.Nonce(), uint64(0xa13a5a8c8f2bb1c4))
+ check("Time", block.Time(), int64(1426516743))
+ check("Size", block.Size(), common.StorageSize(len(blockEnc)))
+
+ to := common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87")
+ check("Transactions", block.Transactions(), Transactions{
+ {
+ Payload: []byte{},
+ Amount: big.NewInt(10),
+ Price: big.NewInt(10),
+ GasLimit: big.NewInt(50000),
+ AccountNonce: 0,
+ V: 27,
+ R: common.FromHex("9bea4c4daac7c7c52e093e6a4c35dbbcf8856f1af7b059ba20253e70848d094f"),
+ S: common.FromHex("8a8fae537ce25ed8cb5af9adac3f141af69bd515bd2ba031522df09b97dd72b1"),
+ Recipient: &to,
+ },
+ })
+
+ ourBlockEnc, err := rlp.EncodeToBytes(&block)
+ if err != nil {
+ t.Fatal("encode error: ", err)
+ }
+ if !bytes.Equal(ourBlockEnc, blockEnc) {
+ t.Errorf("encoded block mismatch:\ngot: %x\nwant: %x", ourBlockEnc, blockEnc)
+ }
+}
diff --git a/core/types/bloom9.go b/core/types/bloom9.go
index af76f226f..64a8ff49a 100644
--- a/core/types/bloom9.go
+++ b/core/types/bloom9.go
@@ -3,32 +3,32 @@ package types
import (
"math/big"
- "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/state"
)
-func CreateBloom(receipts Receipts) []byte {
+func CreateBloom(receipts Receipts) Bloom {
bin := new(big.Int)
for _, receipt := range receipts {
bin.Or(bin, LogsBloom(receipt.logs))
}
- return common.LeftPadBytes(bin.Bytes(), 256)
+ return BytesToBloom(bin.Bytes())
}
func LogsBloom(logs state.Logs) *big.Int {
bin := new(big.Int)
for _, log := range logs {
- data := make([][]byte, len(log.Topics())+1)
- data[0] = log.Address()
+ data := make([]common.Hash, len(log.Topics()))
+ bin.Or(bin, bloom9(log.Address().Bytes()))
for i, topic := range log.Topics() {
- data[i+1] = topic
+ data[i] = topic
}
for _, b := range data {
- bin.Or(bin, common.BigD(bloom9(crypto.Sha3(b)).Bytes()))
+ bin.Or(bin, bloom9(b[:]))
}
}
@@ -36,20 +36,24 @@ func LogsBloom(logs state.Logs) *big.Int {
}
func bloom9(b []byte) *big.Int {
+ b = crypto.Sha3(b[:])
+
r := new(big.Int)
- for i := 0; i < 16; i += 2 {
+ for i := 0; i < 6; i += 2 {
t := big.NewInt(1)
- b := uint(b[i+1]) + 1024*(uint(b[i])&1)
+ b := (uint(b[i+1]) + (uint(b[i]) << 8)) & 2047
r.Or(r, t.Lsh(t, b))
}
return r
}
-func BloomLookup(bin, topic []byte) bool {
- bloom := common.BigD(bin)
- cmp := bloom9(crypto.Sha3(topic))
+var Bloom9 = bloom9
+
+func BloomLookup(bin Bloom, topic common.Hash) bool {
+ bloom := bin.Big()
+ cmp := bloom9(topic[:])
return bloom.And(bloom, cmp).Cmp(cmp) == 0
}
diff --git a/core/types/common.go b/core/types/common.go
index def7936a5..4e885c4c6 100644
--- a/core/types/common.go
+++ b/core/types/common.go
@@ -4,8 +4,40 @@ import (
"math/big"
"github.com/ethereum/go-ethereum/state"
+ "github.com/ethereum/go-ethereum/common"
+
+ "fmt"
)
type BlockProcessor interface {
Process(*Block) (*big.Int, state.Logs, error)
}
+
+const bloomLength = 256
+
+type Bloom [bloomLength]byte
+
+func BytesToBloom(b []byte) Bloom {
+ var bloom Bloom
+ bloom.SetBytes(b)
+ return bloom
+}
+
+func (b *Bloom) SetBytes(d []byte) {
+ if len(b) < len(d) {
+ panic(fmt.Sprintf("bloom bytes too big %d %d", len(b), len(d)))
+ }
+
+ // reverse loop
+ for i := len(d) - 1; i >= 0; i-- {
+ b[bloomLength-len(d)+i] = b[i]
+ }
+}
+
+func (b Bloom) Big() *big.Int {
+ return common.Bytes2Big(b[:])
+}
+
+func (b Bloom) Bytes() []byte {
+ return b[:]
+}
diff --git a/core/types/derive_sha.go b/core/types/derive_sha.go
index 593a31f1c..10e3d7446 100644
--- a/core/types/derive_sha.go
+++ b/core/types/derive_sha.go
@@ -1,8 +1,9 @@
package types
import (
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/ethdb"
+ "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/trie"
)
@@ -11,12 +12,13 @@ type DerivableList interface {
GetRlp(i int) []byte
}
-func DeriveSha(list DerivableList) []byte {
+func DeriveSha(list DerivableList) common.Hash {
db, _ := ethdb.NewMemDatabase()
trie := trie.New(nil, db)
for i := 0; i < list.Len(); i++ {
- trie.Update(common.Encode(i), list.GetRlp(i))
+ key, _ := rlp.EncodeToBytes(i)
+ trie.Update(key, list.GetRlp(i))
}
- return trie.Root()
+ return common.BytesToHash(trie.Root())
}
diff --git a/core/types/receipt.go b/core/types/receipt.go
index be14d0e0e..f88d42b29 100644
--- a/core/types/receipt.go
+++ b/core/types/receipt.go
@@ -3,16 +3,18 @@ package types
import (
"bytes"
"fmt"
+ "io"
"math/big"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/state"
)
type Receipt struct {
PostState []byte
CumulativeGasUsed *big.Int
- Bloom []byte
+ Bloom Bloom
logs state.Logs
}
@@ -20,34 +22,26 @@ func NewReceipt(root []byte, cumalativeGasUsed *big.Int) *Receipt {
return &Receipt{PostState: common.CopyBytes(root), CumulativeGasUsed: new(big.Int).Set(cumalativeGasUsed)}
}
-func NewRecieptFromValue(val *common.Value) *Receipt {
- r := &Receipt{}
- r.RlpValueDecode(val)
-
- return r
-}
-
func (self *Receipt) SetLogs(logs state.Logs) {
self.logs = logs
}
-func (self *Receipt) RlpValueDecode(decoder *common.Value) {
- self.PostState = decoder.Get(0).Bytes()
- self.CumulativeGasUsed = decoder.Get(1).BigInt()
- self.Bloom = decoder.Get(2).Bytes()
-
- it := decoder.Get(3).NewIterator()
- for it.Next() {
- self.logs = append(self.logs, state.NewLogFromValue(it.Value()))
- }
+func (self *Receipt) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs})
}
+/*
func (self *Receipt) RlpData() interface{} {
return []interface{}{self.PostState, self.CumulativeGasUsed, self.Bloom, self.logs.RlpData()}
}
+*/
func (self *Receipt) RlpEncode() []byte {
- return common.Encode(self.RlpData())
+ bytes, err := rlp.EncodeToBytes(self)
+ if err != nil {
+ fmt.Println("TMP -- RECEIPT ENCODE ERROR", err)
+ }
+ return bytes
}
func (self *Receipt) Cmp(other *Receipt) bool {
@@ -64,6 +58,7 @@ func (self *Receipt) String() string {
type Receipts []*Receipt
+/*
func (self Receipts) RlpData() interface{} {
data := make([]interface{}, len(self))
for i, receipt := range self {
@@ -72,9 +67,14 @@ func (self Receipts) RlpData() interface{} {
return data
}
+*/
func (self Receipts) RlpEncode() []byte {
- return common.Encode(self.RlpData())
+ bytes, err := rlp.EncodeToBytes(self)
+ if err != nil {
+ fmt.Println("TMP -- RECEIPTS ENCODE ERROR", err)
+ }
+ return bytes
}
func (self Receipts) Len() int { return len(self) }
diff --git a/core/types/transaction.go b/core/types/transaction.go
index dcd48af11..391fb46f5 100644
--- a/core/types/transaction.go
+++ b/core/types/transaction.go
@@ -1,14 +1,14 @@
package types
import (
- "bytes"
"crypto/ecdsa"
+ "errors"
"fmt"
"math/big"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -20,39 +20,34 @@ type Transaction struct {
AccountNonce uint64
Price *big.Int
GasLimit *big.Int
- Recipient []byte
+ Recipient *common.Address // nil means contract creation
Amount *big.Int
Payload []byte
V byte
R, S []byte
}
-func NewContractCreationTx(Amount, gasAmount, price *big.Int, data []byte) *Transaction {
- return NewTransactionMessage(nil, Amount, gasAmount, price, data)
+func NewContractCreationTx(amount, gasLimit, gasPrice *big.Int, data []byte) *Transaction {
+ return &Transaction{Recipient: nil, Amount: amount, GasLimit: gasLimit, Price: gasPrice, Payload: data}
}
-func NewTransactionMessage(to []byte, Amount, gasAmount, price *big.Int, data []byte) *Transaction {
- return &Transaction{Recipient: to, Amount: Amount, Price: price, GasLimit: gasAmount, Payload: data}
+func NewTransactionMessage(to common.Address, amount, gasAmount, gasPrice *big.Int, data []byte) *Transaction {
+ return &Transaction{Recipient: &to, Amount: amount, GasLimit: gasAmount, Price: gasPrice, Payload: data}
}
func NewTransactionFromBytes(data []byte) *Transaction {
- tx := &Transaction{}
- tx.RlpDecode(data)
-
- return tx
-}
-
-func NewTransactionFromAmount(val *common.Value) *Transaction {
- tx := &Transaction{}
- tx.RlpValueDecode(val)
-
+ // TODO: remove this function if possible. callers would
+ // much better off decoding into transaction directly.
+ // it's not that hard.
+ tx := new(Transaction)
+ rlp.DecodeBytes(data, tx)
return tx
}
-func (tx *Transaction) Hash() []byte {
- data := []interface{}{tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload}
-
- return crypto.Sha3(common.Encode(data))
+func (tx *Transaction) Hash() common.Hash {
+ return rlpHash([]interface{}{
+ tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload,
+ })
}
func (self *Transaction) Data() []byte {
@@ -79,68 +74,47 @@ func (self *Transaction) SetNonce(AccountNonce uint64) {
self.AccountNonce = AccountNonce
}
-func (self *Transaction) From() []byte {
- return self.sender()
+func (self *Transaction) From() (common.Address, error) {
+ pubkey := self.PublicKey()
+ if len(pubkey) == 0 || pubkey[0] != 4 {
+ return common.Address{}, errors.New("invalid public key")
+ }
+ var addr common.Address
+ copy(addr[:], crypto.Sha3(pubkey[1:]))
+ return addr, nil
}
-func (self *Transaction) To() []byte {
- return self.Recipient
+// To returns the recipient of the transaction.
+// If transaction is a contract creation (with no recipient address)
+// To returns nil.
+func (tx *Transaction) To() *common.Address {
+ return tx.Recipient
}
func (tx *Transaction) Curve() (v byte, r []byte, s []byte) {
v = byte(tx.V)
r = common.LeftPadBytes(tx.R, 32)
s = common.LeftPadBytes(tx.S, 32)
-
return
}
func (tx *Transaction) Signature(key []byte) []byte {
hash := tx.Hash()
-
- sig, _ := secp256k1.Sign(hash, key)
-
+ sig, _ := secp256k1.Sign(hash[:], key)
return sig
}
func (tx *Transaction) PublicKey() []byte {
hash := tx.Hash()
-
v, r, s := tx.Curve()
-
sig := append(r, s...)
sig = append(sig, v-27)
//pubkey := crypto.Ecrecover(append(hash, sig...))
- pubkey, _ := secp256k1.RecoverPubkey(hash, sig)
-
+ pubkey, _ := secp256k1.RecoverPubkey(hash[:], sig)
return pubkey
}
-func (tx *Transaction) sender() []byte {
- pubkey := tx.PublicKey()
-
- // Validate the returned key.
- // Return nil if public key isn't in full format
- if len(pubkey) == 0 || pubkey[0] != 4 {
- return nil
- }
-
- return crypto.Sha3(pubkey[1:])[12:]
-}
-
-// TODO: deprecate after new accounts & key stores are integrated
-func (tx *Transaction) Sign(privk []byte) error {
-
- sig := tx.Signature(privk)
-
- tx.R = sig[:32]
- tx.S = sig[32:64]
- tx.V = sig[64] + 27
-
- return nil
-}
-
func (tx *Transaction) SetSignatureValues(sig []byte) error {
tx.R = sig[:32]
tx.S = sig[32:64]
@@ -148,42 +122,40 @@ func (tx *Transaction) SetSignatureValues(sig []byte) error {
return nil
}
-func (tx *Transaction) SignECDSA(key *ecdsa.PrivateKey) error {
- return tx.Sign(crypto.FromECDSA(key))
+func (tx *Transaction) SignECDSA(prv *ecdsa.PrivateKey) error {
+ h := tx.Hash()
+ sig, err := crypto.Sign(h[:], prv)
+ if err != nil {
+ return err
+ }
+ tx.SetSignatureValues(sig)
+ return nil
}
+// TODO: remove
func (tx *Transaction) RlpData() interface{} {
data := []interface{}{tx.AccountNonce, tx.Price, tx.GasLimit, tx.Recipient, tx.Amount, tx.Payload}
-
return append(data, tx.V, new(big.Int).SetBytes(tx.R).Bytes(), new(big.Int).SetBytes(tx.S).Bytes())
}
-func (tx *Transaction) RlpEncode() []byte {
- return common.Encode(tx)
-}
-
-func (tx *Transaction) RlpDecode(data []byte) {
- rlp.Decode(bytes.NewReader(data), tx)
-}
-
-func (tx *Transaction) RlpValueDecode(decoder *common.Value) {
- tx.AccountNonce = decoder.Get(0).Uint()
- tx.Price = decoder.Get(1).BigInt()
- tx.GasLimit = decoder.Get(2).BigInt()
- tx.Recipient = decoder.Get(3).Bytes()
- tx.Amount = decoder.Get(4).BigInt()
- tx.Payload = decoder.Get(5).Bytes()
- tx.V = decoder.Get(6).Byte()
- tx.R = decoder.Get(7).Bytes()
- tx.S = decoder.Get(8).Bytes()
-}
-
func (tx *Transaction) String() string {
+ var from, to string
+ if f, err := tx.From(); err != nil {
+ from = "[invalid sender]"
+ } else {
+ from = fmt.Sprintf("%x", f[:])
+ }
+ if t := tx.To(); t == nil {
+ to = "[contract creation]"
+ } else {
+ to = fmt.Sprintf("%x", t[:])
+ }
+ enc, _ := rlp.EncodeToBytes(tx)
return fmt.Sprintf(`
TX(%x)
Contract: %v
- From: %x
- To: %x
+ From: %s
+ To: %s
Nonce: %v
GasPrice: %v
GasLimit %v
@@ -196,8 +168,8 @@ func (tx *Transaction) String() string {
`,
tx.Hash(),
len(tx.Recipient) == 0,
- tx.From(),
- tx.To(),
+ from,
+ to,
tx.AccountNonce,
tx.Price,
tx.GasLimit,
@@ -206,13 +178,14 @@ func (tx *Transaction) String() string {
tx.V,
tx.R,
tx.S,
- common.Encode(tx),
+ enc,
)
}
// Transaction slice type for basic sorting
type Transactions []*Transaction
+// TODO: remove
func (self Transactions) RlpData() interface{} {
// Marshal the transactions of this block
enc := make([]interface{}, len(self))
@@ -223,9 +196,14 @@ func (self Transactions) RlpData() interface{} {
return enc
}
-func (s Transactions) Len() int { return len(s) }
-func (s Transactions) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
-func (s Transactions) GetRlp(i int) []byte { return common.Rlp(s[i]) }
+
+func (s Transactions) Len() int { return len(s) }
+func (s Transactions) Swap(i, j int) { s[i], s[j] = s[j], s[i] }
+
+func (s Transactions) GetRlp(i int) []byte {
+ enc, _ := rlp.EncodeToBytes(s[i])
+ return enc
+}
type TxByNonce struct{ Transactions }
diff --git a/core/types/transaction_test.go b/core/types/transaction_test.go
index ab1254f4c..0b0dfe3ff 100644
--- a/core/types/transaction_test.go
+++ b/core/types/transaction_test.go
@@ -1 +1,58 @@
package types
+
+import (
+ "bytes"
+ "math/big"
+ "testing"
+
+ "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
+)
+
+// The values in those tests are from the Transaction Tests
+// at github.com/ethereum/tests.
+
+var (
+ emptyTx = NewTransactionMessage(
+ common.HexToAddress("095e7baea6a6c7c4c2dfeb977efac326af552d87"),
+ big.NewInt(0), big.NewInt(0), big.NewInt(0),
+ nil,
+ )
+
+ rightvrsRecipient = common.HexToAddress("b94f5374fce5edbc8e2a8697c15331677e6ebf0b")
+ rightvrsTx = &Transaction{
+ Recipient: &rightvrsRecipient,
+ AccountNonce: 3,
+ Price: big.NewInt(1),
+ GasLimit: big.NewInt(2000),
+ Amount: big.NewInt(10),
+ Payload: common.FromHex("5544"),
+ V: 28,
+ R: common.FromHex("98ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4a"),
+ S: common.FromHex("8887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3"),
+ }
+)
+
+func TestTransactionHash(t *testing.T) {
+ // "EmptyTransaction"
+ if emptyTx.Hash() != common.HexToHash("c775b99e7ad12f50d819fcd602390467e28141316969f4b57f0626f74fe3b386") {
+ t.Errorf("empty transaction hash mismatch, got %x", emptyTx.Hash())
+ }
+
+ // "RightVRSTest"
+ if rightvrsTx.Hash() != common.HexToHash("fe7a79529ed5f7c3375d06b26b186a8644e0e16c373d7a12be41c62d6042b77a") {
+ t.Errorf("RightVRS transaction hash mismatch, got %x", rightvrsTx.Hash())
+ }
+}
+
+func TestTransactionEncode(t *testing.T) {
+ // "RightVRSTest"
+ txb, err := rlp.EncodeToBytes(rightvrsTx)
+ if err != nil {
+ t.Fatalf("encode error: %v", err)
+ }
+ should := common.FromHex("f86103018207d094b94f5374fce5edbc8e2a8697c15331677e6ebf0b0a8255441ca098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa08887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3")
+ if !bytes.Equal(txb, should) {
+ t.Errorf("encoded RLP mismatch, got %x", txb)
+ }
+}
diff --git a/core/vm_env.go b/core/vm_env.go
index c7491bcdc..7845d1cd9 100644
--- a/core/vm_env.go
+++ b/core/vm_env.go
@@ -3,6 +3,7 @@ package core
import (
"math/big"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/vm"
@@ -27,24 +28,24 @@ func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, block *types
}
}
-func (self *VMEnv) Origin() []byte { return self.msg.From() }
-func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() }
-func (self *VMEnv) Coinbase() []byte { return self.block.Coinbase() }
-func (self *VMEnv) Time() int64 { return self.block.Time() }
-func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
-func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() }
-func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
-func (self *VMEnv) State() *state.StateDB { return self.state }
-func (self *VMEnv) Depth() int { return self.depth }
-func (self *VMEnv) SetDepth(i int) { self.depth = i }
-func (self *VMEnv) VmType() vm.Type { return self.typ }
-func (self *VMEnv) SetVmType(t vm.Type) { self.typ = t }
-func (self *VMEnv) GetHash(n uint64) []byte {
+func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f }
+func (self *VMEnv) BlockNumber() *big.Int { return self.block.Number() }
+func (self *VMEnv) Coinbase() common.Address { return self.block.Coinbase() }
+func (self *VMEnv) Time() int64 { return self.block.Time() }
+func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() }
+func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() }
+func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
+func (self *VMEnv) State() *state.StateDB { return self.state }
+func (self *VMEnv) Depth() int { return self.depth }
+func (self *VMEnv) SetDepth(i int) { self.depth = i }
+func (self *VMEnv) VmType() vm.Type { return self.typ }
+func (self *VMEnv) SetVmType(t vm.Type) { self.typ = t }
+func (self *VMEnv) GetHash(n uint64) common.Hash {
if block := self.chain.GetBlockByNumber(n); block != nil {
return block.Hash()
}
- return nil
+ return common.Hash{}
}
func (self *VMEnv) AddLog(log state.Log) {
self.state.AddLog(log)
@@ -53,20 +54,21 @@ func (self *VMEnv) Transfer(from, to vm.Account, amount *big.Int) error {
return vm.Transfer(from, to, amount)
}
-func (self *VMEnv) vm(addr, data []byte, gas, price, value *big.Int) *Execution {
+func (self *VMEnv) vm(addr *common.Address, data []byte, gas, price, value *big.Int) *Execution {
return NewExecution(self, addr, data, gas, price, value)
}
-func (self *VMEnv) Call(me vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) {
- exe := self.vm(addr, data, gas, price, value)
+func (self *VMEnv) Call(me vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
+ exe := self.vm(&addr, data, gas, price, value)
return exe.Call(addr, me)
}
-func (self *VMEnv) CallCode(me vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) {
- exe := self.vm(me.Address(), data, gas, price, value)
+func (self *VMEnv) CallCode(me vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
+ maddr := me.Address()
+ exe := self.vm(&maddr, data, gas, price, value)
return exe.Call(addr, me)
}
-func (self *VMEnv) Create(me vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) {
+func (self *VMEnv) Create(me vm.ContextRef, addr *common.Address, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) {
exe := self.vm(addr, data, gas, price, value)
return exe.Create(me)
}
diff --git a/crypto/crypto.go b/crypto/crypto.go
index bc72928ac..c3d47b629 100644
--- a/crypto/crypto.go
+++ b/crypto/crypto.go
@@ -16,10 +16,11 @@ import (
"errors"
"code.google.com/p/go-uuid/uuid"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto/ecies"
"github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/ethereum/go-ethereum/crypto/sha3"
- "github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
"golang.org/x/crypto/pbkdf2"
"golang.org/x/crypto/ripemd160"
)
@@ -37,9 +38,20 @@ func Sha3(data ...[]byte) []byte {
return d.Sum(nil)
}
+func Sha3Hash(data ...[]byte) (h common.Hash) {
+ d := sha3.NewKeccak256()
+ for _, b := range data {
+ d.Write(b)
+ }
+ d.Sum(h[:0])
+ return h
+}
+
// Creates an ethereum address given the bytes and the nonce
-func CreateAddress(b []byte, nonce uint64) []byte {
- return Sha3(common.NewValue([]interface{}{b, nonce}).Encode())[12:]
+func CreateAddress(b common.Address, nonce uint64) common.Address {
+ data, _ := rlp.EncodeToBytes([]interface{}{b, nonce})
+ return common.BytesToAddress(Sha3(data)[12:])
+ //return Sha3(common.NewValue([]interface{}{b, nonce}).Encode())[12:]
}
func Sha256(data []byte) []byte {
diff --git a/crypto/crypto_test.go b/crypto/crypto_test.go
index 754287641..63a9c3f5e 100644
--- a/crypto/crypto_test.go
+++ b/crypto/crypto_test.go
@@ -7,8 +7,8 @@ import (
"testing"
"time"
- "github.com/ethereum/go-ethereum/crypto/secp256k1"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto/secp256k1"
)
// These tests are sanity checks.
@@ -21,6 +21,12 @@ func TestSha3(t *testing.T) {
checkhash(t, "Sha3-256", func(in []byte) []byte { return Sha3(in) }, msg, exp)
}
+func TestSha3Hash(t *testing.T) {
+ msg := []byte("abc")
+ exp, _ := hex.DecodeString("4e03657aea45a94fc7d47ba826c8d667c0d1e6e33a64a036ec44f58fa12d6c45")
+ checkhash(t, "Sha3-256-array", func(in []byte) []byte { h := Sha3Hash(in); return h[:] }, msg, exp)
+}
+
func TestSha256(t *testing.T) {
msg := []byte("abc")
exp, _ := hex.DecodeString("ba7816bf8f01cfea414140de5dae2223b00361a396177a9cb410ff61f20015ad")
diff --git a/eth/backend.go b/eth/backend.go
index c1aa28f3c..afe314d74 100644
--- a/eth/backend.go
+++ b/eth/backend.go
@@ -295,7 +295,7 @@ func (s *Ethereum) StartMining() error {
servlogger.Errorf("Cannot start mining without coinbase: %v\n", err)
return fmt.Errorf("no coinbase: %v", err)
}
- s.miner.Start(cb)
+ s.miner.Start(common.BytesToAddress(cb))
return nil
}
@@ -405,7 +405,7 @@ func (self *Ethereum) txBroadcastLoop() {
// automatically stops if unsubscribe
for obj := range self.txSub.Chan() {
event := obj.(core.TxPreEvent)
- self.net.Broadcast("eth", TxMsg, event.Tx.RlpData())
+ self.net.Broadcast("eth", TxMsg, []*types.Transaction{event.Tx})
}
}
@@ -414,7 +414,7 @@ func (self *Ethereum) blockBroadcastLoop() {
for obj := range self.blockSub.Chan() {
switch ev := obj.(type) {
case core.NewMinedBlockEvent:
- self.net.Broadcast("eth", NewBlockMsg, ev.Block.RlpData(), ev.Block.Td)
+ self.net.Broadcast("eth", NewBlockMsg, []interface{}{ev.Block, ev.Block.Td})
}
}
}
diff --git a/eth/protocol.go b/eth/protocol.go
index 1d4322886..6d610a663 100644
--- a/eth/protocol.go
+++ b/eth/protocol.go
@@ -1,7 +1,6 @@
package eth
import (
- "bytes"
"fmt"
"math/big"
@@ -78,29 +77,37 @@ type txPool interface {
}
type chainManager interface {
- GetBlockHashesFromHash(hash []byte, amount uint64) (hashes [][]byte)
- GetBlock(hash []byte) (block *types.Block)
- Status() (td *big.Int, currentBlock []byte, genesisBlock []byte)
+ GetBlockHashesFromHash(hash common.Hash, amount uint64) (hashes []common.Hash)
+ GetBlock(hash common.Hash) (block *types.Block)
+ Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash)
}
type blockPool interface {
- AddBlockHashes(next func() ([]byte, bool), peerId string)
+ AddBlockHashes(next func() (common.Hash, bool), peerId string)
AddBlock(block *types.Block, peerId string)
- AddPeer(td *big.Int, currentBlock []byte, peerId string, requestHashes func([]byte) error, requestBlocks func([][]byte) error, peerError func(*errs.Error)) (best bool)
+ AddPeer(td *big.Int, currentBlock common.Hash, peerId string, requestHashes func(common.Hash) error, requestBlocks func([]common.Hash) error, peerError func(*errs.Error)) (best bool)
RemovePeer(peerId string)
}
-// message structs used for rlp decoding
+// message structs used for RLP serialization
type newBlockMsgData struct {
Block *types.Block
TD *big.Int
}
type getBlockHashesMsgData struct {
- Hash []byte
+ Hash common.Hash
Amount uint64
}
+type statusMsgData struct {
+ ProtocolVersion uint32
+ NetworkId uint32
+ TD *big.Int
+ CurrentBlock common.Hash
+ GenesisBlock common.Hash
+}
+
// main entrypoint, wrappers starting a server running the eth protocol
// use this constructor to attach the protocol ("class") to server caps
// the Dev p2p layer then runs the protocol instance on each peer
@@ -133,18 +140,25 @@ func runEthProtocol(protocolVersion, networkId int, txPool txPool, chainManager
},
id: fmt.Sprintf("%x", id[:8]),
}
- err = self.handleStatus()
- if err == nil {
- self.propagateTxs()
- for {
- err = self.handle()
- if err != nil {
- self.blockPool.RemovePeer(self.id)
- break
- }
+
+ // handshake.
+ if err := self.handleStatus(); err != nil {
+ return err
+ }
+ defer self.blockPool.RemovePeer(self.id)
+
+ // propagate existing transactions. new transactions appearing
+ // after this will be sent via broadcasts.
+ if err := p2p.Send(rw, TxMsg, txPool.GetTransactions()); err != nil {
+ return err
+ }
+
+ // main loop. handle incoming messages.
+ for {
+ if err := self.handle(); err != nil {
+ return err
}
}
- return
}
func (self *ethProtocol) handle() error {
@@ -171,7 +185,7 @@ func (self *ethProtocol) handle() error {
}
for _, tx := range txs {
jsonlogger.LogJson(&logger.EthTxReceived{
- TxHash: common.Bytes2Hex(tx.Hash()),
+ TxHash: tx.Hash().Hex(),
RemoteId: self.peer.ID().String(),
})
}
@@ -187,7 +201,7 @@ func (self *ethProtocol) handle() error {
request.Amount = maxHashes
}
hashes := self.chainManager.GetBlockHashesFromHash(request.Hash, request.Amount)
- return p2p.EncodeMsg(self.rw, BlockHashesMsg, common.ByteSliceToInterface(hashes)...)
+ return p2p.Send(self.rw, BlockHashesMsg, hashes)
case BlockHashesMsg:
msgStream := rlp.NewStream(msg.Payload)
@@ -196,14 +210,16 @@ func (self *ethProtocol) handle() error {
}
var i int
- iter := func() (hash []byte, ok bool) {
- hash, err := msgStream.Bytes()
+ iter := func() (hash common.Hash, ok bool) {
+ var h common.Hash
+ err := msgStream.Decode(&h)
if err == rlp.EOL {
- return nil, false
+ return common.Hash{}, false
} else if err != nil {
self.protoError(ErrDecode, "msg %v: after %v hashes : %v", msg, i, err)
- return nil, false
+ return common.Hash{}, false
}
+
i++
return hash, true
}
@@ -215,18 +231,18 @@ func (self *ethProtocol) handle() error {
return err
}
- var blocks []interface{}
+ var blocks []*types.Block
var i int
for {
i++
- var hash []byte
- if err := msgStream.Decode(&hash); err != nil {
- if err == rlp.EOL {
- break
- } else {
- return self.protoError(ErrDecode, "msg %v: %v", msg, err)
- }
+ var hash common.Hash
+ err := msgStream.Decode(&hash)
+ if err == rlp.EOL {
+ break
+ } else if err != nil {
+ return self.protoError(ErrDecode, "msg %v: %v", msg, err)
}
+
block := self.chainManager.GetBlock(hash)
if block != nil {
blocks = append(blocks, block)
@@ -235,7 +251,7 @@ func (self *ethProtocol) handle() error {
break
}
}
- return p2p.EncodeMsg(self.rw, BlocksMsg, blocks...)
+ return p2p.Send(self.rw, BlocksMsg, blocks)
case BlocksMsg:
msgStream := rlp.NewStream(msg.Payload)
@@ -263,10 +279,10 @@ func (self *ethProtocol) handle() error {
_, chainHead, _ := self.chainManager.Status()
jsonlogger.LogJson(&logger.EthChainReceivedNewBlock{
- BlockHash: common.Bytes2Hex(hash),
+ BlockHash: hash.Hex(),
BlockNumber: request.Block.Number(), // this surely must be zero
- ChainHeadHash: common.Bytes2Hex(chainHead),
- BlockPrevHash: common.Bytes2Hex(request.Block.ParentHash()),
+ ChainHeadHash: chainHead.Hex(),
+ BlockPrevHash: request.Block.ParentHash().Hex(),
RemoteId: self.peer.ID().String(),
})
// to simplify backend interface adding a new block
@@ -282,29 +298,8 @@ func (self *ethProtocol) handle() error {
return nil
}
-type statusMsgData struct {
- ProtocolVersion uint32
- NetworkId uint32
- TD *big.Int
- CurrentBlock []byte
- GenesisBlock []byte
-}
-
-func (self *ethProtocol) statusMsg() p2p.Msg {
- td, currentBlock, genesisBlock := self.chainManager.Status()
-
- return p2p.NewMsg(StatusMsg,
- uint32(self.protocolVersion),
- uint32(self.networkId),
- td,
- currentBlock,
- genesisBlock,
- )
-}
-
func (self *ethProtocol) handleStatus() error {
- // send precanned status message
- if err := self.rw.WriteMsg(self.statusMsg()); err != nil {
+ if err := self.sendStatus(); err != nil {
return err
}
@@ -313,11 +308,9 @@ func (self *ethProtocol) handleStatus() error {
if err != nil {
return err
}
-
if msg.Code != StatusMsg {
return self.protoError(ErrNoStatusMsg, "first msg has code %x (!= %x)", msg.Code, StatusMsg)
}
-
if msg.Size > ProtocolMaxMsgSize {
return self.protoError(ErrMsgTooLarge, "%v > %v", msg.Size, ProtocolMaxMsgSize)
}
@@ -329,7 +322,7 @@ func (self *ethProtocol) handleStatus() error {
_, _, genesisBlock := self.chainManager.Status()
- if !bytes.Equal(status.GenesisBlock, genesisBlock) {
+ if status.GenesisBlock != genesisBlock {
return self.protoError(ErrGenesisBlockMismatch, "%x (!= %x)", status.GenesisBlock, genesisBlock)
}
@@ -348,14 +341,14 @@ func (self *ethProtocol) handleStatus() error {
return nil
}
-func (self *ethProtocol) requestBlockHashes(from []byte) error {
+func (self *ethProtocol) requestBlockHashes(from common.Hash) error {
self.peer.Debugf("fetching hashes (%d) %x...\n", maxHashes, from[0:4])
- return p2p.EncodeMsg(self.rw, GetBlockHashesMsg, interface{}(from), uint64(maxHashes))
+ return p2p.Send(self.rw, GetBlockHashesMsg, getBlockHashesMsgData{from, maxHashes})
}
-func (self *ethProtocol) requestBlocks(hashes [][]byte) error {
+func (self *ethProtocol) requestBlocks(hashes []common.Hash) error {
self.peer.Debugf("fetching %v blocks", len(hashes))
- return p2p.EncodeMsg(self.rw, GetBlocksMsg, common.ByteSliceToInterface(hashes)...)
+ return p2p.Send(self.rw, GetBlocksMsg, hashes)
}
func (self *ethProtocol) protoError(code int, format string, params ...interface{}) (err *errs.Error) {
@@ -364,19 +357,20 @@ func (self *ethProtocol) protoError(code int, format string, params ...interface
return
}
+func (self *ethProtocol) sendStatus() error {
+ td, currentBlock, genesisBlock := self.chainManager.Status()
+ return p2p.Send(self.rw, StatusMsg, &statusMsgData{
+ ProtocolVersion: uint32(self.protocolVersion),
+ NetworkId: uint32(self.networkId),
+ TD: td,
+ CurrentBlock: currentBlock,
+ GenesisBlock: genesisBlock,
+ })
+}
+
func (self *ethProtocol) protoErrorDisconnect(err *errs.Error) {
err.Log(self.peer.Logger)
if err.Fatal() {
self.peer.Disconnect(p2p.DiscSubprotocolError)
}
}
-
-func (self *ethProtocol) propagateTxs() {
- transactions := self.txPool.GetTransactions()
- iface := make([]interface{}, len(transactions))
- for i, transaction := range transactions {
- iface[i] = transaction
- }
-
- self.rw.WriteMsg(p2p.NewMsg(TxMsg, iface...))
-}
diff --git a/eth/protocol_test.go b/eth/protocol_test.go
index 108fb4475..7620b3854 100644
--- a/eth/protocol_test.go
+++ b/eth/protocol_test.go
@@ -1,8 +1,6 @@
package eth
import (
- "bytes"
- "io"
"log"
"math/big"
"os"
@@ -29,52 +27,21 @@ func logInit() {
}
}
-type testMsgReadWriter struct {
- in chan p2p.Msg
- out []p2p.Msg
-}
-
-func (self *testMsgReadWriter) In(msg p2p.Msg) {
- self.in <- msg
-}
-
-func (self *testMsgReadWriter) Out() (msg p2p.Msg, ok bool) {
- if len(self.out) > 0 {
- msg = self.out[0]
- self.out = self.out[1:]
- ok = true
- }
- return
-}
-
-func (self *testMsgReadWriter) WriteMsg(msg p2p.Msg) error {
- self.out = append(self.out, msg)
- return nil
-}
-
-func (self *testMsgReadWriter) ReadMsg() (p2p.Msg, error) {
- msg, ok := <-self.in
- if !ok {
- return msg, io.EOF
- }
- return msg, nil
-}
-
type testTxPool struct {
getTransactions func() []*types.Transaction
addTransactions func(txs []*types.Transaction)
}
type testChainManager struct {
- getBlockHashes func(hash []byte, amount uint64) (hashes [][]byte)
- getBlock func(hash []byte) *types.Block
- status func() (td *big.Int, currentBlock []byte, genesisBlock []byte)
+ getBlockHashes func(hash common.Hash, amount uint64) (hashes []common.Hash)
+ getBlock func(hash common.Hash) *types.Block
+ status func() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash)
}
type testBlockPool struct {
- addBlockHashes func(next func() ([]byte, bool), peerId string)
+ addBlockHashes func(next func() (common.Hash, bool), peerId string)
addBlock func(block *types.Block, peerId string) (err error)
- addPeer func(td *big.Int, currentBlock []byte, peerId string, requestHashes func([]byte) error, requestBlocks func([][]byte) error, peerError func(*errs.Error)) (best bool)
+ addPeer func(td *big.Int, currentBlock common.Hash, peerId string, requestHashes func(common.Hash) error, requestBlocks func([]common.Hash) error, peerError func(*errs.Error)) (best bool)
removePeer func(peerId string)
}
@@ -93,28 +60,28 @@ func (self *testTxPool) AddTransactions(txs []*types.Transaction) {
func (self *testTxPool) GetTransactions() types.Transactions { return nil }
-func (self *testChainManager) GetBlockHashesFromHash(hash []byte, amount uint64) (hashes [][]byte) {
+func (self *testChainManager) GetBlockHashesFromHash(hash common.Hash, amount uint64) (hashes []common.Hash) {
if self.getBlockHashes != nil {
hashes = self.getBlockHashes(hash, amount)
}
return
}
-func (self *testChainManager) Status() (td *big.Int, currentBlock []byte, genesisBlock []byte) {
+func (self *testChainManager) Status() (td *big.Int, currentBlock common.Hash, genesisBlock common.Hash) {
if self.status != nil {
td, currentBlock, genesisBlock = self.status()
}
return
}
-func (self *testChainManager) GetBlock(hash []byte) (block *types.Block) {
+func (self *testChainManager) GetBlock(hash common.Hash) (block *types.Block) {
if self.getBlock != nil {
block = self.getBlock(hash)
}
return
}
-func (self *testBlockPool) AddBlockHashes(next func() ([]byte, bool), peerId string) {
+func (self *testBlockPool) AddBlockHashes(next func() (common.Hash, bool), peerId string) {
if self.addBlockHashes != nil {
self.addBlockHashes(next, peerId)
}
@@ -126,7 +93,7 @@ func (self *testBlockPool) AddBlock(block *types.Block, peerId string) {
}
}
-func (self *testBlockPool) AddPeer(td *big.Int, currentBlock []byte, peerId string, requestBlockHashes func([]byte) error, requestBlocks func([][]byte) error, peerError func(*errs.Error)) (best bool) {
+func (self *testBlockPool) AddPeer(td *big.Int, currentBlock common.Hash, peerId string, requestBlockHashes func(common.Hash) error, requestBlocks func([]common.Hash) error, peerError func(*errs.Error)) (best bool) {
if self.addPeer != nil {
best = self.addPeer(td, currentBlock, peerId, requestBlockHashes, requestBlocks, peerError)
}
@@ -147,28 +114,36 @@ func testPeer() *p2p.Peer {
}
type ethProtocolTester struct {
+ p2p.MsgReadWriter // writing to the tester feeds the protocol
+
quit chan error
- rw *testMsgReadWriter // p2p.MsgReadWriter
- txPool *testTxPool // txPool
- chainManager *testChainManager // chainManager
- blockPool *testBlockPool // blockPool
+ pipe *p2p.MsgPipeRW // the protocol read/writes on this end
+ txPool *testTxPool // txPool
+ chainManager *testChainManager // chainManager
+ blockPool *testBlockPool // blockPool
t *testing.T
}
func newEth(t *testing.T) *ethProtocolTester {
+ p1, p2 := p2p.MsgPipe()
return &ethProtocolTester{
- quit: make(chan error),
- rw: &testMsgReadWriter{in: make(chan p2p.Msg, 10)},
- txPool: &testTxPool{},
- chainManager: &testChainManager{},
- blockPool: &testBlockPool{},
- t: t,
+ MsgReadWriter: p1,
+ quit: make(chan error, 1),
+ pipe: p2,
+ txPool: &testTxPool{},
+ chainManager: &testChainManager{},
+ blockPool: &testBlockPool{},
+ t: t,
}
}
func (self *ethProtocolTester) reset() {
- self.rw = &testMsgReadWriter{in: make(chan p2p.Msg, 10)}
- self.quit = make(chan error)
+ self.pipe.Close()
+
+ p1, p2 := p2p.MsgPipe()
+ self.MsgReadWriter = p1
+ self.pipe = p2
+ self.quit = make(chan error, 1)
}
func (self *ethProtocolTester) checkError(expCode int, delay time.Duration) (err error) {
@@ -190,33 +165,8 @@ func (self *ethProtocolTester) checkError(expCode int, delay time.Duration) (err
return
}
-func (self *ethProtocolTester) In(msg p2p.Msg) {
- self.rw.In(msg)
-}
-
-func (self *ethProtocolTester) Out() (p2p.Msg, bool) {
- return self.rw.Out()
-}
-
-func (self *ethProtocolTester) checkMsg(i int, code uint64, val interface{}) (msg p2p.Msg) {
- if i >= len(self.rw.out) {
- self.t.Errorf("expected at least %v msgs, got %v", i, len(self.rw.out))
- return
- }
- msg = self.rw.out[i]
- if msg.Code != code {
- self.t.Errorf("expected msg code %v, got %v", code, msg.Code)
- }
- if val != nil {
- if err := msg.Decode(val); err != nil {
- self.t.Errorf("rlp encoding error: %v", err)
- }
- }
- return
-}
-
func (self *ethProtocolTester) run() {
- err := runEthProtocol(ProtocolVersion, NetworkId, self.txPool, self.chainManager, self.blockPool, testPeer(), self.rw)
+ err := runEthProtocol(ProtocolVersion, NetworkId, self.txPool, self.chainManager, self.blockPool, testPeer(), self.pipe)
self.quit <- err
}
@@ -224,41 +174,52 @@ func TestStatusMsgErrors(t *testing.T) {
logInit()
eth := newEth(t)
td := common.Big1
- currentBlock := []byte{1}
- genesis := []byte{2}
- eth.chainManager.status = func() (*big.Int, []byte, []byte) { return td, currentBlock, genesis }
- go eth.run()
- statusMsg := p2p.NewMsg(4)
- eth.In(statusMsg)
- delay := 1 * time.Second
- eth.checkError(ErrNoStatusMsg, delay)
- var status statusMsgData
- eth.checkMsg(0, StatusMsg, &status) // first outgoing msg should be StatusMsg
- if status.TD.Cmp(td) != 0 ||
- status.ProtocolVersion != ProtocolVersion ||
- status.NetworkId != NetworkId ||
- status.TD.Cmp(td) != 0 ||
- bytes.Compare(status.CurrentBlock, currentBlock) != 0 ||
- bytes.Compare(status.GenesisBlock, genesis) != 0 {
- t.Errorf("incorrect outgoing status")
- }
-
- eth.reset()
+ currentBlock := common.Hash{1}
+ genesis := common.Hash{2}
+ eth.chainManager.status = func() (*big.Int, common.Hash, common.Hash) { return td, currentBlock, genesis }
go eth.run()
- statusMsg = p2p.NewMsg(0, uint32(48), uint32(0), td, currentBlock, genesis)
- eth.In(statusMsg)
- eth.checkError(ErrProtocolVersionMismatch, delay)
- eth.reset()
- go eth.run()
- statusMsg = p2p.NewMsg(0, uint32(49), uint32(1), td, currentBlock, genesis)
- eth.In(statusMsg)
- eth.checkError(ErrNetworkIdMismatch, delay)
+ tests := []struct {
+ code uint64
+ data interface{}
+ wantErrorCode int
+ }{
+ {
+ code: TxMsg, data: []interface{}{},
+ wantErrorCode: ErrNoStatusMsg,
+ },
+ {
+ code: StatusMsg, data: statusMsgData{10, NetworkId, td, currentBlock, genesis},
+ wantErrorCode: ErrProtocolVersionMismatch,
+ },
+ {
+ code: StatusMsg, data: statusMsgData{ProtocolVersion, 999, td, currentBlock, genesis},
+ wantErrorCode: ErrNetworkIdMismatch,
+ },
+ {
+ code: StatusMsg, data: statusMsgData{ProtocolVersion, NetworkId, td, currentBlock, common.Hash{3}},
+ wantErrorCode: ErrGenesisBlockMismatch,
+ },
+ }
+ for _, test := range tests {
+ // first outgoing msg should be StatusMsg.
+ err := p2p.ExpectMsg(eth, StatusMsg, &statusMsgData{
+ ProtocolVersion: ProtocolVersion,
+ NetworkId: NetworkId,
+ TD: td,
+ CurrentBlock: currentBlock,
+ GenesisBlock: genesis,
+ })
+ if err != nil {
+ t.Fatalf("incorrect outgoing status: %v", err)
+ }
- eth.reset()
- go eth.run()
- statusMsg = p2p.NewMsg(0, uint32(49), uint32(0), td, currentBlock, []byte{3})
- eth.In(statusMsg)
- eth.checkError(ErrGenesisBlockMismatch, delay)
+ // the send call might hang until reset because
+ // the protocol might not read the payload.
+ go p2p.Send(eth, test.code, test.data)
+ eth.checkError(test.wantErrorCode, 1*time.Second)
+ eth.reset()
+ go eth.run()
+ }
}
diff --git a/miner/miner.go b/miner/miner.go
index 7bf67a6ec..ccc19c754 100644
--- a/miner/miner.go
+++ b/miner/miner.go
@@ -4,6 +4,7 @@ import (
"math/big"
"github.com/ethereum/ethash"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/pow"
@@ -32,7 +33,7 @@ func (self *Miner) Mining() bool {
return self.mining
}
-func (self *Miner) Start(coinbase []byte) {
+func (self *Miner) Start(coinbase common.Address) {
self.mining = true
self.worker = newWorker(coinbase, self.eth)
self.worker.register(NewCpuMiner(0, self.pow))
diff --git a/miner/worker.go b/miner/worker.go
index 10fc6f508..63d1bfa0b 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -7,9 +7,9 @@ import (
"sync"
"time"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/core/types"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/pow"
@@ -39,7 +39,7 @@ func env(block *types.Block, eth core.Backend) *environment {
coinbase: state.GetOrNewStateObject(block.Coinbase()),
}
for _, ancestor := range eth.ChainManager().GetAncestors(block, 7) {
- env.ancestors.Add(string(ancestor.Hash()))
+ env.ancestors.Add(ancestor.Hash())
}
return env
@@ -71,14 +71,14 @@ type worker struct {
eth core.Backend
chain *core.ChainManager
proc *core.BlockProcessor
- coinbase []byte
+ coinbase common.Address
current *environment
mining bool
}
-func newWorker(coinbase []byte, eth core.Backend) *worker {
+func newWorker(coinbase common.Address, eth core.Backend) *worker {
return &worker{
eth: eth,
mux: eth.EventMux(),
@@ -152,13 +152,13 @@ func (self *worker) wait() {
block := self.current.block
if block.Number().Uint64() == work.Number && block.Nonce() == 0 {
self.current.block.SetNonce(work.Nonce)
- self.current.block.Header().MixDigest = work.MixDigest
+ self.current.block.Header().MixDigest = common.BytesToHash(work.MixDigest)
jsonlogger.LogJson(&logger.EthMinerNewBlock{
- BlockHash: common.Bytes2Hex(block.Hash()),
+ BlockHash: block.Hash().Hex(),
BlockNumber: block.Number(),
- ChainHeadHash: common.Bytes2Hex(block.ParentHeaderHash),
- BlockPrevHash: common.Bytes2Hex(block.ParentHeaderHash),
+ ChainHeadHash: block.ParentHeaderHash.Hex(),
+ BlockPrevHash: block.ParentHeaderHash.Hex(),
})
if err := self.chain.InsertChain(types.Blocks{self.current.block}); err == nil {
@@ -208,9 +208,10 @@ gasLimit:
fallthrough
case core.IsInvalidTxErr(err):
// Remove invalid transactions
- self.chain.TxState().RemoveNonce(tx.From(), tx.Nonce())
+ from, _ := tx.From()
+ self.chain.TxState().RemoveNonce(from, tx.Nonce())
remove = append(remove, tx)
- minerlogger.Infof("TX (%x) failed. Transaction will be removed\n", tx.Hash()[:4])
+ minerlogger.Infof("TX (%x) failed. Transaction will be removed\n", tx.Hash().Bytes()[:4])
case state.IsGasLimitErr(err):
minerlogger.Infof("Gas limit reached for block. %d TXs included in this block\n", i)
// Break on gas limit
@@ -232,13 +233,13 @@ var (
)
func (self *worker) commitUncle(uncle *types.Header) error {
- if self.current.uncles.Has(string(uncle.Hash())) {
+ if self.current.uncles.Has(uncle.Hash()) {
// Error not unique
return core.UncleError("Uncle not unique")
}
- self.current.uncles.Add(string(uncle.Hash()))
+ self.current.uncles.Add(uncle.Hash())
- if !self.current.ancestors.Has(string(uncle.ParentHash)) {
+ if !self.current.ancestors.Has(uncle.ParentHash) {
return core.UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
}
diff --git a/p2p/handshake.go b/p2p/handshake.go
index 7fc497517..031064407 100644
--- a/p2p/handshake.go
+++ b/p2p/handshake.go
@@ -92,7 +92,7 @@ func setupInboundConn(fd net.Conn, prv *ecdsa.PrivateKey, our *protoHandshake) (
return nil, errors.New("node ID in protocol handshake does not match encryption handshake")
}
// TODO: validate that handshake node ID matches
- if err := writeProtocolHandshake(rw, our); err != nil {
+ if err := Send(rw, handshakeMsg, our); err != nil {
return nil, fmt.Errorf("protocol write error: %v", err)
}
return &conn{rw, rhs}, nil
@@ -106,7 +106,7 @@ func setupOutboundConn(fd net.Conn, prv *ecdsa.PrivateKey, our *protoHandshake,
// Run the protocol handshake using authenticated messages.
rw := newRlpxFrameRW(fd, secrets)
- if err := writeProtocolHandshake(rw, our); err != nil {
+ if err := Send(rw, handshakeMsg, our); err != nil {
return nil, fmt.Errorf("protocol write error: %v", err)
}
rhs, err := readProtocolHandshake(rw, our)
@@ -398,10 +398,6 @@ func xor(one, other []byte) (xor []byte) {
return xor
}
-func writeProtocolHandshake(w MsgWriter, our *protoHandshake) error {
- return EncodeMsg(w, handshakeMsg, our.Version, our.Name, our.Caps, our.ListenPort, our.ID[:])
-}
-
func readProtocolHandshake(r MsgReader, our *protoHandshake) (*protoHandshake, error) {
// read and handle remote handshake
msg, err := r.ReadMsg()
diff --git a/p2p/message.go b/p2p/message.go
index 14e4404c9..ef3630a90 100644
--- a/p2p/message.go
+++ b/p2p/message.go
@@ -11,7 +11,6 @@ import (
"sync/atomic"
"time"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
)
@@ -28,13 +27,7 @@ type Msg struct {
Payload io.Reader
}
-// NewMsg creates an RLP-encoded message with the given code.
-func NewMsg(code uint64, params ...interface{}) Msg {
- p := bytes.NewReader(common.Encode(params))
- return Msg{Code: code, Size: uint32(p.Len()), Payload: p}
-}
-
-// Decode parse the RLP content of a message into
+// Decode parses the RLP content of a message into
// the given value, which must be a pointer.
//
// For the decoding rules, please see package rlp.
@@ -76,13 +69,30 @@ type MsgReadWriter interface {
MsgWriter
}
-// EncodeMsg writes an RLP-encoded message with the given code and
-// data elements.
-func EncodeMsg(w MsgWriter, code uint64, data ...interface{}) error {
- return w.WriteMsg(NewMsg(code, data...))
+// Send writes an RLP-encoded message with the given code.
+// data should encode as an RLP list.
+func Send(w MsgWriter, msgcode uint64, data interface{}) error {
+ size, r, err := rlp.EncodeToReader(data)
+ if err != nil {
+ return err
+ }
+ return w.WriteMsg(Msg{Code: msgcode, Size: uint32(size), Payload: r})
+}
+
+// SendItems writes an RLP with the given code and data elements.
+// For a call such as:
+//
+// SendItems(w, code, e1, e2, e3)
+//
+// the message payload will be an RLP list containing the items:
+//
+// [e1, e2, e3]
+//
+func SendItems(w MsgWriter, msgcode uint64, elems ...interface{}) error {
+ return Send(w, msgcode, elems)
}
-// netWrapper wrapsa MsgReadWriter with locks around
+// netWrapper wraps a MsgReadWriter with locks around
// ReadMsg/WriteMsg and applies read/write deadlines.
type netWrapper struct {
rmu, wmu sync.Mutex
@@ -175,7 +185,10 @@ func (p *MsgPipeRW) WriteMsg(msg Msg) error {
case p.w <- msg:
if msg.Size > 0 {
// wait for payload read or discard
- <-consumed
+ select {
+ case <-consumed:
+ case <-p.closing:
+ }
}
return nil
case <-p.closing:
@@ -197,8 +210,8 @@ func (p *MsgPipeRW) ReadMsg() (Msg, error) {
}
// Close unblocks any pending ReadMsg and WriteMsg calls on both ends
-// of the pipe. They will return ErrPipeClosed. Note that Close does
-// not interrupt any reads from a message payload.
+// of the pipe. They will return ErrPipeClosed. Close also
+// interrupts any reads from a message payload.
func (p *MsgPipeRW) Close() error {
if atomic.AddInt32(p.closed, 1) != 1 {
// someone else is already closing
@@ -208,3 +221,35 @@ func (p *MsgPipeRW) Close() error {
close(p.closing)
return nil
}
+
+// ExpectMsg reads a message from r and verifies that its
+// code and encoded RLP content match the provided values.
+// If content is nil, the payload is discarded and not verified.
+func ExpectMsg(r MsgReader, code uint64, content interface{}) error {
+ msg, err := r.ReadMsg()
+ if err != nil {
+ return err
+ }
+ if msg.Code != code {
+ return fmt.Errorf("message code mismatch: got %d, expected %d", msg.Code, code)
+ }
+ if content == nil {
+ return msg.Discard()
+ } else {
+ contentEnc, err := rlp.EncodeToBytes(content)
+ if err != nil {
+ panic("content encode error: " + err.Error())
+ }
+ if int(msg.Size) != len(contentEnc) {
+ return fmt.Errorf("message size mismatch: got %d, want %d", msg.Size, len(contentEnc))
+ }
+ actualContent, err := ioutil.ReadAll(msg.Payload)
+ if err != nil {
+ return err
+ }
+ if !bytes.Equal(actualContent, contentEnc) {
+ return fmt.Errorf("message payload mismatch:\ngot: %x\nwant: %x", actualContent, contentEnc)
+ }
+ }
+ return nil
+}
diff --git a/p2p/message_test.go b/p2p/message_test.go
index 31ed61d87..9a93dd347 100644
--- a/p2p/message_test.go
+++ b/p2p/message_test.go
@@ -5,33 +5,17 @@ import (
"encoding/hex"
"fmt"
"io"
- "io/ioutil"
"runtime"
"strings"
"testing"
"time"
)
-func TestNewMsg(t *testing.T) {
- msg := NewMsg(3, 1, "000")
- if msg.Code != 3 {
- t.Errorf("incorrect code %d, want %d", msg.Code)
- }
- expect := unhex("c50183303030")
- if msg.Size != uint32(len(expect)) {
- t.Errorf("incorrect size %d, want %d", msg.Size, len(expect))
- }
- pl, _ := ioutil.ReadAll(msg.Payload)
- if !bytes.Equal(pl, expect) {
- t.Errorf("incorrect payload content, got %x, want %x", pl, expect)
- }
-}
-
func ExampleMsgPipe() {
rw1, rw2 := MsgPipe()
go func() {
- EncodeMsg(rw1, 8, []byte{0, 0})
- EncodeMsg(rw1, 5, []byte{1, 1})
+ Send(rw1, 8, [][]byte{{0, 0}})
+ Send(rw1, 5, [][]byte{{1, 1}})
rw1.Close()
}()
@@ -40,7 +24,7 @@ func ExampleMsgPipe() {
if err != nil {
break
}
- var data [1][]byte
+ var data [][]byte
msg.Decode(&data)
fmt.Printf("msg: %d, %x\n", msg.Code, data[0])
}
@@ -55,7 +39,7 @@ loop:
rw1, rw2 := MsgPipe()
done := make(chan struct{})
go func() {
- if err := EncodeMsg(rw1, 1); err == nil {
+ if err := SendItems(rw1, 1); err == nil {
t.Error("EncodeMsg returned nil error")
} else if err != ErrPipeClosed {
t.Error("EncodeMsg returned wrong error: got %v, want %v", err, ErrPipeClosed)
diff --git a/p2p/peer.go b/p2p/peer.go
index c2c83abfc..6b97ea58d 100644
--- a/p2p/peer.go
+++ b/p2p/peer.go
@@ -132,7 +132,7 @@ loop:
select {
case <-ping.C:
go func() {
- if err := EncodeMsg(p.rw, pingMsg, nil); err != nil {
+ if err := SendItems(p.rw, pingMsg); err != nil {
p.protoErr <- err
return
}
@@ -161,7 +161,7 @@ loop:
func (p *Peer) politeDisconnect(reason DiscReason) {
done := make(chan struct{})
go func() {
- EncodeMsg(p.rw, discMsg, uint(reason))
+ SendItems(p.rw, discMsg, uint(reason))
// Wait for the other side to close the connection.
// Discard any data that they send until then.
io.Copy(ioutil.Discard, p.conn)
@@ -192,12 +192,13 @@ func (p *Peer) handle(msg Msg) error {
switch {
case msg.Code == pingMsg:
msg.Discard()
- go EncodeMsg(p.rw, pongMsg)
+ go SendItems(p.rw, pongMsg)
case msg.Code == discMsg:
var reason [1]DiscReason
// no need to discard or for error checking, we'll close the
// connection after this.
rlp.Decode(msg.Payload, &reason)
+ p.Debugf("Disconnect requested: %v\n", reason[0])
p.Disconnect(DiscRequested)
return discRequestedError(reason[0])
case msg.Code < baseProtocolLength:
diff --git a/p2p/peer_test.go b/p2p/peer_test.go
index cc9f1f0cd..3c4c71c0c 100644
--- a/p2p/peer_test.go
+++ b/p2p/peer_test.go
@@ -4,13 +4,10 @@ import (
"bytes"
"fmt"
"io"
- "io/ioutil"
"net"
"reflect"
"testing"
"time"
-
- "github.com/ethereum/go-ethereum/rlp"
)
var discard = Protocol{
@@ -55,13 +52,13 @@ func TestPeerProtoReadMsg(t *testing.T) {
Name: "a",
Length: 5,
Run: func(peer *Peer, rw MsgReadWriter) error {
- if err := expectMsg(rw, 2, []uint{1}); err != nil {
+ if err := ExpectMsg(rw, 2, []uint{1}); err != nil {
t.Error(err)
}
- if err := expectMsg(rw, 3, []uint{2}); err != nil {
+ if err := ExpectMsg(rw, 3, []uint{2}); err != nil {
t.Error(err)
}
- if err := expectMsg(rw, 4, []uint{3}); err != nil {
+ if err := ExpectMsg(rw, 4, []uint{3}); err != nil {
t.Error(err)
}
close(done)
@@ -72,9 +69,9 @@ func TestPeerProtoReadMsg(t *testing.T) {
closer, rw, _, errc := testPeer([]Protocol{proto})
defer closer.Close()
- EncodeMsg(rw, baseProtocolLength+2, 1)
- EncodeMsg(rw, baseProtocolLength+3, 2)
- EncodeMsg(rw, baseProtocolLength+4, 3)
+ Send(rw, baseProtocolLength+2, []uint{1})
+ Send(rw, baseProtocolLength+3, []uint{2})
+ Send(rw, baseProtocolLength+4, []uint{3})
select {
case <-done:
@@ -92,10 +89,10 @@ func TestPeerProtoEncodeMsg(t *testing.T) {
Name: "a",
Length: 2,
Run: func(peer *Peer, rw MsgReadWriter) error {
- if err := EncodeMsg(rw, 2); err == nil {
+ if err := SendItems(rw, 2); err == nil {
t.Error("expected error for out-of-range msg code, got nil")
}
- if err := EncodeMsg(rw, 1, "foo", "bar"); err != nil {
+ if err := SendItems(rw, 1, "foo", "bar"); err != nil {
t.Errorf("write error: %v", err)
}
return nil
@@ -104,7 +101,7 @@ func TestPeerProtoEncodeMsg(t *testing.T) {
closer, rw, _, _ := testPeer([]Protocol{proto})
defer closer.Close()
- if err := expectMsg(rw, 17, []string{"foo", "bar"}); err != nil {
+ if err := ExpectMsg(rw, 17, []string{"foo", "bar"}); err != nil {
t.Error(err)
}
}
@@ -115,11 +112,15 @@ func TestPeerWriteForBroadcast(t *testing.T) {
closer, rw, peer, peerErr := testPeer([]Protocol{discard})
defer closer.Close()
+ emptymsg := func(code uint64) Msg {
+ return Msg{Code: code, Size: 0, Payload: bytes.NewReader(nil)}
+ }
+
// test write errors
- if err := peer.writeProtoMsg("b", NewMsg(3)); err == nil {
+ if err := peer.writeProtoMsg("b", emptymsg(3)); err == nil {
t.Errorf("expected error for unknown protocol, got nil")
}
- if err := peer.writeProtoMsg("discard", NewMsg(8)); err == nil {
+ if err := peer.writeProtoMsg("discard", emptymsg(8)); err == nil {
t.Errorf("expected error for out-of-range msg code, got nil")
} else if perr, ok := err.(*peerError); !ok || perr.Code != errInvalidMsgCode {
t.Errorf("wrong error for out-of-range msg code, got %#v", err)
@@ -128,14 +129,14 @@ func TestPeerWriteForBroadcast(t *testing.T) {
// setup for reading the message on the other end
read := make(chan struct{})
go func() {
- if err := expectMsg(rw, 16, nil); err != nil {
+ if err := ExpectMsg(rw, 16, nil); err != nil {
t.Error(err)
}
close(read)
}()
// test successful write
- if err := peer.writeProtoMsg("discard", NewMsg(0)); err != nil {
+ if err := peer.writeProtoMsg("discard", emptymsg(0)); err != nil {
t.Errorf("expect no error for known protocol: %v", err)
}
select {
@@ -150,10 +151,10 @@ func TestPeerPing(t *testing.T) {
closer, rw, _, _ := testPeer(nil)
defer closer.Close()
- if err := EncodeMsg(rw, pingMsg); err != nil {
+ if err := SendItems(rw, pingMsg); err != nil {
t.Fatal(err)
}
- if err := expectMsg(rw, pongMsg, nil); err != nil {
+ if err := ExpectMsg(rw, pongMsg, nil); err != nil {
t.Error(err)
}
}
@@ -163,10 +164,10 @@ func TestPeerDisconnect(t *testing.T) {
closer, rw, _, disc := testPeer(nil)
defer closer.Close()
- if err := EncodeMsg(rw, discMsg, DiscQuitting); err != nil {
+ if err := SendItems(rw, discMsg, DiscQuitting); err != nil {
t.Fatal(err)
}
- if err := expectMsg(rw, discMsg, []interface{}{DiscRequested}); err != nil {
+ if err := ExpectMsg(rw, discMsg, []interface{}{DiscRequested}); err != nil {
t.Error(err)
}
closer.Close() // make test end faster
@@ -192,35 +193,3 @@ func TestNewPeer(t *testing.T) {
p.Disconnect(DiscAlreadyConnected) // Should not hang
}
-
-// expectMsg reads a message from r and verifies that its
-// code and encoded RLP content match the provided values.
-// If content is nil, the payload is discarded and not verified.
-func expectMsg(r MsgReader, code uint64, content interface{}) error {
- msg, err := r.ReadMsg()
- if err != nil {
- return err
- }
- if msg.Code != code {
- return fmt.Errorf("message code mismatch: got %d, expected %d", msg.Code, code)
- }
- if content == nil {
- return msg.Discard()
- } else {
- contentEnc, err := rlp.EncodeToBytes(content)
- if err != nil {
- panic("content encode error: " + err.Error())
- }
- if int(msg.Size) != len(contentEnc) {
- return fmt.Errorf("message size mismatch: got %d, want %d", msg.Size, len(contentEnc))
- }
- actualContent, err := ioutil.ReadAll(msg.Payload)
- if err != nil {
- return err
- }
- if !bytes.Equal(actualContent, contentEnc) {
- return fmt.Errorf("message payload mismatch:\ngot: %x\nwant: %x", actualContent, contentEnc)
- }
- }
- return nil
-}
diff --git a/p2p/rlpx_test.go b/p2p/rlpx_test.go
index 49354c7ed..d98f1c2cd 100644
--- a/p2p/rlpx_test.go
+++ b/p2p/rlpx_test.go
@@ -30,7 +30,7 @@ ba628a4ba590cb43f7848f41c4382885
`)
// Check WriteMsg. This puts a message into the buffer.
- if err := EncodeMsg(rw, 8, 1, 2, 3, 4); err != nil {
+ if err := Send(rw, 8, []uint{1, 2, 3, 4}); err != nil {
t.Fatalf("WriteMsg error: %v", err)
}
written := buf.Bytes()
@@ -102,7 +102,7 @@ func TestRlpxFrameRW(t *testing.T) {
for i := 0; i < 10; i++ {
// write message into conn buffer
wmsg := []interface{}{"foo", "bar", strings.Repeat("test", i)}
- err := EncodeMsg(rw1, uint64(i), wmsg...)
+ err := Send(rw1, uint64(i), wmsg)
if err != nil {
t.Fatalf("WriteMsg error (i=%d): %v", i, err)
}
diff --git a/p2p/server.go b/p2p/server.go
index 9c148ba39..813b0676f 100644
--- a/p2p/server.go
+++ b/p2p/server.go
@@ -9,10 +9,10 @@ import (
"sync"
"time"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/p2p/discover"
"github.com/ethereum/go-ethereum/p2p/nat"
+ "github.com/ethereum/go-ethereum/rlp"
)
const (
@@ -129,10 +129,14 @@ func (srv *Server) SuggestPeer(n *discover.Node) {
// Broadcast sends an RLP-encoded message to all connected peers.
// This method is deprecated and will be removed later.
-func (srv *Server) Broadcast(protocol string, code uint64, data ...interface{}) {
+func (srv *Server) Broadcast(protocol string, code uint64, data interface{}) error {
var payload []byte
if data != nil {
- payload = common.Encode(data)
+ var err error
+ payload, err = rlp.EncodeToBytes(data)
+ if err != nil {
+ return err
+ }
}
srv.lock.RLock()
defer srv.lock.RUnlock()
@@ -146,6 +150,7 @@ func (srv *Server) Broadcast(protocol string, code uint64, data ...interface{})
peer.writeProtoMsg(protocol, msg)
}
}
+ return nil
}
// Start starts running the server.
diff --git a/p2p/server_test.go b/p2p/server_test.go
index 30447050c..14e7c7de2 100644
--- a/p2p/server_test.go
+++ b/p2p/server_test.go
@@ -149,7 +149,7 @@ func TestServerBroadcast(t *testing.T) {
connected.Wait()
// broadcast one message
- srv.Broadcast("discard", 0, "foo")
+ srv.Broadcast("discard", 0, []string{"foo"})
golden := unhex("66e94d166f0a2c3b884cfa59ca34")
// check that the message has been written everywhere
diff --git a/pow/block.go b/pow/block.go
index 136e4bf8d..9ae25bd4d 100644
--- a/pow/block.go
+++ b/pow/block.go
@@ -3,14 +3,15 @@ package pow
import (
"math/big"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
)
type Block interface {
Difficulty() *big.Int
- HashNoNonce() []byte
+ HashNoNonce() common.Hash
Nonce() uint64
- MixDigest() []byte
+ MixDigest() common.Hash
NumberU64() uint64
}
diff --git a/pow/ezp/pow.go b/pow/ezp/pow.go
index 7eba95784..bd2927fe8 100644
--- a/pow/ezp/pow.go
+++ b/pow/ezp/pow.go
@@ -6,8 +6,8 @@ import (
"math/rand"
"time"
- "github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/crypto/sha3"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/pow"
)
@@ -83,17 +83,14 @@ func (pow *EasyPow) Verify(block pow.Block) bool {
return Verify(block)
}
-func verify(hash []byte, diff *big.Int, nonce uint64) bool {
+func verify(hash common.Hash, diff *big.Int, nonce uint64) bool {
sha := sha3.NewKeccak256()
-
n := make([]byte, 8)
binary.PutUvarint(n, nonce)
- d := append(hash, n...)
- sha.Write(d)
-
+ sha.Write(n)
+ sha.Write(hash[:])
verification := new(big.Int).Div(common.BigPow(2, 256), diff)
res := common.BigD(sha.Sum(nil))
-
return res.Cmp(verification) <= 0
}
diff --git a/rlp/decode.go b/rlp/decode.go
index 55f7187a3..6d7e670c2 100644
--- a/rlp/decode.go
+++ b/rlp/decode.go
@@ -2,6 +2,7 @@ package rlp
import (
"bufio"
+ "bytes"
"encoding/binary"
"errors"
"fmt"
@@ -73,6 +74,12 @@ func Decode(r io.Reader, val interface{}) error {
return NewStream(r).Decode(val)
}
+// DecodeBytes parses RLP data from b into val.
+// Please see the documentation of Decode for the decoding rules.
+func DecodeBytes(b []byte, val interface{}) error {
+ return NewStream(bytes.NewReader(b)).Decode(val)
+}
+
type decodeError struct {
msg string
typ reflect.Type
diff --git a/rlp/encode.go b/rlp/encode.go
index 9d11d66bf..7ac74d8fb 100644
--- a/rlp/encode.go
+++ b/rlp/encode.go
@@ -203,8 +203,13 @@ func (w *encbuf) encodeStringHeader(size int) {
}
func (w *encbuf) encodeString(b []byte) {
- w.encodeStringHeader(len(b))
- w.str = append(w.str, b...)
+ if len(b) == 1 && b[0] <= 0x7F {
+ // fits single byte, no string header
+ w.str = append(w.str, b[0])
+ } else {
+ w.encodeStringHeader(len(b))
+ w.str = append(w.str, b...)
+ }
}
func (w *encbuf) list() *listhead {
@@ -386,7 +391,12 @@ func writeUint(val reflect.Value, w *encbuf) error {
}
func writeBigIntPtr(val reflect.Value, w *encbuf) error {
- return writeBigInt(val.Interface().(*big.Int), w)
+ ptr := val.Interface().(*big.Int)
+ if ptr == nil {
+ w.str = append(w.str, 0x80)
+ return nil
+ }
+ return writeBigInt(ptr, w)
}
func writeBigIntNoPtr(val reflect.Value, w *encbuf) error {
@@ -399,9 +409,6 @@ func writeBigInt(i *big.Int, w *encbuf) error {
return fmt.Errorf("rlp: cannot encode negative *big.Int")
} else if cmp == 0 {
w.str = append(w.str, 0x80)
- } else if bits := i.BitLen(); bits < 8 {
- // fits single byte
- w.str = append(w.str, byte(i.Uint64()))
} else {
w.encodeString(i.Bytes())
}
@@ -429,8 +436,13 @@ func writeByteArray(val reflect.Value, w *encbuf) error {
func writeString(val reflect.Value, w *encbuf) error {
s := val.String()
- w.encodeStringHeader(len(s))
- w.str = append(w.str, s...)
+ if len(s) == 1 && s[0] <= 0x7f {
+ // fits single byte, no string header
+ w.str = append(w.str, s[0])
+ } else {
+ w.encodeStringHeader(len(s))
+ w.str = append(w.str, s...)
+ }
return nil
}
diff --git a/rlp/encode_test.go b/rlp/encode_test.go
index c283fbd57..611514bda 100644
--- a/rlp/encode_test.go
+++ b/rlp/encode_test.go
@@ -103,12 +103,18 @@ var encTests = []encTest{
// byte slices, strings
{val: []byte{}, output: "80"},
+ {val: []byte{0x7E}, output: "7E"},
+ {val: []byte{0x7F}, output: "7F"},
+ {val: []byte{0x80}, output: "8180"},
{val: []byte{1, 2, 3}, output: "83010203"},
{val: []namedByteType{1, 2, 3}, output: "83010203"},
{val: [...]namedByteType{1, 2, 3}, output: "83010203"},
{val: "", output: "80"},
+ {val: "\x7E", output: "7E"},
+ {val: "\x7F", output: "7F"},
+ {val: "\x80", output: "8180"},
{val: "dog", output: "83646F67"},
{
val: "Lorem ipsum dolor sit amet, consectetur adipisicing eli",
@@ -196,6 +202,7 @@ var encTests = []encTest{
{val: (*uint)(nil), output: "80"},
{val: (*string)(nil), output: "80"},
{val: (*[]byte)(nil), output: "80"},
+ {val: (*big.Int)(nil), output: "80"},
{val: (*[]string)(nil), output: "C0"},
{val: (*[]interface{})(nil), output: "C0"},
{val: (*[]struct{ uint })(nil), output: "C0"},
diff --git a/rpc/api.go b/rpc/api.go
index afc0bd455..39a6b8f5b 100644
--- a/rpc/api.go
+++ b/rpc/api.go
@@ -676,7 +676,7 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return NewValidationError("Index", "does not exist")
}
- uncle, err := p.GetBlockByHash(common.ToHex(v.Uncles[args.Index]), false)
+ uncle, err := p.GetBlockByHash(v.Uncles[args.Index].Hex(), false)
if err != nil {
return err
}
@@ -695,7 +695,7 @@ func (p *EthereumApi) GetRequestReply(req *RpcRequest, reply *interface{}) error
return NewValidationError("Index", "does not exist")
}
- uncle, err := p.GetBlockByHash(common.ToHex(v.Uncles[args.Index]), false)
+ uncle, err := p.GetBlockByHash(v.Uncles[args.Index].Hex(), false)
if err != nil {
return err
}
@@ -840,12 +840,12 @@ func toFilterOptions(options *FilterOptions) core.FilterOptions {
// Convert optional address slice/string to byte slice
if str, ok := options.Address.(string); ok {
- opts.Address = [][]byte{common.FromHex(str)}
+ opts.Address = []common.Address{common.HexToAddress(str)}
} else if slice, ok := options.Address.([]interface{}); ok {
- bslice := make([][]byte, len(slice))
+ bslice := make([]common.Address, len(slice))
for i, addr := range slice {
if saddr, ok := addr.(string); ok {
- bslice[i] = common.FromHex(saddr)
+ bslice[i] = common.HexToAddress(saddr)
}
}
opts.Address = bslice
@@ -854,16 +854,15 @@ func toFilterOptions(options *FilterOptions) core.FilterOptions {
opts.Earliest = options.Earliest
opts.Latest = options.Latest
- topics := make([][][]byte, len(options.Topics))
+ topics := make([][]common.Hash, len(options.Topics))
for i, topicDat := range options.Topics {
if slice, ok := topicDat.([]interface{}); ok {
- topics[i] = make([][]byte, len(slice))
+ topics[i] = make([]common.Hash, len(slice))
for j, topic := range slice {
- topics[i][j] = common.FromHex(topic.(string))
+ topics[i][j] = common.HexToHash(topic.(string))
}
} else if str, ok := topicDat.(string); ok {
- topics[i] = make([][]byte, 1)
- topics[i][0] = common.FromHex(str)
+ topics[i] = []common.Hash{common.HexToHash(str)}
}
}
opts.Topics = topics
diff --git a/rpc/responses.go b/rpc/responses.go
index eec483fb7..5e197b729 100644
--- a/rpc/responses.go
+++ b/rpc/responses.go
@@ -13,14 +13,14 @@ type BlockRes struct {
fullTx bool
BlockNumber int64 `json:"number"`
- BlockHash []byte `json:"hash"`
- ParentHash []byte `json:"parentHash"`
- Nonce []byte `json:"nonce"`
- Sha3Uncles []byte `json:"sha3Uncles"`
- LogsBloom []byte `json:"logsBloom"`
- TransactionRoot []byte `json:"transactionRoot"`
- StateRoot []byte `json:"stateRoot"`
- Miner []byte `json:"miner"`
+ BlockHash common.Hash `json:"hash"`
+ ParentHash common.Hash `json:"parentHash"`
+ Nonce [8]byte `json:"nonce"`
+ Sha3Uncles common.Hash `json:"sha3Uncles"`
+ LogsBloom types.Bloom `json:"logsBloom"`
+ TransactionRoot common.Hash `json:"transactionRoot"`
+ StateRoot common.Hash `json:"stateRoot"`
+ Miner common.Address `json:"miner"`
Difficulty int64 `json:"difficulty"`
TotalDifficulty int64 `json:"totalDifficulty"`
Size int64 `json:"size"`
@@ -30,7 +30,7 @@ type BlockRes struct {
GasUsed int64 `json:"gasUsed"`
UnixTimestamp int64 `json:"timestamp"`
Transactions []*TransactionRes `json:"transactions"`
- Uncles [][]byte `json:"uncles"`
+ Uncles []common.Hash `json:"uncles"`
}
func (b *BlockRes) MarshalJSON() ([]byte, error) {
@@ -58,14 +58,14 @@ func (b *BlockRes) MarshalJSON() ([]byte, error) {
// convert strict types to hexified strings
ext.BlockNumber = common.ToHex(big.NewInt(b.BlockNumber).Bytes())
- ext.BlockHash = common.ToHex(b.BlockHash)
- ext.ParentHash = common.ToHex(b.ParentHash)
- ext.Nonce = common.ToHex(b.Nonce)
- ext.Sha3Uncles = common.ToHex(b.Sha3Uncles)
- ext.LogsBloom = common.ToHex(b.LogsBloom)
- ext.TransactionRoot = common.ToHex(b.TransactionRoot)
- ext.StateRoot = common.ToHex(b.StateRoot)
- ext.Miner = common.ToHex(b.Miner)
+ ext.BlockHash = b.BlockHash.Hex()
+ ext.ParentHash = b.ParentHash.Hex()
+ ext.Nonce = common.ToHex(b.Nonce[:])
+ ext.Sha3Uncles = b.Sha3Uncles.Hex()
+ ext.LogsBloom = common.ToHex(b.LogsBloom[:])
+ ext.TransactionRoot = b.TransactionRoot.Hex()
+ ext.StateRoot = b.StateRoot.Hex()
+ ext.Miner = b.Miner.Hex()
ext.Difficulty = common.ToHex(big.NewInt(b.Difficulty).Bytes())
ext.TotalDifficulty = common.ToHex(big.NewInt(b.TotalDifficulty).Bytes())
ext.Size = common.ToHex(big.NewInt(b.Size).Bytes())
@@ -81,12 +81,12 @@ func (b *BlockRes) MarshalJSON() ([]byte, error) {
}
} else {
for i, tx := range b.Transactions {
- ext.Transactions[i] = common.ToHex(tx.Hash)
+ ext.Transactions[i] = tx.Hash.Hex()
}
}
ext.Uncles = make([]string, len(b.Uncles))
for i, v := range b.Uncles {
- ext.Uncles[i] = common.ToHex(v)
+ ext.Uncles[i] = v.Hex()
}
return json.Marshal(ext)
@@ -125,7 +125,7 @@ func NewBlockRes(block *types.Block) *BlockRes {
v.TxIndex = int64(i)
res.Transactions[i] = v
}
- res.Uncles = make([][]byte, len(block.Uncles()))
+ res.Uncles = make([]common.Hash, len(block.Uncles()))
for i, uncle := range block.Uncles() {
res.Uncles[i] = uncle.Hash()
}
@@ -133,17 +133,17 @@ func NewBlockRes(block *types.Block) *BlockRes {
}
type TransactionRes struct {
- Hash []byte `json:"hash"`
- Nonce int64 `json:"nonce"`
- BlockHash []byte `json:"blockHash,omitempty"`
- BlockNumber int64 `json:"blockNumber,omitempty"`
- TxIndex int64 `json:"transactionIndex,omitempty"`
- From []byte `json:"from"`
- To []byte `json:"to"`
- Value int64 `json:"value"`
- Gas int64 `json:"gas"`
- GasPrice int64 `json:"gasPrice"`
- Input []byte `json:"input"`
+ Hash common.Hash `json:"hash"`
+ Nonce int64 `json:"nonce"`
+ BlockHash common.Hash `json:"blockHash,omitempty"`
+ BlockNumber int64 `json:"blockNumber,omitempty"`
+ TxIndex int64 `json:"transactionIndex,omitempty"`
+ From common.Address `json:"from"`
+ To *common.Address `json:"to"`
+ Value int64 `json:"value"`
+ Gas int64 `json:"gas"`
+ GasPrice int64 `json:"gasPrice"`
+ Input []byte `json:"input"`
}
func (t *TransactionRes) MarshalJSON() ([]byte, error) {
@@ -161,13 +161,17 @@ func (t *TransactionRes) MarshalJSON() ([]byte, error) {
Input string `json:"input"`
}
- ext.Hash = common.ToHex(t.Hash)
+ ext.Hash = t.Hash.Hex()
ext.Nonce = common.ToHex(big.NewInt(t.Nonce).Bytes())
- ext.BlockHash = common.ToHex(t.BlockHash)
+ ext.BlockHash = t.BlockHash.Hex()
ext.BlockNumber = common.ToHex(big.NewInt(t.BlockNumber).Bytes())
ext.TxIndex = common.ToHex(big.NewInt(t.TxIndex).Bytes())
- ext.From = common.ToHex(t.From)
- ext.To = common.ToHex(t.To)
+ ext.From = t.From.Hex()
+ if t.To == nil {
+ ext.To = "0x00"
+ } else {
+ ext.To = t.To.Hex()
+ }
ext.Value = common.ToHex(big.NewInt(t.Value).Bytes())
ext.Gas = common.ToHex(big.NewInt(t.Gas).Bytes())
ext.GasPrice = common.ToHex(big.NewInt(t.GasPrice).Bytes())
@@ -180,7 +184,7 @@ func NewTransactionRes(tx *types.Transaction) *TransactionRes {
var v = new(TransactionRes)
v.Hash = tx.Hash()
v.Nonce = int64(tx.Nonce())
- v.From = tx.From()
+ v.From, _ = tx.From()
v.To = tx.To()
v.Value = tx.Value().Int64()
v.Gas = tx.Gas().Int64()
diff --git a/rpc/util.go b/rpc/util.go
index 0798ae1d2..724c8b503 100644
--- a/rpc/util.go
+++ b/rpc/util.go
@@ -40,11 +40,11 @@ func toLogs(logs state.Logs) (ls []Log) {
for i, log := range logs {
var l Log
l.Topic = make([]string, len(log.Topics()))
- l.Address = common.ToHex(log.Address())
+ l.Address = log.Address().Hex()
l.Data = common.ToHex(log.Data())
l.Number = log.Number()
for j, topic := range log.Topics() {
- l.Topic[j] = common.ToHex(topic)
+ l.Topic[j] = topic.Hex()
}
ls[i] = l
}
diff --git a/state/dump.go b/state/dump.go
index 6db0d5074..712f8da1f 100644
--- a/state/dump.go
+++ b/state/dump.go
@@ -28,7 +28,7 @@ func (self *StateDB) RawDump() World {
it := self.trie.Iterator()
for it.Next() {
- stateObject := NewStateObjectFromBytes(it.Key, it.Value, self.db)
+ stateObject := NewStateObjectFromBytes(common.BytesToAddress(it.Key), it.Value, self.db)
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/state/log.go b/state/log.go
index a0859aaf2..f8aa4c08c 100644
--- a/state/log.go
+++ b/state/log.go
@@ -2,36 +2,36 @@ package state
import (
"fmt"
+ "io"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
)
type Log interface {
- common.RlpEncodable
-
- Address() []byte
- Topics() [][]byte
+ Address() common.Address
+ Topics() []common.Hash
Data() []byte
Number() uint64
}
type StateLog struct {
- address []byte
- topics [][]byte
+ address common.Address
+ topics []common.Hash
data []byte
number uint64
}
-func NewLog(address []byte, topics [][]byte, data []byte, number uint64) *StateLog {
+func NewLog(address common.Address, topics []common.Hash, data []byte, number uint64) *StateLog {
return &StateLog{address, topics, data, number}
}
-func (self *StateLog) Address() []byte {
+func (self *StateLog) Address() common.Address {
return self.address
}
-func (self *StateLog) Topics() [][]byte {
+func (self *StateLog) Topics() []common.Hash {
return self.topics
}
@@ -43,7 +43,12 @@ func (self *StateLog) Number() uint64 {
return self.number
}
+/*
func NewLogFromValue(decoder *common.Value) *StateLog {
+ var extlog struct {
+
+ }
+
log := &StateLog{
address: decoder.Get(0).Bytes(),
data: decoder.Get(2).Bytes(),
@@ -56,10 +61,17 @@ func NewLogFromValue(decoder *common.Value) *StateLog {
return log
}
+*/
+
+func (self *StateLog) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, []interface{}{self.address, self.topics, self.data})
+}
+/*
func (self *StateLog) RlpData() interface{} {
return []interface{}{self.address, common.ByteSliceToInterface(self.topics), self.data}
}
+*/
func (self *StateLog) String() string {
return fmt.Sprintf(`log: %x %x %x`, self.address, self.topics, self.data)
@@ -67,6 +79,7 @@ func (self *StateLog) String() string {
type Logs []Log
+/*
func (self Logs) RlpData() interface{} {
data := make([]interface{}, len(self))
for i, log := range self {
@@ -75,6 +88,7 @@ func (self Logs) RlpData() interface{} {
return data
}
+*/
func (self Logs) String() (ret string) {
for _, log := range self {
diff --git a/state/managed_state.go b/state/managed_state.go
index aff0206b2..0fcc1be67 100644
--- a/state/managed_state.go
+++ b/state/managed_state.go
@@ -1,6 +1,10 @@
package state
-import "sync"
+import (
+ "sync"
+
+ "github.com/ethereum/go-ethereum/common"
+)
type account struct {
stateObject *StateObject
@@ -29,7 +33,7 @@ func (ms *ManagedState) SetState(statedb *StateDB) {
ms.StateDB = statedb
}
-func (ms *ManagedState) RemoveNonce(addr []byte, n uint64) {
+func (ms *ManagedState) RemoveNonce(addr common.Address, n uint64) {
if ms.hasAccount(addr) {
ms.mu.Lock()
defer ms.mu.Unlock()
@@ -43,7 +47,7 @@ func (ms *ManagedState) RemoveNonce(addr []byte, n uint64) {
}
}
-func (ms *ManagedState) NewNonce(addr []byte) uint64 {
+func (ms *ManagedState) NewNonce(addr common.Address) uint64 {
ms.mu.RLock()
defer ms.mu.RUnlock()
@@ -57,26 +61,27 @@ func (ms *ManagedState) NewNonce(addr []byte) uint64 {
return uint64(len(account.nonces)) + account.nstart
}
-func (ms *ManagedState) hasAccount(addr []byte) bool {
- _, ok := ms.accounts[string(addr)]
+func (ms *ManagedState) hasAccount(addr common.Address) bool {
+ _, ok := ms.accounts[addr.Str()]
return ok
}
-func (ms *ManagedState) getAccount(addr []byte) *account {
- if account, ok := ms.accounts[string(addr)]; !ok {
+func (ms *ManagedState) getAccount(addr common.Address) *account {
+ straddr := addr.Str()
+ if account, ok := ms.accounts[straddr]; !ok {
so := ms.GetOrNewStateObject(addr)
- ms.accounts[string(addr)] = newAccount(so)
+ ms.accounts[straddr] = newAccount(so)
} else {
// Always make sure the state account nonce isn't actually higher
// than the tracked one.
so := ms.StateDB.GetStateObject(addr)
if so != nil && uint64(len(account.nonces))+account.nstart < so.nonce {
- ms.accounts[string(addr)] = newAccount(so)
+ ms.accounts[straddr] = newAccount(so)
}
}
- return ms.accounts[string(addr)]
+ return ms.accounts[straddr]
}
func newAccount(so *StateObject) *account {
diff --git a/state/managed_state_test.go b/state/managed_state_test.go
index 4aad1e1e3..b61f59e6d 100644
--- a/state/managed_state_test.go
+++ b/state/managed_state_test.go
@@ -6,15 +6,15 @@ import (
"github.com/ethereum/go-ethereum/common"
)
-var addr = common.Address([]byte("test"))
+var addr = common.BytesToAddress([]byte("test"))
func create() (*ManagedState, *account) {
ms := ManageState(&StateDB{stateObjects: make(map[string]*StateObject)})
so := &StateObject{address: addr, nonce: 100}
- ms.StateDB.stateObjects[string(addr)] = so
- ms.accounts[string(addr)] = newAccount(so)
+ ms.StateDB.stateObjects[addr.Str()] = so
+ ms.accounts[addr.Str()] = newAccount(so)
- return ms, ms.accounts[string(addr)]
+ return ms, ms.accounts[addr.Str()]
}
func TestNewNonce(t *testing.T) {
@@ -73,7 +73,7 @@ func TestRemoteNonceChange(t *testing.T) {
account.nonces = append(account.nonces, nn...)
nonce := ms.NewNonce(addr)
- ms.StateDB.stateObjects[string(addr)].nonce = 200
+ ms.StateDB.stateObjects[addr.Str()].nonce = 200
nonce = ms.NewNonce(addr)
if nonce != 200 {
t.Error("expected nonce after remote update to be", 201, "got", nonce)
@@ -81,7 +81,7 @@ func TestRemoteNonceChange(t *testing.T) {
ms.NewNonce(addr)
ms.NewNonce(addr)
ms.NewNonce(addr)
- ms.StateDB.stateObjects[string(addr)].nonce = 200
+ ms.StateDB.stateObjects[addr.Str()].nonce = 200
nonce = ms.NewNonce(addr)
if nonce != 204 {
t.Error("expected nonce after remote update to be", 201, "got", nonce)
diff --git a/state/state_object.go b/state/state_object.go
index cdb9abf79..a7c20722c 100644
--- a/state/state_object.go
+++ b/state/state_object.go
@@ -44,7 +44,7 @@ type StateObject struct {
State *StateDB
// Address belonging to this account
- address []byte
+ address common.Address
// The balance of the account
balance *big.Int
// The nonce of the account
@@ -77,12 +77,12 @@ func (self *StateObject) Reset() {
self.State.Reset()
}
-func NewStateObject(addr []byte, db common.Database) *StateObject {
+func NewStateObject(address common.Address, db common.Database) *StateObject {
// This to ensure that it has 20 bytes (and not 0 bytes), thus left or right pad doesn't matter.
- address := common.Address(addr)
+ //address := common.ToAddress(addr)
object := &StateObject{db: db, address: address, balance: new(big.Int), gasPool: new(big.Int), dirty: true}
- object.State = New(nil, db) //New(trie.New(common.Config.Db, ""))
+ object.State = New(common.Hash{}, db) //New(trie.New(common.Config.Db, ""))
object.storage = make(Storage)
object.gasPool = new(big.Int)
object.prepaid = new(big.Int)
@@ -90,12 +90,12 @@ func NewStateObject(addr []byte, db common.Database) *StateObject {
return object
}
-func NewStateObjectFromBytes(address, data []byte, db common.Database) *StateObject {
+func NewStateObjectFromBytes(address common.Address, data []byte, db common.Database) *StateObject {
// TODO clean me up
var extobject struct {
Nonce uint64
Balance *big.Int
- Root []byte
+ Root common.Hash
CodeHash []byte
}
err := rlp.Decode(bytes.NewReader(data), &extobject)
@@ -124,8 +124,8 @@ func (self *StateObject) MarkForDeletion() {
statelogger.Debugf("%x: #%d %v X\n", self.Address(), self.nonce, self.balance)
}
-func (c *StateObject) getAddr(addr []byte) *common.Value {
- return common.NewValueFromBytes([]byte(c.State.trie.Get(addr)))
+func (c *StateObject) getAddr(addr common.Hash) *common.Value {
+ return common.NewValueFromBytes([]byte(c.State.trie.Get(addr[:])))
}
func (c *StateObject) setAddr(addr []byte, value interface{}) {
@@ -133,34 +133,32 @@ func (c *StateObject) setAddr(addr []byte, value interface{}) {
}
func (self *StateObject) GetStorage(key *big.Int) *common.Value {
- return self.GetState(key.Bytes())
+ return self.GetState(common.BytesToHash(key.Bytes()))
}
func (self *StateObject) SetStorage(key *big.Int, value *common.Value) {
- self.SetState(key.Bytes(), value)
+ self.SetState(common.BytesToHash(key.Bytes()), value)
}
func (self *StateObject) Storage() Storage {
return self.storage
}
-func (self *StateObject) GetState(k []byte) *common.Value {
- key := common.LeftPadBytes(k, 32)
-
- value := self.storage[string(key)]
+func (self *StateObject) GetState(key common.Hash) *common.Value {
+ strkey := key.Str()
+ value := self.storage[strkey]
if value == nil {
value = self.getAddr(key)
if !value.IsNil() {
- self.storage[string(key)] = value
+ self.storage[strkey] = value
}
}
return value
}
-func (self *StateObject) SetState(k []byte, value *common.Value) {
- key := common.LeftPadBytes(k, 32)
- self.storage[string(key)] = value.Copy()
+func (self *StateObject) SetState(k common.Hash, value *common.Value) {
+ self.storage[k.Str()] = value.Copy()
self.dirty = true
}
@@ -284,7 +282,7 @@ func (c *StateObject) N() *big.Int {
}
// Returns the address of the contract/account
-func (c *StateObject) Address() []byte {
+func (c *StateObject) Address() common.Address {
return c.address
}
@@ -341,7 +339,7 @@ func (c *StateObject) RlpDecode(data []byte) {
decoder := common.NewValueFromBytes(data)
c.nonce = decoder.Get(0).Uint()
c.balance = decoder.Get(1).BigInt()
- c.State = New(decoder.Get(2).Bytes(), c.db) //New(trie.New(common.Config.Db, decoder.Get(2).Interface()))
+ c.State = New(common.BytesToHash(decoder.Get(2).Bytes()), c.db) //New(trie.New(common.Config.Db, decoder.Get(2).Interface()))
c.storage = make(map[string]*common.Value)
c.gasPool = new(big.Int)
diff --git a/state/state_test.go b/state/state_test.go
index 3a1ea225d..b6e22f891 100644
--- a/state/state_test.go
+++ b/state/state_test.go
@@ -17,15 +17,16 @@ type StateSuite struct {
var _ = checker.Suite(&StateSuite{})
-// var ZeroHash256 = make([]byte, 32)
+var toAddr = common.BytesToAddress
func (s *StateSuite) TestDump(c *checker.C) {
+ return
// generate a few entries
- obj1 := s.state.GetOrNewStateObject([]byte{0x01})
+ obj1 := s.state.GetOrNewStateObject(toAddr([]byte{0x01}))
obj1.AddBalance(big.NewInt(22))
- obj2 := s.state.GetOrNewStateObject([]byte{0x01, 0x02})
+ obj2 := s.state.GetOrNewStateObject(toAddr([]byte{0x01, 0x02}))
obj2.SetCode([]byte{3, 3, 3, 3, 3, 3, 3})
- obj3 := s.state.GetOrNewStateObject([]byte{0x02})
+ obj3 := s.state.GetOrNewStateObject(toAddr([]byte{0x02}))
obj3.SetBalance(big.NewInt(44))
// write some of them to the trie
@@ -80,7 +81,7 @@ func TestNull(t *testing.T) {
}
func (s *StateSuite) TestSnapshot(c *checker.C) {
- stateobjaddr := []byte("aa")
+ stateobjaddr := toAddr([]byte("aa"))
storageaddr := common.Big("0")
data1 := common.NewValue(42)
data2 := common.NewValue(43)
diff --git a/state/statedb.go b/state/statedb.go
index d01b6056d..6fcd39dbc 100644
--- a/state/statedb.go
+++ b/state/statedb.go
@@ -28,8 +28,8 @@ type StateDB struct {
}
// Create a new state from a given trie
-func New(root []byte, db common.Database) *StateDB {
- trie := trie.NewSecure(common.CopyBytes(root), db)
+func New(root common.Hash, db common.Database) *StateDB {
+ trie := trie.NewSecure(root[:], db)
return &StateDB{db: db, trie: trie, stateObjects: make(map[string]*StateObject), refund: make(map[string]*big.Int)}
}
@@ -49,15 +49,16 @@ func (self *StateDB) Logs() Logs {
return self.logs
}
-func (self *StateDB) Refund(addr []byte, gas *big.Int) {
- if self.refund[string(addr)] == nil {
- self.refund[string(addr)] = new(big.Int)
+func (self *StateDB) Refund(address common.Address, gas *big.Int) {
+ addr := address.Str()
+ if self.refund[addr] == nil {
+ self.refund[addr] = new(big.Int)
}
- self.refund[string(addr)].Add(self.refund[string(addr)], gas)
+ self.refund[addr].Add(self.refund[addr], gas)
}
// Retrieve the balance from the given address or 0 if object not found
-func (self *StateDB) GetBalance(addr []byte) *big.Int {
+func (self *StateDB) GetBalance(addr common.Address) *big.Int {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
return stateObject.balance
@@ -66,14 +67,14 @@ func (self *StateDB) GetBalance(addr []byte) *big.Int {
return common.Big0
}
-func (self *StateDB) AddBalance(addr []byte, amount *big.Int) {
+func (self *StateDB) AddBalance(addr common.Address, amount *big.Int) {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
stateObject.AddBalance(amount)
}
}
-func (self *StateDB) GetNonce(addr []byte) uint64 {
+func (self *StateDB) GetNonce(addr common.Address) uint64 {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
return stateObject.nonce
@@ -82,7 +83,7 @@ func (self *StateDB) GetNonce(addr []byte) uint64 {
return 0
}
-func (self *StateDB) GetCode(addr []byte) []byte {
+func (self *StateDB) GetCode(addr common.Address) []byte {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
return stateObject.code
@@ -91,7 +92,7 @@ func (self *StateDB) GetCode(addr []byte) []byte {
return nil
}
-func (self *StateDB) GetState(a, b []byte) []byte {
+func (self *StateDB) GetState(a common.Address, b common.Hash) []byte {
stateObject := self.GetStateObject(a)
if stateObject != nil {
return stateObject.GetState(b).Bytes()
@@ -100,28 +101,28 @@ func (self *StateDB) GetState(a, b []byte) []byte {
return nil
}
-func (self *StateDB) SetNonce(addr []byte, nonce uint64) {
+func (self *StateDB) SetNonce(addr common.Address, nonce uint64) {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
stateObject.SetNonce(nonce)
}
}
-func (self *StateDB) SetCode(addr, code []byte) {
+func (self *StateDB) SetCode(addr common.Address, code []byte) {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
stateObject.SetCode(code)
}
}
-func (self *StateDB) SetState(addr, key []byte, value interface{}) {
+func (self *StateDB) SetState(addr common.Address, key common.Hash, value interface{}) {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
stateObject.SetState(key, common.NewValue(value))
}
}
-func (self *StateDB) Delete(addr []byte) bool {
+func (self *StateDB) Delete(addr common.Address) bool {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
stateObject.MarkForDeletion()
@@ -133,7 +134,7 @@ func (self *StateDB) Delete(addr []byte) bool {
return false
}
-func (self *StateDB) IsDeleted(addr []byte) bool {
+func (self *StateDB) IsDeleted(addr common.Address) bool {
stateObject := self.GetStateObject(addr)
if stateObject != nil {
return stateObject.remove
@@ -147,32 +148,34 @@ func (self *StateDB) IsDeleted(addr []byte) bool {
// Update the given state object and apply it to state trie
func (self *StateDB) UpdateStateObject(stateObject *StateObject) {
- addr := stateObject.Address()
+ //addr := stateObject.Address()
if len(stateObject.CodeHash()) > 0 {
self.db.Put(stateObject.CodeHash(), stateObject.code)
}
- self.trie.Update(addr, stateObject.RlpEncode())
+ addr := stateObject.Address()
+ self.trie.Update(addr[:], stateObject.RlpEncode())
}
// Delete the given state object and delete it from the state trie
func (self *StateDB) DeleteStateObject(stateObject *StateObject) {
- self.trie.Delete(stateObject.Address())
+ addr := stateObject.Address()
+ self.trie.Delete(addr[:])
- delete(self.stateObjects, string(stateObject.Address()))
+ delete(self.stateObjects, addr.Str())
}
// Retrieve a state object given my the address. Nil if not found
-func (self *StateDB) GetStateObject(addr []byte) *StateObject {
- addr = common.Address(addr)
+func (self *StateDB) GetStateObject(addr common.Address) *StateObject {
+ //addr = common.Address(addr)
- stateObject := self.stateObjects[string(addr)]
+ stateObject := self.stateObjects[addr.Str()]
if stateObject != nil {
return stateObject
}
- data := self.trie.Get(addr)
+ data := self.trie.Get(addr[:])
if len(data) == 0 {
return nil
}
@@ -184,11 +187,11 @@ func (self *StateDB) GetStateObject(addr []byte) *StateObject {
}
func (self *StateDB) SetStateObject(object *StateObject) {
- self.stateObjects[string(object.address)] = object
+ self.stateObjects[object.Address().Str()] = object
}
// Retrieve a state object or create a new state object if nil
-func (self *StateDB) GetOrNewStateObject(addr []byte) *StateObject {
+func (self *StateDB) GetOrNewStateObject(addr common.Address) *StateObject {
stateObject := self.GetStateObject(addr)
if stateObject == nil {
stateObject = self.NewStateObject(addr)
@@ -198,19 +201,19 @@ func (self *StateDB) GetOrNewStateObject(addr []byte) *StateObject {
}
// Create a state object whether it exist in the trie or not
-func (self *StateDB) NewStateObject(addr []byte) *StateObject {
- addr = common.Address(addr)
+func (self *StateDB) NewStateObject(addr common.Address) *StateObject {
+ //addr = common.Address(addr)
statelogger.Debugf("(+) %x\n", addr)
stateObject := NewStateObject(addr, self.db)
- self.stateObjects[string(addr)] = stateObject
+ self.stateObjects[addr.Str()] = stateObject
return stateObject
}
// Deprecated
-func (self *StateDB) GetAccount(addr []byte) *StateObject {
+func (self *StateDB) GetAccount(addr common.Address) *StateObject {
return self.GetOrNewStateObject(addr)
}
@@ -223,7 +226,7 @@ func (s *StateDB) Cmp(other *StateDB) bool {
}
func (self *StateDB) Copy() *StateDB {
- state := New(nil, self.db)
+ state := New(common.Hash{}, self.db)
state.trie = self.trie.Copy()
for k, stateObject := range self.stateObjects {
state.stateObjects[k] = stateObject.Copy()
@@ -248,8 +251,8 @@ func (self *StateDB) Set(state *StateDB) {
self.logs = state.logs
}
-func (s *StateDB) Root() []byte {
- return s.trie.Root()
+func (s *StateDB) Root() common.Hash {
+ return common.BytesToHash(s.trie.Root())
}
func (s *StateDB) Trie() *trie.SecureTrie {
diff --git a/tests/blocktest.go b/tests/blocktest.go
index 0b923f08b..44b459c8d 100644
--- a/tests/blocktest.go
+++ b/tests/blocktest.go
@@ -12,8 +12,8 @@ import (
"strconv"
"strings"
- "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/state"
)
@@ -98,15 +98,15 @@ func LoadBlockTests(file string) (map[string]*BlockTest, error) {
// InsertPreState populates the given database with the genesis
// accounts defined by the test.
func (t *BlockTest) InsertPreState(db common.Database) error {
- statedb := state.New(nil, db)
+ statedb := state.New(common.Hash{}, db)
for addrString, acct := range t.preAccounts {
// XXX: is is worth it checking for errors here?
- addr, _ := hex.DecodeString(addrString)
+ //addr, _ := hex.DecodeString(addrString)
code, _ := hex.DecodeString(strings.TrimPrefix(acct.Code, "0x"))
balance, _ := new(big.Int).SetString(acct.Balance, 0)
nonce, _ := strconv.ParseUint(acct.Nonce, 16, 64)
- obj := statedb.NewStateObject(addr)
+ obj := statedb.NewStateObject(common.HexToAddress(addrString))
obj.SetCode(code)
obj.SetBalance(balance)
obj.SetNonce(nonce)
@@ -119,7 +119,7 @@ func (t *BlockTest) InsertPreState(db common.Database) error {
// sync trie to disk
statedb.Sync()
- if !bytes.Equal(t.Genesis.Root(), statedb.Root()) {
+ if t.Genesis.Root() != statedb.Root() {
return errors.New("computed state root does not match genesis block")
}
return nil
@@ -153,23 +153,25 @@ func mustConvertGenesis(testGenesis btHeader) *types.Block {
func mustConvertHeader(in btHeader) *types.Header {
// hex decode these fields
- return &types.Header{
+ header := &types.Header{
//SeedHash: mustConvertBytes(in.SeedHash),
- MixDigest: mustConvertBytes(in.MixHash),
- Bloom: mustConvertBytes(in.Bloom),
- ReceiptHash: mustConvertBytes(in.ReceiptTrie),
- TxHash: mustConvertBytes(in.TransactionsTrie),
- Root: mustConvertBytes(in.StateRoot),
- Coinbase: mustConvertBytes(in.Coinbase),
- UncleHash: mustConvertBytes(in.UncleHash),
- ParentHash: mustConvertBytes(in.ParentHash),
- Nonce: mustConvertBytes(in.Nonce),
+ MixDigest: mustConvertHash(in.MixHash),
+ Bloom: mustConvertBloom(in.Bloom),
+ ReceiptHash: mustConvertHash(in.ReceiptTrie),
+ TxHash: mustConvertHash(in.TransactionsTrie),
+ Root: mustConvertHash(in.StateRoot),
+ Coinbase: mustConvertAddress(in.Coinbase),
+ UncleHash: mustConvertHash(in.UncleHash),
+ ParentHash: mustConvertHash(in.ParentHash),
Extra: string(mustConvertBytes(in.ExtraData)),
GasUsed: mustConvertBigInt10(in.GasUsed),
GasLimit: mustConvertBigInt10(in.GasLimit),
Difficulty: mustConvertBigInt10(in.Difficulty),
Time: mustConvertUint(in.Timestamp),
}
+ // XXX cheats? :-)
+ header.SetNonce(common.BytesToHash(mustConvertBytes(in.Nonce)).Big().Uint64())
+ return header
}
func mustConvertBlocks(testBlocks []btBlock) []*types.Block {
@@ -193,6 +195,30 @@ func mustConvertBytes(in string) []byte {
return out
}
+func mustConvertHash(in string) common.Hash {
+ out, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
+ if err != nil {
+ panic(fmt.Errorf("invalid hex: %q", in))
+ }
+ return common.BytesToHash(out)
+}
+
+func mustConvertAddress(in string) common.Address {
+ out, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
+ if err != nil {
+ panic(fmt.Errorf("invalid hex: %q", in))
+ }
+ return common.BytesToAddress(out)
+}
+
+func mustConvertBloom(in string) types.Bloom {
+ out, err := hex.DecodeString(strings.TrimPrefix(in, "0x"))
+ if err != nil {
+ panic(fmt.Errorf("invalid hex: %q", in))
+ }
+ return types.BytesToBloom(out)
+}
+
func mustConvertBigInt10(in string) *big.Int {
out, ok := new(big.Int).SetString(in, 10)
if !ok {
diff --git a/tests/helper/vm.go b/tests/helper/vm.go
index a7fd98696..44c108870 100644
--- a/tests/helper/vm.go
+++ b/tests/helper/vm.go
@@ -4,9 +4,9 @@ import (
"errors"
"math/big"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core"
"github.com/ethereum/go-ethereum/crypto"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/vm"
)
@@ -18,9 +18,9 @@ type Env struct {
initial bool
Gas *big.Int
- origin []byte
- parent []byte
- coinbase []byte
+ origin common.Address
+ //parent common.Hash
+ coinbase common.Address
number *big.Int
time int64
@@ -41,9 +41,9 @@ func NewEnv(state *state.StateDB) *Env {
func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues map[string]string) *Env {
env := NewEnv(state)
- env.origin = common.Hex2Bytes(exeValues["caller"])
- env.parent = common.Hex2Bytes(envValues["previousHash"])
- env.coinbase = common.Hex2Bytes(envValues["currentCoinbase"])
+ env.origin = common.HexToAddress(exeValues["caller"])
+ //env.parent = common.Hex2Bytes(envValues["previousHash"])
+ env.coinbase = common.HexToAddress(envValues["currentCoinbase"])
env.number = common.Big(envValues["currentNumber"])
env.time = common.Big(envValues["currentTimestamp"]).Int64()
env.difficulty = common.Big(envValues["currentDifficulty"])
@@ -53,17 +53,18 @@ func NewEnvFromMap(state *state.StateDB, envValues map[string]string, exeValues
return env
}
-func (self *Env) Origin() []byte { return self.origin }
-func (self *Env) BlockNumber() *big.Int { return self.number }
-func (self *Env) PrevHash() []byte { return self.parent }
-func (self *Env) Coinbase() []byte { return self.coinbase }
-func (self *Env) Time() int64 { return self.time }
-func (self *Env) Difficulty() *big.Int { return self.difficulty }
-func (self *Env) State() *state.StateDB { return self.state }
-func (self *Env) GasLimit() *big.Int { return self.gasLimit }
-func (self *Env) VmType() vm.Type { return vm.StdVmTy }
-func (self *Env) GetHash(n uint64) []byte {
- return crypto.Sha3([]byte(big.NewInt(int64(n)).String()))
+func (self *Env) Origin() common.Address { return self.origin }
+func (self *Env) BlockNumber() *big.Int { return self.number }
+
+//func (self *Env) PrevHash() []byte { return self.parent }
+func (self *Env) Coinbase() common.Address { return self.coinbase }
+func (self *Env) Time() int64 { return self.time }
+func (self *Env) Difficulty() *big.Int { return self.difficulty }
+func (self *Env) State() *state.StateDB { return self.state }
+func (self *Env) GasLimit() *big.Int { return self.gasLimit }
+func (self *Env) VmType() vm.Type { return vm.StdVmTy }
+func (self *Env) GetHash(n uint64) common.Hash {
+ return common.BytesToHash(crypto.Sha3([]byte(big.NewInt(int64(n)).String())))
}
func (self *Env) AddLog(log state.Log) {
self.logs = append(self.logs, log)
@@ -87,36 +88,38 @@ func (self *Env) Transfer(from, to vm.Account, amount *big.Int) error {
return vm.Transfer(from, to, amount)
}
-func (self *Env) vm(addr, data []byte, gas, price, value *big.Int) *core.Execution {
+func (self *Env) vm(addr *common.Address, data []byte, gas, price, value *big.Int) *core.Execution {
exec := core.NewExecution(self, addr, data, gas, price, value)
return exec
}
-func (self *Env) Call(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) {
+func (self *Env) Call(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
if self.vmTest && self.depth > 0 {
caller.ReturnGas(gas, price)
return nil, nil
}
- exe := self.vm(addr, data, gas, price, value)
+ exe := self.vm(&addr, data, gas, price, value)
ret, err := exe.Call(addr, caller)
self.Gas = exe.Gas
return ret, err
}
-func (self *Env) CallCode(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error) {
+func (self *Env) CallCode(caller vm.ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error) {
if self.vmTest && self.depth > 0 {
caller.ReturnGas(gas, price)
return nil, nil
}
- exe := self.vm(caller.Address(), data, gas, price, value)
+
+ caddr := caller.Address()
+ exe := self.vm(&caddr, data, gas, price, value)
return exe.Call(addr, caller)
}
-func (self *Env) Create(caller vm.ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) {
+func (self *Env) Create(caller vm.ContextRef, addr *common.Address, data []byte, gas, price, value *big.Int) ([]byte, error, vm.ContextRef) {
exe := self.vm(addr, data, gas, price, value)
if self.vmTest {
caller.ReturnGas(gas, price)
@@ -132,8 +135,8 @@ func (self *Env) Create(caller vm.ContextRef, addr, data []byte, gas, price, val
func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Logs, *big.Int, error) {
var (
- to = FromHex(exec["address"])
- from = FromHex(exec["caller"])
+ to = common.HexToAddress(exec["address"])
+ from = common.HexToAddress(exec["caller"])
data = FromHex(exec["data"])
gas = common.Big(exec["gas"])
price = common.Big(exec["gasPrice"])
@@ -156,14 +159,18 @@ func RunVm(state *state.StateDB, env, exec map[string]string) ([]byte, state.Log
func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.Logs, *big.Int, error) {
var (
keyPair, _ = crypto.NewKeyPairFromSec([]byte(common.Hex2Bytes(tx["secretKey"])))
- to = FromHex(tx["to"])
data = FromHex(tx["data"])
gas = common.Big(tx["gasLimit"])
price = common.Big(tx["gasPrice"])
value = common.Big(tx["value"])
- caddr = FromHex(env["currentCoinbase"])
+ caddr = common.HexToAddress(env["currentCoinbase"])
)
+ var to *common.Address
+ if len(tx["to"]) > 2 {
+ t := common.HexToAddress(tx["to"])
+ to = &t
+ }
// Set pre compiled contracts
vm.Precompiled = vm.PrecompiledContracts()
@@ -171,9 +178,9 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.
coinbase := statedb.GetOrNewStateObject(caddr)
coinbase.SetGasPool(common.Big(env["currentGasLimit"]))
- message := NewMessage(keyPair.Address(), to, data, value, gas, price)
+ message := NewMessage(common.BytesToAddress(keyPair.Address()), to, data, value, gas, price)
vmenv := NewEnvFromMap(statedb, env, tx)
- vmenv.origin = keyPair.Address()
+ vmenv.origin = common.BytesToAddress(keyPair.Address())
ret, _, err := core.ApplyMessage(vmenv, message, coinbase)
if core.IsNonceErr(err) || core.IsInvalidTxErr(err) {
statedb.Set(snapshot)
@@ -184,20 +191,21 @@ func RunState(statedb *state.StateDB, env, tx map[string]string) ([]byte, state.
}
type Message struct {
- from, to []byte
+ from common.Address
+ to *common.Address
value, gas, price *big.Int
data []byte
}
-func NewMessage(from, to, data []byte, value, gas, price *big.Int) Message {
+func NewMessage(from common.Address, to *common.Address, data []byte, value, gas, price *big.Int) Message {
return Message{from, to, value, gas, price, data}
}
-func (self Message) Hash() []byte { return nil }
-func (self Message) From() []byte { return self.from }
-func (self Message) To() []byte { return self.to }
-func (self Message) GasPrice() *big.Int { return self.price }
-func (self Message) Gas() *big.Int { return self.gas }
-func (self Message) Value() *big.Int { return self.value }
-func (self Message) Nonce() uint64 { return 0 }
-func (self Message) Data() []byte { return self.data }
+func (self Message) Hash() []byte { return nil }
+func (self Message) From() (common.Address, error) { return self.from, nil }
+func (self Message) To() *common.Address { return self.to }
+func (self Message) GasPrice() *big.Int { return self.price }
+func (self Message) Gas() *big.Int { return self.gas }
+func (self Message) Value() *big.Int { return self.value }
+func (self Message) Nonce() uint64 { return 0 }
+func (self Message) Data() []byte { return self.data }
diff --git a/tests/vm/gh_test.go b/tests/vm/gh_test.go
index 24718de7b..68600d304 100644
--- a/tests/vm/gh_test.go
+++ b/tests/vm/gh_test.go
@@ -6,8 +6,9 @@ import (
"strconv"
"testing"
- "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/core/types"
+ "github.com/ethereum/go-ethereum/ethdb"
"github.com/ethereum/go-ethereum/logger"
"github.com/ethereum/go-ethereum/state"
"github.com/ethereum/go-ethereum/tests/helper"
@@ -39,7 +40,7 @@ func (self Log) Topics() [][]byte {
}
func StateObjectFromAccount(db common.Database, addr string, account Account) *state.StateObject {
- obj := state.NewStateObject(common.Hex2Bytes(addr), db)
+ obj := state.NewStateObject(common.HexToAddress(addr), db)
obj.SetBalance(common.Big(account.Balance))
if common.IsHex(account.Code) {
@@ -81,12 +82,12 @@ func RunVmTest(p string, t *testing.T) {
for name, test := range tests {
db, _ := ethdb.NewMemDatabase()
- statedb := state.New(nil, db)
+ statedb := state.New(common.Hash{}, db)
for addr, account := range test.Pre {
obj := StateObjectFromAccount(db, addr, account)
statedb.SetStateObject(obj)
for a, v := range account.Storage {
- obj.SetState(helper.FromHex(a), common.NewValue(helper.FromHex(v)))
+ obj.SetState(common.HexToHash(a), common.NewValue(helper.FromHex(v)))
}
}
@@ -134,30 +135,31 @@ func RunVmTest(p string, t *testing.T) {
}
for addr, account := range test.Post {
- obj := statedb.GetStateObject(helper.FromHex(addr))
+ obj := statedb.GetStateObject(common.HexToAddress(addr))
if obj == nil {
continue
}
if len(test.Exec) == 0 {
if obj.Balance().Cmp(common.Big(account.Balance)) != 0 {
- t.Errorf("%s's : (%x) balance failed. Expected %v, got %v => %v\n", name, obj.Address()[:4], account.Balance, obj.Balance(), new(big.Int).Sub(common.Big(account.Balance), obj.Balance()))
+ t.Errorf("%s's : (%x) balance failed. Expected %v, got %v => %v\n", name, obj.Address().Bytes()[:4], account.Balance, obj.Balance(), new(big.Int).Sub(common.Big(account.Balance), obj.Balance()))
}
}
for addr, value := range account.Storage {
- v := obj.GetState(helper.FromHex(addr)).Bytes()
+ v := obj.GetState(common.HexToHash(addr)).Bytes()
vexp := helper.FromHex(value)
if bytes.Compare(v, vexp) != 0 {
- t.Errorf("%s's : (%x: %s) storage failed. Expected %x, got %x (%v %v)\n", name, obj.Address()[0:4], addr, vexp, v, common.BigD(vexp), common.BigD(v))
+ t.Errorf("%s's : (%x: %s) storage failed. Expected %x, got %x (%v %v)\n", name, obj.Address().Bytes()[0:4], addr, vexp, v, common.BigD(vexp), common.BigD(v))
}
}
}
if !isVmTest {
statedb.Sync()
- if !bytes.Equal(common.Hex2Bytes(test.PostStateRoot), statedb.Root()) {
+ //if !bytes.Equal(common.Hex2Bytes(test.PostStateRoot), statedb.Root()) {
+ if common.HexToHash(test.PostStateRoot) != statedb.Root() {
t.Errorf("%s's : Post state root error. Expected %s, got %x", name, test.PostStateRoot, statedb.Root())
}
}
@@ -166,16 +168,30 @@ func RunVmTest(p string, t *testing.T) {
if len(test.Logs) != len(logs) {
t.Errorf("log length mismatch. Expected %d, got %d", len(test.Logs), len(logs))
} else {
- /*
- fmt.Println("A", test.Logs)
- fmt.Println("B", logs)
- for i, log := range test.Logs {
- genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256)
- if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) {
- t.Errorf("bloom mismatch")
+ for i, log := range test.Logs {
+ if common.HexToAddress(log.AddressF) != logs[i].Address() {
+ t.Errorf("'%s' log address expected %v got %x", name, log.AddressF, logs[i].Address())
+ }
+
+ if !bytes.Equal(logs[i].Data(), helper.FromHex(log.DataF)) {
+ t.Errorf("'%s' log data expected %v got %x", name, log.DataF, logs[i].Data())
+ }
+
+ if len(log.TopicsF) != len(logs[i].Topics()) {
+ t.Errorf("'%s' log topics length expected %d got %d", name, len(log.TopicsF), logs[i].Topics())
+ } else {
+ for j, topic := range log.TopicsF {
+ if common.HexToHash(topic) != logs[i].Topics()[j] {
+ t.Errorf("'%s' log topic[%d] expected %v got %x", name, j, topic, logs[i].Topics()[j])
}
}
- */
+ }
+ genBloom := common.LeftPadBytes(types.LogsBloom(state.Logs{logs[i]}).Bytes(), 256)
+
+ if !bytes.Equal(genBloom, common.Hex2Bytes(log.BloomF)) {
+ t.Errorf("'%s' bloom mismatch", name)
+ }
+ }
}
}
//statedb.Trie().PrintRoot()
diff --git a/vm/common.go b/vm/common.go
index 90c3361de..5441a4ac5 100644
--- a/vm/common.go
+++ b/vm/common.go
@@ -18,8 +18,23 @@ type Type byte
const (
StdVmTy Type = iota
JitVmTy
-
MaxVmTy
+
+ MaxCallDepth = 1025
+
+ LogTyPretty byte = 0x1
+ LogTyDiff byte = 0x2
+)
+
+var (
+ Pow256 = common.BigPow(2, 256)
+
+ U256 = common.U256
+ S256 = common.S256
+
+ Zero = common.Big0
+
+ max = big.NewInt(math.MaxInt64)
)
func NewVm(env Environment) VirtualMachine {
@@ -34,67 +49,6 @@ func NewVm(env Environment) VirtualMachine {
}
}
-var (
- GasQuickStep = big.NewInt(2)
- GasFastestStep = big.NewInt(3)
- GasFastStep = big.NewInt(5)
- GasMidStep = big.NewInt(8)
- GasSlowStep = big.NewInt(10)
- GasExtStep = big.NewInt(20)
-
- GasStorageGet = big.NewInt(50)
- GasStorageAdd = big.NewInt(20000)
- GasStorageMod = big.NewInt(5000)
- GasLogBase = big.NewInt(375)
- GasLogTopic = big.NewInt(375)
- GasLogByte = big.NewInt(8)
- GasCreate = big.NewInt(32000)
- GasCreateByte = big.NewInt(200)
- GasCall = big.NewInt(40)
- GasCallValueTransfer = big.NewInt(9000)
- GasStipend = big.NewInt(2300)
- GasCallNewAccount = big.NewInt(25000)
- GasReturn = big.NewInt(0)
- GasStop = big.NewInt(0)
- GasJumpDest = big.NewInt(1)
-
- RefundStorage = big.NewInt(15000)
- RefundSuicide = big.NewInt(24000)
-
- GasMemWord = big.NewInt(3)
- GasQuadCoeffDenom = big.NewInt(512)
- GasContractByte = big.NewInt(200)
- GasTransaction = big.NewInt(21000)
- GasTxDataNonzeroByte = big.NewInt(68)
- GasTxDataZeroByte = big.NewInt(4)
- GasTx = big.NewInt(21000)
- GasExp = big.NewInt(10)
- GasExpByte = big.NewInt(10)
-
- GasSha3Base = big.NewInt(30)
- GasSha3Word = big.NewInt(6)
- GasSha256Base = big.NewInt(60)
- GasSha256Word = big.NewInt(12)
- GasRipemdBase = big.NewInt(600)
- GasRipemdWord = big.NewInt(12)
- GasEcrecover = big.NewInt(3000)
- GasIdentityBase = big.NewInt(15)
- GasIdentityWord = big.NewInt(3)
- GasCopyWord = big.NewInt(3)
-
- Pow256 = common.BigPow(2, 256)
-
- LogTyPretty byte = 0x1
- LogTyDiff byte = 0x2
-
- U256 = common.U256
- S256 = common.S256
-
- Zero = common.Big0
-)
-
-const MaxCallDepth = 1025
-
func calcMemSize(off, l *big.Int) *big.Int {
if l.Cmp(common.Big0) == 0 {
return common.Big0
diff --git a/vm/context.go b/vm/context.go
index 1c2f665a4..ea70f2376 100644
--- a/vm/context.go
+++ b/vm/context.go
@@ -9,7 +9,7 @@ import (
type ContextRef interface {
ReturnGas(*big.Int, *big.Int)
- Address() []byte
+ Address() common.Address
SetCode([]byte)
}
@@ -18,7 +18,7 @@ type Context struct {
self ContextRef
Code []byte
- CodeAddr []byte
+ CodeAddr *common.Address
value, Gas, UsedGas, Price *big.Int
@@ -100,7 +100,7 @@ func (c *Context) ReturnGas(gas, price *big.Int) {
/*
* Set / Get
*/
-func (c *Context) Address() []byte {
+func (c *Context) Address() common.Address {
return c.self.Address()
}
@@ -108,7 +108,7 @@ func (self *Context) SetCode(code []byte) {
self.Code = code
}
-func (self *Context) SetCallCode(addr, code []byte) {
+func (self *Context) SetCallCode(addr *common.Address, code []byte) {
self.Code = code
self.CodeAddr = addr
}
diff --git a/vm/environment.go b/vm/environment.go
index 83faaa23e..5d493166c 100644
--- a/vm/environment.go
+++ b/vm/environment.go
@@ -3,19 +3,21 @@ package vm
import (
"errors"
"fmt"
+ "io"
"math/big"
"github.com/ethereum/go-ethereum/common"
+ "github.com/ethereum/go-ethereum/rlp"
"github.com/ethereum/go-ethereum/state"
)
type Environment interface {
State() *state.StateDB
- Origin() []byte
+ Origin() common.Address
BlockNumber() *big.Int
- GetHash(n uint64) []byte
- Coinbase() []byte
+ GetHash(n uint64) common.Hash
+ Coinbase() common.Address
Time() int64
Difficulty() *big.Int
GasLimit() *big.Int
@@ -27,16 +29,16 @@ type Environment interface {
Depth() int
SetDepth(i int)
- Call(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error)
- CallCode(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error)
- Create(me ContextRef, addr, data []byte, gas, price, value *big.Int) ([]byte, error, ContextRef)
+ Call(me ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error)
+ CallCode(me ContextRef, addr common.Address, data []byte, gas, price, value *big.Int) ([]byte, error)
+ Create(me ContextRef, addr *common.Address, data []byte, gas, price, value *big.Int) ([]byte, error, ContextRef)
}
type Account interface {
SubBalance(amount *big.Int)
AddBalance(amount *big.Int)
Balance() *big.Int
- Address() []byte
+ Address() common.Address
}
// generic transfer method
@@ -53,17 +55,17 @@ func Transfer(from, to Account, amount *big.Int) error {
}
type Log struct {
- address []byte
- topics [][]byte
+ address common.Address
+ topics []common.Hash
data []byte
log uint64
}
-func (self *Log) Address() []byte {
+func (self *Log) Address() common.Address {
return self.address
}
-func (self *Log) Topics() [][]byte {
+func (self *Log) Topics() []common.Hash {
return self.topics
}
@@ -75,10 +77,16 @@ func (self *Log) Number() uint64 {
return self.log
}
+func (self *Log) EncodeRLP(w io.Writer) error {
+ return rlp.Encode(w, []interface{}{self.address, self.topics, self.data})
+}
+
+/*
func (self *Log) RlpData() interface{} {
return []interface{}{self.address, common.ByteSliceToInterface(self.topics), self.data}
}
+*/
func (self *Log) String() string {
- return fmt.Sprintf("[A=%x T=%x D=%x]", self.address, self.topics, self.data)
+ return fmt.Sprintf("{%x %x %x}", self.address, self.data, self.topics)
}
diff --git a/vm/gas.go b/vm/gas.go
index a19afeb67..c4d5e4c4e 100644
--- a/vm/gas.go
+++ b/vm/gas.go
@@ -7,6 +7,55 @@ type req struct {
gas *big.Int
}
+var (
+ GasQuickStep = big.NewInt(2)
+ GasFastestStep = big.NewInt(3)
+ GasFastStep = big.NewInt(5)
+ GasMidStep = big.NewInt(8)
+ GasSlowStep = big.NewInt(10)
+ GasExtStep = big.NewInt(20)
+
+ GasStorageGet = big.NewInt(50)
+ GasStorageAdd = big.NewInt(20000)
+ GasStorageMod = big.NewInt(5000)
+ GasLogBase = big.NewInt(375)
+ GasLogTopic = big.NewInt(375)
+ GasLogByte = big.NewInt(8)
+ GasCreate = big.NewInt(32000)
+ GasCreateByte = big.NewInt(200)
+ GasCall = big.NewInt(40)
+ GasCallValueTransfer = big.NewInt(9000)
+ GasStipend = big.NewInt(2300)
+ GasCallNewAccount = big.NewInt(25000)
+ GasReturn = big.NewInt(0)
+ GasStop = big.NewInt(0)
+ GasJumpDest = big.NewInt(1)
+
+ RefundStorage = big.NewInt(15000)
+ RefundSuicide = big.NewInt(24000)
+
+ GasMemWord = big.NewInt(3)
+ GasQuadCoeffDenom = big.NewInt(512)
+ GasContractByte = big.NewInt(200)
+ GasTransaction = big.NewInt(21000)
+ GasTxDataNonzeroByte = big.NewInt(68)
+ GasTxDataZeroByte = big.NewInt(4)
+ GasTx = big.NewInt(21000)
+ GasExp = big.NewInt(10)
+ GasExpByte = big.NewInt(10)
+
+ GasSha3Base = big.NewInt(30)
+ GasSha3Word = big.NewInt(6)
+ GasSha256Base = big.NewInt(60)
+ GasSha256Word = big.NewInt(12)
+ GasRipemdBase = big.NewInt(600)
+ GasRipemdWord = big.NewInt(12)
+ GasEcrecover = big.NewInt(3000)
+ GasIdentityBase = big.NewInt(15)
+ GasIdentityWord = big.NewInt(3)
+ GasCopyWord = big.NewInt(3)
+)
+
var _baseCheck = map[OpCode]req{
// Req stack Gas price
ADD: {2, GasFastestStep},
diff --git a/vm/vm.go b/vm/vm.go
index 089047a95..123da6b03 100644
--- a/vm/vm.go
+++ b/vm/vm.go
@@ -33,10 +33,7 @@ func New(env Environment) *Vm {
}
func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
- //func (self *Vm) Run(me, caller ContextRef, code []byte, value, gas, price *big.Int, callData []byte) (ret []byte, err error) {
self.env.SetDepth(self.env.Depth() + 1)
-
- //context := NewContext(caller, me, code, gas, price)
var (
caller = context.caller
code = context.Code
@@ -44,7 +41,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
price = context.Price
)
- self.Printf("(%d) (%x) %x (code=%d) gas: %v (d) %x", self.env.Depth(), caller.Address()[:4], context.Address(), len(code), context.Gas, callData).Endl()
+ self.Printf("(%d) (%x) %x (code=%d) gas: %v (d) %x", self.env.Depth(), caller.Address().Bytes()[:4], context.Address(), len(code), context.Gas, callData).Endl()
if self.Recoverable {
// Recover from any require exception
@@ -57,13 +54,14 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
ret = context.Return(nil)
err = fmt.Errorf("%v", r)
-
}
}()
}
- if p := Precompiled[string(context.CodeAddr)]; p != nil {
- return self.RunPrecompiled(p, callData, context)
+ if context.CodeAddr != nil {
+ if p := Precompiled[context.CodeAddr.Str()]; p != nil {
+ return self.RunPrecompiled(p, callData, context)
+ }
}
var (
@@ -394,11 +392,11 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
self.Printf(" => (%v) %x", size, data)
// 0x30 range
case ADDRESS:
- stack.push(common.BigD(context.Address()))
+ stack.push(common.Bytes2Big(context.Address().Bytes()))
self.Printf(" => %x", context.Address())
case BALANCE:
- addr := stack.pop().Bytes()
+ addr := common.BigToAddress(stack.pop())
balance := statedb.GetBalance(addr)
stack.push(balance)
@@ -407,12 +405,12 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
case ORIGIN:
origin := self.env.Origin()
- stack.push(common.BigD(origin))
+ stack.push(origin.Big())
self.Printf(" => %x", origin)
case CALLER:
caller := context.caller.Address()
- stack.push(common.BigD(caller))
+ stack.push(common.Bytes2Big(caller.Bytes()))
self.Printf(" => %x", caller)
case CALLVALUE:
@@ -458,7 +456,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
case CODESIZE, EXTCODESIZE:
var code []byte
if op == EXTCODESIZE {
- addr := stack.pop().Bytes()
+ addr := common.BigToAddress(stack.pop())
code = statedb.GetCode(addr)
} else {
@@ -472,7 +470,8 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
case CODECOPY, EXTCODECOPY:
var code []byte
if op == EXTCODECOPY {
- code = statedb.GetCode(stack.pop().Bytes())
+ addr := common.BigToAddress(stack.pop())
+ code = statedb.GetCode(addr)
} else {
code = context.Code
}
@@ -502,7 +501,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
n := new(big.Int).Sub(self.env.BlockNumber(), common.Big257)
if num.Cmp(n) > 0 && num.Cmp(self.env.BlockNumber()) < 0 {
- stack.push(common.BigD(self.env.GetHash(num.Uint64())))
+ stack.push(self.env.GetHash(num.Uint64()).Big())
} else {
stack.push(common.Big0)
}
@@ -511,7 +510,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
case COINBASE:
coinbase := self.env.Coinbase()
- stack.push(common.BigD(coinbase))
+ stack.push(coinbase.Big())
self.Printf(" => 0x%x", coinbase)
case TIMESTAMP:
@@ -562,10 +561,10 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
self.Printf(" => [%d]", n)
case LOG0, LOG1, LOG2, LOG3, LOG4:
n := int(op - LOG0)
- topics := make([][]byte, n)
+ topics := make([]common.Hash, n)
mStart, mSize := stack.pop(), stack.pop()
for i := 0; i < n; i++ {
- topics[i] = common.LeftPadBytes(stack.pop().Bytes(), 32)
+ topics[i] = common.BigToHash(stack.pop()) //common.LeftPadBytes(stack.pop().Bytes(), 32)
}
data := mem.Get(mStart.Int64(), mSize.Int64())
@@ -592,16 +591,18 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
self.Printf(" => [%v] 0x%x", off, val)
case SLOAD:
- loc := stack.pop()
- val := common.BigD(statedb.GetState(context.Address(), loc.Bytes()))
+ loc := common.BigToHash(stack.pop())
+ val := common.Bytes2Big(statedb.GetState(context.Address(), loc))
stack.push(val)
- self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
+ self.Printf(" {0x%x : 0x%x}", loc, val.Bytes())
case SSTORE:
- loc, val := stack.pop(), stack.pop()
- statedb.SetState(context.Address(), loc.Bytes(), val)
+ loc := common.BigToHash(stack.pop())
+ val := stack.pop()
+
+ statedb.SetState(context.Address(), loc, val)
- self.Printf(" {0x%x : 0x%x}", loc.Bytes(), val.Bytes())
+ self.Printf(" {0x%x : 0x%x}", loc, val.Bytes())
case JUMP:
jump(pc, stack.pop())
@@ -634,7 +635,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
offset, size = stack.pop(), stack.pop()
input = mem.Get(offset.Int64(), size.Int64())
gas = new(big.Int).Set(context.Gas)
- addr []byte
+ addr common.Address
)
self.Endl()
@@ -654,7 +655,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
}
addr = ref.Address()
- stack.push(common.BigD(addr))
+ stack.push(addr.Big())
}
@@ -668,7 +669,7 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
// pop return size and offset
retOffset, retSize := stack.pop(), stack.pop()
- address := common.Address(addr.Bytes())
+ address := common.BigToAddress(addr)
self.Printf(" => %x", address).Endl()
// Get the arguments from the memory
@@ -706,10 +707,10 @@ func (self *Vm) Run(context *Context, callData []byte) (ret []byte, err error) {
return context.Return(ret), nil
case SUICIDE:
- receiver := statedb.GetOrNewStateObject(stack.pop().Bytes())
+ receiver := statedb.GetOrNewStateObject(common.BigToAddress(stack.pop()))
balance := statedb.GetBalance(context.Address())
- self.Printf(" => (%x) %v", receiver.Address()[:4], balance)
+ self.Printf(" => (%x) %v", receiver.Address().Bytes()[:4], balance)
receiver.AddBalance(balance)
@@ -769,7 +770,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
var g *big.Int
y, x := stack.data[stack.len()-2], stack.data[stack.len()-1]
- val := statedb.GetState(context.Address(), x.Bytes())
+ val := statedb.GetState(context.Address(), common.BigToHash(x))
if len(val) == 0 && len(y.Bytes()) > 0 {
// 0 => non 0
g = GasStorageAdd
@@ -821,7 +822,7 @@ func (self *Vm) calculateGasAndSize(context *Context, caller ContextRef, op OpCo
gas.Add(gas, stack.data[stack.len()-1])
if op == CALL {
- if self.env.State().GetStateObject(stack.data[stack.len()-2].Bytes()) == nil {
+ if self.env.State().GetStateObject(common.BigToAddress(stack.data[stack.len()-2])) == nil {
gas.Add(gas, GasCallNewAccount)
}
}
diff --git a/whisper/envelope.go b/whisper/envelope.go
index 577638046..9ec9fc318 100644
--- a/whisper/envelope.go
+++ b/whisper/envelope.go
@@ -6,9 +6,9 @@ import (
"fmt"
"time"
+ "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/crypto"
"github.com/ethereum/go-ethereum/crypto/ecies"
- "github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/rlp"
)
diff --git a/whisper/peer.go b/whisper/peer.go
index 4bd9428f5..ee5bffd0b 100644
--- a/whisper/peer.go
+++ b/whisper/peer.go
@@ -77,12 +77,11 @@ func (self *peer) broadcast(envelopes []*Envelope) error {
}
if i > 0 {
- if err := p2p.EncodeMsg(self.ws, envelopesMsg, envs[:i]...); err != nil {
+ if err := p2p.Send(self.ws, envelopesMsg, envs[:i]); err != nil {
return err
}
self.peer.DebugDetailln("broadcasted", i, "message(s)")
}
-
return nil
}
@@ -92,7 +91,7 @@ func (self *peer) addKnown(envelope *Envelope) {
func (self *peer) handleStatus() error {
ws := self.ws
- if err := ws.WriteMsg(self.statusMsg()); err != nil {
+ if err := p2p.SendItems(ws, statusMsg, protocolVersion); err != nil {
return err
}
msg, err := ws.ReadMsg()
@@ -115,7 +114,3 @@ func (self *peer) handleStatus() error {
}
return msg.Discard() // ignore anything after protocol version
}
-
-func (self *peer) statusMsg() p2p.Msg {
- return p2p.NewMsg(statusMsg, protocolVersion)
-}
diff --git a/xeth/state.go b/xeth/state.go
index 7d9ceab1b..f645a9cac 100644
--- a/xeth/state.go
+++ b/xeth/state.go
@@ -19,7 +19,7 @@ func (self *State) State() *state.StateDB {
}
func (self *State) Get(addr string) *Object {
- return &Object{self.state.GetStateObject(common.FromHex(addr))}
+ return &Object{self.state.GetStateObject(common.HexToAddress(addr))}
}
func (self *State) SafeGet(addr string) *Object {
@@ -27,9 +27,9 @@ func (self *State) SafeGet(addr string) *Object {
}
func (self *State) safeGet(addr string) *state.StateObject {
- object := self.state.GetStateObject(common.FromHex(addr))
+ object := self.state.GetStateObject(common.HexToAddress(addr))
if object == nil {
- object = state.NewStateObject(common.FromHex(addr), self.xeth.eth.StateDb())
+ object = state.NewStateObject(common.HexToAddress(addr), self.xeth.eth.StateDb())
}
return object
diff --git a/xeth/types.go b/xeth/types.go
index 6b3b6d29f..b4ba7bab0 100644
--- a/xeth/types.go
+++ b/xeth/types.go
@@ -91,12 +91,12 @@ func NewBlock(block *types.Block) *Block {
return &Block{
ref: block, Size: block.Size().String(),
Number: int(block.NumberU64()), GasUsed: block.GasUsed().String(),
- GasLimit: block.GasLimit().String(), Hash: common.ToHex(block.Hash()),
+ GasLimit: block.GasLimit().String(), Hash: block.Hash().Hex(),
Transactions: txlist, Uncles: ulist,
Time: block.Time(),
- Coinbase: common.ToHex(block.Coinbase()),
- PrevHash: common.ToHex(block.ParentHash()),
- Bloom: common.ToHex(block.Bloom()),
+ Coinbase: block.Coinbase().Hex(),
+ PrevHash: block.ParentHash().Hex(),
+ Bloom: common.ToHex(block.Bloom().Bytes()),
Raw: block.String(),
}
}
@@ -110,7 +110,7 @@ func (self *Block) ToString() string {
}
func (self *Block) GetTransaction(hash string) *Transaction {
- tx := self.ref.Transaction(common.FromHex(hash))
+ tx := self.ref.Transaction(common.HexToHash(hash))
if tx == nil {
return nil
}
@@ -135,12 +135,12 @@ type Transaction struct {
}
func NewTx(tx *types.Transaction) *Transaction {
- hash := common.ToHex(tx.Hash())
- receiver := common.ToHex(tx.To())
+ hash := tx.Hash().Hex()
+ receiver := tx.To().Hex()
if len(receiver) == 0 {
- receiver = common.ToHex(core.AddressFromMessage(tx))
+ receiver = core.AddressFromMessage(tx).Hex()
}
- sender := common.ToHex(tx.From())
+ sender, _ := tx.From()
createsContract := core.MessageCreatesContract(tx)
var data string
@@ -150,7 +150,7 @@ func NewTx(tx *types.Transaction) *Transaction {
data = common.ToHex(tx.Data())
}
- return &Transaction{ref: tx, Hash: hash, Value: common.CurrencyToString(tx.Value()), Address: receiver, Contract: createsContract, Gas: tx.Gas().String(), GasPrice: tx.GasPrice().String(), Data: data, Sender: sender, CreatesContract: createsContract, RawData: common.ToHex(tx.Data())}
+ return &Transaction{ref: tx, Hash: hash, Value: common.CurrencyToString(tx.Value()), Address: receiver, Contract: createsContract, Gas: tx.Gas().String(), GasPrice: tx.GasPrice().String(), Data: data, Sender: sender.Hex(), CreatesContract: createsContract, RawData: common.ToHex(tx.Data())}
}
func (self *Transaction) ToString() string {
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 115bd787a..686ed4432 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -116,14 +116,14 @@ func (self *XEth) State() *State { return self.state }
func (self *XEth) Whisper() *Whisper { return self.whisper }
func (self *XEth) BlockByHash(strHash string) *Block {
- hash := common.FromHex(strHash)
+ hash := common.HexToHash(strHash)
block := self.chainManager.GetBlock(hash)
return NewBlock(block)
}
func (self *XEth) EthBlockByHash(strHash string) *types.Block {
- hash := common.FromHex(strHash)
+ hash := common.HexToHash(strHash)
block := self.chainManager.GetBlock(hash)
return block
@@ -293,9 +293,9 @@ func (self *XEth) PushTx(encodedTx string) (string, error) {
if tx.To() == nil {
addr := core.AddressFromMessage(tx)
- return common.ToHex(addr), nil
+ return addr.Hex(), nil
}
- return common.ToHex(tx.Hash()), nil
+ return tx.Hash().Hex(), nil
}
var (
@@ -306,8 +306,8 @@ var (
func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr string) (string, error) {
statedb := self.State().State() //self.chainManager.TransState()
msg := callmsg{
- from: statedb.GetOrNewStateObject(common.FromHex(fromStr)),
- to: common.FromHex(toStr),
+ from: statedb.GetOrNewStateObject(common.HexToAddress(fromStr)),
+ to: common.HexToAddress(toStr),
gas: common.Big(gasStr),
gasPrice: common.Big(gasPriceStr),
value: common.Big(valueStr),
@@ -330,8 +330,8 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st
func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeStr string) (string, error) {
var (
- from []byte
- to []byte
+ from = common.HexToAddress(fromStr)
+ to = common.HexToAddress(toStr)
value = common.NewValue(valueStr)
gas = common.NewValue(gasStr)
price = common.NewValue(gasPriceStr)
@@ -339,10 +339,8 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt
contractCreation bool
)
- from = common.FromHex(fromStr)
data = common.FromHex(codeStr)
- to = common.FromHex(toStr)
- if len(to) == 0 {
+ if len(toStr) == 0 {
contractCreation = true
}
@@ -368,21 +366,19 @@ func (self *XEth) Transact(fromStr, toStr, valueStr, gasStr, gasPriceStr, codeSt
if contractCreation {
addr := core.AddressFromMessage(tx)
pipelogger.Infof("Contract addr %x\n", addr)
- }
- if types.IsContractAddr(to) {
- return common.ToHex(core.AddressFromMessage(tx)), nil
+ return core.AddressFromMessage(tx).Hex(), nil
}
- return common.ToHex(tx.Hash()), nil
+ return tx.Hash().Hex(), nil
}
-func (self *XEth) sign(tx *types.Transaction, from []byte, didUnlock bool) error {
- sig, err := self.accountManager.Sign(accounts.Account{Address: from}, tx.Hash())
+func (self *XEth) sign(tx *types.Transaction, from common.Address, didUnlock bool) error {
+ sig, err := self.accountManager.Sign(accounts.Account{Address: from.Bytes()}, tx.Hash().Bytes())
if err == accounts.ErrLocked {
if didUnlock {
return fmt.Errorf("sender account still locked after successful unlock")
}
- if !self.frontend.UnlockAccount(from) {
+ if !self.frontend.UnlockAccount(from.Bytes()) {
return fmt.Errorf("could not unlock sender account")
}
// retry signing, the account should now be unlocked.
@@ -397,17 +393,17 @@ func (self *XEth) sign(tx *types.Transaction, from []byte, didUnlock bool) error
// callmsg is the message type used for call transations.
type callmsg struct {
from *state.StateObject
- to []byte
+ to common.Address
gas, gasPrice *big.Int
value *big.Int
data []byte
}
// accessor boilerplate to implement core.Message
-func (m callmsg) From() []byte { return m.from.Address() }
-func (m callmsg) Nonce() uint64 { return m.from.Nonce() }
-func (m callmsg) To() []byte { return m.to }
-func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
-func (m callmsg) Gas() *big.Int { return m.gas }
-func (m callmsg) Value() *big.Int { return m.value }
-func (m callmsg) Data() []byte { return m.data }
+func (m callmsg) From() (common.Address, error) { return m.from.Address(), nil }
+func (m callmsg) Nonce() uint64 { return m.from.Nonce() }
+func (m callmsg) To() *common.Address { return &m.to }
+func (m callmsg) GasPrice() *big.Int { return m.gasPrice }
+func (m callmsg) Gas() *big.Int { return m.gas }
+func (m callmsg) Value() *big.Int { return m.value }
+func (m callmsg) Data() []byte { return m.data }