diff options
author | Ethan Buchman <ethan@coinculture.info> | 2015-02-28 05:05:03 +0800 |
---|---|---|
committer | Ethan Buchman <ethan@coinculture.info> | 2015-02-28 05:05:03 +0800 |
commit | 0efd6a881afac0b3082f3b1e8780e3438eea5b02 (patch) | |
tree | 41433292b4e22af54bdf747202a1edd799e7ec6e /core | |
parent | 5a827417d9cef0d2a765df11e747b1755bf04898 (diff) | |
download | dexon-0efd6a881afac0b3082f3b1e8780e3438eea5b02.tar.gz dexon-0efd6a881afac0b3082f3b1e8780e3438eea5b02.tar.zst dexon-0efd6a881afac0b3082f3b1e8780e3438eea5b02.zip |
public functions for making chains on the fly
Diffstat (limited to 'core')
-rw-r--r-- | core/chain_makers.go | 131 | ||||
-rw-r--r-- | core/chain_manager_test.go | 96 |
2 files changed, 131 insertions, 96 deletions
diff --git a/core/chain_makers.go b/core/chain_makers.go new file mode 100644 index 000000000..eb43f8aa0 --- /dev/null +++ b/core/chain_makers.go @@ -0,0 +1,131 @@ +package core + +import ( + "fmt" + "github.com/ethereum/go-ethereum/core/types" + "github.com/ethereum/go-ethereum/ethutil" + "github.com/ethereum/go-ethereum/event" + "github.com/ethereum/go-ethereum/pow" + "github.com/ethereum/go-ethereum/state" + "math/big" +) + +// So we can generate blocks easily +type FakePow struct{} + +func (f FakePow) Search(block pow.Block, stop <-chan struct{}) []byte { return nil } +func (f FakePow) Verify(block pow.Block) bool { return true } +func (f FakePow) GetHashrate() int64 { return 0 } +func (f FakePow) Turbo(bool) {} + +func NewBlockFromParent(addr []byte, parent *types.Block) *types.Block { + return newBlockFromParent(addr, parent) +} + +func MakeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database) *types.Block { + return makeBlock(bman, parent, i, db) +} + +func MakeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database) types.Blocks { + return makeChain(bman, parent, max, db) +} + +func NewChainMan(block *types.Block, eventMux *event.TypeMux, db ethutil.Database) *ChainManager { + return newChainManager(block, eventMux, db) +} + +func NewBlockProc(db ethutil.Database, txpool *TxPool, cman *ChainManager, eventMux *event.TypeMux) *BlockProcessor { + return newBlockProcessor(db, txpool, cman, eventMux) +} + +func NewCanonical(n int, db ethutil.Database) (*BlockProcessor, error) { + return newCanonical(n, db) +} + +func newBlockFromParent(addr []byte, parent *types.Block) *types.Block { + block := types.NewBlock(parent.Hash(), addr, parent.Root(), ethutil.BigPow(2, 32), nil, "") + + block.SetUncles(nil) + block.SetTransactions(nil) + block.SetReceipts(nil) + + header := block.Header() + header.Difficulty = CalcDifficulty(block, parent) + header.Number = new(big.Int).Add(parent.Header().Number, ethutil.Big1) + header.GasLimit = CalcGasLimit(parent, block) + + block.Td = parent.Td + + return block +} + +// Actually make a block by simulating what miner would do +func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database) *types.Block { + addr := ethutil.LeftPadBytes([]byte{byte(i)}, 20) + block := newBlockFromParent(addr, parent) + state := state.New(block.Root(), db) + cbase := state.GetOrNewStateObject(addr) + cbase.SetGasPool(CalcGasLimit(parent, block)) + cbase.AddBalance(BlockReward) + state.Update(ethutil.Big0) + block.SetRoot(state.Root()) + return block +} + +// Make a chain with real blocks +// Runs ProcessWithParent to get proper state roots +func makeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database) types.Blocks { + bman.bc.currentBlock = parent + blocks := make(types.Blocks, max) + for i := 0; i < max; i++ { + block := makeBlock(bman, parent, i, db) + td, err := bman.processWithParent(block, parent) + if err != nil { + fmt.Println("process with parent failed", err) + panic(err) + } + block.Td = td + blocks[i] = block + parent = block + fmt.Printf("New Block: %x\n", block.Hash()) + } + fmt.Println("Done making chain") + return blocks +} + +// Create a new chain manager starting from given block +// Effectively a fork factory +func newChainManager(block *types.Block, eventMux *event.TypeMux, db ethutil.Database) *ChainManager { + bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: eventMux} + if block == nil { + bc.Reset() + } else { + bc.currentBlock = block + bc.td = block.Td + } + return bc +} + +// block processor with fake pow +func newBlockProcessor(db ethutil.Database, txpool *TxPool, cman *ChainManager, eventMux *event.TypeMux) *BlockProcessor { + bman := NewBlockProcessor(db, txpool, newChainManager(nil, eventMux, db), eventMux) + bman.Pow = FakePow{} + return bman +} + +// Make a new canonical chain by running InsertChain +// on result of makeChain +func newCanonical(n int, db ethutil.Database) (*BlockProcessor, error) { + eventMux := &event.TypeMux{} + txpool := NewTxPool(eventMux) + + bman := newBlockProcessor(db, txpool, newChainManager(nil, eventMux, db), eventMux) + bman.bc.SetProcessor(bman) + parent := bman.bc.CurrentBlock() + if n == 0 { + return bman, nil + } + lchain := makeChain(bman, parent, n, db) + bman.bc.InsertChain(lchain) + return bman, nil +} diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go index a357a8b1a..b76ac187c 100644 --- a/core/chain_manager_test.go +++ b/core/chain_manager_test.go @@ -19,107 +19,11 @@ import ( "github.com/ethereum/go-ethereum/state" ) -// So we can generate blocks easily -type fakePow struct{} - -func (f fakePow) Search(block pow.Block, stop <-chan struct{}) []byte { return nil } -func (f fakePow) Verify(block pow.Block) bool { return true } -func (f fakePow) GetHashrate() int64 { return 0 } -func (f fakePow) Turbo(bool) {} - func init() { runtime.GOMAXPROCS(runtime.NumCPU()) ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH") } -func newBlockFromParent(addr []byte, parent *types.Block) *types.Block { - block := types.NewBlock(parent.Hash(), addr, parent.Root(), ethutil.BigPow(2, 32), nil, "") - - block.SetUncles(nil) - block.SetTransactions(nil) - block.SetReceipts(nil) - - header := block.Header() - header.Difficulty = CalcDifficulty(block, parent) - header.Number = new(big.Int).Add(parent.Header().Number, ethutil.Big1) - header.GasLimit = CalcGasLimit(parent, block) - - block.Td = parent.Td - - return block -} - -// Actually make a block by simulating what miner would do -func makeBlock(bman *BlockProcessor, parent *types.Block, i int, db ethutil.Database) *types.Block { - addr := ethutil.LeftPadBytes([]byte{byte(i)}, 20) - block := newBlockFromParent(addr, parent) - state := state.New(block.Root(), db) - cbase := state.GetOrNewStateObject(addr) - cbase.SetGasPool(CalcGasLimit(parent, block)) - cbase.AddAmount(BlockReward) - state.Update(ethutil.Big0) - block.SetRoot(state.Root()) - return block -} - -// Make a chain with real blocks -// Runs ProcessWithParent to get proper state roots -func makeChain(bman *BlockProcessor, parent *types.Block, max int, db ethutil.Database) types.Blocks { - bman.bc.currentBlock = parent - blocks := make(types.Blocks, max) - for i := 0; i < max; i++ { - block := makeBlock(bman, parent, i, db) - td, err := bman.processWithParent(block, parent) - if err != nil { - fmt.Println("process with parent failed", err) - panic(err) - } - block.Td = td - blocks[i] = block - parent = block - fmt.Printf("New Block: %x\n", block.Hash()) - } - fmt.Println("Done making chain") - return blocks -} - -// Create a new chain manager starting from given block -// Effectively a fork factory -func newChainManager(block *types.Block, eventMux *event.TypeMux, db ethutil.Database) *ChainManager { - bc := &ChainManager{db: db, genesisBlock: GenesisBlock(db), eventMux: eventMux} - if block == nil { - bc.Reset() - } else { - bc.currentBlock = block - bc.td = block.Td - } - return bc -} - -// block processor with fake pow -func newBlockProcessor(db ethutil.Database, txpool *TxPool, cman *ChainManager, eventMux *event.TypeMux) *BlockProcessor { - bman := NewBlockProcessor(db, txpool, newChainManager(nil, eventMux, db), eventMux) - bman.Pow = fakePow{} - return bman -} - -// Make a new canonical chain by running InsertChain -// on result of makeChain -func newCanonical(n int, db ethutil.Database) (*BlockProcessor, error) { - eventMux := &event.TypeMux{} - txpool := NewTxPool(eventMux) - - bman := newBlockProcessor(db, txpool, newChainManager(nil, eventMux, db), eventMux) - bman.bc.SetProcessor(bman) - parent := bman.bc.CurrentBlock() - if n == 0 { - return bman, nil - } - lchain := makeChain(bman, parent, n, db) - bman.bc.InsertChain(lchain) - return bman, nil -} - // Test fork of length N starting from block i func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big.Int)) { fmt.Println("Testing Fork!") |