aboutsummaryrefslogtreecommitdiffstats
path: root/core
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 /core
parent654564e164b3b6f7f4ba1e8bbd6fcd64776068fa (diff)
downloadgo-tangerine-1d42888d3047dabfb352c94a2051e7af14d2a509.tar.gz
go-tangerine-1d42888d3047dabfb352c94a2051e7af14d2a509.tar.zst
go-tangerine-1d42888d3047dabfb352c94a2051e7af14d2a509.zip
core/types: make blocks immutable
Diffstat (limited to 'core')
-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
11 files changed, 343 insertions, 459 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 }