mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-21 20:26:41 +00:00
test forks from arbitrary heights
This commit is contained in:
parent
24523b893d
commit
f6914301d3
1 changed files with 93 additions and 64 deletions
|
|
@ -20,6 +20,7 @@ func init() {
|
|||
initDB()
|
||||
}
|
||||
|
||||
// Called from each Test to re-init the DB
|
||||
func initDB() {
|
||||
ethutil.ReadConfig(".ethtest", "/tmp/ethtest", "")
|
||||
ethutil.Config.Db, _ = ethdb.NewMemDatabase()
|
||||
|
|
@ -49,6 +50,7 @@ func (e *fakeEth) ClientIdentity() wire.ClientIdentity { return n
|
|||
func (e *fakeEth) Db() ethutil.Database { return nil }
|
||||
func (e *fakeEth) EventMux() *event.TypeMux { return nil }
|
||||
|
||||
// Create new block from coinbase and parent
|
||||
func newBlockFromParent(addr []byte, parent *types.Block) *types.Block {
|
||||
block := types.CreateBlock(
|
||||
parent.Root(),
|
||||
|
|
@ -65,7 +67,7 @@ func newBlockFromParent(addr []byte, parent *types.Block) *types.Block {
|
|||
}
|
||||
|
||||
// Actually make a block by simulating what miner would do
|
||||
func makeblock(bman *BlockManager, parent *types.Block, i int) *types.Block {
|
||||
func makeBlock(bman *BlockManager, parent *types.Block, i int) *types.Block {
|
||||
addr := ethutil.LeftPadBytes([]byte{byte(i)}, 20)
|
||||
block := newBlockFromParent(addr, parent)
|
||||
cbase := block.State().GetOrNewStateObject(addr)
|
||||
|
|
@ -80,13 +82,13 @@ func makeblock(bman *BlockManager, parent *types.Block, i int) *types.Block {
|
|||
|
||||
// Make a chain with real blocks
|
||||
// Runs ProcessWithParent to get proper state roots
|
||||
func makechain(bman *BlockManager, parent *types.Block, max int) *BlockChain {
|
||||
func makeChain(bman *BlockManager, parent *types.Block, max int) *BlockChain {
|
||||
bman.bc.CurrentBlock = parent
|
||||
bman.bc.LastBlockHash = parent.Hash()
|
||||
blocks := make(types.Blocks, max)
|
||||
var td *big.Int
|
||||
for i := 0; i < max; i++ {
|
||||
block := makeblock(bman, parent, i)
|
||||
block := makeBlock(bman, parent, i)
|
||||
// add the parent and its difficulty to the working chain
|
||||
// so ProcessWithParent can access it
|
||||
bman.bc.workingChain = NewChain(types.Blocks{parent})
|
||||
|
|
@ -99,13 +101,14 @@ func makechain(bman *BlockManager, parent *types.Block, max int) *BlockChain {
|
|||
return lchain
|
||||
}
|
||||
|
||||
// Make a new canonical chain by running TestChain and InsertChain
|
||||
// on result of makechain
|
||||
// Make a new canonical chain n block long
|
||||
// by running TestChain and InsertChain
|
||||
// on result of makeChain
|
||||
func newCanonical(n int) (*BlockManager, error) {
|
||||
bman := &BlockManager{bc: NewChainManager(), Pow: fakePow{}, eth: &fakeEth{}}
|
||||
bman.bc.SetProcessor(bman)
|
||||
parent := bman.bc.CurrentBlock
|
||||
lchain := makechain(bman, parent, 5)
|
||||
lchain := makeChain(bman, parent, n)
|
||||
|
||||
_, err := bman.bc.TestChain(lchain)
|
||||
if err != nil {
|
||||
|
|
@ -115,14 +118,41 @@ func newCanonical(n int) (*BlockManager, error) {
|
|||
return bman, nil
|
||||
}
|
||||
|
||||
// new chain manager without setLastBlock
|
||||
func newChainManager() *ChainManager {
|
||||
// Create a new chain manager starting from given block
|
||||
// Effectively a fork factory
|
||||
func newChainManager(block *types.Block) *ChainManager {
|
||||
bc := &ChainManager{}
|
||||
bc.genesisBlock = types.NewBlockFromBytes(ethutil.Encode(Genesis))
|
||||
bc.Reset()
|
||||
if block == nil {
|
||||
bc.Reset()
|
||||
} else {
|
||||
bc.CurrentBlock = block
|
||||
bc.SetTotalDifficulty(ethutil.Big("0"))
|
||||
bc.TD = block.BlockInfo().TD
|
||||
}
|
||||
return bc
|
||||
}
|
||||
|
||||
// Test fork of length N starting from block i
|
||||
func testFork(t *testing.T, bman *BlockManager, i, N int, f func(td1, td2 *big.Int)) {
|
||||
var b *types.Block = nil
|
||||
if i > 0 {
|
||||
b = bman.bc.GetBlockByNumber(uint64(i))
|
||||
}
|
||||
bman2 := &BlockManager{bc: newChainManager(b), Pow: fakePow{}, eth: &fakeEth{}}
|
||||
bman2.bc.SetProcessor(bman2)
|
||||
parent := bman2.bc.CurrentBlock
|
||||
chainB := makeChain(bman2, parent, N)
|
||||
// test second chain against first
|
||||
td2, err := bman.bc.TestChain(chainB)
|
||||
if err != nil && !IsTDError(err) {
|
||||
t.Error("expected chainB not to give errors:", err)
|
||||
}
|
||||
// Compare difficulties
|
||||
f(bman.bc.TD, td2)
|
||||
}
|
||||
|
||||
// Test basic extension of canonical chain with new blocks
|
||||
func TestExtendCanonical(t *testing.T) {
|
||||
initDB()
|
||||
// make first chain starting from genesis
|
||||
|
|
@ -131,95 +161,94 @@ func TestExtendCanonical(t *testing.T) {
|
|||
t.Fatal("Could not make new canonical chain:", err)
|
||||
}
|
||||
|
||||
// make second chain starting from end of first chain
|
||||
bman2 := &BlockManager{bc: NewChainManager(), Pow: fakePow{}, eth: &fakeEth{}}
|
||||
bman2.bc.SetProcessor(bman2)
|
||||
parent := bman.bc.CurrentBlock
|
||||
chainB := makechain(bman2, parent, 3)
|
||||
|
||||
// test second chain against first
|
||||
td2, err := bman.bc.TestChain(chainB)
|
||||
if err != nil && !IsTDError(err) {
|
||||
t.Error("expected chainB not to give errors:", 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)
|
||||
}
|
||||
}
|
||||
|
||||
if td2.Cmp(bman.bc.TD) <= 0 {
|
||||
t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", bman.bc.TD)
|
||||
}
|
||||
// Start fork from current height (5)
|
||||
testFork(t, bman, 5, 1, f)
|
||||
testFork(t, bman, 5, 2, f)
|
||||
testFork(t, bman, 5, 5, f)
|
||||
testFork(t, bman, 5, 10, f)
|
||||
}
|
||||
|
||||
// Test a fork with less TD than the canonical chain
|
||||
func TestShorterFork(t *testing.T) {
|
||||
initDB()
|
||||
// make first chain starting from genesis
|
||||
bman, err := newCanonical(5)
|
||||
bman, err := newCanonical(10)
|
||||
if err != nil {
|
||||
t.Fatal("Could not make new canonical chain:", err)
|
||||
}
|
||||
|
||||
// make second, shorter chain, starting from genesis
|
||||
bman2 := &BlockManager{bc: newChainManager(), Pow: fakePow{}, eth: &fakeEth{}}
|
||||
bman2.bc.SetProcessor(bman2)
|
||||
parent := bman2.bc.CurrentBlock
|
||||
chainB := makechain(bman2, parent, 3)
|
||||
|
||||
// test second chain against first
|
||||
td2, err := bman.bc.TestChain(chainB)
|
||||
if err != nil && !IsTDError(err) {
|
||||
t.Error("expected chainB not to give errors:", 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)
|
||||
}
|
||||
}
|
||||
|
||||
if td2.Cmp(bman.bc.TD) >= 0 {
|
||||
t.Error("expected chainB to have lower difficulty. Got", td2, "expected less than", bman.bc.TD)
|
||||
}
|
||||
// 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, 3, f)
|
||||
testFork(t, bman, 1, 7, f)
|
||||
testFork(t, bman, 5, 3, f)
|
||||
testFork(t, bman, 5, 4, f)
|
||||
}
|
||||
|
||||
// Test a fork with more TD than canonical chain
|
||||
func TestLongerFork(t *testing.T) {
|
||||
initDB()
|
||||
// make first chain starting from genesis
|
||||
bman, err := newCanonical(5)
|
||||
bman, err := newCanonical(10)
|
||||
if err != nil {
|
||||
t.Fatal("Could not make new canonical chain:", err)
|
||||
}
|
||||
|
||||
// make second, longer chain, starting from genesis
|
||||
bman2 := &BlockManager{bc: newChainManager(), Pow: fakePow{}, eth: &fakeEth{}}
|
||||
bman2.bc.SetProcessor(bman2)
|
||||
parent := bman2.bc.CurrentBlock
|
||||
chainB := makechain(bman2, parent, 10)
|
||||
|
||||
td, err := bman.bc.TestChain(chainB)
|
||||
if err != nil {
|
||||
t.Error("expected chainB not to give errors:", 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)
|
||||
}
|
||||
}
|
||||
|
||||
if td.Cmp(bman.bc.TD) <= 0 {
|
||||
t.Error("expected chainB to have higher difficulty. Got", td, "expected more than", bman.bc.TD)
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
|
||||
// Test a fork with equal TD to canonical chain
|
||||
func TestEqualFork(t *testing.T) {
|
||||
initDB()
|
||||
bman, err := newCanonical(5)
|
||||
bman, err := newCanonical(10)
|
||||
if err != nil {
|
||||
t.Fatal("Could not make new canonical chain:", err)
|
||||
}
|
||||
|
||||
bman2 := &BlockManager{bc: newChainManager(), Pow: fakePow{}, eth: &fakeEth{}}
|
||||
bman2.bc.SetProcessor(bman2)
|
||||
parent := bman2.bc.CurrentBlock
|
||||
|
||||
chainB := makechain(bman2, parent, 5)
|
||||
|
||||
td, err := bman.bc.TestChain(chainB)
|
||||
if err != nil && !IsTDError(err) {
|
||||
t.Error("expected chainB not to give errors:", err)
|
||||
f := func(td1, td2 *big.Int) {
|
||||
if td2.Cmp(td1) != 0 {
|
||||
t.Error("expected chainB to have equal difficulty. Got", td2, "expected less than", td1)
|
||||
}
|
||||
}
|
||||
|
||||
if td.Cmp(bman.bc.TD) != 0 {
|
||||
t.Error("expected chainB to have equal difficulty. Got", td, "expected less than", bman.bc.TD)
|
||||
}
|
||||
// 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)
|
||||
}
|
||||
|
||||
// Test a broken chain (no common ancestor)
|
||||
func TestBrokenChain(t *testing.T) {
|
||||
initDB()
|
||||
bman, err := newCanonical(5)
|
||||
|
|
@ -231,7 +260,7 @@ func TestBrokenChain(t *testing.T) {
|
|||
bman2.bc.SetProcessor(bman2)
|
||||
parent := bman2.bc.CurrentBlock
|
||||
|
||||
chainB := makechain(bman2, parent, 5)
|
||||
chainB := makeChain(bman2, parent, 5)
|
||||
chainB.Remove(chainB.Front())
|
||||
|
||||
_, err = bman.bc.TestChain(chainB)
|
||||
|
|
@ -253,7 +282,7 @@ func BenchmarkChainTesting(b *testing.B) {
|
|||
bman2.bc.SetProcessor(bman2)
|
||||
parent := bman2.bc.CurrentBlock
|
||||
|
||||
chain := makechain(bman2, parent, chainlen)
|
||||
chain := makeChain(bman2, parent, chainlen)
|
||||
|
||||
stime := time.Now()
|
||||
bman.bc.TestChain(chain)
|
||||
|
|
|
|||
Loading…
Reference in a new issue