aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Lange <fjl@twurst.com>2015-06-16 18:41:50 +0800
committerJeffrey Wilcke <geffobscura@gmail.com>2015-06-30 00:51:47 +0800
commit1d42888d3047dabfb352c94a2051e7af14d2a509 (patch)
tree8ca68ca98bd697f26f2033a5480e78ccbf064162
parent654564e164b3b6f7f4ba1e8bbd6fcd64776068fa (diff)
downloaddexon-1d42888d3047dabfb352c94a2051e7af14d2a509.tar.gz
dexon-1d42888d3047dabfb352c94a2051e7af14d2a509.tar.zst
dexon-1d42888d3047dabfb352c94a2051e7af14d2a509.zip
core/types: make blocks immutable
-rw-r--r--core/block_cache_test.go6
-rw-r--r--core/block_processor.go95
-rw-r--r--core/block_processor_test.go16
-rw-r--r--core/chain_makers.go58
-rw-r--r--core/chain_manager.go94
-rw-r--r--core/chain_manager_test.go30
-rw-r--r--core/genesis.go37
-rw-r--r--core/state_transition.go9
-rw-r--r--core/transaction_pool.go2
-rw-r--r--core/types/block.go421
-rw-r--r--core/vm_env.go34
-rw-r--r--eth/downloader/downloader_test.go5
-rw-r--r--miner/agent.go6
-rw-r--r--miner/remote_agent.go4
-rw-r--r--miner/worker.go184
-rw-r--r--tests/block_test_util.go11
-rw-r--r--xeth/xeth.go10
17 files changed, 446 insertions, 576 deletions
diff --git a/core/block_cache_test.go b/core/block_cache_test.go
index 43ab847f9..80d118599 100644
--- a/core/block_cache_test.go
+++ b/core/block_cache_test.go
@@ -11,12 +11,12 @@ import (
func newChain(size int) (chain []*types.Block) {
var parentHash common.Hash
for i := 0; i < size; i++ {
- block := types.NewBlock(parentHash, common.Address{}, common.Hash{}, new(big.Int), 0, nil)
- block.Header().Number = big.NewInt(int64(i))
+ head := &types.Header{ParentHash: parentHash, Number: big.NewInt(int64(i))}
+ block := types.NewBlock(head, nil, nil, nil)
chain = append(chain, block)
parentHash = block.Hash()
}
- return
+ return chain
}
func insertChainCache(cache *BlockCache, chain []*types.Block) {
diff --git a/core/block_processor.go b/core/block_processor.go
index e30ced312..2fd8c04c0 100644
--- a/core/block_processor.go
+++ b/core/block_processor.go
@@ -57,8 +57,8 @@ func NewBlockProcessor(db, extra common.Database, pow pow.PoW, chainManager *Cha
}
func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block *types.Block, transientProcess bool) (receipts types.Receipts, err error) {
- coinbase := statedb.GetOrNewStateObject(block.Header().Coinbase)
- coinbase.SetGasLimit(block.Header().GasLimit)
+ coinbase := statedb.GetOrNewStateObject(block.Coinbase())
+ coinbase.SetGasLimit(block.GasLimit())
// Process the transactions on to parent state
receipts, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), transientProcess)
@@ -69,11 +69,11 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block
return receipts, nil
}
-func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *state.StateDB, block *types.Block, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) {
+func (self *BlockProcessor) ApplyTransaction(coinbase *state.StateObject, statedb *state.StateDB, header *types.Header, tx *types.Transaction, usedGas *big.Int, transientProcess bool) (*types.Receipt, *big.Int, error) {
// If we are mining this block and validating we want to set the logs back to 0
cb := statedb.GetStateObject(coinbase.Address())
- _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, block), tx, cb)
+ _, gas, err := ApplyMessage(NewEnv(statedb, self.bc, tx, header), tx, cb)
if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) {
return nil, nil, err
}
@@ -108,12 +108,13 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
totalUsedGas = big.NewInt(0)
err error
cumulativeSum = new(big.Int)
+ header = block.Header()
)
for i, tx := range txs {
statedb.StartRecord(tx.Hash(), block.Hash(), i)
- receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, block, tx, totalUsedGas, transientProcess)
+ receipt, txGas, err := self.ApplyTransaction(coinbase, statedb, header, tx, totalUsedGas, transientProcess)
if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) {
return nil, err
}
@@ -142,11 +143,10 @@ func (sm *BlockProcessor) RetryProcess(block *types.Block) (logs state.Logs, err
sm.mutex.Lock()
defer sm.mutex.Unlock()
- header := block.Header()
- if !sm.bc.HasBlock(header.ParentHash) {
- return nil, ParentError(header.ParentHash)
+ if !sm.bc.HasBlock(block.ParentHash()) {
+ return nil, ParentError(block.ParentHash())
}
- parent := sm.bc.GetBlock(header.ParentHash)
+ parent := sm.bc.GetBlock(block.ParentHash())
// FIXME Change to full header validation. See #1225
errch := make(chan bool)
@@ -168,30 +168,32 @@ func (sm *BlockProcessor) Process(block *types.Block) (logs state.Logs, err erro
sm.mutex.Lock()
defer sm.mutex.Unlock()
- header := block.Header()
- if sm.bc.HasBlock(header.Hash()) {
- return nil, &KnownBlockError{header.Number, header.Hash()}
+ if sm.bc.HasBlock(block.Hash()) {
+ return nil, &KnownBlockError{block.Number(), block.Hash()}
}
- if !sm.bc.HasBlock(header.ParentHash) {
- return nil, ParentError(header.ParentHash)
+ if !sm.bc.HasBlock(block.ParentHash()) {
+ return nil, ParentError(block.ParentHash())
}
- parent := sm.bc.GetBlock(header.ParentHash)
+ parent := sm.bc.GetBlock(block.ParentHash())
return sm.processWithParent(block, parent)
}
func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs state.Logs, err error) {
// Create a new state based on the parent's root (e.g., create copy)
state := state.New(parent.Root(), sm.db)
+ header := block.Header()
+ uncles := block.Uncles()
+ txs := block.Transactions()
// Block validation
- if err = ValidateHeader(sm.Pow, block.Header(), parent.Header(), false); err != nil {
+ if err = ValidateHeader(sm.Pow, header, parent.Header(), false); err != nil {
return
}
// There can be at most two uncles
- if len(block.Uncles()) > 2 {
- return nil, ValidationError("Block can only contain maximum 2 uncles (contained %v)", len(block.Uncles()))
+ if len(uncles) > 2 {
+ return nil, ValidationError("Block can only contain maximum 2 uncles (contained %v)", len(uncles))
}
receipts, err := sm.TransitionState(state, parent, block, false)
@@ -199,8 +201,6 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
return
}
- header := block.Header()
-
// 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)
@@ -211,7 +211,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
// The transactions Trie's root (R = (Tr [[i, RLP(T1)], [i, RLP(T2)], ... [n, RLP(Tn)]]))
// can be used by light clients to make sure they've received the correct Txs
- txSha := types.DeriveSha(block.Transactions())
+ txSha := types.DeriveSha(txs)
if txSha != header.TxHash {
err = fmt.Errorf("invalid transaction root hash. received=%x calculated=%x", header.TxHash, txSha)
return
@@ -225,7 +225,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
}
// Verify UncleHash before running other uncle validations
- unclesSha := block.CalculateUnclesHash()
+ unclesSha := types.CalcUncleHash(uncles)
if unclesSha != header.UncleHash {
err = fmt.Errorf("invalid uncles root hash. received=%x calculated=%x", header.UncleHash, unclesSha)
return
@@ -236,7 +236,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
return
}
// Accumulate static rewards; block reward, uncle's and uncle inclusion.
- AccumulateRewards(state, block)
+ AccumulateRewards(state, header, uncles)
// Commit state objects/accounts to a temporary trie (does not save)
// used to calculate the state root.
@@ -260,11 +260,34 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
return state.Logs(), nil
}
+// AccumulateRewards credits the coinbase of the given block with the
+// mining reward. The total reward consists of the static block reward
+// and rewards for included uncles.
+func AccumulateRewards(statedb *state.StateDB, header *types.Header, uncles []*types.Header) {
+ reward := new(big.Int).Set(BlockReward)
+
+ for _, uncle := range uncles {
+ num := new(big.Int).Add(big.NewInt(8), uncle.Number)
+ num.Sub(num, header.Number)
+
+ r := new(big.Int)
+ r.Mul(BlockReward, num)
+ r.Div(r, big.NewInt(8))
+
+ statedb.AddBalance(uncle.Coinbase, r)
+
+ reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32)))
+ }
+
+ // Get the account associated with the coinbase
+ statedb.AddBalance(header.Coinbase, reward)
+}
+
func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *types.Block) error {
ancestors := set.New()
uncles := set.New()
ancestorHeaders := make(map[common.Hash]*types.Header)
- for _, ancestor := range sm.bc.GetAncestors(block, 7) {
+ for _, ancestor := range sm.bc.GetBlocksFromHash(block.ParentHash(), 7) {
ancestorHeaders[ancestor.Hash()] = ancestor.Header()
ancestors.Add(ancestor.Hash())
// Include ancestors uncles in the uncle set. Uncles must be unique.
@@ -325,7 +348,7 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
// TODO: remove backward compatibility
var (
- parent = sm.bc.GetBlock(block.Header().ParentHash)
+ parent = sm.bc.GetBlock(block.ParentHash())
state = state.New(parent.Root(), sm.db)
)
@@ -341,7 +364,7 @@ func ValidateHeader(pow pow.PoW, block, parent *types.Header, checkPow bool) err
return fmt.Errorf("Block extra data too long (%d)", len(block.Extra))
}
- expd := CalcDifficulty(block, parent)
+ expd := CalcDifficulty(int64(block.Time), int64(parent.Time), parent.Difficulty)
if expd.Cmp(block.Difficulty) != 0 {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd)
}
@@ -375,26 +398,6 @@ func ValidateHeader(pow pow.PoW, block, parent *types.Header, checkPow bool) err
return nil
}
-func AccumulateRewards(statedb *state.StateDB, block *types.Block) {
- reward := new(big.Int).Set(BlockReward)
-
- for _, uncle := range block.Uncles() {
- num := new(big.Int).Add(big.NewInt(8), uncle.Number)
- num.Sub(num, block.Number())
-
- r := new(big.Int)
- r.Mul(BlockReward, num)
- r.Div(r, big.NewInt(8))
-
- statedb.AddBalance(uncle.Coinbase, r)
-
- reward.Add(reward, new(big.Int).Div(BlockReward, big.NewInt(32)))
- }
-
- // Get the account associated with the coinbase
- statedb.AddBalance(block.Header().Coinbase, reward)
-}
-
func getBlockReceipts(db common.Database, bhash common.Hash) (receipts types.Receipts, err error) {
var rdata []byte
rdata, err = db.Get(append(receiptsPre, bhash[:]...))
diff --git a/core/block_processor_test.go b/core/block_processor_test.go
index e38c815ef..bd77a2fc2 100644
--- a/core/block_processor_test.go
+++ b/core/block_processor_test.go
@@ -26,20 +26,18 @@ func proc() (*BlockProcessor, *ChainManager) {
}
func TestNumber(t *testing.T) {
- _, chain := proc()
- block1 := chain.NewBlock(common.Address{})
- block1.Header().Number = big.NewInt(3)
- block1.Header().Time--
-
pow := ezp.New()
- err := ValidateHeader(pow, block1.Header(), chain.Genesis().Header(), false)
+ bp, chain := proc()
+ header := makeHeader(chain.Genesis(), 0, bp.db, 0)
+ header.Number = big.NewInt(3)
+ err := ValidateHeader(pow, header, chain.Genesis().Header(), false)
if err != BlockNumberErr {
- t.Errorf("expected block number error %v", err)
+ t.Errorf("expected block number error, got %q", err)
}
- block1 = chain.NewBlock(common.Address{})
- err = ValidateHeader(pow, block1.Header(), chain.Genesis().Header(), false)
+ header = makeHeader(chain.Genesis(), 0, bp.db, 0)
+ err = ValidateHeader(pow, header, chain.Genesis().Header(), false)
if err == BlockNumberErr {
t.Errorf("didn't expect block number error")
}
diff --git a/core/chain_makers.go b/core/chain_makers.go
index 76acfd6ca..e704fd088 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -29,12 +29,8 @@ var (
// Utility functions for making chains on the fly
// Exposed for sake of testing from other packages (eg. go-ethash)
-func NewBlockFromParent(addr common.Address, parent *types.Block) *types.Block {
- return newBlockFromParent(addr, parent)
-}
-
func MakeBlock(bman *BlockProcessor, parent *types.Block, i int, db common.Database, seed int) *types.Block {
- return makeBlock(bman, parent, i, db, seed)
+ return types.NewBlock(makeHeader(parent, i, db, seed), nil, nil, nil)
}
func MakeChain(bman *BlockProcessor, parent *types.Block, max int, db common.Database, seed int) types.Blocks {
@@ -53,46 +49,38 @@ func NewCanonical(n int, db common.Database) (*BlockProcessor, error) {
return newCanonical(n, db)
}
-// block time is fixed at 10 seconds
-func newBlockFromParent(addr common.Address, parent *types.Block) *types.Block {
- block := types.NewBlock(parent.Hash(), addr, parent.Root(), common.BigPow(2, 32), 0, nil)
- block.SetUncles(nil)
- block.SetTransactions(nil)
- block.SetReceipts(nil)
-
- header := block.Header()
- header.Difficulty = CalcDifficulty(block.Header(), parent.Header())
- header.Number = new(big.Int).Add(parent.Header().Number, common.Big1)
- header.Time = parent.Header().Time + 10
- header.GasLimit = CalcGasLimit(parent)
-
- block.Td = parent.Td
-
- return 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 {
+// makeHeader creates the header for a new empty block, simulating
+// what miner would do. We seed chains by the first byte of the coinbase.
+func makeHeader(parent *types.Block, i int, db common.Database, seed int) *types.Header {
var addr common.Address
- addr[0], addr[19] = byte(seed), byte(i)
- block := newBlockFromParent(addr, parent)
- state := state.New(block.Root(), db)
+ addr[0], addr[19] = byte(seed), byte(i) // 'random' coinbase
+ time := parent.Time() + 10 // block time is fixed at 10 seconds
+
+ // ensure that the block's coinbase has the block reward in the state.
+ state := state.New(parent.Root(), db)
cbase := state.GetOrNewStateObject(addr)
cbase.SetGasLimit(CalcGasLimit(parent))
cbase.AddBalance(BlockReward)
state.Update()
- block.SetRoot(state.Root())
- return block
+
+ return &types.Header{
+ Root: state.Root(),
+ ParentHash: parent.Hash(),
+ Coinbase: addr,
+ Difficulty: CalcDifficulty(time, parent.Time(), parent.Difficulty()),
+ Number: new(big.Int).Add(parent.Number(), common.Big1),
+ Time: uint64(time),
+ GasLimit: CalcGasLimit(parent),
+ }
}
-// Make a chain with real blocks
-// Runs ProcessWithParent to get proper state roots
+// makeChain creates a valid chain of empty blocks.
func makeChain(bman *BlockProcessor, parent *types.Block, max int, db common.Database, seed int) types.Blocks {
bman.bc.currentBlock = parent
blocks := make(types.Blocks, max)
for i := 0; i < max; i++ {
- block := makeBlock(bman, parent, i, db, seed)
+ block := types.NewBlock(makeHeader(parent, i, db, seed), nil, nil, nil)
+ // Use ProcessWithParent to verify that we have produced a valid block.
_, err := bman.processWithParent(block, parent)
if err != nil {
fmt.Println("process with parent failed", err)
@@ -129,7 +117,7 @@ func newBlockProcessor(db common.Database, cman *ChainManager, eventMux *event.T
}
// Make a new, deterministic canonical chain by running InsertChain
-// on result of makeChain
+// on result of makeChain.
func newCanonical(n int, db common.Database) (*BlockProcessor, error) {
eventMux := &event.TypeMux{}
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 3b9b7517b..8a79e3e8a 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -38,23 +38,24 @@ const (
maxTimeFutureBlocks = 30
)
-func CalcDifficulty(block, parent *types.Header) *big.Int {
+// CalcDifficulty is the difficulty adjustment algorithm. It returns
+// the difficulty that a new block b should have when created at time
+// given the parent block's time and difficulty.
+func CalcDifficulty(time int64, parentTime int64, parentDiff *big.Int) *big.Int {
diff := new(big.Int)
-
- adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor)
- if big.NewInt(int64(block.Time)-int64(parent.Time)).Cmp(params.DurationLimit) < 0 {
- diff.Add(parent.Difficulty, adjust)
+ adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor)
+ if big.NewInt(time-parentTime).Cmp(params.DurationLimit) < 0 {
+ diff.Add(parentDiff, adjust)
} else {
- diff.Sub(parent.Difficulty, adjust)
+ diff.Sub(parentDiff, adjust)
}
-
if diff.Cmp(params.MinimumDifficulty) < 0 {
return params.MinimumDifficulty
}
-
return diff
}
+// CalcTD computes the total difficulty of block.
func CalcTD(block, parent *types.Block) *big.Int {
if parent == nil {
return block.Difficulty()
@@ -62,6 +63,8 @@ func CalcTD(block, parent *types.Block) *big.Int {
return new(big.Int).Add(parent.Td, block.Header().Difficulty)
}
+// CalcGasLimit computes the gas limit of the next block after parent.
+// The result may be modified by the caller.
func CalcGasLimit(parent *types.Block) *big.Int {
decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3))
@@ -71,11 +74,11 @@ func CalcGasLimit(parent *types.Block) *big.Int {
gl := new(big.Int).Sub(parent.GasLimit(), decay)
gl = gl.Add(gl, contrib)
gl = gl.Add(gl, big.NewInt(1))
- gl = common.BigMax(gl, params.MinGasLimit)
+ gl.Set(common.BigMax(gl, params.MinGasLimit))
if gl.Cmp(params.GenesisGasLimit) < 0 {
- gl2 := new(big.Int).Add(parent.GasLimit(), decay)
- return common.BigMin(params.GenesisGasLimit, gl2)
+ gl.Add(parent.GasLimit(), decay)
+ gl.Set(common.BigMin(gl, params.GenesisGasLimit))
}
return gl
}
@@ -255,50 +258,11 @@ func (bc *ChainManager) makeCache() {
bc.cache = NewBlockCache(blockCacheLimit)
}
// load in last `blockCacheLimit` - 1 blocks. Last block is the current.
- ancestors := bc.GetAncestors(bc.currentBlock, blockCacheLimit-1)
- ancestors = append(ancestors, bc.currentBlock)
- for _, block := range ancestors {
+ for _, block := range bc.GetBlocksFromHash(bc.currentBlock.Hash(), blockCacheLimit) {
bc.cache.Push(block)
}
}
-// Block creation & chain handling
-func (bc *ChainManager) NewBlock(coinbase common.Address) *types.Block {
- bc.mu.RLock()
- defer bc.mu.RUnlock()
-
- var (
- root common.Hash
- parentHash common.Hash
- )
-
- if bc.currentBlock != nil {
- root = bc.currentBlock.Header().Root
- parentHash = bc.lastBlockHash
- }
-
- block := types.NewBlock(
- parentHash,
- coinbase,
- root,
- common.BigPow(2, 32),
- 0,
- nil)
- block.SetUncles(nil)
- block.SetTransactions(nil)
- block.SetReceipts(nil)
-
- parent := bc.currentBlock
- if parent != nil {
- header := block.Header()
- header.Difficulty = CalcDifficulty(block.Header(), parent.Header())
- header.Number = new(big.Int).Add(parent.Header().Number, common.Big1)
- header.GasLimit = CalcGasLimit(parent)
- }
-
- return block
-}
-
func (bc *ChainManager) Reset() {
bc.mu.Lock()
defer bc.mu.Unlock()
@@ -463,6 +427,19 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block {
}
+// GetBlocksFromHash returns the block corresponding to hash and up to n-1 ancestors.
+func (self *ChainManager) GetBlocksFromHash(hash common.Hash, n int) (blocks []*types.Block) {
+ for i := 0; i < n; i++ {
+ block := self.GetBlock(hash)
+ if block == nil {
+ break
+ }
+ blocks = append(blocks, block)
+ hash = block.ParentHash()
+ }
+ return
+}
+
// non blocking version
func (self *ChainManager) getBlockByNumber(num uint64) *types.Block {
key, _ := self.blockDb.Get(append(blockNumPre, big.NewInt(int64(num)).Bytes()...))
@@ -482,19 +459,6 @@ func (self *ChainManager) GetUnclesInChain(block *types.Block, length int) (uncl
return
}
-func (self *ChainManager) GetAncestors(block *types.Block, length int) (blocks []*types.Block) {
- for i := 0; i < length; i++ {
- block = self.GetBlock(block.ParentHash())
- if block == nil {
- break
- }
-
- blocks = append(blocks, block)
- }
-
- return
-}
-
// setTotalDifficulty updates the TD of the chain manager. Note, this function
// assumes that the `mu` mutex is held!
func (bc *ChainManager) setTotalDifficulty(td *big.Int) {
@@ -621,14 +585,12 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) {
return i, fmt.Errorf("%v: BlockFutureErr, %v > %v", BlockFutureErr, block.Time(), max)
}
- block.SetQueued(true)
self.futureBlocks.Push(block)
stats.queued++
continue
}
if IsParentErr(err) && self.futureBlocks.Has(block.ParentHash()) {
- block.SetQueued(true)
self.futureBlocks.Push(block)
stats.queued++
continue
diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go
index c56a3b3e1..afec1d0f1 100644
--- a/core/chain_manager_test.go
+++ b/core/chain_manager_test.go
@@ -117,7 +117,7 @@ func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) {
}
func loadChain(fn string, t *testing.T) (types.Blocks, error) {
- fh, err := os.OpenFile(filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm)
+ fh, err := os.OpenFile(filepath.Join("..", "_data", fn), os.O_RDONLY, os.ModePerm)
if err != nil {
return nil, err
}
@@ -265,7 +265,7 @@ func TestBrokenChain(t *testing.T) {
}
func TestChainInsertions(t *testing.T) {
- t.Skip() // travil fails.
+ t.Skip("Skipped: outdated test files")
db, _ := ethdb.NewMemDatabase()
@@ -303,7 +303,7 @@ func TestChainInsertions(t *testing.T) {
}
func TestChainMultipleInsertions(t *testing.T) {
- t.Skip() // travil fails.
+ t.Skip("Skipped: outdated test files")
db, _ := ethdb.NewMemDatabase()
@@ -346,8 +346,8 @@ func TestChainMultipleInsertions(t *testing.T) {
}
}
-func TestGetAncestors(t *testing.T) {
- t.Skip() // travil fails.
+func TestGetBlocksFromHash(t *testing.T) {
+ t.Skip("Skipped: outdated test files")
db, _ := ethdb.NewMemDatabase()
chainMan := theChainManager(db, t)
@@ -361,8 +361,8 @@ func TestGetAncestors(t *testing.T) {
chainMan.write(block)
}
- ancestors := chainMan.GetAncestors(chain[len(chain)-1], 4)
- fmt.Println(ancestors)
+ blocks := chainMan.GetBlocksFromHash(chain[len(chain)-1].Hash(), 4)
+ fmt.Println(blocks)
}
type bproc struct{}
@@ -372,15 +372,17 @@ func (bproc) Process(*types.Block) (state.Logs, error) { return nil, nil }
func makeChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block {
var chain []*types.Block
for i, difficulty := range d {
- header := &types.Header{Number: big.NewInt(int64(i + 1)), Difficulty: big.NewInt(int64(difficulty))}
- block := types.NewBlockWithHeader(header)
- copy(block.HeaderHash[:2], []byte{byte(i + 1), seed})
+ header := &types.Header{
+ Coinbase: common.Address{seed},
+ Number: big.NewInt(int64(i + 1)),
+ Difficulty: big.NewInt(int64(difficulty)),
+ }
if i == 0 {
- block.ParentHeaderHash = genesis.Hash()
+ header.ParentHash = genesis.Hash()
} else {
- copy(block.ParentHeaderHash[:2], []byte{byte(i), seed})
+ header.ParentHash = chain[i-1].Hash()
}
-
+ block := types.NewBlockWithHeader(header)
chain = append(chain, block)
}
return chain
@@ -399,7 +401,6 @@ func chm(genesis *types.Block, db common.Database) *ChainManager {
}
func TestReorgLongest(t *testing.T) {
- t.Skip("skipped while cache is removed")
db, _ := ethdb.NewMemDatabase()
genesis := GenesisBlock(0, db)
bc := chm(genesis, db)
@@ -419,7 +420,6 @@ func TestReorgLongest(t *testing.T) {
}
func TestReorgShortest(t *testing.T) {
- t.Skip("skipped while cache is removed")
db, _ := ethdb.NewMemDatabase()
genesis := GenesisBlock(0, db)
bc := chm(genesis, db)
diff --git a/core/genesis.go b/core/genesis.go
index dd894e0b0..de2eee9db 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -11,38 +11,18 @@ import (
"github.com/ethereum/go-ethereum/params"
)
-/*
- * This is the special genesis block.
- */
-
-var ZeroHash256 = make([]byte, 32)
-var ZeroHash160 = make([]byte, 20)
-var ZeroHash512 = make([]byte, 64)
-
+// GenesisBlock creates a genesis block with the given nonce.
func GenesisBlock(nonce uint64, db common.Database) *types.Block {
- genesis := types.NewBlock(common.Hash{}, common.Address{}, common.Hash{}, params.GenesisDifficulty, nonce, nil)
- genesis.Header().Number = common.Big0
- genesis.Header().GasLimit = params.GenesisGasLimit
- genesis.Header().GasUsed = common.Big0
- genesis.Header().Time = 0
-
- genesis.Td = common.Big0
-
- genesis.SetUncles([]*types.Header{})
- genesis.SetTransactions(types.Transactions{})
- genesis.SetReceipts(types.Receipts{})
-
var accounts map[string]struct {
Balance string
Code string
}
err := json.Unmarshal(GenesisAccounts, &accounts)
if err != nil {
- fmt.Println("enable to decode genesis json data:", err)
+ fmt.Println("unable to decode genesis json data:", err)
os.Exit(1)
}
-
- statedb := state.New(genesis.Root(), db)
+ statedb := state.New(common.Hash{}, db)
for addr, account := range accounts {
codedAddr := common.Hex2Bytes(addr)
accountState := statedb.CreateAccount(common.BytesToAddress(codedAddr))
@@ -51,10 +31,15 @@ func GenesisBlock(nonce uint64, db common.Database) *types.Block {
statedb.UpdateStateObject(accountState)
}
statedb.Sync()
- genesis.Header().Root = statedb.Root()
- genesis.Td = params.GenesisDifficulty
- return genesis
+ block := types.NewBlock(&types.Header{
+ Difficulty: params.GenesisDifficulty,
+ GasLimit: params.GenesisGasLimit,
+ Nonce: types.EncodeNonce(nonce),
+ Root: statedb.Root(),
+ }, nil, nil, nil)
+ block.Td = params.GenesisDifficulty
+ return block
}
var GenesisAccounts = []byte(`{
diff --git a/core/state_transition.go b/core/state_transition.go
index 915dd466b..2c8770cbe 100644
--- a/core/state_transition.go
+++ b/core/state_transition.go
@@ -73,16 +73,17 @@ func MessageGasValue(msg Message) *big.Int {
return new(big.Int).Mul(msg.Gas(), msg.GasPrice())
}
-func IntrinsicGas(msg Message) *big.Int {
+// IntrinsicGas computes the 'intrisic gas' for a message
+// with the given data.
+func IntrinsicGas(data []byte) *big.Int {
igas := new(big.Int).Set(params.TxGas)
- for _, byt := range msg.Data() {
+ for _, byt := range data {
if byt != 0 {
igas.Add(igas, params.TxDataNonZeroGas)
} else {
igas.Add(igas, params.TxDataZeroGas)
}
}
-
return igas
}
@@ -195,7 +196,7 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
sender, _ := self.From() // err checked in preCheck
// Pay intrinsic gas
- if err = self.UseGas(IntrinsicGas(self.msg)); err != nil {
+ if err = self.UseGas(IntrinsicGas(self.msg.Data())); err != nil {
return nil, nil, InvalidTxError(err)
}
diff --git a/core/transaction_pool.go b/core/transaction_pool.go
index 45db04eef..bf28647c3 100644
--- a/core/transaction_pool.go
+++ b/core/transaction_pool.go
@@ -180,7 +180,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
}
// Should supply enough intrinsic gas
- if tx.Gas().Cmp(IntrinsicGas(tx)) < 0 {
+ if tx.Gas().Cmp(IntrinsicGas(tx.Data())) < 0 {
return ErrIntrinsicGas
}
diff --git a/core/types/block.go b/core/types/block.go
index d7963981e..31ea478d4 100644
--- a/core/types/block.go
+++ b/core/types/block.go
@@ -15,71 +15,59 @@ import (
"github.com/ethereum/go-ethereum/rlp"
)
-type Header struct {
- // Hash to the previous block
- ParentHash common.Hash
- // Uncles of this block
- UncleHash common.Hash
- // The coin base address
- Coinbase common.Address
- // Block Trie state
- Root common.Hash
- // Tx sha
- TxHash common.Hash
- // Receipt sha
- ReceiptHash common.Hash
- // Bloom
- Bloom Bloom
- // Difficulty for the current block
- Difficulty *big.Int
- // The block number
- Number *big.Int
- // Gas limit
- GasLimit *big.Int
- // Gas used
- GasUsed *big.Int
- // Creation time
- Time uint64
- // Extra data
- Extra []byte
- // Mix digest for quick checking to prevent DOS
- MixDigest common.Hash
- // Nonce
- Nonce [8]byte
-}
+// A BlockNonce is a 64-bit hash which proves (combined with the
+// mix-hash) that a suffcient amount of computation has been carried
+// out on a block.
+type BlockNonce [8]byte
-func (self *Header) Hash() common.Hash {
- return rlpHash(self.rlpData(true))
+func EncodeNonce(i uint64) BlockNonce {
+ var n BlockNonce
+ binary.BigEndian.PutUint64(n[:], i)
+ return n
}
-func (self *Header) HashNoNonce() common.Hash {
- return rlpHash(self.rlpData(false))
+func (n BlockNonce) Uint64() uint64 {
+ return binary.BigEndian.Uint64(n[:])
}
-func (self *Header) rlpData(withNonce bool) []interface{} {
- fields := []interface{}{
- self.ParentHash,
- self.UncleHash,
- self.Coinbase,
- self.Root,
- self.TxHash,
- self.ReceiptHash,
- self.Bloom,
- self.Difficulty,
- self.Number,
- self.GasLimit,
- self.GasUsed,
- self.Time,
- self.Extra,
- }
- if withNonce {
- fields = append(fields, self.MixDigest, self.Nonce)
- }
- return fields
-}
-
-func (self *Header) RlpData() interface{} {
- return self.rlpData(true)
+type Header struct {
+ ParentHash common.Hash // Hash to the previous block
+ UncleHash common.Hash // Uncles of this block
+ Coinbase common.Address // The coin base address
+ Root common.Hash // Block Trie state
+ TxHash common.Hash // Tx sha
+ ReceiptHash common.Hash // Receipt sha
+ Bloom Bloom // Bloom
+ Difficulty *big.Int // Difficulty for the current block
+ Number *big.Int // The block number
+ GasLimit *big.Int // Gas limit
+ GasUsed *big.Int // Gas used
+ Time uint64 // Creation time
+ Extra []byte // Extra data
+ MixDigest common.Hash // for quick difficulty verification
+ Nonce BlockNonce
+}
+
+func (h *Header) Hash() common.Hash {
+ return rlpHash(h)
+}
+
+func (h *Header) HashNoNonce() common.Hash {
+ return rlpHash([]interface{}{
+ h.ParentHash,
+ h.UncleHash,
+ h.Coinbase,
+ h.Root,
+ h.TxHash,
+ h.ReceiptHash,
+ h.Bloom,
+ h.Difficulty,
+ h.Number,
+ h.GasLimit,
+ h.GasUsed,
+ h.Time,
+ h.Extra,
+ })
}
func (h *Header) UnmarshalJSON(data []byte) error {
@@ -112,20 +100,14 @@ func rlpHash(x interface{}) (h common.Hash) {
}
type Block struct {
- // Preset Hash for mock (Tests)
- HeaderHash common.Hash
- ParentHeaderHash common.Hash
- // ^^^^ ignore ^^^^
-
header *Header
uncles []*Header
transactions Transactions
- Td *big.Int
- queued bool // flag for blockpool to skip TD check
+ receipts Receipts
+ Td *big.Int
+ queued bool // flag for blockpool to skip TD check
ReceivedAt time.Time
-
- receipts Receipts
}
// StorageBlock defines the RLP encoding of a Block stored in the
@@ -148,43 +130,90 @@ type storageblock struct {
TD *big.Int
}
-func NewBlock(parentHash common.Hash, coinbase common.Address, root common.Hash, difficulty *big.Int, nonce uint64, extra []byte) *Block {
- header := &Header{
- Root: root,
- ParentHash: parentHash,
- Coinbase: coinbase,
- Difficulty: difficulty,
- Time: uint64(time.Now().Unix()),
- Extra: extra,
- GasUsed: new(big.Int),
- GasLimit: new(big.Int),
- Number: new(big.Int),
+var (
+ emptyRootHash = DeriveSha(Transactions{})
+ emptyUncleHash = CalcUncleHash(nil)
+)
+
+// NewBlock creates a new block. The input data is copied,
+// changes to header and to the field values will not affect the
+// block.
+//
+// The values of TxHash, UncleHash, ReceiptHash and Bloom in header
+// are ignored and set to values derived from the given txs, uncles
+// and receipts.
+func NewBlock(header *Header, txs []*Transaction, uncles []*Header, receipts []*Receipt) *Block {
+ b := &Block{header: copyHeader(header), Td: new(big.Int)}
+
+ // TODO: panic if len(txs) != len(receipts)
+ if len(txs) == 0 {
+ b.header.TxHash = emptyRootHash
+ } else {
+ b.header.TxHash = DeriveSha(Transactions(txs))
+ b.transactions = make(Transactions, len(txs))
+ copy(b.transactions, txs)
}
- header.SetNonce(nonce)
- block := &Block{header: header}
- block.Td = new(big.Int)
- return block
-}
+ if len(receipts) == 0 {
+ b.header.ReceiptHash = emptyRootHash
+ } else {
+ b.header.ReceiptHash = DeriveSha(Receipts(receipts))
+ b.header.Bloom = CreateBloom(receipts)
+ b.receipts = make([]*Receipt, len(receipts))
+ copy(b.receipts, receipts)
+ }
-func (self *Header) SetNonce(nonce uint64) {
- binary.BigEndian.PutUint64(self.Nonce[:], nonce)
+ if len(uncles) == 0 {
+ b.header.UncleHash = emptyUncleHash
+ } else {
+ b.header.UncleHash = CalcUncleHash(uncles)
+ b.uncles = make([]*Header, len(uncles))
+ for i := range uncles {
+ b.uncles[i] = copyHeader(uncles[i])
+ }
+ }
+
+ return b
}
+// NewBlockWithHeader creates a block with the given header data. The
+// header data is copied, changes to header and to the field values
+// will not affect the block.
func NewBlockWithHeader(header *Header) *Block {
- return &Block{header: header}
+ return &Block{header: copyHeader(header)}
+}
+
+func copyHeader(h *Header) *Header {
+ cpy := *h
+ if cpy.Difficulty = new(big.Int); h.Difficulty != nil {
+ cpy.Difficulty.Set(h.Difficulty)
+ }
+ if cpy.Number = new(big.Int); h.Number != nil {
+ cpy.Number.Set(h.Number)
+ }
+ if cpy.GasLimit = new(big.Int); h.GasLimit != nil {
+ cpy.GasLimit.Set(h.GasLimit)
+ }
+ if cpy.GasUsed = new(big.Int); h.GasUsed != nil {
+ cpy.GasUsed.Set(h.GasUsed)
+ }
+ if len(h.Extra) > 0 {
+ cpy.Extra = make([]byte, len(h.Extra))
+ copy(cpy.Extra, h.Extra)
+ }
+ return &cpy
}
-func (self *Block) ValidateFields() error {
- if self.header == nil {
+func (b *Block) ValidateFields() error {
+ if b.header == nil {
return fmt.Errorf("header is nil")
}
- for i, transaction := range self.transactions {
+ for i, transaction := range b.transactions {
if transaction == nil {
return fmt.Errorf("transaction %d is nil", i)
}
}
- for i, uncle := range self.uncles {
+ for i, uncle := range b.uncles {
if uncle == nil {
return fmt.Errorf("uncle %d is nil", i)
}
@@ -192,64 +221,48 @@ func (self *Block) ValidateFields() error {
return nil
}
-func (self *Block) DecodeRLP(s *rlp.Stream) error {
+func (b *Block) DecodeRLP(s *rlp.Stream) error {
var eb extblock
if err := s.Decode(&eb); err != nil {
return err
}
- self.header, self.uncles, self.transactions = eb.Header, eb.Uncles, eb.Txs
+ b.header, b.uncles, b.transactions = eb.Header, eb.Uncles, eb.Txs
return nil
}
-func (self Block) EncodeRLP(w io.Writer) error {
+func (b Block) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, extblock{
- Header: self.header,
- Txs: self.transactions,
- Uncles: self.uncles,
+ Header: b.header,
+ Txs: b.transactions,
+ Uncles: b.uncles,
})
}
-func (self *StorageBlock) DecodeRLP(s *rlp.Stream) error {
+func (b *StorageBlock) DecodeRLP(s *rlp.Stream) error {
var sb storageblock
if err := s.Decode(&sb); err != nil {
return err
}
- self.header, self.uncles, self.transactions, self.Td = sb.Header, sb.Uncles, sb.Txs, sb.TD
+ b.header, b.uncles, b.transactions, b.Td = sb.Header, sb.Uncles, sb.Txs, sb.TD
return nil
}
-func (self StorageBlock) EncodeRLP(w io.Writer) error {
+func (b StorageBlock) EncodeRLP(w io.Writer) error {
return rlp.Encode(w, storageblock{
- Header: self.header,
- Txs: self.transactions,
- Uncles: self.uncles,
- TD: self.Td,
+ Header: b.header,
+ Txs: b.transactions,
+ Uncles: b.uncles,
+ TD: b.Td,
})
}
-func (self *Block) Header() *Header {
- return self.header
-}
-
-func (self *Block) Uncles() []*Header {
- return self.uncles
-}
-
-func (self *Block) CalculateUnclesHash() common.Hash {
- return rlpHash(self.uncles)
-}
+// TODO: copies
+func (b *Block) Uncles() []*Header { return b.uncles }
+func (b *Block) Transactions() Transactions { return b.transactions }
+func (b *Block) Receipts() Receipts { return b.receipts }
-func (self *Block) SetUncles(uncleHeaders []*Header) {
- self.uncles = uncleHeaders
- self.header.UncleHash = rlpHash(uncleHeaders)
-}
-
-func (self *Block) Transactions() Transactions {
- return self.transactions
-}
-
-func (self *Block) Transaction(hash common.Hash) *Transaction {
- for _, transaction := range self.transactions {
+func (b *Block) Transaction(hash common.Hash) *Transaction {
+ for _, transaction := range b.transactions {
if transaction.Hash() == hash {
return transaction
}
@@ -257,74 +270,33 @@ func (self *Block) Transaction(hash common.Hash) *Transaction {
return nil
}
-func (self *Block) SetTransactions(transactions Transactions) {
- self.transactions = transactions
- self.header.TxHash = DeriveSha(transactions)
-}
-func (self *Block) AddTransaction(transaction *Transaction) {
- self.transactions = append(self.transactions, transaction)
- self.SetTransactions(self.transactions)
-}
-
-func (self *Block) Receipts() Receipts {
- return self.receipts
-}
-
-func (self *Block) SetReceipts(receipts Receipts) {
- self.receipts = receipts
- self.header.ReceiptHash = DeriveSha(receipts)
- self.header.Bloom = CreateBloom(receipts)
-}
-func (self *Block) AddReceipt(receipt *Receipt) {
- self.receipts = append(self.receipts, receipt)
- self.SetReceipts(self.receipts)
-}
-
-func (self *Block) RlpData() interface{} {
- return []interface{}{self.header, self.transactions, self.uncles}
-}
+func (b *Block) Number() *big.Int { return new(big.Int).Set(b.header.Number) }
+func (b *Block) GasLimit() *big.Int { return new(big.Int).Set(b.header.GasLimit) }
+func (b *Block) GasUsed() *big.Int { return new(big.Int).Set(b.header.GasUsed) }
+func (b *Block) Difficulty() *big.Int { return new(big.Int).Set(b.header.Difficulty) }
-func (self *Block) RlpDataForStorage() interface{} {
- return []interface{}{self.header, self.transactions, self.uncles, self.Td /* TODO receipts */}
-}
+func (b *Block) NumberU64() uint64 { return b.header.Number.Uint64() }
+func (b *Block) MixDigest() common.Hash { return b.header.MixDigest }
+func (b *Block) Nonce() uint64 { return binary.BigEndian.Uint64(b.header.Nonce[:]) }
+func (b *Block) Bloom() Bloom { return b.header.Bloom }
+func (b *Block) Coinbase() common.Address { return b.header.Coinbase }
+func (b *Block) Time() int64 { return int64(b.header.Time) }
+func (b *Block) Root() common.Hash { return b.header.Root }
+func (b *Block) ParentHash() common.Hash { return b.header.ParentHash }
+func (b *Block) TxHash() common.Hash { return b.header.TxHash }
+func (b *Block) ReceiptHash() common.Hash { return b.header.ReceiptHash }
+func (b *Block) UncleHash() common.Hash { return b.header.UncleHash }
+func (b *Block) Extra() []byte { return common.CopyBytes(b.header.Extra) }
-// 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() common.Hash { return self.header.MixDigest }
-func (self *Block) Nonce() uint64 {
- return binary.BigEndian.Uint64(self.header.Nonce[:])
-}
-func (self *Block) SetNonce(nonce uint64) {
- self.header.SetNonce(nonce)
-}
+func (b *Block) Header() *Header { return copyHeader(b.header) }
-func (self *Block) Queued() bool { return self.queued }
-func (self *Block) SetQueued(q bool) { self.queued = q }
-
-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]
- }
- return nil
-}
-func (self *Block) GetUncle(i int) *Header {
- if len(self.uncles) > i {
- return self.uncles[i]
- }
- return nil
+func (b *Block) HashNoNonce() common.Hash {
+ return b.header.HashNoNonce()
}
-func (self *Block) Size() common.StorageSize {
+func (b *Block) Size() common.StorageSize {
c := writeCounter(0)
- rlp.Encode(&c, self)
+ rlp.Encode(&c, b)
return common.StorageSize(c)
}
@@ -335,48 +307,32 @@ func (c *writeCounter) Write(b []byte) (int, error) {
return len(b), nil
}
-// Implement pow.Block
-func (self *Block) Difficulty() *big.Int { return self.header.Difficulty }
-func (self *Block) HashNoNonce() common.Hash { return self.header.HashNoNonce() }
-
-func (self *Block) Hash() common.Hash {
- if (self.HeaderHash != common.Hash{}) {
- return self.HeaderHash
- } else {
- return self.header.Hash()
- }
+func CalcUncleHash(uncles []*Header) common.Hash {
+ return rlpHash(uncles)
}
-func (self *Block) ParentHash() common.Hash {
- if (self.ParentHeaderHash != common.Hash{}) {
- return self.ParentHeaderHash
- } else {
- return self.header.ParentHash
+// WithMiningResult returns a new block with the data from b
+// where nonce and mix digest are set to the provided values.
+func (b *Block) WithMiningResult(nonce uint64, mixDigest common.Hash) *Block {
+ cpy := *b.header
+ binary.BigEndian.PutUint64(cpy.Nonce[:], nonce)
+ cpy.MixDigest = mixDigest
+ return &Block{
+ header: &cpy,
+ transactions: b.transactions,
+ receipts: b.receipts,
+ uncles: b.uncles,
+ Td: b.Td,
}
}
-func (self *Block) Copy() *Block {
- block := NewBlock(self.header.ParentHash, self.Coinbase(), self.Root(), new(big.Int), self.Nonce(), self.header.Extra)
- block.header.Bloom = self.header.Bloom
- block.header.TxHash = self.header.TxHash
- block.transactions = self.transactions
- block.header.UncleHash = self.header.UncleHash
- block.uncles = self.uncles
- block.header.GasLimit.Set(self.header.GasLimit)
- block.header.GasUsed.Set(self.header.GasUsed)
- block.header.ReceiptHash = self.header.ReceiptHash
- block.header.Difficulty.Set(self.header.Difficulty)
- block.header.Number.Set(self.header.Number)
- block.header.Time = self.header.Time
- block.header.MixDigest = self.header.MixDigest
- if self.Td != nil {
- block.Td.Set(self.Td)
- }
+// Implement pow.Block
- return block
+func (b *Block) Hash() common.Hash {
+ return b.header.Hash()
}
-func (self *Block) String() string {
+func (b *Block) String() string {
str := fmt.Sprintf(`Block(#%v): Size: %v TD: %v {
MinerHash: %x
%v
@@ -385,20 +341,11 @@ Transactions:
Uncles:
%v
}
-`, self.Number(), self.Size(), self.Td, self.header.HashNoNonce(), self.header, self.transactions, self.uncles)
-
- if (self.HeaderHash != common.Hash{}) {
- str += fmt.Sprintf("\nFake hash = %x", self.HeaderHash)
- }
-
- if (self.ParentHeaderHash != common.Hash{}) {
- str += fmt.Sprintf("\nFake parent hash = %x", self.ParentHeaderHash)
- }
-
+`, b.Number(), b.Size(), b.Td, b.header.HashNoNonce(), b.header, b.transactions, b.uncles)
return str
}
-func (self *Header) String() string {
+func (h *Header) String() string {
return fmt.Sprintf(`Header(%x):
[
ParentHash: %x
@@ -414,9 +361,9 @@ func (self *Header) String() string {
GasUsed: %v
Time: %v
Extra: %s
- MixDigest: %x
+ MixDigest: %x
Nonce: %x
-]`, self.Hash(), self.ParentHash, self.UncleHash, self.Coinbase, self.Root, self.TxHash, self.ReceiptHash, self.Bloom, self.Difficulty, self.Number, self.GasLimit, self.GasUsed, self.Time, self.Extra, self.MixDigest, self.Nonce)
+]`, h.Hash(), h.ParentHash, h.UncleHash, h.Coinbase, h.Root, h.TxHash, h.ReceiptHash, h.Bloom, h.Difficulty, h.Number, h.GasLimit, h.GasUsed, h.Time, h.Extra, h.MixDigest, h.Nonce)
}
type Blocks []*Block
@@ -442,4 +389,4 @@ func (self blockSorter) Swap(i, j int) {
}
func (self blockSorter) Less(i, j int) bool { return self.by(self.blocks[i], self.blocks[j]) }
-func Number(b1, b2 *Block) bool { return b1.Header().Number.Cmp(b2.Header().Number) < 0 }
+func Number(b1, b2 *Block) bool { return b1.header.Number.Cmp(b2.header.Number) < 0 }
diff --git a/core/vm_env.go b/core/vm_env.go
index da862d5c8..6dd83acde 100644
--- a/core/vm_env.go
+++ b/core/vm_env.go
@@ -10,32 +10,32 @@ import (
)
type VMEnv struct {
- state *state.StateDB
- block *types.Block
- msg Message
- depth int
- chain *ChainManager
- typ vm.Type
+ state *state.StateDB
+ header *types.Header
+ msg Message
+ depth int
+ chain *ChainManager
+ typ vm.Type
// structured logging
logs []vm.StructLog
}
-func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, block *types.Block) *VMEnv {
+func NewEnv(state *state.StateDB, chain *ChainManager, msg Message, header *types.Header) *VMEnv {
return &VMEnv{
- chain: chain,
- state: state,
- block: block,
- msg: msg,
- typ: vm.StdVmTy,
+ chain: chain,
+ state: state,
+ header: header,
+ msg: msg,
+ typ: vm.StdVmTy,
}
}
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) BlockNumber() *big.Int { return self.header.Number }
+func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase }
+func (self *VMEnv) Time() int64 { return int64(self.header.Time) }
+func (self *VMEnv) Difficulty() *big.Int { return self.header.Difficulty }
+func (self *VMEnv) GasLimit() *big.Int { return self.header.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 }
diff --git a/eth/downloader/downloader_test.go b/eth/downloader/downloader_test.go
index 4fc4e1434..fb8aa7e4b 100644
--- a/eth/downloader/downloader_test.go
+++ b/eth/downloader/downloader_test.go
@@ -40,7 +40,10 @@ func createHashes(amount int, root common.Hash) (hashes []common.Hash) {
// createBlock assembles a new block at the given chain height.
func createBlock(i int, parent, hash common.Hash) *types.Block {
- header := &types.Header{Number: big.NewInt(int64(i))}
+ header := &types.Header{
+ Hash: hash,
+ Number: big.NewInt(int64(i))
+ }
block := types.NewBlockWithHeader(header)
block.HeaderHash = hash
block.ParentHeaderHash = parent
diff --git a/miner/agent.go b/miner/agent.go
index 3ed3ba839..a7d017aa5 100644
--- a/miner/agent.go
+++ b/miner/agent.go
@@ -90,15 +90,13 @@ done:
}
}
-func (self *CpuAgent) mine(block *types.Block, stop <- chan struct{}) {
+func (self *CpuAgent) mine(block *types.Block, stop <-chan struct{}) {
glog.V(logger.Debug).Infof("(re)started agent[%d]. mining...\n", self.index)
// Mine
nonce, mixDigest := self.pow.Search(block, stop)
if nonce != 0 {
- block.SetNonce(nonce)
- block.Header().MixDigest = common.BytesToHash(mixDigest)
- self.returnCh <- block
+ self.returnCh <- block.WithMiningResult(nonce, common.BytesToHash(mixDigest))
} else {
self.returnCh <- nil
}
diff --git a/miner/remote_agent.go b/miner/remote_agent.go
index 80cc9053e..6a44782f6 100644
--- a/miner/remote_agent.go
+++ b/miner/remote_agent.go
@@ -81,9 +81,7 @@ func (a *RemoteAgent) SubmitWork(nonce uint64, mixDigest, seedHash common.Hash)
// Make sure the external miner was working on the right hash
if a.currentWork != nil && a.work != nil {
- a.currentWork.SetNonce(nonce)
- a.currentWork.Header().MixDigest = mixDigest
- a.returnCh <- a.currentWork
+ a.returnCh <- a.currentWork.WithMiningResult(nonce, mixDigest)
//a.returnCh <- Work{a.currentWork.Number().Uint64(), nonce, mixDigest.Bytes(), seedHash.Bytes()}
return true
}
diff --git a/miner/worker.go b/miner/worker.go
index 55c23376c..3a2d7a41b 100644
--- a/miner/worker.go
+++ b/miner/worker.go
@@ -49,10 +49,8 @@ type uint64RingBuffer struct {
// environment is the workers current environment and holds
// all of the current state information
type environment struct {
- totalUsedGas *big.Int // total gas usage in the cycle
state *state.StateDB // apply state changes here
coinbase *state.StateObject // the miner's account
- block *types.Block // the new block
ancestors *set.Set // ancestor set (used for checking uncle parent validity)
family *set.Set // family set (used for checking uncle invalidity)
uncles *set.Set // uncle set
@@ -63,22 +61,12 @@ type environment struct {
ownedAccounts *set.Set
lowGasTxs types.Transactions
localMinedBlocks *uint64RingBuffer // the most recent block numbers that were mined locally (used to check block inclusion)
-}
-// env returns a new environment for the current cycle
-func env(block *types.Block, eth core.Backend) *environment {
- state := state.New(block.Root(), eth.StateDb())
- env := &environment{
- totalUsedGas: new(big.Int),
- state: state,
- block: block,
- ancestors: set.New(),
- family: set.New(),
- uncles: set.New(),
- coinbase: state.GetOrNewStateObject(block.Coinbase()),
- }
+ block *types.Block // the new block
- return env
+ header *types.Header
+ txs []*types.Transaction
+ receipts []*types.Receipt
}
// worker is the main object which takes care of applying messages to the new state
@@ -137,14 +125,20 @@ func newWorker(coinbase common.Address, eth core.Backend) *worker {
func (self *worker) pendingState() *state.StateDB {
self.currentMu.Lock()
defer self.currentMu.Unlock()
-
return self.current.state
}
func (self *worker) pendingBlock() *types.Block {
self.currentMu.Lock()
defer self.currentMu.Unlock()
-
+ if atomic.LoadInt32(&self.mining) == 0 {
+ return types.NewBlock(
+ self.current.header,
+ self.current.txs,
+ nil,
+ self.current.receipts,
+ )
+ }
return self.current.block
}
@@ -206,7 +200,7 @@ out:
// Apply transaction to the pending state if we're not mining
if atomic.LoadInt32(&self.mining) == 0 {
self.mu.Lock()
- self.commitTransactions(types.Transactions{ev.Tx})
+ self.current.commitTransactions(types.Transactions{ev.Tx}, self.gasPrice, self.proc)
self.mu.Unlock()
}
}
@@ -259,8 +253,8 @@ func (self *worker) wait() {
jsonlogger.LogJson(&logger.EthMinerNewBlock{
BlockHash: block.Hash().Hex(),
BlockNumber: block.Number(),
- ChainHeadHash: block.ParentHeaderHash.Hex(),
- BlockPrevHash: block.ParentHeaderHash.Hex(),
+ ChainHeadHash: block.ParentHash().Hex(),
+ BlockPrevHash: block.ParentHash().Hex(),
})
} else {
self.commitNewWork()
@@ -271,14 +265,12 @@ func (self *worker) wait() {
func (self *worker) push() {
if atomic.LoadInt32(&self.mining) == 1 {
- self.current.block.SetRoot(self.current.state.Root())
-
// push new work to agents
for _, agent := range self.agents {
atomic.AddInt32(&self.atWork, 1)
if agent.Work() != nil {
- agent.Work() <- self.current.block.Copy()
+ agent.Work() <- self.current.block
} else {
common.Report(fmt.Sprintf("%v %T\n", agent, agent))
}
@@ -286,22 +278,20 @@ func (self *worker) push() {
}
}
-func (self *worker) makeCurrent() {
- block := self.chain.NewBlock(self.coinbase)
- parent := self.chain.GetBlock(block.ParentHash())
- // TMP fix for build server ...
- if parent == nil {
- return
- }
-
- if block.Time() <= parent.Time() {
- block.Header().Time = parent.Header().Time + 1
+// makeCurrent creates a new environment for the current cycle.
+func (self *worker) makeCurrent(parent *types.Block, header *types.Header) {
+ state := state.New(parent.Root(), self.eth.StateDb())
+ current := &environment{
+ state: state,
+ ancestors: set.New(),
+ family: set.New(),
+ uncles: set.New(),
+ header: header,
+ coinbase: state.GetOrNewStateObject(self.coinbase),
}
- block.Header().Extra = self.extra
// when 08 is processed ancestors contain 07 (quick block)
- current := env(block, self.eth)
- for _, ancestor := range self.chain.GetAncestors(block, 7) {
+ for _, ancestor := range self.chain.GetBlocksFromHash(parent.Hash(), 7) {
for _, uncle := range ancestor.Uncles() {
current.family.Add(uncle.Hash())
}
@@ -309,6 +299,7 @@ func (self *worker) makeCurrent() {
current.ancestors.Add(ancestor.Hash())
}
accounts, _ := self.eth.AccountManager().Accounts()
+
// Keep track of transactions which return errors so they can be removed
current.remove = set.New()
current.tcount = 0
@@ -318,9 +309,6 @@ func (self *worker) makeCurrent() {
if self.current != nil {
current.localMinedBlocks = self.current.localMinedBlocks
}
-
- current.coinbase.SetGasLimit(core.CalcGasLimit(parent))
-
self.current = current
}
@@ -352,13 +340,13 @@ func (self *worker) isBlockLocallyMined(deepBlockNum uint64) bool {
//Does the block at {deepBlockNum} send earnings to my coinbase?
var block = self.chain.GetBlockByNumber(deepBlockNum)
- return block != nil && block.Header().Coinbase == self.coinbase
+ return block != nil && block.Coinbase() == self.coinbase
}
func (self *worker) logLocalMinedBlocks(previous *environment) {
if previous != nil && self.current.localMinedBlocks != nil {
- nextBlockNum := self.current.block.Number().Uint64()
- for checkBlockNum := previous.block.Number().Uint64(); checkBlockNum < nextBlockNum; checkBlockNum++ {
+ nextBlockNum := self.current.block.NumberU64()
+ for checkBlockNum := previous.block.NumberU64(); checkBlockNum < nextBlockNum; checkBlockNum++ {
inspectBlockNum := checkBlockNum - miningLogAtDepth
if self.isBlockLocallyMined(inspectBlockNum) {
glog.V(logger.Info).Infof("🔨 🔗 Mined %d blocks back: block #%v", miningLogAtDepth, inspectBlockNum)
@@ -376,18 +364,35 @@ func (self *worker) commitNewWork() {
defer self.currentMu.Unlock()
tstart := time.Now()
+ parent := self.chain.CurrentBlock()
+ tstamp := tstart.Unix()
+ if tstamp <= parent.Time() {
+ tstamp = parent.Time() + 1
+ }
+ num := parent.Number()
+ header := &types.Header{
+ ParentHash: parent.Hash(),
+ Number: num.Add(num, common.Big1),
+ Difficulty: core.CalcDifficulty(tstamp, parent.Time(), parent.Difficulty()),
+ GasLimit: core.CalcGasLimit(parent),
+ GasUsed: new(big.Int),
+ Coinbase: self.coinbase,
+ Extra: self.extra,
+ Time: uint64(tstamp),
+ }
previous := self.current
- self.makeCurrent()
+ self.makeCurrent(parent, header)
current := self.current
+ // commit transactions for this run.
transactions := self.eth.TxPool().GetTransactions()
sort.Sort(types.TxByNonce{transactions})
-
- // commit transactions for this run
- self.commitTransactions(transactions)
+ current.coinbase.SetGasLimit(header.GasLimit)
+ current.commitTransactions(transactions, self.gasPrice, self.proc)
self.eth.TxPool().RemoveTransactions(current.lowGasTxs)
+ // compute uncles for the new block.
var (
uncles []*types.Header
badUncles []common.Hash
@@ -396,88 +401,76 @@ func (self *worker) commitNewWork() {
if len(uncles) == 2 {
break
}
-
if err := self.commitUncle(uncle.Header()); err != nil {
if glog.V(logger.Ridiculousness) {
glog.V(logger.Detail).Infof("Bad uncle found and will be removed (%x)\n", hash[:4])
glog.V(logger.Detail).Infoln(uncle)
}
-
badUncles = append(badUncles, hash)
} else {
glog.V(logger.Debug).Infof("commiting %x as uncle\n", hash[:4])
uncles = append(uncles, uncle.Header())
}
}
-
- // We only care about logging if we're actually mining
- if atomic.LoadInt32(&self.mining) == 1 {
- glog.V(logger.Info).Infof("commit new work on block %v with %d txs & %d uncles. Took %v\n", current.block.Number(), current.tcount, len(uncles), time.Since(tstart))
- self.logLocalMinedBlocks(previous)
- }
-
for _, hash := range badUncles {
delete(self.possibleUncles, hash)
}
- self.current.block.SetUncles(uncles)
+ // commit state root after all state transitions.
+ core.AccumulateRewards(self.current.state, header, uncles)
+ current.state.Update()
+ header.Root = current.state.Root()
- core.AccumulateRewards(self.current.state, self.current.block)
+ // create the new block whose nonce will be mined.
+ current.block = types.NewBlock(header, current.txs, uncles, current.receipts)
- self.current.state.Update()
+ // We only care about logging if we're actually mining.
+ if atomic.LoadInt32(&self.mining) == 1 {
+ glog.V(logger.Info).Infof("commit new work on block %v with %d txs & %d uncles. Took %v\n", current.block.Number(), current.tcount, len(uncles), time.Since(tstart))
+ self.logLocalMinedBlocks(previous)
+ }
self.push()
}
-var (
- inclusionReward = new(big.Int).Div(core.BlockReward, big.NewInt(32))
- _uncleReward = new(big.Int).Mul(core.BlockReward, big.NewInt(15))
- uncleReward = new(big.Int).Div(_uncleReward, big.NewInt(16))
-)
-
func (self *worker) commitUncle(uncle *types.Header) error {
- if self.current.uncles.Has(uncle.Hash()) {
- // Error not unique
+ hash := uncle.Hash()
+ if self.current.uncles.Has(hash) {
return core.UncleError("Uncle not unique")
}
-
if !self.current.ancestors.Has(uncle.ParentHash) {
return core.UncleError(fmt.Sprintf("Uncle's parent unknown (%x)", uncle.ParentHash[0:4]))
}
-
- if self.current.family.Has(uncle.Hash()) {
- return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", uncle.Hash()))
+ if self.current.family.Has(hash) {
+ return core.UncleError(fmt.Sprintf("Uncle already in family (%x)", hash))
}
self.current.uncles.Add(uncle.Hash())
-
return nil
}
-func (self *worker) commitTransactions(transactions types.Transactions) {
- current := self.current
-
+func (env *environment) commitTransactions(transactions types.Transactions, gasPrice *big.Int, proc *core.BlockProcessor) {
for _, tx := range transactions {
// We can skip err. It has already been validated in the tx pool
from, _ := tx.From()
// Check if it falls within margin. Txs from owned accounts are always processed.
- if tx.GasPrice().Cmp(self.gasPrice) < 0 && !current.ownedAccounts.Has(from) {
+ if tx.GasPrice().Cmp(gasPrice) < 0 && !env.ownedAccounts.Has(from) {
// ignore the transaction and transactor. We ignore the transactor
// because nonce will fail after ignoring this transaction so there's
// no point
- current.lowGasTransactors.Add(from)
+ env.lowGasTransactors.Add(from)
- glog.V(logger.Info).Infof("transaction(%x) below gas price (tx=%v ask=%v). All sequential txs from this address(%x) will be ignored\n", tx.Hash().Bytes()[:4], common.CurrencyToString(tx.GasPrice()), common.CurrencyToString(self.gasPrice), from[:4])
+ glog.V(logger.Info).Infof("transaction(%x) below gas price (tx=%v ask=%v). All sequential txs from this address(%x) will be ignored\n", tx.Hash().Bytes()[:4], common.CurrencyToString(tx.GasPrice()), common.CurrencyToString(gasPrice), from[:4])
}
// Continue with the next transaction if the transaction sender is included in
// the low gas tx set. This will also remove the tx and all sequential transaction
// from this transactor
- if current.lowGasTransactors.Has(from) {
+ if env.lowGasTransactors.Has(from) {
// add tx to the low gas set. This will be removed at the end of the run
// owned accounts are ignored
- if !current.ownedAccounts.Has(from) {
- current.lowGasTxs = append(current.lowGasTxs, tx)
+ if !env.ownedAccounts.Has(from) {
+ env.lowGasTxs = append(env.lowGasTxs, tx)
}
continue
}
@@ -487,46 +480,41 @@ func (self *worker) commitTransactions(transactions types.Transactions) {
// the transaction is processed (that could potentially be included in the block) it
// will throw a nonce error because the previous transaction hasn't been processed.
// Therefor we need to ignore any transaction after the ignored one.
- if current.ignoredTransactors.Has(from) {
+ if env.ignoredTransactors.Has(from) {
continue
}
- self.current.state.StartRecord(tx.Hash(), common.Hash{}, 0)
+ env.state.StartRecord(tx.Hash(), common.Hash{}, 0)
- err := self.commitTransaction(tx)
+ err := env.commitTransaction(tx, proc)
switch {
case core.IsNonceErr(err) || core.IsInvalidTxErr(err):
- current.remove.Add(tx.Hash())
+ env.remove.Add(tx.Hash())
if glog.V(logger.Detail) {
glog.Infof("TX (%x) failed, will be removed: %v\n", tx.Hash().Bytes()[:4], err)
}
case state.IsGasLimitErr(err):
- from, _ := tx.From()
// ignore the transactor so no nonce errors will be thrown for this account
// next time the worker is run, they'll be picked up again.
- current.ignoredTransactors.Add(from)
+ env.ignoredTransactors.Add(from)
glog.V(logger.Detail).Infof("Gas limit reached for (%x) in this block. Continue to try smaller txs\n", from[:4])
default:
- current.tcount++
+ env.tcount++
}
}
-
- self.current.block.Header().GasUsed = self.current.totalUsedGas
}
-func (self *worker) commitTransaction(tx *types.Transaction) error {
- snap := self.current.state.Copy()
- receipt, _, err := self.proc.ApplyTransaction(self.current.coinbase, self.current.state, self.current.block, tx, self.current.totalUsedGas, true)
+func (env *environment) commitTransaction(tx *types.Transaction, proc *core.BlockProcessor) error {
+ snap := env.state.Copy()
+ receipt, _, err := proc.ApplyTransaction(env.coinbase, env.state, env.header, tx, env.header.GasUsed, true)
if err != nil && (core.IsNonceErr(err) || state.IsGasLimitErr(err) || core.IsInvalidTxErr(err)) {
- self.current.state.Set(snap)
+ env.state.Set(snap)
return err
}
-
- self.current.block.AddTransaction(tx)
- self.current.block.AddReceipt(receipt)
-
+ env.txs = append(env.txs, tx)
+ env.receipts = append(env.receipts, receipt)
return nil
}
diff --git a/tests/block_test_util.go b/tests/block_test_util.go
index 5fdc6402e..450ef86a1 100644
--- a/tests/block_test_util.go
+++ b/tests/block_test_util.go
@@ -245,7 +245,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error {
if b.BlockHeader == nil {
continue // OK - block is supposed to be invalid, continue with next block
} else {
- return fmt.Errorf("Block RLP decoding failed when expected to succeed: ", err)
+ return fmt.Errorf("Block RLP decoding failed when expected to succeed: %v", err)
}
}
// RLP decoding worked, try to insert into chain:
@@ -254,7 +254,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error {
if b.BlockHeader == nil {
continue // OK - block is supposed to be invalid, continue with next block
} else {
- return fmt.Errorf("Block insertion into chain failed: ", err)
+ return fmt.Errorf("Block insertion into chain failed: %v", err)
}
}
if b.BlockHeader == nil {
@@ -262,7 +262,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error {
}
err = t.validateBlockHeader(b.BlockHeader, cb.Header())
if err != nil {
- return fmt.Errorf("Block header validation failed: ", err)
+ return fmt.Errorf("Block header validation failed: %v", err)
}
}
return nil
@@ -286,7 +286,7 @@ func (s *BlockTest) validateBlockHeader(h *btHeader, h2 *types.Header) error {
expectedNonce := mustConvertBytes(h.Nonce)
if !bytes.Equal(expectedNonce, h2.Nonce[:]) {
- return fmt.Errorf("Nonce: expected: %v, decoded: %v", expectedNonce, h2.Nonce[:])
+ return fmt.Errorf("Nonce: expected: %v, decoded: %v", expectedNonce, h2.Nonce)
}
expectedNumber := mustConvertBigInt(h.Number, 16)
@@ -423,9 +423,8 @@ func mustConvertHeader(in btHeader) *types.Header {
GasLimit: mustConvertBigInt(in.GasLimit, 16),
Difficulty: mustConvertBigInt(in.Difficulty, 16),
Time: mustConvertUint(in.Timestamp, 16),
+ Nonce: types.EncodeNonce(mustConvertUint(in.Nonce, 16)),
}
- // XXX cheats? :-)
- header.SetNonce(mustConvertUint(in.Nonce, 16))
return header
}
diff --git a/xeth/xeth.go b/xeth/xeth.go
index 11d30ebac..0dbedff43 100644
--- a/xeth/xeth.go
+++ b/xeth/xeth.go
@@ -209,8 +209,8 @@ func (self *XEth) AtStateNum(num int64) *XEth {
// - could be removed in favour of mining on testdag (natspec e2e + networking)
// + filters
func (self *XEth) ApplyTestTxs(statedb *state.StateDB, address common.Address, txc uint64) (uint64, *XEth) {
-
- block := self.backend.ChainManager().NewBlock(address)
+ chain := self.backend.ChainManager()
+ header := chain.CurrentBlock().Header()
coinbase := statedb.GetStateObject(address)
coinbase.SetGasLimit(big.NewInt(10000000))
txs := self.backend.TxPool().GetQueuedTransactions()
@@ -218,7 +218,7 @@ func (self *XEth) ApplyTestTxs(statedb *state.StateDB, address common.Address, t
for i := 0; i < len(txs); i++ {
for _, tx := range txs {
if tx.Nonce() == txc {
- _, _, err := core.ApplyMessage(core.NewEnv(statedb, self.backend.ChainManager(), tx, block), tx, coinbase)
+ _, _, err := core.ApplyMessage(core.NewEnv(statedb, self.backend.ChainManager(), tx, header), tx, coinbase)
if err != nil {
panic(err)
}
@@ -845,8 +845,8 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st
msg.gasPrice = self.DefaultGasPrice()
}
- block := self.CurrentBlock()
- vmenv := core.NewEnv(statedb, self.backend.ChainManager(), msg, block)
+ header := self.CurrentBlock().Header()
+ vmenv := core.NewEnv(statedb, self.backend.ChainManager(), msg, header)
res, gas, err := core.ApplyMessage(vmenv, msg, from)
return common.ToHex(res), gas.String(), err