go-ethereum/core/chain_makers.go

134 lines
4.3 KiB
Go
Raw Normal View History

package core
import (
"fmt"
2015-03-03 10:55:23 -06:00
"math/big"
2015-03-16 05:27:38 -05:00
"github.com/ethereum/go-ethereum/common"
2015-04-01 16:58:26 -05:00
"github.com/ethereum/go-ethereum/core/state"
2015-03-16 17:48:18 -05:00
"github.com/ethereum/go-ethereum/core/types"
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/pow"
)
// So we can generate blocks easily
type FakePow struct{}
func (f FakePow) Search(block pow.Block, stop <-chan struct{}) (uint64, []byte) {
return 0, nil
2015-02-28 13:58:37 -06:00
}
func (f FakePow) Verify(block pow.Block) bool { return true }
func (f FakePow) GetHashrate() int64 { return 0 }
func (f FakePow) Turbo(bool) {}
// So we can deterministically seed different blockchains
var (
CanonicalSeed = 1
ForkSeed = 2
)
2015-02-28 13:58:37 -06:00
// Utility functions for making chains on the fly
// Exposed for sake of testing from other packages (eg. go-ethash)
2015-03-16 05:27:38 -05:00
func MakeBlock(bman *BlockProcessor, parent *types.Block, i int, db common.Database, seed int) *types.Block {
2015-06-16 05:41:50 -05:00
return types.NewBlock(makeHeader(parent, i, db, seed), nil, nil, nil)
}
2015-03-16 05:27:38 -05:00
func MakeChain(bman *BlockProcessor, parent *types.Block, max int, db common.Database, seed int) types.Blocks {
2015-02-28 13:58:37 -06:00
return makeChain(bman, parent, max, db, seed)
}
2015-03-16 05:27:38 -05:00
func NewChainMan(block *types.Block, eventMux *event.TypeMux, db common.Database) *ChainManager {
return newChainManager(block, eventMux, db)
}
func NewBlockProc(db common.Database, cman *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
return newBlockProcessor(db, cman, eventMux)
}
2015-03-16 05:27:38 -05:00
func NewCanonical(n int, db common.Database) (*BlockProcessor, error) {
return newCanonical(n, db)
}
2015-06-16 05:41:50 -05:00
// 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 {
2015-03-16 17:48:18 -05:00
var addr common.Address
2015-06-16 05:41:50 -05:00
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)
2015-04-01 16:58:26 -05:00
state.Update()
2015-06-16 05:41:50 -05:00
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),
}
}
2015-06-16 05:41:50 -05:00
// makeChain creates a valid chain of empty blocks.
2015-03-16 05:27:38 -05:00
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++ {
2015-06-16 05:41:50 -05:00
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)
panic(err)
}
2015-05-15 05:24:29 -05:00
block.Td = CalcTD(block, parent)
blocks[i] = block
parent = block
}
return blocks
}
// Create a new chain manager starting from given block
// Effectively a fork factory
2015-03-16 05:27:38 -05:00
func newChainManager(block *types.Block, eventMux *event.TypeMux, db common.Database) *ChainManager {
genesis := GenesisBlock(0, db)
2015-05-18 10:46:47 -05:00
bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: eventMux, pow: FakePow{}}
2015-04-22 06:09:59 -05:00
bc.txState = state.ManageState(state.New(genesis.Root(), db))
bc.futureBlocks = NewBlockCache(1000)
if block == nil {
bc.Reset()
} else {
bc.currentBlock = block
bc.td = block.Td
}
return bc
}
// block processor with fake pow
func newBlockProcessor(db common.Database, cman *ChainManager, eventMux *event.TypeMux) *BlockProcessor {
chainMan := newChainManager(nil, eventMux, db)
bman := NewBlockProcessor(db, db, FakePow{}, chainMan, eventMux)
return bman
}
2015-02-28 13:58:37 -06:00
// Make a new, deterministic canonical chain by running InsertChain
2015-06-16 05:41:50 -05:00
// on result of makeChain.
2015-03-16 05:27:38 -05:00
func newCanonical(n int, db common.Database) (*BlockProcessor, error) {
eventMux := &event.TypeMux{}
bman := newBlockProcessor(db, newChainManager(nil, eventMux, db), eventMux)
bman.bc.SetProcessor(bman)
parent := bman.bc.CurrentBlock()
if n == 0 {
return bman, nil
}
2015-02-28 13:58:37 -06:00
lchain := makeChain(bman, parent, n, db, CanonicalSeed)
_, err := bman.bc.InsertChain(lchain)
2015-02-28 13:58:37 -06:00
return bman, err
}