blockchain_test.go 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665
  1. // Copyright 2014 The go-ethereum Authors
  2. // This file is part of the go-ethereum library.
  3. //
  4. // The go-ethereum library is free software: you can redistribute it and/or modify
  5. // it under the terms of the GNU Lesser General Public License as published by
  6. // the Free Software Foundation, either version 3 of the License, or
  7. // (at your option) any later version.
  8. //
  9. // The go-ethereum library is distributed in the hope that it will be useful,
  10. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. // GNU Lesser General Public License for more details.
  13. //
  14. // You should have received a copy of the GNU Lesser General Public License
  15. // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
  16. package core
  17. import (
  18. "fmt"
  19. "math/big"
  20. "math/rand"
  21. "os"
  22. "path/filepath"
  23. "runtime"
  24. "strconv"
  25. "testing"
  26. "github.com/ethereum/ethash"
  27. "github.com/ethereum/go-ethereum/common"
  28. "github.com/ethereum/go-ethereum/core/types"
  29. "github.com/ethereum/go-ethereum/core/vm"
  30. "github.com/ethereum/go-ethereum/crypto"
  31. "github.com/ethereum/go-ethereum/ethdb"
  32. "github.com/ethereum/go-ethereum/event"
  33. "github.com/ethereum/go-ethereum/params"
  34. "github.com/ethereum/go-ethereum/pow"
  35. "github.com/ethereum/go-ethereum/rlp"
  36. "github.com/hashicorp/golang-lru"
  37. )
  38. func init() {
  39. runtime.GOMAXPROCS(runtime.NumCPU())
  40. }
  41. func thePow() pow.PoW {
  42. pow, _ := ethash.NewForTesting()
  43. return pow
  44. }
  45. func theBlockChain(db ethdb.Database, t *testing.T) *BlockChain {
  46. var eventMux event.TypeMux
  47. WriteTestNetGenesisBlock(db, 0)
  48. blockchain, err := NewBlockChain(db, thePow(), &eventMux)
  49. if err != nil {
  50. t.Error("failed creating chainmanager:", err)
  51. t.FailNow()
  52. return nil
  53. }
  54. blockMan := NewBlockProcessor(db, nil, blockchain, &eventMux)
  55. blockchain.SetProcessor(blockMan)
  56. return blockchain
  57. }
  58. // Test fork of length N starting from block i
  59. func testFork(t *testing.T, bman *BlockProcessor, i, N int, f func(td1, td2 *big.Int)) {
  60. // switch databases to process the new chain
  61. db, err := ethdb.NewMemDatabase()
  62. if err != nil {
  63. t.Fatal("Failed to create db:", err)
  64. }
  65. // copy old chain up to i into new db with deterministic canonical
  66. bman2, err := newCanonical(i, db)
  67. if err != nil {
  68. t.Fatal("could not make new canonical in testFork", err)
  69. }
  70. // assert the bmans have the same block at i
  71. bi1 := bman.bc.GetBlockByNumber(uint64(i)).Hash()
  72. bi2 := bman2.bc.GetBlockByNumber(uint64(i)).Hash()
  73. if bi1 != bi2 {
  74. fmt.Printf("%+v\n%+v\n\n", bi1, bi2)
  75. t.Fatal("chains do not have the same hash at height", i)
  76. }
  77. bman2.bc.SetProcessor(bman2)
  78. // extend the fork
  79. parent := bman2.bc.CurrentBlock()
  80. chainB := makeChain(parent, N, db, forkSeed)
  81. _, err = bman2.bc.InsertChain(chainB)
  82. if err != nil {
  83. t.Fatal("Insert chain error for fork:", err)
  84. }
  85. tdpre := bman.bc.Td()
  86. // Test the fork's blocks on the original chain
  87. td, err := testChain(chainB, bman)
  88. if err != nil {
  89. t.Fatal("expected chainB not to give errors:", err)
  90. }
  91. // Compare difficulties
  92. f(tdpre, td)
  93. // Loop over parents making sure reconstruction is done properly
  94. }
  95. func printChain(bc *BlockChain) {
  96. for i := bc.CurrentBlock().Number().Uint64(); i > 0; i-- {
  97. b := bc.GetBlockByNumber(uint64(i))
  98. fmt.Printf("\t%x %v\n", b.Hash(), b.Difficulty())
  99. }
  100. }
  101. // process blocks against a chain
  102. func testChain(chainB types.Blocks, bman *BlockProcessor) (*big.Int, error) {
  103. for _, block := range chainB {
  104. _, _, err := bman.bc.processor.Process(block)
  105. if err != nil {
  106. if IsKnownBlockErr(err) {
  107. continue
  108. }
  109. return nil, err
  110. }
  111. bman.bc.mu.Lock()
  112. WriteTd(bman.bc.chainDb, block.Hash(), new(big.Int).Add(block.Difficulty(), bman.bc.GetTd(block.ParentHash())))
  113. WriteBlock(bman.bc.chainDb, block)
  114. bman.bc.mu.Unlock()
  115. }
  116. return bman.bc.GetTd(chainB[len(chainB)-1].Hash()), nil
  117. }
  118. func loadChain(fn string, t *testing.T) (types.Blocks, error) {
  119. fh, err := os.OpenFile(filepath.Join("..", "_data", fn), os.O_RDONLY, os.ModePerm)
  120. if err != nil {
  121. return nil, err
  122. }
  123. defer fh.Close()
  124. var chain types.Blocks
  125. if err := rlp.Decode(fh, &chain); err != nil {
  126. return nil, err
  127. }
  128. return chain, nil
  129. }
  130. func insertChain(done chan bool, blockchain *BlockChain, chain types.Blocks, t *testing.T) {
  131. _, err := blockchain.InsertChain(chain)
  132. if err != nil {
  133. fmt.Println(err)
  134. t.FailNow()
  135. }
  136. done <- true
  137. }
  138. func TestLastBlock(t *testing.T) {
  139. db, err := ethdb.NewMemDatabase()
  140. if err != nil {
  141. t.Fatal("Failed to create db:", err)
  142. }
  143. bchain := theBlockChain(db, t)
  144. block := makeChain(bchain.CurrentBlock(), 1, db, 0)[0]
  145. bchain.insert(block)
  146. if block.Hash() != GetHeadBlockHash(db) {
  147. t.Errorf("Write/Get HeadBlockHash failed")
  148. }
  149. }
  150. func TestExtendCanonical(t *testing.T) {
  151. CanonicalLength := 5
  152. db, err := ethdb.NewMemDatabase()
  153. if err != nil {
  154. t.Fatal("Failed to create db:", err)
  155. }
  156. // make first chain starting from genesis
  157. bman, err := newCanonical(CanonicalLength, db)
  158. if err != nil {
  159. t.Fatal("Could not make new canonical chain:", err)
  160. }
  161. f := func(td1, td2 *big.Int) {
  162. if td2.Cmp(td1) <= 0 {
  163. t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1)
  164. }
  165. }
  166. // Start fork from current height (CanonicalLength)
  167. testFork(t, bman, CanonicalLength, 1, f)
  168. testFork(t, bman, CanonicalLength, 2, f)
  169. testFork(t, bman, CanonicalLength, 5, f)
  170. testFork(t, bman, CanonicalLength, 10, f)
  171. }
  172. func TestShorterFork(t *testing.T) {
  173. db, err := ethdb.NewMemDatabase()
  174. if err != nil {
  175. t.Fatal("Failed to create db:", err)
  176. }
  177. // make first chain starting from genesis
  178. bman, err := newCanonical(10, db)
  179. if err != nil {
  180. t.Fatal("Could not make new canonical chain:", err)
  181. }
  182. f := func(td1, td2 *big.Int) {
  183. if td2.Cmp(td1) >= 0 {
  184. t.Error("expected chainB to have lower difficulty. Got", td2, "expected less than", td1)
  185. }
  186. }
  187. // Sum of numbers must be less than 10
  188. // for this to be a shorter fork
  189. testFork(t, bman, 0, 3, f)
  190. testFork(t, bman, 0, 7, f)
  191. testFork(t, bman, 1, 1, f)
  192. testFork(t, bman, 1, 7, f)
  193. testFork(t, bman, 5, 3, f)
  194. testFork(t, bman, 5, 4, f)
  195. }
  196. func TestLongerFork(t *testing.T) {
  197. db, err := ethdb.NewMemDatabase()
  198. if err != nil {
  199. t.Fatal("Failed to create db:", err)
  200. }
  201. // make first chain starting from genesis
  202. bman, err := newCanonical(10, db)
  203. if err != nil {
  204. t.Fatal("Could not make new canonical chain:", err)
  205. }
  206. f := func(td1, td2 *big.Int) {
  207. if td2.Cmp(td1) <= 0 {
  208. t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1)
  209. }
  210. }
  211. // Sum of numbers must be greater than 10
  212. // for this to be a longer fork
  213. testFork(t, bman, 0, 11, f)
  214. testFork(t, bman, 0, 15, f)
  215. testFork(t, bman, 1, 10, f)
  216. testFork(t, bman, 1, 12, f)
  217. testFork(t, bman, 5, 6, f)
  218. testFork(t, bman, 5, 8, f)
  219. }
  220. func TestEqualFork(t *testing.T) {
  221. db, err := ethdb.NewMemDatabase()
  222. if err != nil {
  223. t.Fatal("Failed to create db:", err)
  224. }
  225. bman, err := newCanonical(10, db)
  226. if err != nil {
  227. t.Fatal("Could not make new canonical chain:", err)
  228. }
  229. f := func(td1, td2 *big.Int) {
  230. if td2.Cmp(td1) != 0 {
  231. t.Error("expected chainB to have equal difficulty. Got", td2, "expected ", td1)
  232. }
  233. }
  234. // Sum of numbers must be equal to 10
  235. // for this to be an equal fork
  236. testFork(t, bman, 0, 10, f)
  237. testFork(t, bman, 1, 9, f)
  238. testFork(t, bman, 2, 8, f)
  239. testFork(t, bman, 5, 5, f)
  240. testFork(t, bman, 6, 4, f)
  241. testFork(t, bman, 9, 1, f)
  242. }
  243. func TestBrokenChain(t *testing.T) {
  244. db, err := ethdb.NewMemDatabase()
  245. if err != nil {
  246. t.Fatal("Failed to create db:", err)
  247. }
  248. bman, err := newCanonical(10, db)
  249. if err != nil {
  250. t.Fatal("Could not make new canonical chain:", err)
  251. }
  252. db2, err := ethdb.NewMemDatabase()
  253. if err != nil {
  254. t.Fatal("Failed to create db:", err)
  255. }
  256. bman2, err := newCanonical(10, db2)
  257. if err != nil {
  258. t.Fatal("Could not make new canonical chain:", err)
  259. }
  260. bman2.bc.SetProcessor(bman2)
  261. parent := bman2.bc.CurrentBlock()
  262. chainB := makeChain(parent, 5, db2, forkSeed)
  263. chainB = chainB[1:]
  264. _, err = testChain(chainB, bman)
  265. if err == nil {
  266. t.Error("expected broken chain to return error")
  267. }
  268. }
  269. func TestChainInsertions(t *testing.T) {
  270. t.Skip("Skipped: outdated test files")
  271. db, _ := ethdb.NewMemDatabase()
  272. chain1, err := loadChain("valid1", t)
  273. if err != nil {
  274. fmt.Println(err)
  275. t.FailNow()
  276. }
  277. chain2, err := loadChain("valid2", t)
  278. if err != nil {
  279. fmt.Println(err)
  280. t.FailNow()
  281. }
  282. blockchain := theBlockChain(db, t)
  283. const max = 2
  284. done := make(chan bool, max)
  285. go insertChain(done, blockchain, chain1, t)
  286. go insertChain(done, blockchain, chain2, t)
  287. for i := 0; i < max; i++ {
  288. <-done
  289. }
  290. if chain2[len(chain2)-1].Hash() != blockchain.CurrentBlock().Hash() {
  291. t.Error("chain2 is canonical and shouldn't be")
  292. }
  293. if chain1[len(chain1)-1].Hash() != blockchain.CurrentBlock().Hash() {
  294. t.Error("chain1 isn't canonical and should be")
  295. }
  296. }
  297. func TestChainMultipleInsertions(t *testing.T) {
  298. t.Skip("Skipped: outdated test files")
  299. db, _ := ethdb.NewMemDatabase()
  300. const max = 4
  301. chains := make([]types.Blocks, max)
  302. var longest int
  303. for i := 0; i < max; i++ {
  304. var err error
  305. name := "valid" + strconv.Itoa(i+1)
  306. chains[i], err = loadChain(name, t)
  307. if len(chains[i]) >= len(chains[longest]) {
  308. longest = i
  309. }
  310. fmt.Println("loaded", name, "with a length of", len(chains[i]))
  311. if err != nil {
  312. fmt.Println(err)
  313. t.FailNow()
  314. }
  315. }
  316. blockchain := theBlockChain(db, t)
  317. done := make(chan bool, max)
  318. for i, chain := range chains {
  319. // XXX the go routine would otherwise reference the same (chain[3]) variable and fail
  320. i := i
  321. chain := chain
  322. go func() {
  323. insertChain(done, blockchain, chain, t)
  324. fmt.Println(i, "done")
  325. }()
  326. }
  327. for i := 0; i < max; i++ {
  328. <-done
  329. }
  330. if chains[longest][len(chains[longest])-1].Hash() != blockchain.CurrentBlock().Hash() {
  331. t.Error("Invalid canonical chain")
  332. }
  333. }
  334. type bproc struct{}
  335. func (bproc) Process(*types.Block) (vm.Logs, types.Receipts, error) { return nil, nil, nil }
  336. func makeChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block {
  337. var chain []*types.Block
  338. for i, difficulty := range d {
  339. header := &types.Header{
  340. Coinbase: common.Address{seed},
  341. Number: big.NewInt(int64(i + 1)),
  342. Difficulty: big.NewInt(int64(difficulty)),
  343. }
  344. if i == 0 {
  345. header.ParentHash = genesis.Hash()
  346. } else {
  347. header.ParentHash = chain[i-1].Hash()
  348. }
  349. block := types.NewBlockWithHeader(header)
  350. chain = append(chain, block)
  351. }
  352. return chain
  353. }
  354. func chm(genesis *types.Block, db ethdb.Database) *BlockChain {
  355. var eventMux event.TypeMux
  356. bc := &BlockChain{chainDb: db, genesisBlock: genesis, eventMux: &eventMux, pow: FakePow{}}
  357. bc.headerCache, _ = lru.New(100)
  358. bc.bodyCache, _ = lru.New(100)
  359. bc.bodyRLPCache, _ = lru.New(100)
  360. bc.tdCache, _ = lru.New(100)
  361. bc.blockCache, _ = lru.New(100)
  362. bc.futureBlocks, _ = lru.New(100)
  363. bc.processor = bproc{}
  364. bc.ResetWithGenesisBlock(genesis)
  365. return bc
  366. }
  367. func TestReorgLongest(t *testing.T) {
  368. db, _ := ethdb.NewMemDatabase()
  369. genesis, err := WriteTestNetGenesisBlock(db, 0)
  370. if err != nil {
  371. t.Error(err)
  372. t.FailNow()
  373. }
  374. bc := chm(genesis, db)
  375. chain1 := makeChainWithDiff(genesis, []int{1, 2, 4}, 10)
  376. chain2 := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 11)
  377. bc.InsertChain(chain1)
  378. bc.InsertChain(chain2)
  379. prev := bc.CurrentBlock()
  380. for block := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, bc.GetBlockByNumber(block.NumberU64()-1) {
  381. if prev.ParentHash() != block.Hash() {
  382. t.Errorf("parent hash mismatch %x - %x", prev.ParentHash(), block.Hash())
  383. }
  384. }
  385. }
  386. func TestBadHashes(t *testing.T) {
  387. db, _ := ethdb.NewMemDatabase()
  388. genesis, err := WriteTestNetGenesisBlock(db, 0)
  389. if err != nil {
  390. t.Error(err)
  391. t.FailNow()
  392. }
  393. bc := chm(genesis, db)
  394. chain := makeChainWithDiff(genesis, []int{1, 2, 4}, 10)
  395. BadHashes[chain[2].Header().Hash()] = true
  396. _, err = bc.InsertChain(chain)
  397. if !IsBadHashError(err) {
  398. t.Errorf("error mismatch: want: BadHashError, have: %v", err)
  399. }
  400. }
  401. func TestReorgBadHashes(t *testing.T) {
  402. db, _ := ethdb.NewMemDatabase()
  403. genesis, err := WriteTestNetGenesisBlock(db, 0)
  404. if err != nil {
  405. t.Error(err)
  406. t.FailNow()
  407. }
  408. bc := chm(genesis, db)
  409. chain := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 11)
  410. bc.InsertChain(chain)
  411. if chain[3].Header().Hash() != bc.LastBlockHash() {
  412. t.Errorf("last block hash mismatch: want: %x, have: %x", chain[3].Header().Hash(), bc.LastBlockHash())
  413. }
  414. // NewChainManager should check BadHashes when loading it db
  415. BadHashes[chain[3].Header().Hash()] = true
  416. var eventMux event.TypeMux
  417. ncm, err := NewBlockChain(db, FakePow{}, &eventMux)
  418. if err != nil {
  419. t.Errorf("NewChainManager err: %s", err)
  420. }
  421. // check it set head to (valid) parent of bad hash block
  422. if chain[2].Header().Hash() != ncm.LastBlockHash() {
  423. t.Errorf("last block hash mismatch: want: %x, have: %x", chain[2].Header().Hash(), ncm.LastBlockHash())
  424. }
  425. if chain[2].Header().GasLimit.Cmp(ncm.GasLimit()) != 0 {
  426. t.Errorf("current block gasLimit mismatch: want: %x, have: %x", chain[2].Header().GasLimit, ncm.GasLimit())
  427. }
  428. }
  429. func TestReorgShortest(t *testing.T) {
  430. db, _ := ethdb.NewMemDatabase()
  431. genesis, err := WriteTestNetGenesisBlock(db, 0)
  432. if err != nil {
  433. t.Error(err)
  434. t.FailNow()
  435. }
  436. bc := chm(genesis, db)
  437. chain1 := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 10)
  438. chain2 := makeChainWithDiff(genesis, []int{1, 10}, 11)
  439. bc.InsertChain(chain1)
  440. bc.InsertChain(chain2)
  441. prev := bc.CurrentBlock()
  442. for block := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, bc.GetBlockByNumber(block.NumberU64()-1) {
  443. if prev.ParentHash() != block.Hash() {
  444. t.Errorf("parent hash mismatch %x - %x", prev.ParentHash(), block.Hash())
  445. }
  446. }
  447. }
  448. func TestInsertNonceError(t *testing.T) {
  449. for i := 1; i < 25 && !t.Failed(); i++ {
  450. db, _ := ethdb.NewMemDatabase()
  451. genesis, err := WriteTestNetGenesisBlock(db, 0)
  452. if err != nil {
  453. t.Error(err)
  454. t.FailNow()
  455. }
  456. bc := chm(genesis, db)
  457. bc.processor = NewBlockProcessor(db, bc.pow, bc, bc.eventMux)
  458. blocks := makeChain(bc.currentBlock, i, db, 0)
  459. fail := rand.Int() % len(blocks)
  460. failblock := blocks[fail]
  461. bc.pow = failPow{failblock.NumberU64()}
  462. n, err := bc.InsertChain(blocks)
  463. // Check that the returned error indicates the nonce failure.
  464. if n != fail {
  465. t.Errorf("(i=%d) wrong failed block index: got %d, want %d", i, n, fail)
  466. }
  467. if !IsBlockNonceErr(err) {
  468. t.Fatalf("(i=%d) got %q, want a nonce error", i, err)
  469. }
  470. nerr := err.(*BlockNonceErr)
  471. if nerr.Number.Cmp(failblock.Number()) != 0 {
  472. t.Errorf("(i=%d) wrong block number in error, got %v, want %v", i, nerr.Number, failblock.Number())
  473. }
  474. if nerr.Hash != failblock.Hash() {
  475. t.Errorf("(i=%d) wrong block hash in error, got %v, want %v", i, nerr.Hash, failblock.Hash())
  476. }
  477. // Check that all no blocks after the failing block have been inserted.
  478. for _, block := range blocks[fail:] {
  479. if bc.HasBlock(block.Hash()) {
  480. t.Errorf("(i=%d) invalid block %d present in chain", i, block.NumberU64())
  481. }
  482. }
  483. }
  484. }
  485. // Tests that chain reorganizations handle transaction removals and reinsertions.
  486. func TestChainTxReorgs(t *testing.T) {
  487. params.MinGasLimit = big.NewInt(125000) // Minimum the gas limit may ever be.
  488. params.GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block.
  489. var (
  490. key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  491. key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
  492. key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
  493. addr1 = crypto.PubkeyToAddress(key1.PublicKey)
  494. addr2 = crypto.PubkeyToAddress(key2.PublicKey)
  495. addr3 = crypto.PubkeyToAddress(key3.PublicKey)
  496. db, _ = ethdb.NewMemDatabase()
  497. )
  498. genesis := WriteGenesisBlockForTesting(db,
  499. GenesisAccount{addr1, big.NewInt(1000000)},
  500. GenesisAccount{addr2, big.NewInt(1000000)},
  501. GenesisAccount{addr3, big.NewInt(1000000)},
  502. )
  503. // Create two transactions shared between the chains:
  504. // - postponed: transaction included at a later block in the forked chain
  505. // - swapped: transaction included at the same block number in the forked chain
  506. postponed, _ := types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key1)
  507. swapped, _ := types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key1)
  508. // Create two transactions that will be dropped by the forked chain:
  509. // - pastDrop: transaction dropped retroactively from a past block
  510. // - freshDrop: transaction dropped exactly at the block where the reorg is detected
  511. var pastDrop, freshDrop *types.Transaction
  512. // Create three transactions that will be added in the forked chain:
  513. // - pastAdd: transaction added before the reorganiztion is detected
  514. // - freshAdd: transaction added at the exact block the reorg is detected
  515. // - futureAdd: transaction added after the reorg has already finished
  516. var pastAdd, freshAdd, futureAdd *types.Transaction
  517. chain := GenerateChain(genesis, db, 3, func(i int, gen *BlockGen) {
  518. switch i {
  519. case 0:
  520. pastDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key2)
  521. gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point
  522. gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork
  523. case 2:
  524. freshDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key2)
  525. gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point
  526. gen.AddTx(swapped) // This transaction will be swapped out at the exact height
  527. gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain
  528. }
  529. })
  530. // Import the chain. This runs all block validation rules.
  531. evmux := &event.TypeMux{}
  532. chainman, _ := NewBlockChain(db, FakePow{}, evmux)
  533. chainman.SetProcessor(NewBlockProcessor(db, FakePow{}, chainman, evmux))
  534. if i, err := chainman.InsertChain(chain); err != nil {
  535. t.Fatalf("failed to insert original chain[%d]: %v", i, err)
  536. }
  537. // overwrite the old chain
  538. chain = GenerateChain(genesis, db, 5, func(i int, gen *BlockGen) {
  539. switch i {
  540. case 0:
  541. pastAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key3)
  542. gen.AddTx(pastAdd) // This transaction needs to be injected during reorg
  543. case 2:
  544. gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain
  545. gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain
  546. freshAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key3)
  547. gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time
  548. case 3:
  549. futureAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key3)
  550. gen.AddTx(futureAdd) // This transaction will be added after a full reorg
  551. }
  552. })
  553. if _, err := chainman.InsertChain(chain); err != nil {
  554. t.Fatalf("failed to insert forked chain: %v", err)
  555. }
  556. // removed tx
  557. for i, tx := range (types.Transactions{pastDrop, freshDrop}) {
  558. if GetTransaction(db, tx.Hash()) != nil {
  559. t.Errorf("drop %d: tx found while shouldn't have been", i)
  560. }
  561. if GetReceipt(db, tx.Hash()) != nil {
  562. t.Errorf("drop %d: receipt found while shouldn't have been", i)
  563. }
  564. }
  565. // added tx
  566. for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) {
  567. if GetTransaction(db, tx.Hash()) == nil {
  568. t.Errorf("add %d: expected tx to be found", i)
  569. }
  570. if GetReceipt(db, tx.Hash()) == nil {
  571. t.Errorf("add %d: expected receipt to be found", i)
  572. }
  573. }
  574. // shared tx
  575. for i, tx := range (types.Transactions{postponed, swapped}) {
  576. if GetTransaction(db, tx.Hash()) == nil {
  577. t.Errorf("share %d: expected tx to be found", i)
  578. }
  579. if GetReceipt(db, tx.Hash()) == nil {
  580. t.Errorf("share %d: expected receipt to be found", i)
  581. }
  582. }
  583. }