From 6244b10a8f74d92addf977994e5a9c0e457229bb Mon Sep 17 00:00:00 2001 From: obscuren Date: Mon, 8 Jun 2015 12:12:13 +0200 Subject: core: settable genesis nonce You can set the nonce of the block with `--genesisnonce`. When the genesis nonce changes and it doesn't match with the first block in your database it will fail. A new `datadir` must be given if the nonce of the genesis block changes. --- core/block_processor_test.go | 7 +++++- core/chain_makers.go | 2 +- core/chain_manager.go | 24 +++++++++++++-------- core/chain_manager_test.go | 51 +++++++++++++++++++++++++++++++++----------- core/genesis.go | 4 ++-- 5 files changed, 62 insertions(+), 26 deletions(-) (limited to 'core') diff --git a/core/block_processor_test.go b/core/block_processor_test.go index b52c3d3f8..97b80038d 100644 --- a/core/block_processor_test.go +++ b/core/block_processor_test.go @@ -1,6 +1,7 @@ package core import ( + "fmt" "math/big" "testing" @@ -16,7 +17,11 @@ func proc() (*BlockProcessor, *ChainManager) { db, _ := ethdb.NewMemDatabase() var mux event.TypeMux - chainMan := NewChainManager(db, db, thePow(), &mux) + genesis := GenesisBlock(0, db) + chainMan, err := NewChainManager(genesis, db, db, thePow(), &mux) + if err != nil { + fmt.Println(err) + } return NewBlockProcessor(db, db, ezp.New(), chainMan, &mux), chainMan } diff --git a/core/chain_makers.go b/core/chain_makers.go index 3039e52da..4e685f599 100644 --- a/core/chain_makers.go +++ b/core/chain_makers.go @@ -108,7 +108,7 @@ func makeChain(bman *BlockProcessor, parent *types.Block, max int, db common.Dat // Create a new chain manager starting from given block // Effectively a fork factory func newChainManager(block *types.Block, eventMux *event.TypeMux, db common.Database) *ChainManager { - genesis := GenesisBlock(db) + genesis := GenesisBlock(0, db) bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: eventMux, pow: FakePow{}} bc.txState = state.ManageState(state.New(genesis.Root(), db)) bc.futureBlocks = NewBlockCache(1000) diff --git a/core/chain_manager.go b/core/chain_manager.go index 291e411ae..edd1cc742 100644 --- a/core/chain_manager.go +++ b/core/chain_manager.go @@ -109,16 +109,22 @@ type ChainManager struct { pow pow.PoW } -func NewChainManager(blockDb, stateDb common.Database, pow pow.PoW, mux *event.TypeMux) *ChainManager { +func NewChainManager(genesis *types.Block, blockDb, stateDb common.Database, pow pow.PoW, mux *event.TypeMux) (*ChainManager, error) { bc := &ChainManager{ - blockDb: blockDb, - stateDb: stateDb, - genesisBlock: GenesisBlock(stateDb), - eventMux: mux, - quit: make(chan struct{}), - cache: NewBlockCache(blockCacheLimit), - pow: pow, + blockDb: blockDb, + stateDb: stateDb, + eventMux: mux, + quit: make(chan struct{}), + cache: NewBlockCache(blockCacheLimit), + pow: pow, } + + // Check the genesis block given to the chain manager. If the genesis block mismatches block number 0 + // throw an error. If no block or the same block's found continue. + if g := bc.GetBlockByNumber(0); g != nil && g.Hash() != genesis.Hash() { + return nil, fmt.Errorf("Genesis mismatch. Maybe different nonce (%d vs %d)? %x / %x", g.Nonce(), genesis.Nonce(), g.Hash().Bytes()[:4], genesis.Hash().Bytes()[:4]) + } + bc.genesisBlock = genesis bc.setLastState() // Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain @@ -144,7 +150,7 @@ func NewChainManager(blockDb, stateDb common.Database, pow pow.PoW, mux *event.T go bc.update() - return bc + return bc, nil } func (bc *ChainManager) SetHead(head *types.Block) { diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go index 45bec7140..c56a3b3e1 100644 --- a/core/chain_manager_test.go +++ b/core/chain_manager_test.go @@ -29,6 +29,21 @@ func thePow() pow.PoW { return pow } +func theChainManager(db common.Database, t *testing.T) *ChainManager { + var eventMux event.TypeMux + genesis := GenesisBlock(0, db) + chainMan, err := NewChainManager(genesis, db, db, thePow(), &eventMux) + if err != nil { + t.Error("failed creating chainmanager:", err) + t.FailNow() + return nil + } + blockMan := NewBlockProcessor(db, db, nil, chainMan, &eventMux) + chainMan.SetProcessor(blockMan) + + return chainMan +} + // 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)) { // switch databases to process the new chain @@ -266,10 +281,7 @@ func TestChainInsertions(t *testing.T) { t.FailNow() } - var eventMux event.TypeMux - chainMan := NewChainManager(db, db, thePow(), &eventMux) - blockMan := NewBlockProcessor(db, db, nil, chainMan, &eventMux) - chainMan.SetProcessor(blockMan) + chainMan := theChainManager(db, t) const max = 2 done := make(chan bool, max) @@ -311,10 +323,9 @@ func TestChainMultipleInsertions(t *testing.T) { t.FailNow() } } - var eventMux event.TypeMux - chainMan := NewChainManager(db, db, thePow(), &eventMux) - blockMan := NewBlockProcessor(db, db, nil, chainMan, &eventMux) - chainMan.SetProcessor(blockMan) + + chainMan := theChainManager(db, t) + done := make(chan bool, max) for i, chain := range chains { // XXX the go routine would otherwise reference the same (chain[3]) variable and fail @@ -339,8 +350,7 @@ func TestGetAncestors(t *testing.T) { t.Skip() // travil fails. db, _ := ethdb.NewMemDatabase() - var eventMux event.TypeMux - chainMan := NewChainManager(db, db, thePow(), &eventMux) + chainMan := theChainManager(db, t) chain, err := loadChain("valid1", t) if err != nil { fmt.Println(err) @@ -391,7 +401,7 @@ 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(db) + genesis := GenesisBlock(0, db) bc := chm(genesis, db) chain1 := makeChainWithDiff(genesis, []int{1, 2, 4}, 10) @@ -411,7 +421,7 @@ func TestReorgLongest(t *testing.T) { func TestReorgShortest(t *testing.T) { t.Skip("skipped while cache is removed") db, _ := ethdb.NewMemDatabase() - genesis := GenesisBlock(db) + genesis := GenesisBlock(0, db) bc := chm(genesis, db) chain1 := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 10) @@ -431,7 +441,7 @@ func TestReorgShortest(t *testing.T) { func TestInsertNonceError(t *testing.T) { for i := 1; i < 25 && !t.Failed(); i++ { db, _ := ethdb.NewMemDatabase() - genesis := GenesisBlock(db) + genesis := GenesisBlock(0, db) bc := chm(genesis, db) bc.processor = NewBlockProcessor(db, db, bc.pow, bc, bc.eventMux) blocks := makeChain(bc.processor.(*BlockProcessor), bc.currentBlock, i, db, 0) @@ -465,6 +475,21 @@ func TestInsertNonceError(t *testing.T) { } } +func TestGenesisMismatch(t *testing.T) { + db, _ := ethdb.NewMemDatabase() + var mux event.TypeMux + genesis := GenesisBlock(0, db) + _, err := NewChainManager(genesis, db, db, thePow(), &mux) + if err != nil { + t.Error(err) + } + genesis = GenesisBlock(1, db) + _, err = NewChainManager(genesis, db, db, thePow(), &mux) + if err == nil { + t.Error("expected genesis mismatch error") + } +} + // failpow returns false from Verify for a certain block number. type failpow struct{ num uint64 } diff --git a/core/genesis.go b/core/genesis.go index a9b7339f3..dd894e0b0 100644 --- a/core/genesis.go +++ b/core/genesis.go @@ -19,8 +19,8 @@ var ZeroHash256 = make([]byte, 32) var ZeroHash160 = make([]byte, 20) var ZeroHash512 = make([]byte, 64) -func GenesisBlock(db common.Database) *types.Block { - genesis := types.NewBlock(common.Hash{}, common.Address{}, common.Hash{}, params.GenesisDifficulty, 42, nil) +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 -- cgit v1.2.3