Commit 1d42888d authored by Felix Lange's avatar Felix Lange Committed by Jeffrey Wilcke

core/types: make blocks immutable

parent 654564e1
...@@ -11,12 +11,12 @@ import ( ...@@ -11,12 +11,12 @@ import (
func newChain(size int) (chain []*types.Block) { func newChain(size int) (chain []*types.Block) {
var parentHash common.Hash var parentHash common.Hash
for i := 0; i < size; i++ { for i := 0; i < size; i++ {
block := types.NewBlock(parentHash, common.Address{}, common.Hash{}, new(big.Int), 0, nil) head := &types.Header{ParentHash: parentHash, Number: big.NewInt(int64(i))}
block.Header().Number = big.NewInt(int64(i)) block := types.NewBlock(head, nil, nil, nil)
chain = append(chain, block) chain = append(chain, block)
parentHash = block.Hash() parentHash = block.Hash()
} }
return return chain
} }
func insertChainCache(cache *BlockCache, chain []*types.Block) { func insertChainCache(cache *BlockCache, chain []*types.Block) {
......
...@@ -57,8 +57,8 @@ func NewBlockProcessor(db, extra common.Database, pow pow.PoW, chainManager *Cha ...@@ -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) { 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 := statedb.GetOrNewStateObject(block.Coinbase())
coinbase.SetGasLimit(block.Header().GasLimit) coinbase.SetGasLimit(block.GasLimit())
// Process the transactions on to parent state // Process the transactions on to parent state
receipts, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), transientProcess) receipts, err = sm.ApplyTransactions(coinbase, statedb, block, block.Transactions(), transientProcess)
...@@ -69,11 +69,11 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block ...@@ -69,11 +69,11 @@ func (sm *BlockProcessor) TransitionState(statedb *state.StateDB, parent, block
return receipts, nil 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 // If we are mining this block and validating we want to set the logs back to 0
cb := statedb.GetStateObject(coinbase.Address()) 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)) { if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) {
return nil, nil, err return nil, nil, err
} }
...@@ -108,12 +108,13 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state ...@@ -108,12 +108,13 @@ func (self *BlockProcessor) ApplyTransactions(coinbase *state.StateObject, state
totalUsedGas = big.NewInt(0) totalUsedGas = big.NewInt(0)
err error err error
cumulativeSum = new(big.Int) cumulativeSum = new(big.Int)
header = block.Header()
) )
for i, tx := range txs { for i, tx := range txs {
statedb.StartRecord(tx.Hash(), block.Hash(), i) 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)) { if err != nil && (IsNonceErr(err) || state.IsGasLimitErr(err) || IsInvalidTxErr(err)) {
return nil, err return nil, err
} }
...@@ -142,11 +143,10 @@ func (sm *BlockProcessor) RetryProcess(block *types.Block) (logs state.Logs, err ...@@ -142,11 +143,10 @@ func (sm *BlockProcessor) RetryProcess(block *types.Block) (logs state.Logs, err
sm.mutex.Lock() sm.mutex.Lock()
defer sm.mutex.Unlock() defer sm.mutex.Unlock()
header := block.Header() if !sm.bc.HasBlock(block.ParentHash()) {
if !sm.bc.HasBlock(header.ParentHash) { return nil, ParentError(block.ParentHash())
return nil, ParentError(header.ParentHash)
} }
parent := sm.bc.GetBlock(header.ParentHash) parent := sm.bc.GetBlock(block.ParentHash())
// FIXME Change to full header validation. See #1225 // FIXME Change to full header validation. See #1225
errch := make(chan bool) errch := make(chan bool)
...@@ -168,30 +168,32 @@ func (sm *BlockProcessor) Process(block *types.Block) (logs state.Logs, err erro ...@@ -168,30 +168,32 @@ func (sm *BlockProcessor) Process(block *types.Block) (logs state.Logs, err erro
sm.mutex.Lock() sm.mutex.Lock()
defer sm.mutex.Unlock() defer sm.mutex.Unlock()
header := block.Header() if sm.bc.HasBlock(block.Hash()) {
if sm.bc.HasBlock(header.Hash()) { return nil, &KnownBlockError{block.Number(), block.Hash()}
return nil, &KnownBlockError{header.Number, header.Hash()}
} }
if !sm.bc.HasBlock(header.ParentHash) { if !sm.bc.HasBlock(block.ParentHash()) {
return nil, ParentError(header.ParentHash) return nil, ParentError(block.ParentHash())
} }
parent := sm.bc.GetBlock(header.ParentHash) parent := sm.bc.GetBlock(block.ParentHash())
return sm.processWithParent(block, parent) return sm.processWithParent(block, parent)
} }
func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs state.Logs, err error) { 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) // Create a new state based on the parent's root (e.g., create copy)
state := state.New(parent.Root(), sm.db) state := state.New(parent.Root(), sm.db)
header := block.Header()
uncles := block.Uncles()
txs := block.Transactions()
// Block validation // 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 return
} }
// There can be at most two uncles // There can be at most two uncles
if len(block.Uncles()) > 2 { if len(uncles) > 2 {
return nil, ValidationError("Block can only contain maximum 2 uncles (contained %v)", len(block.Uncles())) return nil, ValidationError("Block can only contain maximum 2 uncles (contained %v)", len(uncles))
} }
receipts, err := sm.TransitionState(state, parent, block, false) receipts, err := sm.TransitionState(state, parent, block, false)
...@@ -199,8 +201,6 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st ...@@ -199,8 +201,6 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
return return
} }
header := block.Header()
// Validate the received block's bloom with the one derived from the generated receipts. // Validate the received block's bloom with the one derived from the generated receipts.
// For valid blocks this should always validate to true. // For valid blocks this should always validate to true.
rbloom := types.CreateBloom(receipts) rbloom := types.CreateBloom(receipts)
...@@ -211,7 +211,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st ...@@ -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)]])) // 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 // 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 { if txSha != header.TxHash {
err = fmt.Errorf("invalid transaction root hash. received=%x calculated=%x", header.TxHash, txSha) err = fmt.Errorf("invalid transaction root hash. received=%x calculated=%x", header.TxHash, txSha)
return return
...@@ -225,7 +225,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st ...@@ -225,7 +225,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
} }
// Verify UncleHash before running other uncle validations // Verify UncleHash before running other uncle validations
unclesSha := block.CalculateUnclesHash() unclesSha := types.CalcUncleHash(uncles)
if unclesSha != header.UncleHash { if unclesSha != header.UncleHash {
err = fmt.Errorf("invalid uncles root hash. received=%x calculated=%x", header.UncleHash, unclesSha) err = fmt.Errorf("invalid uncles root hash. received=%x calculated=%x", header.UncleHash, unclesSha)
return return
...@@ -236,7 +236,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st ...@@ -236,7 +236,7 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
return return
} }
// Accumulate static rewards; block reward, uncle's and uncle inclusion. // 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) // Commit state objects/accounts to a temporary trie (does not save)
// used to calculate the state root. // used to calculate the state root.
...@@ -260,11 +260,34 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st ...@@ -260,11 +260,34 @@ func (sm *BlockProcessor) processWithParent(block, parent *types.Block) (logs st
return state.Logs(), nil 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 { func (sm *BlockProcessor) VerifyUncles(statedb *state.StateDB, block, parent *types.Block) error {
ancestors := set.New() ancestors := set.New()
uncles := set.New() uncles := set.New()
ancestorHeaders := make(map[common.Hash]*types.Header) 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() ancestorHeaders[ancestor.Hash()] = ancestor.Header()
ancestors.Add(ancestor.Hash()) ancestors.Add(ancestor.Hash())
// Include ancestors uncles in the uncle set. Uncles must be unique. // 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 ...@@ -325,7 +348,7 @@ func (sm *BlockProcessor) GetLogs(block *types.Block) (logs state.Logs, err erro
// TODO: remove backward compatibility // TODO: remove backward compatibility
var ( var (
parent = sm.bc.GetBlock(block.Header().ParentHash) parent = sm.bc.GetBlock(block.ParentHash())
state = state.New(parent.Root(), sm.db) state = state.New(parent.Root(), sm.db)
) )
...@@ -341,7 +364,7 @@ func ValidateHeader(pow pow.PoW, block, parent *types.Header, checkPow bool) err ...@@ -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)) 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 { if expd.Cmp(block.Difficulty) != 0 {
return fmt.Errorf("Difficulty check failed for block %v, %v", block.Difficulty, expd) 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 ...@@ -375,26 +398,6 @@ func ValidateHeader(pow pow.PoW, block, parent *types.Header, checkPow bool) err
return nil 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) { func getBlockReceipts(db common.Database, bhash common.Hash) (receipts types.Receipts, err error) {
var rdata []byte var rdata []byte
rdata, err = db.Get(append(receiptsPre, bhash[:]...)) rdata, err = db.Get(append(receiptsPre, bhash[:]...))
......
...@@ -26,20 +26,18 @@ func proc() (*BlockProcessor, *ChainManager) { ...@@ -26,20 +26,18 @@ func proc() (*BlockProcessor, *ChainManager) {
} }
func TestNumber(t *testing.T) { func TestNumber(t *testing.T) {
_, chain := proc()
block1 := chain.NewBlock(common.Address{})
block1.Header().Number = big.NewInt(3)
block1.Header().Time--
pow := ezp.New() 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 { 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{}) header = makeHeader(chain.Genesis(), 0, bp.db, 0)
err = ValidateHeader(pow, block1.Header(), chain.Genesis().Header(), false) err = ValidateHeader(pow, header, chain.Genesis().Header(), false)
if err == BlockNumberErr { if err == BlockNumberErr {
t.Errorf("didn't expect block number error") t.Errorf("didn't expect block number error")
} }
......
...@@ -29,12 +29,8 @@ var ( ...@@ -29,12 +29,8 @@ var (
// Utility functions for making chains on the fly // Utility functions for making chains on the fly
// Exposed for sake of testing from other packages (eg. go-ethash) // 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 { 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 { 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) { ...@@ -53,46 +49,38 @@ func NewCanonical(n int, db common.Database) (*BlockProcessor, error) {
return newCanonical(n, db) return newCanonical(n, db)
} }
// block time is fixed at 10 seconds // makeHeader creates the header for a new empty block, simulating
func newBlockFromParent(addr common.Address, parent *types.Block) *types.Block { // what miner would do. We seed chains by the first byte of the coinbase.
block := types.NewBlock(parent.Hash(), addr, parent.Root(), common.BigPow(2, 32), 0, nil) func makeHeader(parent *types.Block, i int, db common.Database, seed int) *types.Header {
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 {
var addr common.Address var addr common.Address
addr[0], addr[19] = byte(seed), byte(i) addr[0], addr[19] = byte(seed), byte(i) // 'random' coinbase
block := newBlockFromParent(addr, parent) time := parent.Time() + 10 // block time is fixed at 10 seconds
state := state.New(block.Root(), db)
// ensure that the block's coinbase has the block reward in the state.
state := state.New(parent.Root(), db)
cbase := state.GetOrNewStateObject(addr) cbase := state.GetOrNewStateObject(addr)
cbase.SetGasLimit(CalcGasLimit(parent)) cbase.SetGasLimit(CalcGasLimit(parent))
cbase.AddBalance(BlockReward) cbase.AddBalance(BlockReward)
state.Update() 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 // makeChain creates a valid chain of empty blocks.
// Runs ProcessWithParent to get proper state roots
func makeChain(bman *BlockProcessor, parent *types.Block, max int, db common.Database, seed int) types.Blocks { func makeChain(bman *BlockProcessor, parent *types.Block, max int, db common.Database, seed int) types.Blocks {
bman.bc.currentBlock = parent bman.bc.currentBlock = parent
blocks := make(types.Blocks, max) blocks := make(types.Blocks, max)
for i := 0; i < max; i++ { 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) _, err := bman.processWithParent(block, parent)
if err != nil { if err != nil {
fmt.Println("process with parent failed", err) fmt.Println("process with parent failed", err)
...@@ -129,7 +117,7 @@ func newBlockProcessor(db common.Database, cman *ChainManager, eventMux *event.T ...@@ -129,7 +117,7 @@ func newBlockProcessor(db common.Database, cman *ChainManager, eventMux *event.T
} }
// Make a new, deterministic canonical chain by running InsertChain // 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) { func newCanonical(n int, db common.Database) (*BlockProcessor, error) {
eventMux := &event.TypeMux{} eventMux := &event.TypeMux{}
......
...@@ -38,23 +38,24 @@ const ( ...@@ -38,23 +38,24 @@ const (
maxTimeFutureBlocks = 30 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) diff := new(big.Int)
adjust := new(big.Int).Div(parentDiff, params.DifficultyBoundDivisor)
adjust := new(big.Int).Div(parent.Difficulty, params.DifficultyBoundDivisor) if big.NewInt(time-parentTime).Cmp(params.DurationLimit) < 0 {
if big.NewInt(int64(block.Time)-int64(parent.Time)).Cmp(params.DurationLimit) < 0 { diff.Add(parentDiff, adjust)
diff.Add(parent.Difficulty, adjust)
} else { } else {
diff.Sub(parent.Difficulty, adjust) diff.Sub(parentDiff, adjust)
} }
if diff.Cmp(params.MinimumDifficulty) < 0 { if diff.Cmp(params.MinimumDifficulty) < 0 {
return params.MinimumDifficulty return params.MinimumDifficulty
} }
return diff return diff
} }
// CalcTD computes the total difficulty of block.
func CalcTD(block, parent *types.Block) *big.Int { func CalcTD(block, parent *types.Block) *big.Int {
if parent == nil { if parent == nil {
return block.Difficulty() return block.Difficulty()
...@@ -62,6 +63,8 @@ func CalcTD(block, parent *types.Block) *big.Int { ...@@ -62,6 +63,8 @@ func CalcTD(block, parent *types.Block) *big.Int {
return new(big.Int).Add(parent.Td, block.Header().Difficulty) 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 { func CalcGasLimit(parent *types.Block) *big.Int {
decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor) decay := new(big.Int).Div(parent.GasLimit(), params.GasLimitBoundDivisor)
contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3)) contrib := new(big.Int).Mul(parent.GasUsed(), big.NewInt(3))
...@@ -71,11 +74,11 @@ func CalcGasLimit(parent *types.Block) *big.Int { ...@@ -71,11 +74,11 @@ func CalcGasLimit(parent *types.Block) *big.Int {
gl := new(big.Int).Sub(parent.GasLimit(), decay) gl := new(big.Int).Sub(parent.GasLimit(), decay)
gl = gl.Add(gl, contrib) gl = gl.Add(gl, contrib)
gl = gl.Add(gl, big.NewInt(1)) 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 { if gl.Cmp(params.GenesisGasLimit) < 0 {
gl2 := new(big.Int).Add(parent.GasLimit(), decay) gl.Add(parent.GasLimit(), decay)
return common.BigMin(params.GenesisGasLimit, gl2) gl.Set(common.BigMin(gl, params.GenesisGasLimit))
} }
return gl return gl
} }
...@@ -255,50 +258,11 @@ func (bc *ChainManager) makeCache() { ...@@ -255,50 +258,11 @@ func (bc *ChainManager) makeCache() {
bc.cache = NewBlockCache(blockCacheLimit) bc.cache = NewBlockCache(blockCacheLimit)
} }
// load in last `blockCacheLimit` - 1 blocks. Last block is the current. // load in last `blockCacheLimit` - 1 blocks. Last block is the current.
ancestors := bc.GetAncestors(bc.currentBlock, blockCacheLimit-1) for _, block := range bc.GetBlocksFromHash(bc.currentBlock.Hash(), blockCacheLimit) {
ancestors = append(ancestors, bc.currentBlock)
for _, block := range ancestors {
bc.cache.Push(block) 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() { func (bc *ChainManager) Reset() {
bc.mu.Lock() bc.mu.Lock()
defer bc.mu.Unlock() defer bc.mu.Unlock()
...@@ -463,6 +427,19 @@ func (self *ChainManager) GetBlockByNumber(num uint64) *types.Block { ...@@ -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 // non blocking version
func (self *ChainManager) getBlockByNumber(num uint64) *types.Block { func (self *ChainManager) getBlockByNumber(num uint64) *types.Block {
key, _ := self.blockDb.Get(append(blockNumPre, big.NewInt(int64(num)).Bytes()...)) 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 ...@@ -482,19 +459,6 @@ func (self *ChainManager) GetUnclesInChain(block *types.Block, length int) (uncl
return 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 // setTotalDifficulty updates the TD of the chain manager. Note, this function
// assumes that the `mu` mutex is held! // assumes that the `mu` mutex is held!
func (bc *ChainManager) setTotalDifficulty(td *big.Int) { func (bc *ChainManager) setTotalDifficulty(td *big.Int) {
...@@ -621,14 +585,12 @@ func (self *ChainManager) InsertChain(chain types.Blocks) (int, error) { ...@@ -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) return i, fmt.Errorf("%v: BlockFutureErr, %v > %v", BlockFutureErr, block.Time(), max)
} }
block.SetQueued(true)
self.futureBlocks.Push(block) self.futureBlocks.Push(block)
stats.queued++ stats.queued++
continue continue
} }
if IsParentErr(err) && self.futureBlocks.Has(block.ParentHash()) { if IsParentErr(err) && self.futureBlocks.Has(block.ParentHash()) {
block.SetQueued(true)
self.futureBlocks.Push(block) self.futureBlocks.Push(block)
stats.queued++ stats.queued++
continue continue
......
...@@ -117,7 +117,7 @@ func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) { ...@@ -117,7 +117,7 @@ func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) {
} }
func loadChain(fn string, t *testing.T) (types.Blocks, 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 { if err != nil {
return nil, err return nil, err
} }
...@@ -265,7 +265,7 @@ func TestBrokenChain(t *testing.T) { ...@@ -265,7 +265,7 @@ func TestBrokenChain(t *testing.T) {
} }
func TestChainInsertions(t *testing.T) { func TestChainInsertions(t *testing.T) {
t.Skip() // travil fails. t.Skip("Skipped: outdated test files")
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
...@@ -303,7 +303,7 @@ func TestChainInsertions(t *testing.T) { ...@@ -303,7 +303,7 @@ func TestChainInsertions(t *testing.T) {
} }
func TestChainMultipleInsertions(t *testing.T) { func TestChainMultipleInsertions(t *testing.T) {
t.Skip() // travil fails. t.Skip("Skipped: outdated test files")
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
...@@ -346,8 +346,8 @@ func TestChainMultipleInsertions(t *testing.T) { ...@@ -346,8 +346,8 @@ func TestChainMultipleInsertions(t *testing.T) {
} }
} }
func TestGetAncestors(t *testing.T) { func TestGetBlocksFromHash(t *testing.T) {
t.Skip() // travil fails. t.Skip("Skipped: outdated test files")
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
chainMan := theChainManager(db, t) chainMan := theChainManager(db, t)
...@@ -361,8 +361,8 @@ func TestGetAncestors(t *testing.T) { ...@@ -361,8 +361,8 @@ func TestGetAncestors(t *testing.T) {
chainMan.write(block) chainMan.write(block)
} }
ancestors := chainMan.GetAncestors(chain[len(chain)-1], 4) blocks := chainMan.GetBlocksFromHash(chain[len(chain)-1].Hash(), 4)
fmt.Println(ancestors) fmt.Println(blocks)
} }
type bproc struct{} type bproc struct{}
...@@ -372,15 +372,17 @@ func (bproc) Process(*types.Block) (state.Logs, error) { return nil, nil } ...@@ -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 { func makeChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block {
var chain []*types.Block var chain []*types.Block
for i, difficulty := range d { for i, difficulty := range d {
header := &types.Header{Number: big.NewInt(int64(i + 1)), Difficulty: big.NewInt(int64(difficulty))} header := &types.Header{
block := types.NewBlockWithHeader(header) Coinbase: common.Address{seed},
copy(block.HeaderHash[:2], []byte{byte(i + 1), seed}) Number: big.NewInt(int64(i + 1)),
Difficulty: big.NewInt(int64(difficulty)),
}
if i == 0 { if i == 0 {
block.ParentHeaderHash = genesis.Hash() header.ParentHash = genesis.Hash()
} else { } else {
copy(block.ParentHeaderHash[:2], []byte{byte(i), seed}) header.ParentHash = chain[i-1].Hash()
} }
block := types.NewBlockWithHeader(header)
chain = append(chain, block) chain = append(chain, block)
} }
return chain return chain
...@@ -399,7 +401,6 @@ func chm(genesis *types.Block, db common.Database) *ChainManager { ...@@ -399,7 +401,6 @@ func chm(genesis *types.Block, db common.Database) *ChainManager {
} }
func TestReorgLongest(t *testing.T) { func TestReorgLongest(t *testing.T) {
t.Skip("skipped while cache is removed")
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
genesis := GenesisBlock(0, db) genesis := GenesisBlock(0, db)
bc := chm(genesis, db) bc := chm(genesis, db)
...@@ -419,7 +420,6 @@ func TestReorgLongest(t *testing.T) { ...@@ -419,7 +420,6 @@ func TestReorgLongest(t *testing.T) {
} }
func TestReorgShortest(t *testing.T) { func TestReorgShortest(t *testing.T) {
t.Skip("skipped while cache is removed")
db, _ := ethdb.NewMemDatabase() db, _ := ethdb.NewMemDatabase()
genesis := GenesisBlock(0, db) genesis := GenesisBlock(0, db)
bc := chm(genesis, db) bc := chm(genesis, db)
......
...@@ -11,38 +11,18 @@ import ( ...@@ -11,38 +11,18 @@ import (
"github.com/ethereum/go-ethereum/params" "github.com/ethereum/go-ethereum/params"
) )
/* // GenesisBlock creates a genesis block with the given nonce.
* This is the special genesis block.
*/
var ZeroHash256 = make([]byte, 32)
var ZeroHash160 = make([]byte, 20)
var ZeroHash512 = make([]byte, 64)
func GenesisBlock(nonce uint64, db common.Database) *types.Block { 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 { var accounts map[string]struct {
Balance string Balance string
Code string Code string
} }
err := json.Unmarshal(GenesisAccounts, &accounts) err := json.Unmarshal(GenesisAccounts, &accounts)
if err != nil { if err != nil {
fmt.Println("enable to decode genesis json data:", err) fmt.Println("unable to decode genesis json data:", err)
os.Exit(1) os.Exit(1)
} }
statedb := state.New(common.Hash{}, db)
statedb := state.New(genesis.Root(), db)
for addr, account := range accounts { for addr, account := range accounts {
codedAddr := common.Hex2Bytes(addr) codedAddr := common.Hex2Bytes(addr)
accountState := statedb.CreateAccount(common.BytesToAddress(codedAddr)) accountState := statedb.CreateAccount(common.BytesToAddress(codedAddr))
...@@ -51,10 +31,15 @@ func GenesisBlock(nonce uint64, db common.Database) *types.Block { ...@@ -51,10 +31,15 @@ func GenesisBlock(nonce uint64, db common.Database) *types.Block {
statedb.UpdateStateObject(accountState) statedb.UpdateStateObject(accountState)
} }
statedb.Sync() 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(`{ var GenesisAccounts = []byte(`{
......
...@@ -73,16 +73,17 @@ func MessageGasValue(msg Message) *big.Int { ...@@ -73,16 +73,17 @@ func MessageGasValue(msg Message) *big.Int {
return new(big.Int).Mul(msg.Gas(), msg.GasPrice()) 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) igas := new(big.Int).Set(params.TxGas)
for _, byt := range msg.Data() { for _, byt := range data {
if byt != 0 { if byt != 0 {
igas.Add(igas, params.TxDataNonZeroGas) igas.Add(igas, params.TxDataNonZeroGas)
} else { } else {
igas.Add(igas, params.TxDataZeroGas) igas.Add(igas, params.TxDataZeroGas)
} }
} }
return igas return igas
} }
...@@ -195,7 +196,7 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er ...@@ -195,7 +196,7 @@ func (self *StateTransition) transitionState() (ret []byte, usedGas *big.Int, er
sender, _ := self.From() // err checked in preCheck sender, _ := self.From() // err checked in preCheck
// Pay intrinsic gas // 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) return nil, nil, InvalidTxError(err)
} }
......
...@@ -180,7 +180,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error { ...@@ -180,7 +180,7 @@ func (pool *TxPool) validateTx(tx *types.Transaction) error {
} }
// Should supply enough intrinsic gas // Should supply enough intrinsic gas
if tx.Gas().Cmp(IntrinsicGas(tx)) < 0 { if tx.Gas().Cmp(IntrinsicGas(tx.Data())) < 0 {
return ErrIntrinsicGas return ErrIntrinsicGas
} }
......
This diff is collapsed.
...@@ -10,32 +10,32 @@ import ( ...@@ -10,32 +10,32 @@ import (
) )
type VMEnv struct { type VMEnv struct {
state *state.StateDB state *state.StateDB
block *types.Block header *types.Header
msg Message msg Message
depth int depth int
chain *ChainManager chain *ChainManager
typ vm.Type typ vm.Type
// structured logging // structured logging
logs []vm.StructLog 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{ return &VMEnv{
chain: chain, chain: chain,
state: state, state: state,
block: block, header: header,
msg: msg, msg: msg,
typ: vm.StdVmTy, typ: vm.StdVmTy,
} }
} }
func (self *VMEnv) Origin() common.Address { f, _ := self.msg.From(); return f } 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) BlockNumber() *big.Int { return self.header.Number }
func (self *VMEnv) Coinbase() common.Address { return self.block.Coinbase() } func (self *VMEnv) Coinbase() common.Address { return self.header.Coinbase }
func (self *VMEnv) Time() int64 { return self.block.Time() } func (self *VMEnv) Time() int64 { return int64(self.header.Time) }
func (self *VMEnv) Difficulty() *big.Int { return self.block.Difficulty() } func (self *VMEnv) Difficulty() *big.Int { return self.header.Difficulty }
func (self *VMEnv) GasLimit() *big.Int { return self.block.GasLimit() } func (self *VMEnv) GasLimit() *big.Int { return self.header.GasLimit }
func (self *VMEnv) Value() *big.Int { return self.msg.Value() } func (self *VMEnv) Value() *big.Int { return self.msg.Value() }
func (self *VMEnv) State() *state.StateDB { return self.state } func (self *VMEnv) State() *state.StateDB { return self.state }
func (self *VMEnv) Depth() int { return self.depth } func (self *VMEnv) Depth() int { return self.depth }
......
...@@ -40,7 +40,10 @@ func createHashes(amount int, root common.Hash) (hashes []common.Hash) { ...@@ -40,7 +40,10 @@ func createHashes(amount int, root common.Hash) (hashes []common.Hash) {
// createBlock assembles a new block at the given chain height. // createBlock assembles a new block at the given chain height.
func createBlock(i int, parent, hash common.Hash) *types.Block { 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 := types.NewBlockWithHeader(header)
block.HeaderHash = hash block.HeaderHash = hash
block.ParentHeaderHash = parent block.ParentHeaderHash = parent
......
...@@ -90,15 +90,13 @@ done: ...@@ -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) glog.V(logger.Debug).Infof("(re)started agent[%d]. mining...\n", self.index)
// Mine // Mine
nonce, mixDigest := self.pow.Search(block, stop) nonce, mixDigest := self.pow.Search(block, stop)
if nonce != 0 { if nonce != 0 {
block.SetNonce(nonce) self.returnCh <- block.WithMiningResult(nonce, common.BytesToHash(mixDigest))
block.Header().MixDigest = common.BytesToHash(mixDigest)
self.returnCh <- block
} else { } else {
self.returnCh <- nil self.returnCh <- nil
} }
......
...@@ -81,9 +81,7 @@ func (a *RemoteAgent) SubmitWork(nonce uint64, mixDigest, seedHash common.Hash) ...@@ -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 // Make sure the external miner was working on the right hash
if a.currentWork != nil && a.work != nil { if a.currentWork != nil && a.work != nil {
a.currentWork.SetNonce(nonce) a.returnCh <- a.currentWork.WithMiningResult(nonce, mixDigest)
a.currentWork.Header().MixDigest = mixDigest
a.returnCh <- a.currentWork
//a.returnCh <- Work{a.currentWork.Number().Uint64(), nonce, mixDigest.Bytes(), seedHash.Bytes()} //a.returnCh <- Work{a.currentWork.Number().Uint64(), nonce, mixDigest.Bytes(), seedHash.Bytes()}
return true return true
} }
......
This diff is collapsed.
...@@ -245,7 +245,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error { ...@@ -245,7 +245,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error {
if b.BlockHeader == nil { if b.BlockHeader == nil {
continue // OK - block is supposed to be invalid, continue with next block continue // OK - block is supposed to be invalid, continue with next block
} else { } 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: // RLP decoding worked, try to insert into chain:
...@@ -254,7 +254,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error { ...@@ -254,7 +254,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error {
if b.BlockHeader == nil { if b.BlockHeader == nil {
continue // OK - block is supposed to be invalid, continue with next block continue // OK - block is supposed to be invalid, continue with next block
} else { } else {
return fmt.Errorf("Block insertion into chain failed: ", err) return fmt.Errorf("Block insertion into chain failed: %v", err)
} }
} }
if b.BlockHeader == nil { if b.BlockHeader == nil {
...@@ -262,7 +262,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error { ...@@ -262,7 +262,7 @@ func (t *BlockTest) TryBlocksInsert(chainManager *core.ChainManager) error {
} }
err = t.validateBlockHeader(b.BlockHeader, cb.Header()) err = t.validateBlockHeader(b.BlockHeader, cb.Header())
if err != nil { if err != nil {
return fmt.Errorf("Block header validation failed: ", err) return fmt.Errorf("Block header validation failed: %v", err)
} }
} }
return nil return nil
...@@ -286,7 +286,7 @@ func (s *BlockTest) validateBlockHeader(h *btHeader, h2 *types.Header) error { ...@@ -286,7 +286,7 @@ func (s *BlockTest) validateBlockHeader(h *btHeader, h2 *types.Header) error {
expectedNonce := mustConvertBytes(h.Nonce) expectedNonce := mustConvertBytes(h.Nonce)
if !bytes.Equal(expectedNonce, h2.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) expectedNumber := mustConvertBigInt(h.Number, 16)
...@@ -423,9 +423,8 @@ func mustConvertHeader(in btHeader) *types.Header { ...@@ -423,9 +423,8 @@ func mustConvertHeader(in btHeader) *types.Header {
GasLimit: mustConvertBigInt(in.GasLimit, 16), GasLimit: mustConvertBigInt(in.GasLimit, 16),
Difficulty: mustConvertBigInt(in.Difficulty, 16), Difficulty: mustConvertBigInt(in.Difficulty, 16),
Time: mustConvertUint(in.Timestamp, 16), Time: mustConvertUint(in.Timestamp, 16),
Nonce: types.EncodeNonce(mustConvertUint(in.Nonce, 16)),
} }
// XXX cheats? :-)
header.SetNonce(mustConvertUint(in.Nonce, 16))
return header return header
} }
......
...@@ -209,8 +209,8 @@ func (self *XEth) AtStateNum(num int64) *XEth { ...@@ -209,8 +209,8 @@ func (self *XEth) AtStateNum(num int64) *XEth {
// - could be removed in favour of mining on testdag (natspec e2e + networking) // - could be removed in favour of mining on testdag (natspec e2e + networking)
// + filters // + filters
func (self *XEth) ApplyTestTxs(statedb *state.StateDB, address common.Address, txc uint64) (uint64, *XEth) { func (self *XEth) ApplyTestTxs(statedb *state.StateDB, address common.Address, txc uint64) (uint64, *XEth) {
chain := self.backend.ChainManager()
block := self.backend.ChainManager().NewBlock(address) header := chain.CurrentBlock().Header()
coinbase := statedb.GetStateObject(address) coinbase := statedb.GetStateObject(address)
coinbase.SetGasLimit(big.NewInt(10000000)) coinbase.SetGasLimit(big.NewInt(10000000))
txs := self.backend.TxPool().GetQueuedTransactions() txs := self.backend.TxPool().GetQueuedTransactions()
...@@ -218,7 +218,7 @@ func (self *XEth) ApplyTestTxs(statedb *state.StateDB, address common.Address, t ...@@ -218,7 +218,7 @@ func (self *XEth) ApplyTestTxs(statedb *state.StateDB, address common.Address, t
for i := 0; i < len(txs); i++ { for i := 0; i < len(txs); i++ {
for _, tx := range txs { for _, tx := range txs {
if tx.Nonce() == txc { 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 { if err != nil {
panic(err) panic(err)
} }
...@@ -845,8 +845,8 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st ...@@ -845,8 +845,8 @@ func (self *XEth) Call(fromStr, toStr, valueStr, gasStr, gasPriceStr, dataStr st
msg.gasPrice = self.DefaultGasPrice() msg.gasPrice = self.DefaultGasPrice()
} }
block := self.CurrentBlock() header := self.CurrentBlock().Header()
vmenv := core.NewEnv(statedb, self.backend.ChainManager(), msg, block) vmenv := core.NewEnv(statedb, self.backend.ChainManager(), msg, header)
res, gas, err := core.ApplyMessage(vmenv, msg, from) res, gas, err := core.ApplyMessage(vmenv, msg, from)
return common.ToHex(res), gas.String(), err return common.ToHex(res), gas.String(), err
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment