diff options
Diffstat (limited to 'core/chain_manager_test.go')
-rw-r--r-- | core/chain_manager_test.go | 194 |
1 files changed, 194 insertions, 0 deletions
diff --git a/core/chain_manager_test.go b/core/chain_manager_test.go index bc3a264d1..b562b677d 100644 --- a/core/chain_manager_test.go +++ b/core/chain_manager_test.go @@ -3,6 +3,7 @@ package core import ( "bytes" "fmt" + "math/big" "os" "path" "runtime" @@ -21,6 +22,75 @@ func init() { ethutil.ReadConfig("/tmp/ethtest", "/tmp/ethtest", "ETH") } +// 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 + db, err := ethdb.NewMemDatabase() + if err != nil { + t.Fatal("Failed to create db:", err) + } + // copy old chain up to i into new db with deterministic canonical + bman2, err := newCanonical(i, db) + if err != nil { + t.Fatal("could not make new canonical in testFork", err) + } + // asert the bmans have the same block at i + bi1 := bman.bc.GetBlockByNumber(uint64(i)).Hash() + bi2 := bman2.bc.GetBlockByNumber(uint64(i)).Hash() + if bytes.Compare(bi1, bi2) != 0 { + t.Fatal("chains do not have the same hash at height", i) + } + + bman2.bc.SetProcessor(bman2) + + // extend the fork + parent := bman2.bc.CurrentBlock() + chainB := makeChain(bman2, parent, N, db, ForkSeed) + err = bman2.bc.InsertChain(chainB) + if err != nil { + t.Fatal("Insert chain error for fork:", err) + } + + tdpre := bman.bc.Td() + // Test the fork's blocks on the original chain + td, err := testChain(chainB, bman) + if err != nil { + t.Fatal("expected chainB not to give errors:", err) + } + // Compare difficulties + f(tdpre, td) +} + +func printChain(bc *ChainManager) { + for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- { + b := bc.GetBlockByNumber(uint64(i)) + fmt.Printf("\t%x\n", b.Hash()) + } +} + +// process blocks against a chain +func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) { + td := new(big.Int) + for _, block := range chainB { + td2, err := bman.bc.processor.Process(block) + if err != nil { + if IsKnownBlockErr(err) { + continue + } + return nil, err + } + block.Td = td2 + td = td2 + + bman.bc.mu.Lock() + { + bman.bc.write(block) + } + bman.bc.mu.Unlock() + } + return td, nil +} + func loadChain(fn string, t *testing.T) (types.Blocks, error) { fh, err := os.OpenFile(path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm) if err != nil { @@ -45,6 +115,130 @@ func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t * done <- true } +func TestExtendCanonical(t *testing.T) { + CanonicalLength := 5 + db, err := ethdb.NewMemDatabase() + if err != nil { + t.Fatal("Failed to create db:", err) + } + // make first chain starting from genesis + bman, err := newCanonical(CanonicalLength, db) + if err != nil { + t.Fatal("Could not make new canonical chain:", err) + } + f := func(td1, td2 *big.Int) { + if td2.Cmp(td1) <= 0 { + t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1) + } + } + // Start fork from current height (CanonicalLength) + testFork(t, bman, CanonicalLength, 1, f) + testFork(t, bman, CanonicalLength, 2, f) + testFork(t, bman, CanonicalLength, 5, f) + testFork(t, bman, CanonicalLength, 10, f) +} + +func TestShorterFork(t *testing.T) { + db, err := ethdb.NewMemDatabase() + if err != nil { + t.Fatal("Failed to create db:", err) + } + // make first chain starting from genesis + bman, err := newCanonical(10, db) + if err != nil { + t.Fatal("Could not make new canonical chain:", err) + } + f := func(td1, td2 *big.Int) { + if td2.Cmp(td1) >= 0 { + t.Error("expected chainB to have lower difficulty. Got", td2, "expected less than", td1) + } + } + // Sum of numbers must be less than 10 + // for this to be a shorter fork + testFork(t, bman, 0, 3, f) + testFork(t, bman, 0, 7, f) + testFork(t, bman, 1, 1, f) + testFork(t, bman, 1, 7, f) + testFork(t, bman, 5, 3, f) + testFork(t, bman, 5, 4, f) +} + +func TestLongerFork(t *testing.T) { + db, err := ethdb.NewMemDatabase() + if err != nil { + t.Fatal("Failed to create db:", err) + } + // make first chain starting from genesis + bman, err := newCanonical(10, db) + if err != nil { + t.Fatal("Could not make new canonical chain:", err) + } + f := func(td1, td2 *big.Int) { + if td2.Cmp(td1) <= 0 { + t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1) + } + } + // Sum of numbers must be greater than 10 + // for this to be a longer fork + testFork(t, bman, 0, 11, f) + testFork(t, bman, 0, 15, f) + testFork(t, bman, 1, 10, f) + testFork(t, bman, 1, 12, f) + testFork(t, bman, 5, 6, f) + testFork(t, bman, 5, 8, f) +} + +func TestEqualFork(t *testing.T) { + db, err := ethdb.NewMemDatabase() + if err != nil { + t.Fatal("Failed to create db:", err) + } + bman, err := newCanonical(10, db) + if err != nil { + t.Fatal("Could not make new canonical chain:", err) + } + f := func(td1, td2 *big.Int) { + if td2.Cmp(td1) != 0 { + t.Error("expected chainB to have equal difficulty. Got", td2, "expected ", td1) + } + } + // Sum of numbers must be equal to 10 + // for this to be an equal fork + testFork(t, bman, 0, 10, f) + testFork(t, bman, 1, 9, f) + testFork(t, bman, 2, 8, f) + testFork(t, bman, 5, 5, f) + testFork(t, bman, 6, 4, f) + testFork(t, bman, 9, 1, f) +} + +func TestBrokenChain(t *testing.T) { + db, err := ethdb.NewMemDatabase() + if err != nil { + t.Fatal("Failed to create db:", err) + } + bman, err := newCanonical(10, db) + if err != nil { + t.Fatal("Could not make new canonical chain:", err) + } + db2, err := ethdb.NewMemDatabase() + if err != nil { + t.Fatal("Failed to create db:", err) + } + bman2, err := newCanonical(10, db2) + if err != nil { + t.Fatal("Could not make new canonical chain:", err) + } + bman2.bc.SetProcessor(bman2) + parent := bman2.bc.CurrentBlock() + chainB := makeChain(bman2, parent, 5, db2, ForkSeed) + chainB = chainB[1:] + _, err = testChain(chainB, bman) + if err == nil { + t.Error("expected broken chain to return error") + } +} + func TestChainInsertions(t *testing.T) { t.Skip() // travil fails. |