aboutsummaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
Diffstat (limited to 'core')
-rw-r--r--core/bench_test.go4
-rw-r--r--core/block_processor_test.go4
-rw-r--r--core/chain_makers.go4
-rw-r--r--core/chain_makers_test.go4
-rw-r--r--core/chain_manager.go85
-rw-r--r--core/chain_manager_test.go46
-rw-r--r--core/chain_util.go25
-rw-r--r--core/genesis.go134
8 files changed, 196 insertions, 110 deletions
diff --git a/core/bench_test.go b/core/bench_test.go
index 645df48c2..018d27d8d 100644
--- a/core/bench_test.go
+++ b/core/bench_test.go
@@ -162,13 +162,13 @@ func benchInsertChain(b *testing.B, disk bool, gen func(int, *BlockGen)) {
// Generate a chain of b.N blocks using the supplied block
// generator function.
- genesis := GenesisBlockForTesting(db, benchRootAddr, benchRootFunds)
+ genesis := WriteGenesisBlockForTesting(db, benchRootAddr, benchRootFunds)
chain := GenerateChain(genesis, db, b.N, gen)
// Time the insertion of the new chain.
// State and blocks are stored in the same DB.
evmux := new(event.TypeMux)
- chainman, _ := NewChainManager(genesis, db, db, db, FakePow{}, evmux)
+ chainman, _ := NewChainManager(db, db, db, FakePow{}, evmux)
chainman.SetProcessor(NewBlockProcessor(db, db, FakePow{}, chainman, evmux))
defer chainman.Stop()
b.ReportAllocs()
diff --git a/core/block_processor_test.go b/core/block_processor_test.go
index 4250b897b..dab5be974 100644
--- a/core/block_processor_test.go
+++ b/core/block_processor_test.go
@@ -33,8 +33,8 @@ func proc() (*BlockProcessor, *ChainManager) {
db, _ := ethdb.NewMemDatabase()
var mux event.TypeMux
- genesis := GenesisBlock(0, db)
- chainMan, err := NewChainManager(genesis, db, db, db, thePow(), &mux)
+ WriteTestNetGenesisBlock(db, db, 0)
+ chainMan, err := NewChainManager(db, db, db, thePow(), &mux)
if err != nil {
fmt.Println(err)
}
diff --git a/core/chain_makers.go b/core/chain_makers.go
index 501fe7a92..93f381e78 100644
--- a/core/chain_makers.go
+++ b/core/chain_makers.go
@@ -183,7 +183,9 @@ func makeHeader(parent *types.Block, state *state.StateDB) *types.Header {
// InsertChain on the result of makeChain.
func newCanonical(n int, db common.Database) (*BlockProcessor, error) {
evmux := &event.TypeMux{}
- chainman, _ := NewChainManager(GenesisBlock(0, db), db, db, db, FakePow{}, evmux)
+
+ WriteTestNetGenesisBlock(db, db, 0)
+ chainman, _ := NewChainManager(db, db, db, FakePow{}, evmux)
bman := NewBlockProcessor(db, db, FakePow{}, chainman, evmux)
bman.bc.SetProcessor(bman)
parent := bman.bc.CurrentBlock()
diff --git a/core/chain_makers_test.go b/core/chain_makers_test.go
index 2f001be9b..ddd54d217 100644
--- a/core/chain_makers_test.go
+++ b/core/chain_makers_test.go
@@ -39,7 +39,7 @@ func ExampleGenerateChain() {
)
// Ensure that key1 has some funds in the genesis block.
- genesis := GenesisBlockForTesting(db, addr1, big.NewInt(1000000))
+ genesis := WriteGenesisBlockForTesting(db, addr1, big.NewInt(1000000))
// This call generates a chain of 5 blocks. The function runs for
// each block and adds different features to gen based on the
@@ -74,7 +74,7 @@ func ExampleGenerateChain() {
// Import the chain. This runs all block validation rules.
evmux := &event.TypeMux{}
- chainman, _ := NewChainManager(genesis, db, db, db, FakePow{}, evmux)
+ chainman, _ := NewChainManager(db, db, db, FakePow{}, evmux)
chainman.SetProcessor(NewBlockProcessor(db, db, FakePow{}, chainman, evmux))
if i, err := chainman.InsertChain(chain); err != nil {
fmt.Printf("insert error (block %d): %v\n", i, err)
diff --git a/core/chain_manager.go b/core/chain_manager.go
index 3c5eb0e8a..8fa13ddec 100644
--- a/core/chain_manager.go
+++ b/core/chain_manager.go
@@ -18,6 +18,7 @@
package core
import (
+ "errors"
"fmt"
"io"
"math/big"
@@ -34,7 +35,6 @@ import (
"github.com/ethereum/go-ethereum/logger/glog"
"github.com/ethereum/go-ethereum/metrics"
"github.com/ethereum/go-ethereum/pow"
- "github.com/ethereum/go-ethereum/rlp"
"github.com/hashicorp/golang-lru"
)
@@ -42,10 +42,9 @@ var (
chainlogger = logger.NewLogger("CHAIN")
jsonlogger = logger.NewJsonLogger()
- blockHashPre = []byte("block-hash-")
- blockNumPre = []byte("block-num-")
-
blockInsertTimer = metrics.NewTimer("chain/inserts")
+
+ ErrNoGenesis = errors.New("Genesis not found in chain")
)
const (
@@ -88,25 +87,32 @@ type ChainManager struct {
pow pow.PoW
}
-func NewChainManager(genesis *types.Block, blockDb, stateDb, extraDb common.Database, pow pow.PoW, mux *event.TypeMux) (*ChainManager, error) {
+func NewChainManager(blockDb, stateDb, extraDb common.Database, pow pow.PoW, mux *event.TypeMux) (*ChainManager, error) {
cache, _ := lru.New(blockCacheLimit)
bc := &ChainManager{
- blockDb: blockDb,
- stateDb: stateDb,
- extraDb: extraDb,
- genesisBlock: GenesisBlock(42, stateDb),
- eventMux: mux,
- quit: make(chan struct{}),
- cache: cache,
- 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()
+ blockDb: blockDb,
+ stateDb: stateDb,
+ extraDb: extraDb,
+ eventMux: mux,
+ quit: make(chan struct{}),
+ cache: cache,
+ pow: pow,
+ }
+
+ bc.genesisBlock = bc.GetBlockByNumber(0)
+ if bc.genesisBlock == nil {
+ // XXX Uncomment me before Frontier
+ //return nil, ErrNoGenesis
+ genesis, err := WriteTestNetGenesisBlock(bc.stateDb, bc.blockDb, 42)
+ if err != nil {
+ glog.Fatalln("genisis err", err)
+ }
+ bc.genesisBlock = genesis
+ }
+
+ if err := bc.setLastState(); err != nil {
+ return nil, err
+ }
// Check the current state of the block hashes and make sure that we do not have any of the bad blocks in our chain
for hash, _ := range BadHashes {
@@ -226,7 +232,7 @@ func (bc *ChainManager) recover() bool {
return false
}
-func (bc *ChainManager) setLastState() {
+func (bc *ChainManager) setLastState() error {
data, _ := bc.blockDb.Get([]byte("LastBlock"))
if len(data) != 0 {
block := bc.GetBlock(common.BytesToHash(data))
@@ -250,6 +256,8 @@ func (bc *ChainManager) setLastState() {
if glog.V(logger.Info) {
glog.Infof("Last block (#%v) %x TD=%v\n", bc.currentBlock.Number(), bc.currentBlock.Hash(), bc.td)
}
+
+ return nil
}
func (bc *ChainManager) makeCache() {
@@ -272,7 +280,11 @@ func (bc *ChainManager) Reset() {
bc.cache, _ = lru.New(blockCacheLimit)
// Prepare the genesis block
- bc.write(bc.genesisBlock)
+ err := WriteBlock(bc.blockDb, bc.genesisBlock)
+ if err != nil {
+ glog.Fatalln("db err:", err)
+ }
+
bc.insert(bc.genesisBlock)
bc.currentBlock = bc.genesisBlock
bc.makeCache()
@@ -295,7 +307,12 @@ func (bc *ChainManager) ResetWithGenesisBlock(gb *types.Block) {
// Prepare the genesis block
gb.Td = gb.Difficulty()
bc.genesisBlock = gb
- bc.write(bc.genesisBlock)
+
+ err := WriteBlock(bc.blockDb, bc.genesisBlock)
+ if err != nil {
+ glog.Fatalln("db err:", err)
+ }
+
bc.insert(bc.genesisBlock)
bc.currentBlock = bc.genesisBlock
bc.makeCache()
@@ -357,21 +374,6 @@ func (bc *ChainManager) insert(block *types.Block) {
bc.lastBlockHash = block.Hash()
}
-func (bc *ChainManager) write(block *types.Block) {
- tstart := time.Now()
-
- enc, _ := rlp.EncodeToBytes((*types.StorageBlock)(block))
- key := append(blockHashPre, block.Hash().Bytes()...)
- err := bc.blockDb.Put(key, enc)
- if err != nil {
- glog.Fatal("db write fail:", err)
- }
-
- if glog.V(logger.Debug) {
- glog.Infof("wrote block #%v %s. Took %v\n", block.Number(), common.PP(block.Hash().Bytes()), time.Since(tstart))
- }
-}
-
// Accessors
func (bc *ChainManager) Genesis() *types.Block {
return bc.genesisBlock
@@ -535,7 +537,10 @@ func (self *ChainManager) WriteBlock(block *types.Block, queued bool) (status wr
status = SideStatTy
}
- self.write(block)
+ err = WriteBlock(self.blockDb, block)
+ if err != nil {
+ glog.Fatalln("db err:", err)
+ }
// Delete from future blocks
self.futureBlocks.Remove(block.Hash())
diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go
index 92f080f01..5f8cfd4f4 100644
--- a/core/chain_manager_test.go
+++ b/core/chain_manager_test.go
@@ -48,8 +48,8 @@ func thePow() pow.PoW {
func theChainManager(db common.Database, t *testing.T) *ChainManager {
var eventMux event.TypeMux
- genesis := GenesisBlock(0, db)
- chainMan, err := NewChainManager(genesis, db, db, db, thePow(), &eventMux)
+ WriteTestNetGenesisBlock(db, db, 0)
+ chainMan, err := NewChainManager(db, db, db, thePow(), &eventMux)
if err != nil {
t.Error("failed creating chainmanager:", err)
t.FailNow()
@@ -125,7 +125,7 @@ func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) {
bman.bc.mu.Lock()
{
- bman.bc.write(block)
+ WriteBlock(bman.bc.blockDb, block)
}
bman.bc.mu.Unlock()
}
@@ -362,25 +362,6 @@ func TestChainMultipleInsertions(t *testing.T) {
}
}
-func TestGetBlocksFromHash(t *testing.T) {
- t.Skip("Skipped: outdated test files")
-
- db, _ := ethdb.NewMemDatabase()
- chainMan := theChainManager(db, t)
- chain, err := loadChain("valid1", t)
- if err != nil {
- fmt.Println(err)
- t.FailNow()
- }
-
- for _, block := range chain {
- chainMan.write(block)
- }
-
- blocks := chainMan.GetBlocksFromHash(chain[len(chain)-1].Hash(), 4)
- fmt.Println(blocks)
-}
-
type bproc struct{}
func (bproc) Process(*types.Block) (state.Logs, types.Receipts, error) { return nil, nil, nil }
@@ -418,7 +399,12 @@ func chm(genesis *types.Block, db common.Database) *ChainManager {
func TestReorgLongest(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
- genesis := GenesisBlock(0, db)
+
+ genesis, err := WriteTestNetGenesisBlock(db, db, 0)
+ if err != nil {
+ t.Error(err)
+ t.FailNow()
+ }
bc := chm(genesis, db)
chain1 := makeChainWithDiff(genesis, []int{1, 2, 4}, 10)
@@ -437,7 +423,11 @@ func TestReorgLongest(t *testing.T) {
func TestReorgShortest(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
- genesis := GenesisBlock(0, db)
+ genesis, err := WriteTestNetGenesisBlock(db, db, 0)
+ if err != nil {
+ t.Error(err)
+ t.FailNow()
+ }
bc := chm(genesis, db)
chain1 := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 10)
@@ -457,7 +447,11 @@ func TestReorgShortest(t *testing.T) {
func TestInsertNonceError(t *testing.T) {
for i := 1; i < 25 && !t.Failed(); i++ {
db, _ := ethdb.NewMemDatabase()
- genesis := GenesisBlock(0, db)
+ genesis, err := WriteTestNetGenesisBlock(db, db, 0)
+ if err != nil {
+ t.Error(err)
+ t.FailNow()
+ }
bc := chm(genesis, db)
bc.processor = NewBlockProcessor(db, db, bc.pow, bc, bc.eventMux)
blocks := makeChain(bc.currentBlock, i, db, 0)
@@ -491,6 +485,7 @@ func TestInsertNonceError(t *testing.T) {
}
}
+/*
func TestGenesisMismatch(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
var mux event.TypeMux
@@ -505,6 +500,7 @@ func TestGenesisMismatch(t *testing.T) {
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/chain_util.go b/core/chain_util.go
index 7e3d8eba8..253396ed7 100644
--- a/core/chain_util.go
+++ b/core/chain_util.go
@@ -19,6 +19,7 @@ package core
import (
"bytes"
"math/big"
+ "time"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/types"
@@ -28,6 +29,11 @@ import (
"github.com/ethereum/go-ethereum/rlp"
)
+var (
+ blockHashPre = []byte("block-hash-")
+ blockNumPre = []byte("block-num-")
+)
+
// 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.
@@ -118,3 +124,22 @@ func WriteHead(db common.Database, block *types.Block) error {
}
return nil
}
+
+// WriteBlock writes a block to the database
+func WriteBlock(db common.Database, block *types.Block) error {
+ tstart := time.Now()
+
+ enc, _ := rlp.EncodeToBytes((*types.StorageBlock)(block))
+ key := append(blockHashPre, block.Hash().Bytes()...)
+ err := db.Put(key, enc)
+ if err != nil {
+ glog.Fatal("db write fail:", err)
+ return err
+ }
+
+ if glog.V(logger.Debug) {
+ glog.Infof("wrote block #%v %s. Took %v\n", block.Number(), common.PP(block.Hash().Bytes()), time.Since(tstart))
+ }
+
+ return nil
+}
diff --git a/core/genesis.go b/core/genesis.go
index 2d369aae0..8c9a21c7e 100644
--- a/core/genesis.go
+++ b/core/genesis.go
@@ -19,8 +19,10 @@ package core
import (
"encoding/json"
"fmt"
+ "io"
+ "io/ioutil"
"math/big"
- "os"
+ "strings"
"github.com/ethereum/go-ethereum/common"
"github.com/ethereum/go-ethereum/core/state"
@@ -28,51 +30,71 @@ import (
"github.com/ethereum/go-ethereum/params"
)
-// GenesisBlock creates a genesis block with the given nonce.
-func GenesisBlock(nonce uint64, db common.Database) *types.Block {
- var accounts map[string]struct {
- Balance string
- Code string
- }
- err := json.Unmarshal(GenesisAccounts, &accounts)
+// WriteGenesisBlock writes the genesis block to the database as block number 0
+func WriteGenesisBlock(stateDb, blockDb common.Database, reader io.Reader) (*types.Block, error) {
+ contents, err := ioutil.ReadAll(reader)
if err != nil {
- fmt.Println("unable to decode genesis json data:", err)
- os.Exit(1)
+ return nil, err
}
- statedb := state.New(common.Hash{}, db)
- for addr, account := range accounts {
- codedAddr := common.Hex2Bytes(addr)
- accountState := statedb.CreateAccount(common.BytesToAddress(codedAddr))
- accountState.SetBalance(common.Big(account.Balance))
- accountState.SetCode(common.FromHex(account.Code))
- statedb.UpdateStateObject(accountState)
+
+ var genesis struct {
+ Nonce string
+ Timestamp string
+ ParentHash string
+ ExtraData string
+ GasLimit string
+ Difficulty string
+ Mixhash string
+ Coinbase string
+ Alloc map[string]struct {
+ Code string
+ Storage map[string]string
+ Balance string
+ }
}
- statedb.Sync()
+ if err := json.Unmarshal(contents, &genesis); err != nil {
+ return nil, err
+ }
+
+ statedb := state.New(common.Hash{}, stateDb)
+ for addr, account := range genesis.Alloc {
+ address := common.HexToAddress(addr)
+ statedb.AddBalance(address, common.String2Big(account.Balance))
+ statedb.SetCode(address, common.Hex2Bytes(account.Code))
+ for key, value := range account.Storage {
+ statedb.SetState(address, common.HexToHash(key), common.HexToHash(value))
+ }
+ }
+ statedb.SyncObjects()
+
+ difficulty := common.String2Big(genesis.Difficulty)
block := types.NewBlock(&types.Header{
- Difficulty: params.GenesisDifficulty,
- GasLimit: params.GenesisGasLimit,
- Nonce: types.EncodeNonce(nonce),
+ Nonce: types.EncodeNonce(common.String2Big(genesis.Nonce).Uint64()),
+ Time: common.String2Big(genesis.Timestamp).Uint64(),
+ ParentHash: common.HexToHash(genesis.ParentHash),
+ Extra: common.Hex2Bytes(genesis.ExtraData),
+ GasLimit: common.String2Big(genesis.GasLimit),
+ Difficulty: difficulty,
+ MixDigest: common.HexToHash(genesis.Mixhash),
+ Coinbase: common.HexToAddress(genesis.Coinbase),
Root: statedb.Root(),
}, nil, nil, nil)
- block.Td = params.GenesisDifficulty
- return block
-}
+ block.Td = difficulty
-var GenesisAccounts = []byte(`{
- "0000000000000000000000000000000000000001": {"balance": "1"},
- "0000000000000000000000000000000000000002": {"balance": "1"},
- "0000000000000000000000000000000000000003": {"balance": "1"},
- "0000000000000000000000000000000000000004": {"balance": "1"},
- "dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
- "e4157b34ea9615cfbde6b4fda419828124b70c78": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
- "b9c015918bdaba24b4ff057a92a3873d6eb201be": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
- "6c386a4b26f73c802f34673f7248bb118f97424a": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
- "cd2a3d9f938e13cd947ec05abc7fe734df8dd826": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
- "2ef47100e0787b915105fd5e3f4ff6752079d5cb": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
- "e6716f9544a56c530d868e4bfbacb172315bdead": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
- "1a26338f0d905e295fccb71fa9ea849ffa12aaf4": {"balance": "1606938044258990275541962092341162602522202993782792835301376"}
-}`)
+ statedb.Sync()
+
+ err = WriteBlock(blockDb, block)
+ if err != nil {
+ return nil, err
+ }
+ err = WriteHead(blockDb, block)
+ if err != nil {
+ return nil, err
+ }
+
+ return block, nil
+}
// GenesisBlockForTesting creates a block in which addr has the given wei balance.
// The state trie of the block is written to db.
@@ -90,3 +112,39 @@ func GenesisBlockForTesting(db common.Database, addr common.Address, balance *bi
block.Td = params.GenesisDifficulty
return block
}
+
+func WriteGenesisBlockForTesting(db common.Database, addr common.Address, balance *big.Int) *types.Block {
+ testGenesis := fmt.Sprintf(`{
+ "nonce":"0x%x",
+ "gasLimit":"0x%x",
+ "difficulty":"0x%x",
+ "alloc": {
+ "0x%x":{"balance":"0x%x"}
+ }
+}`, types.EncodeNonce(0), params.GenesisGasLimit.Bytes(), params.GenesisDifficulty.Bytes(), addr, balance.Bytes())
+ block, _ := WriteGenesisBlock(db, db, strings.NewReader(testGenesis))
+ return block
+}
+
+func WriteTestNetGenesisBlock(stateDb, blockDb common.Database, nonce uint64) (*types.Block, error) {
+ testGenesis := fmt.Sprintf(`{
+ "nonce":"0x%x",
+ "gasLimit":"0x%x",
+ "difficulty":"0x%x",
+ "alloc": {
+ "0000000000000000000000000000000000000001": {"balance": "1"},
+ "0000000000000000000000000000000000000002": {"balance": "1"},
+ "0000000000000000000000000000000000000003": {"balance": "1"},
+ "0000000000000000000000000000000000000004": {"balance": "1"},
+ "dbdbdb2cbd23b783741e8d7fcf51e459b497e4a6": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
+ "e4157b34ea9615cfbde6b4fda419828124b70c78": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
+ "b9c015918bdaba24b4ff057a92a3873d6eb201be": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
+ "6c386a4b26f73c802f34673f7248bb118f97424a": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
+ "cd2a3d9f938e13cd947ec05abc7fe734df8dd826": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
+ "2ef47100e0787b915105fd5e3f4ff6752079d5cb": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
+ "e6716f9544a56c530d868e4bfbacb172315bdead": {"balance": "1606938044258990275541962092341162602522202993782792835301376"},
+ "1a26338f0d905e295fccb71fa9ea849ffa12aaf4": {"balance": "1606938044258990275541962092341162602522202993782792835301376"}
+ }
+}`, types.EncodeNonce(nonce), params.GenesisGasLimit.Bytes(), params.GenesisDifficulty.Bytes())
+ return WriteGenesisBlock(stateDb, blockDb, strings.NewReader(testGenesis))
+}