| 
									
										
										
										
											2014-12-04 10:28:02 +01:00
										 |  |  | package core | 
					
						
							| 
									
										
										
										
											2014-12-17 12:57:35 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | import ( | 
					
						
							|  |  |  | 	"fmt" | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | 	"math/big" | 
					
						
							| 
									
										
										
										
											2014-12-30 13:32:01 +01:00
										 |  |  | 	"os" | 
					
						
							| 
									
										
										
										
											2014-12-17 12:57:35 +01:00
										 |  |  | 	"path" | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | 	"runtime" | 
					
						
							| 
									
										
										
										
											2014-12-30 15:42:26 +01:00
										 |  |  | 	"strconv" | 
					
						
							| 
									
										
										
										
											2014-12-17 12:57:35 +01:00
										 |  |  | 	"testing" | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-30 00:08:43 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/common" | 
					
						
							| 
									
										
										
										
											2015-04-29 12:43:24 +02:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/state" | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/core/types" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/ethdb" | 
					
						
							|  |  |  | 	"github.com/ethereum/go-ethereum/event" | 
					
						
							| 
									
										
										
										
											2014-12-30 13:32:01 +01:00
										 |  |  | 	"github.com/ethereum/go-ethereum/rlp" | 
					
						
							| 
									
										
										
										
											2014-12-17 12:57:35 +01:00
										 |  |  | ) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | func init() { | 
					
						
							|  |  |  | 	runtime.GOMAXPROCS(runtime.NumCPU()) | 
					
						
							| 
									
										
										
										
											2015-01-02 11:16:30 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | // 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) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	// asert the bmans have the same block at i | 
					
						
							|  |  |  | 	bi1 := bman.bc.GetBlockByNumber(uint64(i)).Hash() | 
					
						
							|  |  |  | 	bi2 := bman2.bc.GetBlockByNumber(uint64(i)).Hash() | 
					
						
							| 
									
										
										
										
											2015-03-18 13:38:47 +01:00
										 |  |  | 	if bi1 != bi2 { | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 		t.Fatal("chains do not have the same hash at height", i) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | 	bman2.bc.SetProcessor(bman2) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	// extend the fork | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | 	parent := bman2.bc.CurrentBlock() | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	chainB := makeChain(bman2, parent, N, db, ForkSeed) | 
					
						
							| 
									
										
										
										
											2015-04-29 15:09:37 +02:00
										 |  |  | 	_, err = bman2.bc.InsertChain(chainB) | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal("Insert chain error for fork:", err) | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	tdpre := bman.bc.Td() | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	// Test the fork's blocks on the original chain | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | 	td, err := testChain(chainB, bman) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal("expected chainB not to give errors:", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// Compare difficulties | 
					
						
							|  |  |  | 	f(tdpre, td) | 
					
						
							| 
									
										
										
										
											2015-04-29 12:43:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// Loop over parents making sure reconstruction is done properly | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | func printChain(bc *ChainManager) { | 
					
						
							|  |  |  | 	for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- { | 
					
						
							|  |  |  | 		b := bc.GetBlockByNumber(uint64(i)) | 
					
						
							| 
									
										
										
										
											2015-04-29 12:43:24 +02:00
										 |  |  | 		fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty()) | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // process blocks against a chain | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) { | 
					
						
							|  |  |  | 	td := new(big.Int) | 
					
						
							|  |  |  | 	for _, block := range chainB { | 
					
						
							| 
									
										
										
										
											2015-04-20 16:02:50 +02:00
										 |  |  | 		_, err := bman.bc.processor.Process(block) | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | 		if err != nil { | 
					
						
							|  |  |  | 			if IsKnownBlockErr(err) { | 
					
						
							|  |  |  | 				continue | 
					
						
							|  |  |  | 			} | 
					
						
							|  |  |  | 			return nil, err | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2015-04-20 16:02:50 +02:00
										 |  |  | 		parent := bman.bc.GetBlock(block.ParentHash()) | 
					
						
							|  |  |  | 		block.Td = CalculateTD(block, parent) | 
					
						
							|  |  |  | 		td = block.Td | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		bman.bc.mu.Lock() | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			bman.bc.write(block) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		bman.bc.mu.Unlock() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return td, nil | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-30 13:32:01 +01:00
										 |  |  | func loadChain(fn string, t *testing.T) (types.Blocks, error) { | 
					
						
							| 
									
										
										
										
											2015-01-02 13:00:25 +01:00
										 |  |  | 	fh, err := os.OpenFile(path.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm) | 
					
						
							| 
									
										
										
										
											2014-12-17 12:57:35 +01:00
										 |  |  | 	if err != nil { | 
					
						
							| 
									
										
										
										
											2014-12-30 13:32:01 +01:00
										 |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2014-12-17 12:57:35 +01:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-30 13:32:01 +01:00
										 |  |  | 	defer fh.Close() | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	var chain types.Blocks | 
					
						
							|  |  |  | 	if err := rlp.Decode(fh, &chain); err != nil { | 
					
						
							|  |  |  | 		return nil, err | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-30 13:32:01 +01:00
										 |  |  | 	return chain, nil | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *testing.T) { | 
					
						
							| 
									
										
										
										
											2015-04-29 15:09:37 +02:00
										 |  |  | 	_, err := chainMan.InsertChain(chain) | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		fmt.Println(err) | 
					
						
							|  |  |  | 		t.FailNow() | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-01-02 11:16:30 +01:00
										 |  |  | 	done <- true | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | func TestExtendCanonical(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	CanonicalLength := 5 | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | 	db, err := ethdb.NewMemDatabase() | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		t.Fatal("Failed to create db:", err) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// make first chain starting from genesis | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	bman, err := newCanonical(CanonicalLength, db) | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | 	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) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	// 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) | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 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 | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	testFork(t, bman, 0, 10, f) | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | 	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() | 
					
						
							| 
									
										
										
										
											2015-02-28 14:58:37 -05:00
										 |  |  | 	chainB := makeChain(bman2, parent, 5, db2, ForkSeed) | 
					
						
							| 
									
										
										
										
											2015-02-17 22:02:15 -05:00
										 |  |  | 	chainB = chainB[1:] | 
					
						
							|  |  |  | 	_, err = testChain(chainB, bman) | 
					
						
							|  |  |  | 	if err == nil { | 
					
						
							|  |  |  | 		t.Error("expected broken chain to return error") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | func TestChainInsertions(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2015-01-24 18:40:03 +01:00
										 |  |  | 	t.Skip() // travil fails. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-07 13:17:48 +01:00
										 |  |  | 	db, _ := ethdb.NewMemDatabase() | 
					
						
							| 
									
										
										
										
											2015-01-02 11:16:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-30 15:42:26 +01:00
										 |  |  | 	chain1, err := loadChain("valid1", t) | 
					
						
							| 
									
										
										
										
											2014-12-30 13:32:01 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		fmt.Println(err) | 
					
						
							|  |  |  | 		t.FailNow() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-30 15:42:26 +01:00
										 |  |  | 	chain2, err := loadChain("valid2", t) | 
					
						
							| 
									
										
										
										
											2014-12-30 13:32:01 +01:00
										 |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		fmt.Println(err) | 
					
						
							|  |  |  | 		t.FailNow() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | 	var eventMux event.TypeMux | 
					
						
							| 
									
										
										
										
											2015-03-06 20:07:35 +01:00
										 |  |  | 	chainMan := NewChainManager(db, db, &eventMux) | 
					
						
							| 
									
										
										
										
											2015-04-24 17:45:51 +02:00
										 |  |  | 	txPool := NewTxPool(&eventMux, chainMan.State, func() *big.Int { return big.NewInt(100000000) }) | 
					
						
							| 
									
										
										
										
											2015-03-12 14:50:35 +01:00
										 |  |  | 	blockMan := NewBlockProcessor(db, db, nil, txPool, chainMan, &eventMux) | 
					
						
							| 
									
										
										
										
											2014-12-18 13:12:54 +01:00
										 |  |  | 	chainMan.SetProcessor(blockMan) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	const max = 2 | 
					
						
							|  |  |  | 	done := make(chan bool, max) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	go insertChain(done, chainMan, chain1, t) | 
					
						
							|  |  |  | 	go insertChain(done, chainMan, chain2, t) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < max; i++ { | 
					
						
							|  |  |  | 		<-done | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-30 13:32:01 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-18 13:38:47 +01:00
										 |  |  | 	if chain2[len(chain2)-1].Hash() != chainMan.CurrentBlock().Hash() { | 
					
						
							| 
									
										
										
										
											2014-12-30 13:32:01 +01:00
										 |  |  | 		t.Error("chain2 is canonical and shouldn't be") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-18 13:38:47 +01:00
										 |  |  | 	if chain1[len(chain1)-1].Hash() != chainMan.CurrentBlock().Hash() { | 
					
						
							| 
									
										
										
										
											2014-12-30 13:32:01 +01:00
										 |  |  | 		t.Error("chain1 isn't canonical and should be") | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2014-12-17 12:57:35 +01:00
										 |  |  | } | 
					
						
							| 
									
										
										
										
											2014-12-30 15:42:26 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestChainMultipleInsertions(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2015-01-24 18:40:03 +01:00
										 |  |  | 	t.Skip() // travil fails. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-07 13:17:48 +01:00
										 |  |  | 	db, _ := ethdb.NewMemDatabase() | 
					
						
							| 
									
										
										
										
											2015-01-02 11:16:30 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-30 15:42:26 +01:00
										 |  |  | 	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() | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	var eventMux event.TypeMux | 
					
						
							| 
									
										
										
										
											2015-03-06 20:07:35 +01:00
										 |  |  | 	chainMan := NewChainManager(db, db, &eventMux) | 
					
						
							| 
									
										
										
										
											2015-04-24 17:45:51 +02:00
										 |  |  | 	txPool := NewTxPool(&eventMux, chainMan.State, func() *big.Int { return big.NewInt(100000000) }) | 
					
						
							| 
									
										
										
										
											2015-03-12 14:50:35 +01:00
										 |  |  | 	blockMan := NewBlockProcessor(db, db, nil, txPool, chainMan, &eventMux) | 
					
						
							| 
									
										
										
										
											2014-12-30 15:42:26 +01:00
										 |  |  | 	chainMan.SetProcessor(blockMan) | 
					
						
							|  |  |  | 	done := make(chan bool, max) | 
					
						
							|  |  |  | 	for i, chain := range chains { | 
					
						
							| 
									
										
										
										
											2015-01-02 11:16:30 +01:00
										 |  |  | 		// XXX the go routine would otherwise reference the same (chain[3]) variable and fail | 
					
						
							|  |  |  | 		i := i | 
					
						
							|  |  |  | 		chain := chain | 
					
						
							| 
									
										
										
										
											2014-12-30 15:42:26 +01:00
										 |  |  | 		go func() { | 
					
						
							|  |  |  | 			insertChain(done, chainMan, chain, t) | 
					
						
							|  |  |  | 			fmt.Println(i, "done") | 
					
						
							|  |  |  | 		}() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for i := 0; i < max; i++ { | 
					
						
							|  |  |  | 		<-done | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-03-18 13:38:47 +01:00
										 |  |  | 	if chains[longest][len(chains[longest])-1].Hash() != chainMan.CurrentBlock().Hash() { | 
					
						
							| 
									
										
										
										
											2014-12-30 15:42:26 +01:00
										 |  |  | 		t.Error("Invalid canonical chain") | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-01-12 10:19:27 +01:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestGetAncestors(t *testing.T) { | 
					
						
							| 
									
										
										
										
											2015-01-24 18:46:35 +01:00
										 |  |  | 	t.Skip() // travil fails. | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-01-12 10:19:27 +01:00
										 |  |  | 	db, _ := ethdb.NewMemDatabase() | 
					
						
							|  |  |  | 	var eventMux event.TypeMux | 
					
						
							| 
									
										
										
										
											2015-03-06 20:07:35 +01:00
										 |  |  | 	chainMan := NewChainManager(db, db, &eventMux) | 
					
						
							| 
									
										
										
										
											2015-01-12 10:19:27 +01:00
										 |  |  | 	chain, err := loadChain("valid1", t) | 
					
						
							|  |  |  | 	if err != nil { | 
					
						
							|  |  |  | 		fmt.Println(err) | 
					
						
							|  |  |  | 		t.FailNow() | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for _, block := range chain { | 
					
						
							|  |  |  | 		chainMan.write(block) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	ancestors := chainMan.GetAncestors(chain[len(chain)-1], 4) | 
					
						
							|  |  |  | 	fmt.Println(ancestors) | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-04-29 12:43:24 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | type bproc struct{} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func (bproc) Process(*types.Block) (state.Logs, error) { return nil, nil } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func makeChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block { | 
					
						
							|  |  |  | 	var chain []*types.Block | 
					
						
							|  |  |  | 	for i, difficulty := range d { | 
					
						
							|  |  |  | 		header := &types.Header{Number: big.NewInt(int64(i + 1)), Difficulty: big.NewInt(int64(difficulty))} | 
					
						
							|  |  |  | 		block := types.NewBlockWithHeader(header) | 
					
						
							|  |  |  | 		copy(block.HeaderHash[:2], []byte{byte(i + 1), seed}) | 
					
						
							|  |  |  | 		if i == 0 { | 
					
						
							|  |  |  | 			block.ParentHeaderHash = genesis.Hash() | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			copy(block.ParentHeaderHash[:2], []byte{byte(i), seed}) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		chain = append(chain, block) | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	return chain | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-30 00:08:43 +02:00
										 |  |  | func chm(genesis *types.Block, db common.Database) *ChainManager { | 
					
						
							| 
									
										
										
										
											2015-04-29 12:43:24 +02:00
										 |  |  | 	var eventMux event.TypeMux | 
					
						
							|  |  |  | 	bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: &eventMux} | 
					
						
							|  |  |  | 	bc.cache = NewBlockCache(100) | 
					
						
							|  |  |  | 	bc.futureBlocks = NewBlockCache(100) | 
					
						
							|  |  |  | 	bc.processor = bproc{} | 
					
						
							|  |  |  | 	bc.ResetWithGenesisBlock(genesis) | 
					
						
							|  |  |  | 	bc.txState = state.ManageState(bc.State()) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-30 00:08:43 +02:00
										 |  |  | 	return bc | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | func TestReorgLongest(t *testing.T) { | 
					
						
							|  |  |  | 	db, _ := ethdb.NewMemDatabase() | 
					
						
							|  |  |  | 	genesis := GenesisBlock(db) | 
					
						
							|  |  |  | 	bc := chm(genesis, db) | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-04-29 12:43:24 +02:00
										 |  |  | 	chain1 := makeChainWithDiff(genesis, []int{1, 2, 4}, 10) | 
					
						
							|  |  |  | 	chain2 := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 11) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bc.InsertChain(chain1) | 
					
						
							|  |  |  | 	bc.InsertChain(chain2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	prev := bc.CurrentBlock() | 
					
						
							|  |  |  | 	for block := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, bc.GetBlockByNumber(block.NumberU64()-1) { | 
					
						
							|  |  |  | 		if prev.ParentHash() != block.Hash() { | 
					
						
							|  |  |  | 			t.Errorf("parent hash mismatch %x - %x", prev.ParentHash(), block.Hash()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2015-04-30 00:08:43 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | func TestReorgShortest(t *testing.T) { | 
					
						
							|  |  |  | 	db, _ := ethdb.NewMemDatabase() | 
					
						
							|  |  |  | 	genesis := GenesisBlock(db) | 
					
						
							|  |  |  | 	bc := chm(genesis, db) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	chain1 := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 10) | 
					
						
							|  |  |  | 	chain2 := makeChainWithDiff(genesis, []int{1, 10}, 11) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	bc.InsertChain(chain1) | 
					
						
							|  |  |  | 	bc.InsertChain(chain2) | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	prev := bc.CurrentBlock() | 
					
						
							|  |  |  | 	for block := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, bc.GetBlockByNumber(block.NumberU64()-1) { | 
					
						
							|  |  |  | 		if prev.ParentHash() != block.Hash() { | 
					
						
							|  |  |  | 			t.Errorf("parent hash mismatch %x - %x", prev.ParentHash(), block.Hash()) | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } |