aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-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.go83
-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
21 files changed, 558 insertions, 373 deletions
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..ff37ea28a 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))
@@ -505,7 +506,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)
}