chain_manager_test.go 11 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430
  1. package core
  2. import (
  3. "fmt"
  4. "math/big"
  5. "os"
  6. "path/filepath"
  7. "runtime"
  8. "strconv"
  9. "testing"
  10. "github.com/ethereum/ethash"
  11. "github.com/ethereum/go-ethereum/common"
  12. "github.com/ethereum/go-ethereum/core/state"
  13. "github.com/ethereum/go-ethereum/core/types"
  14. "github.com/ethereum/go-ethereum/ethdb"
  15. "github.com/ethereum/go-ethereum/event"
  16. "github.com/ethereum/go-ethereum/pow"
  17. "github.com/ethereum/go-ethereum/rlp"
  18. )
  19. func init() {
  20. runtime.GOMAXPROCS(runtime.NumCPU())
  21. }
  22. func thePow() pow.PoW {
  23. pow, _ := ethash.NewForTesting()
  24. return pow
  25. }
  26. // Test fork of length N starting from block i
  27. func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big.Int)) {
  28. // switch databases to process the new chain
  29. db, err := ethdb.NewMemDatabase()
  30. if err != nil {
  31. t.Fatal("Failed to create db:", err)
  32. }
  33. // copy old chain up to i into new db with deterministic canonical
  34. bman2, err := newCanonical(i, db)
  35. if err != nil {
  36. t.Fatal("could not make new canonical in testFork", err)
  37. }
  38. // asert the bmans have the same block at i
  39. bi1 := bman.bc.GetBlockByNumber(uint64(i)).Hash()
  40. bi2 := bman2.bc.GetBlockByNumber(uint64(i)).Hash()
  41. if bi1 != bi2 {
  42. t.Fatal("chains do not have the same hash at height", i)
  43. }
  44. bman2.bc.SetProcessor(bman2)
  45. // extend the fork
  46. parent := bman2.bc.CurrentBlock()
  47. chainB := makeChain(bman2, parent, N, db, ForkSeed)
  48. _, err = bman2.bc.InsertChain(chainB)
  49. if err != nil {
  50. t.Fatal("Insert chain error for fork:", err)
  51. }
  52. tdpre := bman.bc.Td()
  53. // Test the fork's blocks on the original chain
  54. td, err := testChain(chainB, bman)
  55. if err != nil {
  56. t.Fatal("expected chainB not to give errors:", err)
  57. }
  58. // Compare difficulties
  59. f(tdpre, td)
  60. // Loop over parents making sure reconstruction is done properly
  61. }
  62. func printChain(bc *ChainManager) {
  63. for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- {
  64. b := bc.GetBlockByNumber(uint64(i))
  65. fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty())
  66. }
  67. }
  68. // process blocks against a chain
  69. func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) {
  70. td := new(big.Int)
  71. for _, block := range chainB {
  72. _, err := bman.bc.processor.Process(block)
  73. if err != nil {
  74. if IsKnownBlockErr(err) {
  75. continue
  76. }
  77. return nil, err
  78. }
  79. parent := bman.bc.GetBlock(block.ParentHash())
  80. block.Td = CalcTD(block, parent)
  81. td = block.Td
  82. bman.bc.mu.Lock()
  83. {
  84. bman.bc.write(block)
  85. }
  86. bman.bc.mu.Unlock()
  87. }
  88. return td, nil
  89. }
  90. func loadChain(fn string, t *testing.T) (types.Blocks, error) {
  91. fh, err := os.OpenFile(filepath.Join(os.Getenv("GOPATH"), "src", "github.com", "ethereum", "go-ethereum", "_data", fn), os.O_RDONLY, os.ModePerm)
  92. if err != nil {
  93. return nil, err
  94. }
  95. defer fh.Close()
  96. var chain types.Blocks
  97. if err := rlp.Decode(fh, &chain); err != nil {
  98. return nil, err
  99. }
  100. return chain, nil
  101. }
  102. func insertChain(done chan bool, chainMan *ChainManager, chain types.Blocks, t *testing.T) {
  103. _, err := chainMan.InsertChain(chain)
  104. if err != nil {
  105. fmt.Println(err)
  106. t.FailNow()
  107. }
  108. done <- true
  109. }
  110. func TestExtendCanonical(t *testing.T) {
  111. CanonicalLength := 5
  112. db, err := ethdb.NewMemDatabase()
  113. if err != nil {
  114. t.Fatal("Failed to create db:", err)
  115. }
  116. // make first chain starting from genesis
  117. bman, err := newCanonical(CanonicalLength, db)
  118. if err != nil {
  119. t.Fatal("Could not make new canonical chain:", err)
  120. }
  121. f := func(td1, td2 *big.Int) {
  122. if td2.Cmp(td1) <= 0 {
  123. t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1)
  124. }
  125. }
  126. // Start fork from current height (CanonicalLength)
  127. testFork(t, bman, CanonicalLength, 1, f)
  128. testFork(t, bman, CanonicalLength, 2, f)
  129. testFork(t, bman, CanonicalLength, 5, f)
  130. testFork(t, bman, CanonicalLength, 10, f)
  131. }
  132. func TestShorterFork(t *testing.T) {
  133. db, err := ethdb.NewMemDatabase()
  134. if err != nil {
  135. t.Fatal("Failed to create db:", err)
  136. }
  137. // make first chain starting from genesis
  138. bman, err := newCanonical(10, db)
  139. if err != nil {
  140. t.Fatal("Could not make new canonical chain:", err)
  141. }
  142. f := func(td1, td2 *big.Int) {
  143. if td2.Cmp(td1) >= 0 {
  144. t.Error("expected chainB to have lower difficulty. Got", td2, "expected less than", td1)
  145. }
  146. }
  147. // Sum of numbers must be less than 10
  148. // for this to be a shorter fork
  149. testFork(t, bman, 0, 3, f)
  150. testFork(t, bman, 0, 7, f)
  151. testFork(t, bman, 1, 1, f)
  152. testFork(t, bman, 1, 7, f)
  153. testFork(t, bman, 5, 3, f)
  154. testFork(t, bman, 5, 4, f)
  155. }
  156. func TestLongerFork(t *testing.T) {
  157. db, err := ethdb.NewMemDatabase()
  158. if err != nil {
  159. t.Fatal("Failed to create db:", err)
  160. }
  161. // make first chain starting from genesis
  162. bman, err := newCanonical(10, db)
  163. if err != nil {
  164. t.Fatal("Could not make new canonical chain:", err)
  165. }
  166. f := func(td1, td2 *big.Int) {
  167. if td2.Cmp(td1) <= 0 {
  168. t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1)
  169. }
  170. }
  171. // Sum of numbers must be greater than 10
  172. // for this to be a longer fork
  173. testFork(t, bman, 0, 11, f)
  174. testFork(t, bman, 0, 15, f)
  175. testFork(t, bman, 1, 10, f)
  176. testFork(t, bman, 1, 12, f)
  177. testFork(t, bman, 5, 6, f)
  178. testFork(t, bman, 5, 8, f)
  179. }
  180. func TestEqualFork(t *testing.T) {
  181. db, err := ethdb.NewMemDatabase()
  182. if err != nil {
  183. t.Fatal("Failed to create db:", err)
  184. }
  185. bman, err := newCanonical(10, db)
  186. if err != nil {
  187. t.Fatal("Could not make new canonical chain:", err)
  188. }
  189. f := func(td1, td2 *big.Int) {
  190. if td2.Cmp(td1) != 0 {
  191. t.Error("expected chainB to have equal difficulty. Got", td2, "expected ", td1)
  192. }
  193. }
  194. // Sum of numbers must be equal to 10
  195. // for this to be an equal fork
  196. testFork(t, bman, 0, 10, f)
  197. testFork(t, bman, 1, 9, f)
  198. testFork(t, bman, 2, 8, f)
  199. testFork(t, bman, 5, 5, f)
  200. testFork(t, bman, 6, 4, f)
  201. testFork(t, bman, 9, 1, f)
  202. }
  203. func TestBrokenChain(t *testing.T) {
  204. db, err := ethdb.NewMemDatabase()
  205. if err != nil {
  206. t.Fatal("Failed to create db:", err)
  207. }
  208. bman, err := newCanonical(10, db)
  209. if err != nil {
  210. t.Fatal("Could not make new canonical chain:", err)
  211. }
  212. db2, err := ethdb.NewMemDatabase()
  213. if err != nil {
  214. t.Fatal("Failed to create db:", err)
  215. }
  216. bman2, err := newCanonical(10, db2)
  217. if err != nil {
  218. t.Fatal("Could not make new canonical chain:", err)
  219. }
  220. bman2.bc.SetProcessor(bman2)
  221. parent := bman2.bc.CurrentBlock()
  222. chainB := makeChain(bman2, parent, 5, db2, ForkSeed)
  223. chainB = chainB[1:]
  224. _, err = testChain(chainB, bman)
  225. if err == nil {
  226. t.Error("expected broken chain to return error")
  227. }
  228. }
  229. func TestChainInsertions(t *testing.T) {
  230. t.Skip() // travil fails.
  231. db, _ := ethdb.NewMemDatabase()
  232. chain1, err := loadChain("valid1", t)
  233. if err != nil {
  234. fmt.Println(err)
  235. t.FailNow()
  236. }
  237. chain2, err := loadChain("valid2", t)
  238. if err != nil {
  239. fmt.Println(err)
  240. t.FailNow()
  241. }
  242. var eventMux event.TypeMux
  243. chainMan := NewChainManager(db, db, thePow(), &eventMux)
  244. txPool := NewTxPool(&eventMux, chainMan.State, func() *big.Int { return big.NewInt(100000000) })
  245. blockMan := NewBlockProcessor(db, db, nil, txPool, chainMan, &eventMux)
  246. chainMan.SetProcessor(blockMan)
  247. const max = 2
  248. done := make(chan bool, max)
  249. go insertChain(done, chainMan, chain1, t)
  250. go insertChain(done, chainMan, chain2, t)
  251. for i := 0; i < max; i++ {
  252. <-done
  253. }
  254. if chain2[len(chain2)-1].Hash() != chainMan.CurrentBlock().Hash() {
  255. t.Error("chain2 is canonical and shouldn't be")
  256. }
  257. if chain1[len(chain1)-1].Hash() != chainMan.CurrentBlock().Hash() {
  258. t.Error("chain1 isn't canonical and should be")
  259. }
  260. }
  261. func TestChainMultipleInsertions(t *testing.T) {
  262. t.Skip() // travil fails.
  263. db, _ := ethdb.NewMemDatabase()
  264. const max = 4
  265. chains := make([]types.Blocks, max)
  266. var longest int
  267. for i := 0; i < max; i++ {
  268. var err error
  269. name := "valid" + strconv.Itoa(i+1)
  270. chains[i], err = loadChain(name, t)
  271. if len(chains[i]) >= len(chains[longest]) {
  272. longest = i
  273. }
  274. fmt.Println("loaded", name, "with a length of", len(chains[i]))
  275. if err != nil {
  276. fmt.Println(err)
  277. t.FailNow()
  278. }
  279. }
  280. var eventMux event.TypeMux
  281. chainMan := NewChainManager(db, db, thePow(), &eventMux)
  282. txPool := NewTxPool(&eventMux, chainMan.State, func() *big.Int { return big.NewInt(100000000) })
  283. blockMan := NewBlockProcessor(db, db, nil, txPool, chainMan, &eventMux)
  284. chainMan.SetProcessor(blockMan)
  285. done := make(chan bool, max)
  286. for i, chain := range chains {
  287. // XXX the go routine would otherwise reference the same (chain[3]) variable and fail
  288. i := i
  289. chain := chain
  290. go func() {
  291. insertChain(done, chainMan, chain, t)
  292. fmt.Println(i, "done")
  293. }()
  294. }
  295. for i := 0; i < max; i++ {
  296. <-done
  297. }
  298. if chains[longest][len(chains[longest])-1].Hash() != chainMan.CurrentBlock().Hash() {
  299. t.Error("Invalid canonical chain")
  300. }
  301. }
  302. func TestGetAncestors(t *testing.T) {
  303. t.Skip() // travil fails.
  304. db, _ := ethdb.NewMemDatabase()
  305. var eventMux event.TypeMux
  306. chainMan := NewChainManager(db, db, thePow(), &eventMux)
  307. chain, err := loadChain("valid1", t)
  308. if err != nil {
  309. fmt.Println(err)
  310. t.FailNow()
  311. }
  312. for _, block := range chain {
  313. chainMan.write(block)
  314. }
  315. ancestors := chainMan.GetAncestors(chain[len(chain)-1], 4)
  316. fmt.Println(ancestors)
  317. }
  318. type bproc struct{}
  319. func (bproc) Process(*types.Block) (state.Logs, error) { return nil, nil }
  320. func makeChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block {
  321. var chain []*types.Block
  322. for i, difficulty := range d {
  323. header := &types.Header{Number: big.NewInt(int64(i + 1)), Difficulty: big.NewInt(int64(difficulty))}
  324. block := types.NewBlockWithHeader(header)
  325. copy(block.HeaderHash[:2], []byte{byte(i + 1), seed})
  326. if i == 0 {
  327. block.ParentHeaderHash = genesis.Hash()
  328. } else {
  329. copy(block.ParentHeaderHash[:2], []byte{byte(i), seed})
  330. }
  331. chain = append(chain, block)
  332. }
  333. return chain
  334. }
  335. func chm(genesis *types.Block, db common.Database) *ChainManager {
  336. var eventMux event.TypeMux
  337. bc := &ChainManager{blockDb: db, stateDb: db, genesisBlock: genesis, eventMux: &eventMux, pow: FakePow{}}
  338. bc.cache = NewBlockCache(100)
  339. bc.futureBlocks = NewBlockCache(100)
  340. bc.processor = bproc{}
  341. bc.ResetWithGenesisBlock(genesis)
  342. bc.txState = state.ManageState(bc.State())
  343. return bc
  344. }
  345. func TestReorgLongest(t *testing.T) {
  346. t.Skip("skipped while cache is removed")
  347. db, _ := ethdb.NewMemDatabase()
  348. genesis := GenesisBlock(db)
  349. bc := chm(genesis, db)
  350. chain1 := makeChainWithDiff(genesis, []int{1, 2, 4}, 10)
  351. chain2 := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 11)
  352. bc.InsertChain(chain1)
  353. bc.InsertChain(chain2)
  354. prev := bc.CurrentBlock()
  355. for block := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, bc.GetBlockByNumber(block.NumberU64()-1) {
  356. if prev.ParentHash() != block.Hash() {
  357. t.Errorf("parent hash mismatch %x - %x", prev.ParentHash(), block.Hash())
  358. }
  359. }
  360. }
  361. func TestReorgShortest(t *testing.T) {
  362. t.Skip("skipped while cache is removed")
  363. db, _ := ethdb.NewMemDatabase()
  364. genesis := GenesisBlock(db)
  365. bc := chm(genesis, db)
  366. chain1 := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 10)
  367. chain2 := makeChainWithDiff(genesis, []int{1, 10}, 11)
  368. bc.InsertChain(chain1)
  369. bc.InsertChain(chain2)
  370. prev := bc.CurrentBlock()
  371. for block := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, bc.GetBlockByNumber(block.NumberU64()-1) {
  372. if prev.ParentHash() != block.Hash() {
  373. t.Errorf("parent hash mismatch %x - %x", prev.ParentHash(), block.Hash())
  374. }
  375. }
  376. }