core: refactor genesis handling

This commit solves several issues concerning the genesis block:

* Genesis/ChainConfig loading was handled by cmd/geth code. This left
  library users in the cold. They could specify a JSON-encoded
  string and overwrite the config, but didn't get any of the additional
  checks performed by geth.
* Decoding and writing of genesis JSON was conflated in
  WriteGenesisBlock. This made it a lot harder to embed the genesis
  block into the forthcoming config file loader. This commit changes
  things so there is a single Genesis type that represents genesis
  blocks. All uses of Write*Genesis* are changed to use the new type
  instead.
* If the chain config supplied by the user was incompatible with the
  current chain (i.e. the chain had already advanced beyond a scheduled
  fork), it got overwritten. This is not an issue in practice because
  previous forks have always had the highest total difficulty. It might
  matter in the future though. The new code reverts the local chain to
  the point of the fork when upgrading configuration.

The change to genesis block data removes compression library
dependencies from package core.
This commit is contained in:
Felix Lange
2017-03-02 14:03:33 +01:00
parent 67c47459f2
commit 37dd9086ec
45 changed files with 1379 additions and 1275 deletions

View File

@@ -20,10 +20,6 @@ import (
"fmt"
"math/big"
"math/rand"
"os"
"path/filepath"
"runtime"
"strconv"
"testing"
"time"
@@ -36,24 +32,21 @@ import (
"github.com/ethereum/go-ethereum/event"
"github.com/ethereum/go-ethereum/params"
"github.com/ethereum/go-ethereum/pow"
"github.com/ethereum/go-ethereum/rlp"
"github.com/hashicorp/golang-lru"
)
func init() {
runtime.GOMAXPROCS(runtime.NumCPU())
}
func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain {
var eventMux event.TypeMux
WriteTestNetGenesisBlock(db)
blockchain, err := NewBlockChain(db, testChainConfig(), pow.NewTestEthash(), &eventMux, vm.Config{})
if err != nil {
t.Error("failed creating blockchain:", err)
t.FailNow()
return nil
// newTestBlockChain creates a blockchain without validation.
func newTestBlockChain() *BlockChain {
db, _ := ethdb.NewMemDatabase()
gspec := &Genesis{
Config: params.TestChainConfig,
Difficulty: big.NewInt(1),
}
gspec.MustCommit(db)
blockchain, err := NewBlockChain(db, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
if err != nil {
panic(err)
}
blockchain.SetValidator(bproc{})
return blockchain
}
@@ -171,21 +164,6 @@ func testHeaderChainImport(chain []*types.Header, blockchain *BlockChain) error
return nil
}
func loadChain(fn string, t *testing.T) (types.Blocks, error) {
fh, err := os.OpenFile(filepath.Join("..", "_data", fn), os.O_RDONLY, os.ModePerm)
if err != nil {
return nil, err
}
defer fh.Close()
var chain types.Blocks
if err := rlp.Decode(fh, &chain); err != nil {
return nil, err
}
return chain, nil
}
func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) {
_, err := blockchain.InsertChain(chain)
if err != nil {
@@ -196,12 +174,10 @@ func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *
}
func TestLastBlock(t *testing.T) {
db, _ := ethdb.NewMemDatabase()
bchain := theBlockChain(db, t)
block := makeBlockChain(bchain.CurrentBlock(), 1, db, 0)[0]
bchain := newTestBlockChain()
block := makeBlockChain(bchain.CurrentBlock(), 1, bchain.chainDb, 0)[0]
bchain.insert(block)
if block.Hash() != GetHeadBlockHash(db) {
if block.Hash() != GetHeadBlockHash(bchain.chainDb) {
t.Errorf("Write/Get HeadBlockHash failed")
}
}
@@ -340,88 +316,6 @@ func testBrokenChain(t *testing.T, full bool) {
}
}
func TestChainInsertions(t *testing.T) {
t.Skip("Skipped: outdated test files")
db, _ := ethdb.NewMemDatabase()
chain1, err := loadChain("valid1", t)
if err != nil {
fmt.Println(err)
t.FailNow()
}
chain2, err := loadChain("valid2", t)
if err != nil {
fmt.Println(err)
t.FailNow()
}
blockchain := theBlockChain(db, t)
const max = 2
done := make(chan bool, max)
go insertChain(done, blockchain, chain1, t)
go insertChain(done, blockchain, chain2, t)
for i := 0; i < max; i++ {
<-done
}
if chain2[len(chain2)-1].Hash() != blockchain.CurrentBlock().Hash() {
t.Error("chain2 is canonical and shouldn't be")
}
if chain1[len(chain1)-1].Hash() != blockchain.CurrentBlock().Hash() {
t.Error("chain1 isn't canonical and should be")
}
}
func TestChainMultipleInsertions(t *testing.T) {
t.Skip("Skipped: outdated test files")
db, _ := ethdb.NewMemDatabase()
const max = 4
chains := make([]types.Blocks, max)
var longest int
for i := 0; i < max; i++ {
var err error
name := "valid" + strconv.Itoa(i+1)
chains[i], err = loadChain(name, t)
if len(chains[i]) >= len(chains[longest]) {
longest = i
}
fmt.Println("loaded", name, "with a length of", len(chains[i]))
if err != nil {
fmt.Println(err)
t.FailNow()
}
}
blockchain := theBlockChain(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
i := i
chain := chain
go func() {
insertChain(done, blockchain, chain, t)
fmt.Println(i, "done")
}()
}
for i := 0; i < max; i++ {
<-done
}
if chains[longest][len(chains[longest])-1].Hash() != blockchain.CurrentBlock().Hash() {
t.Error("Invalid canonical chain")
}
}
type bproc struct{}
func (bproc) ValidateBlock(*types.Block) error { return nil }
@@ -452,6 +346,7 @@ func makeBlockChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.B
UncleHash: types.EmptyUncleHash,
TxHash: types.EmptyRootHash,
ReceiptHash: types.EmptyRootHash,
Time: big.NewInt(int64(i) + 1),
}
if i == 0 {
header.ParentHash = genesis.Hash()
@@ -464,29 +359,6 @@ func makeBlockChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.B
return chain
}
func chm(genesis *types.Block, db ethdb.Database) *BlockChain {
var eventMux event.TypeMux
bc := &BlockChain{
chainDb: db,
genesisBlock: genesis,
eventMux: &eventMux,
pow: pow.FakePow{},
config: testChainConfig(),
}
valFn := func() HeaderValidator { return bc.Validator() }
bc.hc, _ = NewHeaderChain(db, testChainConfig(), valFn, bc.getProcInterrupt)
bc.bodyCache, _ = lru.New(100)
bc.bodyRLPCache, _ = lru.New(100)
bc.blockCache, _ = lru.New(100)
bc.futureBlocks, _ = lru.New(100)
bc.badBlocks, _ = lru.New(10)
bc.SetValidator(bproc{})
bc.SetProcessor(bproc{})
bc.ResetWithGenesisBlock(genesis)
return bc
}
// Tests that reorganising a long difficult chain after a short easy one
// overwrites the canonical numbers and links in the database.
func TestReorgLongHeaders(t *testing.T) { testReorgLong(t, false) }
@@ -506,18 +378,15 @@ func testReorgShort(t *testing.T, full bool) {
}
func testReorg(t *testing.T, first, second []int, td int64, full bool) {
// Create a pristine block chain
db, _ := ethdb.NewMemDatabase()
genesis, _ := WriteTestNetGenesisBlock(db)
bc := chm(genesis, db)
bc := newTestBlockChain()
// Insert an easy and a difficult chain afterwards
if full {
bc.InsertChain(makeBlockChainWithDiff(genesis, first, 11))
bc.InsertChain(makeBlockChainWithDiff(genesis, second, 22))
bc.InsertChain(makeBlockChainWithDiff(bc.genesisBlock, first, 11))
bc.InsertChain(makeBlockChainWithDiff(bc.genesisBlock, second, 22))
} else {
bc.InsertHeaderChain(makeHeaderChainWithDiff(genesis, first, 11), 1)
bc.InsertHeaderChain(makeHeaderChainWithDiff(genesis, second, 22), 1)
bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, first, 11), 1)
bc.InsertHeaderChain(makeHeaderChainWithDiff(bc.genesisBlock, second, 22), 1)
}
// Check that the chain is valid number and link wise
if full {
@@ -536,7 +405,7 @@ func testReorg(t *testing.T, first, second []int, td int64, full bool) {
}
}
// Make sure the chain total difficulty is the correct one
want := new(big.Int).Add(genesis.Difficulty(), big.NewInt(td))
want := new(big.Int).Add(bc.genesisBlock.Difficulty(), big.NewInt(td))
if full {
if have := bc.GetTdByHash(bc.CurrentBlock().Hash()); have.Cmp(want) != 0 {
t.Errorf("total difficulty mismatch: have %v, want %v", have, want)
@@ -553,19 +422,16 @@ func TestBadHeaderHashes(t *testing.T) { testBadHashes(t, false) }
func TestBadBlockHashes(t *testing.T) { testBadHashes(t, true) }
func testBadHashes(t *testing.T, full bool) {
// Create a pristine block chain
db, _ := ethdb.NewMemDatabase()
genesis, _ := WriteTestNetGenesisBlock(db)
bc := chm(genesis, db)
bc := newTestBlockChain()
// Create a chain, ban a hash and try to import
var err error
if full {
blocks := makeBlockChainWithDiff(genesis, []int{1, 2, 4}, 10)
blocks := makeBlockChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10)
BadHashes[blocks[2].Header().Hash()] = true
_, err = bc.InsertChain(blocks)
} else {
headers := makeHeaderChainWithDiff(genesis, []int{1, 2, 4}, 10)
headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 4}, 10)
BadHashes[headers[2].Hash()] = true
_, err = bc.InsertHeaderChain(headers, 1)
}
@@ -580,14 +446,11 @@ func TestReorgBadHeaderHashes(t *testing.T) { testReorgBadHashes(t, false) }
func TestReorgBadBlockHashes(t *testing.T) { testReorgBadHashes(t, true) }
func testReorgBadHashes(t *testing.T, full bool) {
// Create a pristine block chain
db, _ := ethdb.NewMemDatabase()
genesis, _ := WriteTestNetGenesisBlock(db)
bc := chm(genesis, db)
bc := newTestBlockChain()
// Create a chain, import and ban afterwards
headers := makeHeaderChainWithDiff(genesis, []int{1, 2, 3, 4}, 10)
blocks := makeBlockChainWithDiff(genesis, []int{1, 2, 3, 4}, 10)
headers := makeHeaderChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10)
blocks := makeBlockChainWithDiff(bc.genesisBlock, []int{1, 2, 3, 4}, 10)
if full {
if _, err := bc.InsertChain(blocks); err != nil {
@@ -608,8 +471,9 @@ func testReorgBadHashes(t *testing.T, full bool) {
BadHashes[headers[3].Hash()] = true
defer func() { delete(BadHashes, headers[3].Hash()) }()
}
// Create a new chain manager and check it rolled back the state
ncm, err := NewBlockChain(db, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
// Create a new BlockChain and check that it rolled back the state.
ncm, err := NewBlockChain(bc.chainDb, bc.config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
if err != nil {
t.Fatalf("failed to create new chain manager: %v", err)
}
@@ -663,7 +527,7 @@ func testInsertNonceError(t *testing.T, full bool) {
failHash = headers[failAt].Hash()
blockchain.pow = failPow{failNum}
blockchain.validator = NewBlockValidator(testChainConfig(), blockchain, failPow{failNum})
blockchain.validator = NewBlockValidator(params.TestChainConfig, blockchain, failPow{failNum})
failRes, err = blockchain.InsertHeaderChain(headers, 1)
}
@@ -705,10 +569,11 @@ func TestFastVsFullChains(t *testing.T) {
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
genesis = GenesisBlockForTesting(gendb, address, funds)
signer = types.NewEIP155Signer(big.NewInt(1))
gspec = testGenesis(address, funds)
genesis = gspec.MustCommit(gendb)
signer = types.NewEIP155Signer(gspec.Config.ChainId)
)
blocks, receipts := GenerateChain(params.TestChainConfig, genesis, gendb, 1024, func(i int, block *BlockGen) {
blocks, receipts := GenerateChain(gspec.Config, genesis, gendb, 1024, func(i int, block *BlockGen) {
block.SetCoinbase(common.Address{0x00})
// If the block number is multiple of 3, send a few bonus transactions to the miner
@@ -728,17 +593,17 @@ func TestFastVsFullChains(t *testing.T) {
})
// Import the chain as an archive node for the comparison baseline
archiveDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
archive, _ := NewBlockChain(archiveDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
gspec.MustCommit(archiveDb)
archive, _ := NewBlockChain(archiveDb, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
if n, err := archive.InsertChain(blocks); err != nil {
t.Fatalf("failed to process block %d: %v", n, err)
}
// Fast import the chain as a non-archive node to test
fastDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
fast, _ := NewBlockChain(fastDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
gspec.MustCommit(fastDb)
fast, _ := NewBlockChain(fastDb, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
headers := make([]*types.Header, len(blocks))
for i, block := range blocks {
@@ -788,10 +653,11 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
key, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
genesis = GenesisBlockForTesting(gendb, address, funds)
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{address: {Balance: funds}}}
genesis = gspec.MustCommit(gendb)
)
height := uint64(1024)
blocks, receipts := GenerateChain(params.TestChainConfig, genesis, gendb, int(height), nil)
blocks, receipts := GenerateChain(gspec.Config, genesis, gendb, int(height), nil)
// Configure a subchain to roll back
remove := []common.Hash{}
@@ -812,9 +678,9 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
}
// Import the chain as an archive node and ensure all pointers are updated
archiveDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(archiveDb, GenesisAccount{address, funds})
gspec.MustCommit(archiveDb)
archive, _ := NewBlockChain(archiveDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
archive, _ := NewBlockChain(archiveDb, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
if n, err := archive.InsertChain(blocks); err != nil {
t.Fatalf("failed to process block %d: %v", n, err)
@@ -825,8 +691,8 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a non-archive node and ensure all pointers are updated
fastDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(fastDb, GenesisAccount{address, funds})
fast, _ := NewBlockChain(fastDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
gspec.MustCommit(fastDb)
fast, _ := NewBlockChain(fastDb, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
headers := make([]*types.Header, len(blocks))
for i, block := range blocks {
@@ -844,8 +710,8 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Import the chain as a light node and ensure all pointers are updated
lightDb, _ := ethdb.NewMemDatabase()
WriteGenesisBlockForTesting(lightDb, GenesisAccount{address, funds})
light, _ := NewBlockChain(lightDb, testChainConfig(), pow.FakePow{}, new(event.TypeMux), vm.Config{})
gspec.MustCommit(lightDb)
light, _ := NewBlockChain(lightDb, gspec.Config, pow.FakePow{}, new(event.TypeMux), vm.Config{})
if n, err := light.InsertHeaderChain(headers, 1); err != nil {
t.Fatalf("failed to insert header %d: %v", n, err)
@@ -857,9 +723,6 @@ func TestLightVsFastVsFullChainHeads(t *testing.T) {
// Tests that chain reorganisations handle transaction removals and reinsertions.
func TestChainTxReorgs(t *testing.T) {
params.MinGasLimit = big.NewInt(125000) // Minimum the gas limit may ever be.
params.GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block.
var (
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
@@ -868,13 +731,19 @@ func TestChainTxReorgs(t *testing.T) {
addr2 = crypto.PubkeyToAddress(key2.PublicKey)
addr3 = crypto.PubkeyToAddress(key3.PublicKey)
db, _ = ethdb.NewMemDatabase()
signer = types.NewEIP155Signer(big.NewInt(1))
)
genesis := WriteGenesisBlockForTesting(db,
GenesisAccount{addr1, big.NewInt(1000000)},
GenesisAccount{addr2, big.NewInt(1000000)},
GenesisAccount{addr3, big.NewInt(1000000)},
gspec = &Genesis{
Config: params.TestChainConfig,
GasLimit: 3141592,
Alloc: GenesisAlloc{
addr1: {Balance: big.NewInt(1000000)},
addr2: {Balance: big.NewInt(1000000)},
addr3: {Balance: big.NewInt(1000000)},
},
}
genesis = gspec.MustCommit(db)
signer = types.NewEIP155Signer(gspec.Config.ChainId)
)
// Create two transactions shared between the chains:
// - postponed: transaction included at a later block in the forked chain
// - swapped: transaction included at the same block number in the forked chain
@@ -892,7 +761,7 @@ func TestChainTxReorgs(t *testing.T) {
// - futureAdd: transaction added after the reorg has already finished
var pastAdd, freshAdd, futureAdd *types.Transaction
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {
chain, _ := GenerateChain(gspec.Config, genesis, db, 3, func(i int, gen *BlockGen) {
switch i {
case 0:
pastDrop, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), bigTxGas, nil, nil), signer, key2)
@@ -911,13 +780,13 @@ func TestChainTxReorgs(t *testing.T) {
})
// Import the chain. This runs all block validation rules.
evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, testChainConfig(), pow.FakePow{}, evmux, vm.Config{})
blockchain, _ := NewBlockChain(db, gspec.Config, pow.FakePow{}, evmux, vm.Config{})
if i, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert original chain[%d]: %v", i, err)
}
// overwrite the old chain
chain, _ = GenerateChain(params.TestChainConfig, genesis, db, 5, func(i int, gen *BlockGen) {
chain, _ = GenerateChain(gspec.Config, genesis, db, 5, func(i int, gen *BlockGen) {
switch i {
case 0:
pastAdd, _ = types.SignTx(types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), bigTxGas, nil, nil), signer, key3)
@@ -969,23 +838,20 @@ func TestChainTxReorgs(t *testing.T) {
}
func TestLogReorgs(t *testing.T) {
params.MinGasLimit = big.NewInt(125000) // Minimum the gas limit may ever be.
params.GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block.
var (
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
db, _ = ethdb.NewMemDatabase()
// this code generates a log
code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
signer = types.NewEIP155Signer(big.NewInt(1))
)
genesis := WriteGenesisBlockForTesting(db,
GenesisAccount{addr1, big.NewInt(10000000000000)},
code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00")
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}}
genesis = gspec.MustCommit(db)
signer = types.NewEIP155Signer(gspec.Config.ChainId)
)
evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, testChainConfig(), pow.FakePow{}, evmux, vm.Config{})
var evmux event.TypeMux
blockchain, _ := NewBlockChain(db, gspec.Config, pow.FakePow{}, &evmux, vm.Config{})
subs := evmux.Subscribe(RemovedLogsEvent{})
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 2, func(i int, gen *BlockGen) {
@@ -1017,19 +883,20 @@ func TestReorgSideEvent(t *testing.T) {
db, _ = ethdb.NewMemDatabase()
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
addr1 = crypto.PubkeyToAddress(key1.PublicKey)
genesis = WriteGenesisBlockForTesting(db, GenesisAccount{addr1, big.NewInt(10000000000000)})
signer = types.NewEIP155Signer(big.NewInt(1))
gspec = testGenesis(addr1, big.NewInt(10000000000000))
genesis = gspec.MustCommit(db)
signer = types.NewEIP155Signer(gspec.Config.ChainId)
)
evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, testChainConfig(), pow.FakePow{}, evmux, vm.Config{})
blockchain, _ := NewBlockChain(db, gspec.Config, pow.FakePow{}, evmux, vm.Config{})
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 3, func(i int, gen *BlockGen) {})
chain, _ := GenerateChain(gspec.Config, genesis, db, 3, func(i int, gen *BlockGen) {})
if _, err := blockchain.InsertChain(chain); err != nil {
t.Fatalf("failed to insert chain: %v", err)
}
replacementBlocks, _ := GenerateChain(params.TestChainConfig, genesis, db, 4, func(i int, gen *BlockGen) {
replacementBlocks, _ := GenerateChain(gspec.Config, genesis, db, 4, func(i int, gen *BlockGen) {
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil), signer, key1)
if i == 2 {
gen.OffsetTime(-1)
@@ -1092,28 +959,21 @@ done:
// Tests if the canonical block can be fetched from the database during chain insertion.
func TestCanonicalBlockRetrieval(t *testing.T) {
var (
db, _ = ethdb.NewMemDatabase()
genesis = WriteGenesisBlockForTesting(db)
)
evmux := &event.TypeMux{}
blockchain, _ := NewBlockChain(db, testChainConfig(), pow.FakePow{}, evmux, vm.Config{})
chain, _ := GenerateChain(params.TestChainConfig, genesis, db, 10, func(i int, gen *BlockGen) {})
bc := newTestBlockChain()
chain, _ := GenerateChain(bc.config, bc.genesisBlock, bc.chainDb, 10, func(i int, gen *BlockGen) {})
for i := range chain {
go func(block *types.Block) {
// try to retrieve a block by its canonical hash and see if the block data can be retrieved.
for {
ch := GetCanonicalHash(db, block.NumberU64())
ch := GetCanonicalHash(bc.chainDb, block.NumberU64())
if ch == (common.Hash{}) {
continue // busy wait for canonical hash to be written
}
if ch != block.Hash() {
t.Fatalf("unknown canonical hash, want %s, got %s", block.Hash().Hex(), ch.Hex())
}
fb := GetBlock(db, ch, block.NumberU64())
fb := GetBlock(bc.chainDb, ch, block.NumberU64())
if fb == nil {
t.Fatalf("unable to retrieve block %d for canonical hash: %s", block.NumberU64(), ch.Hex())
}
@@ -1124,7 +984,7 @@ func TestCanonicalBlockRetrieval(t *testing.T) {
}
}(chain[i])
blockchain.InsertChain(types.Blocks{chain[i]})
bc.InsertChain(types.Blocks{chain[i]})
}
}
@@ -1136,13 +996,16 @@ func TestEIP155Transition(t *testing.T) {
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
deleteAddr = common.Address{1}
genesis = WriteGenesisBlockForTesting(db, GenesisAccount{address, funds}, GenesisAccount{deleteAddr, new(big.Int)})
config = &params.ChainConfig{ChainId: big.NewInt(1), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}
mux event.TypeMux
gspec = &Genesis{
Config: &params.ChainConfig{ChainId: big.NewInt(1), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)},
Alloc: GenesisAlloc{address: {Balance: funds}, deleteAddr: {Balance: new(big.Int)}},
}
genesis = gspec.MustCommit(db)
mux event.TypeMux
)
blockchain, _ := NewBlockChain(db, config, pow.FakePow{}, &mux, vm.Config{})
blocks, _ := GenerateChain(config, genesis, db, 4, func(i int, block *BlockGen) {
blockchain, _ := NewBlockChain(db, gspec.Config, pow.FakePow{}, &mux, vm.Config{})
blocks, _ := GenerateChain(gspec.Config, genesis, db, 4, func(i int, block *BlockGen) {
var (
tx *types.Transaction
err error
@@ -1164,7 +1027,7 @@ func TestEIP155Transition(t *testing.T) {
}
block.AddTx(tx)
tx, err = basicTx(types.NewEIP155Signer(config.ChainId))
tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainId))
if err != nil {
t.Fatal(err)
}
@@ -1176,7 +1039,7 @@ func TestEIP155Transition(t *testing.T) {
}
block.AddTx(tx)
tx, err = basicTx(types.NewEIP155Signer(config.ChainId))
tx, err = basicTx(types.NewEIP155Signer(gspec.Config.ChainId))
if err != nil {
t.Fatal(err)
}
@@ -1204,7 +1067,7 @@ func TestEIP155Transition(t *testing.T) {
}
// generate an invalid chain id transaction
config = &params.ChainConfig{ChainId: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}
config := &params.ChainConfig{ChainId: big.NewInt(2), EIP155Block: big.NewInt(2), HomesteadBlock: new(big.Int)}
blocks, _ = GenerateChain(config, blocks[len(blocks)-1], db, 4, func(i int, block *BlockGen) {
var (
tx *types.Transaction
@@ -1236,22 +1099,24 @@ func TestEIP161AccountRemoval(t *testing.T) {
address = crypto.PubkeyToAddress(key.PublicKey)
funds = big.NewInt(1000000000)
theAddr = common.Address{1}
genesis = WriteGenesisBlockForTesting(db, GenesisAccount{address, funds})
config = &params.ChainConfig{
ChainId: big.NewInt(1),
HomesteadBlock: new(big.Int),
EIP155Block: new(big.Int),
EIP158Block: big.NewInt(2),
gspec = &Genesis{
Config: &params.ChainConfig{
ChainId: big.NewInt(1),
HomesteadBlock: new(big.Int),
EIP155Block: new(big.Int),
EIP158Block: big.NewInt(2),
},
Alloc: GenesisAlloc{address: {Balance: funds}},
}
mux event.TypeMux
blockchain, _ = NewBlockChain(db, config, pow.FakePow{}, &mux, vm.Config{})
genesis = gspec.MustCommit(db)
mux event.TypeMux
blockchain, _ = NewBlockChain(db, gspec.Config, pow.FakePow{}, &mux, vm.Config{})
)
blocks, _ := GenerateChain(config, genesis, db, 3, func(i int, block *BlockGen) {
blocks, _ := GenerateChain(gspec.Config, genesis, db, 3, func(i int, block *BlockGen) {
var (
tx *types.Transaction
err error
signer = types.NewEIP155Signer(config.ChainId)
signer = types.NewEIP155Signer(gspec.Config.ChainId)
)
switch i {
case 0:
@@ -1279,7 +1144,7 @@ func TestEIP161AccountRemoval(t *testing.T) {
t.Fatal(err)
}
if blockchain.stateCache.Exist(theAddr) {
t.Error("account should not expect")
t.Error("account should not exist")
}
// account musn't be created post eip 161
@@ -1287,6 +1152,6 @@ func TestEIP161AccountRemoval(t *testing.T) {
t.Fatal(err)
}
if blockchain.stateCache.Exist(theAddr) {
t.Error("account should not expect")
t.Error("account should not exist")
}
}