chain_manager_test.go 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599
  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/state"
  29. "github.com/ethereum/go-ethereum/core/types"
  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 theChainManager(db ethdb.Database, t *testing.T) *ChainManager {
  46. var eventMux event.TypeMux
  47. WriteTestNetGenesisBlock(db, 0)
  48. chainMan, err := NewChainManager(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, chainMan, &eventMux)
  55. chainMan.SetProcessor(blockMan)
  56. return chainMan
  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. // asert 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 *ChainManager) {
  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, chainMan *ChainManager, chain types.Blocks, t *testing.T) {
  131. _, err := chainMan.InsertChain(chain)
  132. if err != nil {
  133. fmt.Println(err)
  134. t.FailNow()
  135. }
  136. done <- true
  137. }
  138. func TestExtendCanonical(t *testing.T) {
  139. CanonicalLength := 5
  140. db, err := ethdb.NewMemDatabase()
  141. if err != nil {
  142. t.Fatal("Failed to create db:", err)
  143. }
  144. // make first chain starting from genesis
  145. bman, err := newCanonical(CanonicalLength, db)
  146. if err != nil {
  147. t.Fatal("Could not make new canonical chain:", err)
  148. }
  149. f := func(td1, td2 *big.Int) {
  150. if td2.Cmp(td1) <= 0 {
  151. t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1)
  152. }
  153. }
  154. // Start fork from current height (CanonicalLength)
  155. testFork(t, bman, CanonicalLength, 1, f)
  156. testFork(t, bman, CanonicalLength, 2, f)
  157. testFork(t, bman, CanonicalLength, 5, f)
  158. testFork(t, bman, CanonicalLength, 10, f)
  159. }
  160. func TestShorterFork(t *testing.T) {
  161. db, err := ethdb.NewMemDatabase()
  162. if err != nil {
  163. t.Fatal("Failed to create db:", err)
  164. }
  165. // make first chain starting from genesis
  166. bman, err := newCanonical(10, db)
  167. if err != nil {
  168. t.Fatal("Could not make new canonical chain:", err)
  169. }
  170. f := func(td1, td2 *big.Int) {
  171. if td2.Cmp(td1) >= 0 {
  172. t.Error("expected chainB to have lower difficulty. Got", td2, "expected less than", td1)
  173. }
  174. }
  175. // Sum of numbers must be less than 10
  176. // for this to be a shorter fork
  177. testFork(t, bman, 0, 3, f)
  178. testFork(t, bman, 0, 7, f)
  179. testFork(t, bman, 1, 1, f)
  180. testFork(t, bman, 1, 7, f)
  181. testFork(t, bman, 5, 3, f)
  182. testFork(t, bman, 5, 4, f)
  183. }
  184. func TestLongerFork(t *testing.T) {
  185. db, err := ethdb.NewMemDatabase()
  186. if err != nil {
  187. t.Fatal("Failed to create db:", err)
  188. }
  189. // make first chain starting from genesis
  190. bman, err := newCanonical(10, db)
  191. if err != nil {
  192. t.Fatal("Could not make new canonical chain:", err)
  193. }
  194. f := func(td1, td2 *big.Int) {
  195. if td2.Cmp(td1) <= 0 {
  196. t.Error("expected chainB to have higher difficulty. Got", td2, "expected more than", td1)
  197. }
  198. }
  199. // Sum of numbers must be greater than 10
  200. // for this to be a longer fork
  201. testFork(t, bman, 0, 11, f)
  202. testFork(t, bman, 0, 15, f)
  203. testFork(t, bman, 1, 10, f)
  204. testFork(t, bman, 1, 12, f)
  205. testFork(t, bman, 5, 6, f)
  206. testFork(t, bman, 5, 8, f)
  207. }
  208. func TestEqualFork(t *testing.T) {
  209. db, err := ethdb.NewMemDatabase()
  210. if err != nil {
  211. t.Fatal("Failed to create db:", err)
  212. }
  213. bman, err := newCanonical(10, db)
  214. if err != nil {
  215. t.Fatal("Could not make new canonical chain:", err)
  216. }
  217. f := func(td1, td2 *big.Int) {
  218. if td2.Cmp(td1) != 0 {
  219. t.Error("expected chainB to have equal difficulty. Got", td2, "expected ", td1)
  220. }
  221. }
  222. // Sum of numbers must be equal to 10
  223. // for this to be an equal fork
  224. testFork(t, bman, 0, 10, f)
  225. testFork(t, bman, 1, 9, f)
  226. testFork(t, bman, 2, 8, f)
  227. testFork(t, bman, 5, 5, f)
  228. testFork(t, bman, 6, 4, f)
  229. testFork(t, bman, 9, 1, f)
  230. }
  231. func TestBrokenChain(t *testing.T) {
  232. db, err := ethdb.NewMemDatabase()
  233. if err != nil {
  234. t.Fatal("Failed to create db:", err)
  235. }
  236. bman, err := newCanonical(10, db)
  237. if err != nil {
  238. t.Fatal("Could not make new canonical chain:", err)
  239. }
  240. db2, err := ethdb.NewMemDatabase()
  241. if err != nil {
  242. t.Fatal("Failed to create db:", err)
  243. }
  244. bman2, err := newCanonical(10, db2)
  245. if err != nil {
  246. t.Fatal("Could not make new canonical chain:", err)
  247. }
  248. bman2.bc.SetProcessor(bman2)
  249. parent := bman2.bc.CurrentBlock()
  250. chainB := makeChain(parent, 5, db2, forkSeed)
  251. chainB = chainB[1:]
  252. _, err = testChain(chainB, bman)
  253. if err == nil {
  254. t.Error("expected broken chain to return error")
  255. }
  256. }
  257. func TestChainInsertions(t *testing.T) {
  258. t.Skip("Skipped: outdated test files")
  259. db, _ := ethdb.NewMemDatabase()
  260. chain1, err := loadChain("valid1", t)
  261. if err != nil {
  262. fmt.Println(err)
  263. t.FailNow()
  264. }
  265. chain2, err := loadChain("valid2", t)
  266. if err != nil {
  267. fmt.Println(err)
  268. t.FailNow()
  269. }
  270. chainMan := theChainManager(db, t)
  271. const max = 2
  272. done := make(chan bool, max)
  273. go insertChain(done, chainMan, chain1, t)
  274. go insertChain(done, chainMan, chain2, t)
  275. for i := 0; i < max; i++ {
  276. <-done
  277. }
  278. if chain2[len(chain2)-1].Hash() != chainMan.CurrentBlock().Hash() {
  279. t.Error("chain2 is canonical and shouldn't be")
  280. }
  281. if chain1[len(chain1)-1].Hash() != chainMan.CurrentBlock().Hash() {
  282. t.Error("chain1 isn't canonical and should be")
  283. }
  284. }
  285. func TestChainMultipleInsertions(t *testing.T) {
  286. t.Skip("Skipped: outdated test files")
  287. db, _ := ethdb.NewMemDatabase()
  288. const max = 4
  289. chains := make([]types.Blocks, max)
  290. var longest int
  291. for i := 0; i < max; i++ {
  292. var err error
  293. name := "valid" + strconv.Itoa(i+1)
  294. chains[i], err = loadChain(name, t)
  295. if len(chains[i]) >= len(chains[longest]) {
  296. longest = i
  297. }
  298. fmt.Println("loaded", name, "with a length of", len(chains[i]))
  299. if err != nil {
  300. fmt.Println(err)
  301. t.FailNow()
  302. }
  303. }
  304. chainMan := theChainManager(db, t)
  305. done := make(chan bool, max)
  306. for i, chain := range chains {
  307. // XXX the go routine would otherwise reference the same (chain[3]) variable and fail
  308. i := i
  309. chain := chain
  310. go func() {
  311. insertChain(done, chainMan, chain, t)
  312. fmt.Println(i, "done")
  313. }()
  314. }
  315. for i := 0; i < max; i++ {
  316. <-done
  317. }
  318. if chains[longest][len(chains[longest])-1].Hash() != chainMan.CurrentBlock().Hash() {
  319. t.Error("Invalid canonical chain")
  320. }
  321. }
  322. type bproc struct{}
  323. func (bproc) Process(*types.Block) (state.Logs, types.Receipts, error) { return nil, nil, nil }
  324. func makeChainWithDiff(genesis *types.Block, d []int, seed byte) []*types.Block {
  325. var chain []*types.Block
  326. for i, difficulty := range d {
  327. header := &types.Header{
  328. Coinbase: common.Address{seed},
  329. Number: big.NewInt(int64(i + 1)),
  330. Difficulty: big.NewInt(int64(difficulty)),
  331. }
  332. if i == 0 {
  333. header.ParentHash = genesis.Hash()
  334. } else {
  335. header.ParentHash = chain[i-1].Hash()
  336. }
  337. block := types.NewBlockWithHeader(header)
  338. chain = append(chain, block)
  339. }
  340. return chain
  341. }
  342. func chm(genesis *types.Block, db ethdb.Database) *ChainManager {
  343. var eventMux event.TypeMux
  344. bc := &ChainManager{chainDb: db, genesisBlock: genesis, eventMux: &eventMux, pow: FakePow{}}
  345. bc.headerCache, _ = lru.New(100)
  346. bc.bodyCache, _ = lru.New(100)
  347. bc.bodyRLPCache, _ = lru.New(100)
  348. bc.tdCache, _ = lru.New(100)
  349. bc.blockCache, _ = lru.New(100)
  350. bc.futureBlocks, _ = lru.New(100)
  351. bc.processor = bproc{}
  352. bc.ResetWithGenesisBlock(genesis)
  353. return bc
  354. }
  355. func TestReorgLongest(t *testing.T) {
  356. db, _ := ethdb.NewMemDatabase()
  357. genesis, err := WriteTestNetGenesisBlock(db, 0)
  358. if err != nil {
  359. t.Error(err)
  360. t.FailNow()
  361. }
  362. bc := chm(genesis, db)
  363. chain1 := makeChainWithDiff(genesis, []int{1, 2, 4}, 10)
  364. chain2 := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 11)
  365. bc.InsertChain(chain1)
  366. bc.InsertChain(chain2)
  367. prev := bc.CurrentBlock()
  368. for block := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, bc.GetBlockByNumber(block.NumberU64()-1) {
  369. if prev.ParentHash() != block.Hash() {
  370. t.Errorf("parent hash mismatch %x - %x", prev.ParentHash(), block.Hash())
  371. }
  372. }
  373. }
  374. func TestReorgShortest(t *testing.T) {
  375. db, _ := ethdb.NewMemDatabase()
  376. genesis, err := WriteTestNetGenesisBlock(db, 0)
  377. if err != nil {
  378. t.Error(err)
  379. t.FailNow()
  380. }
  381. bc := chm(genesis, db)
  382. chain1 := makeChainWithDiff(genesis, []int{1, 2, 3, 4}, 10)
  383. chain2 := makeChainWithDiff(genesis, []int{1, 10}, 11)
  384. bc.InsertChain(chain1)
  385. bc.InsertChain(chain2)
  386. prev := bc.CurrentBlock()
  387. for block := bc.GetBlockByNumber(bc.CurrentBlock().NumberU64() - 1); block.NumberU64() != 0; prev, block = block, bc.GetBlockByNumber(block.NumberU64()-1) {
  388. if prev.ParentHash() != block.Hash() {
  389. t.Errorf("parent hash mismatch %x - %x", prev.ParentHash(), block.Hash())
  390. }
  391. }
  392. }
  393. func TestInsertNonceError(t *testing.T) {
  394. for i := 1; i < 25 && !t.Failed(); i++ {
  395. db, _ := ethdb.NewMemDatabase()
  396. genesis, err := WriteTestNetGenesisBlock(db, 0)
  397. if err != nil {
  398. t.Error(err)
  399. t.FailNow()
  400. }
  401. bc := chm(genesis, db)
  402. bc.processor = NewBlockProcessor(db, bc.pow, bc, bc.eventMux)
  403. blocks := makeChain(bc.currentBlock, i, db, 0)
  404. fail := rand.Int() % len(blocks)
  405. failblock := blocks[fail]
  406. bc.pow = failPow{failblock.NumberU64()}
  407. n, err := bc.InsertChain(blocks)
  408. // Check that the returned error indicates the nonce failure.
  409. if n != fail {
  410. t.Errorf("(i=%d) wrong failed block index: got %d, want %d", i, n, fail)
  411. }
  412. if !IsBlockNonceErr(err) {
  413. t.Fatalf("(i=%d) got %q, want a nonce error", i, err)
  414. }
  415. nerr := err.(*BlockNonceErr)
  416. if nerr.Number.Cmp(failblock.Number()) != 0 {
  417. t.Errorf("(i=%d) wrong block number in error, got %v, want %v", i, nerr.Number, failblock.Number())
  418. }
  419. if nerr.Hash != failblock.Hash() {
  420. t.Errorf("(i=%d) wrong block hash in error, got %v, want %v", i, nerr.Hash, failblock.Hash())
  421. }
  422. // Check that all no blocks after the failing block have been inserted.
  423. for _, block := range blocks[fail:] {
  424. if bc.HasBlock(block.Hash()) {
  425. t.Errorf("(i=%d) invalid block %d present in chain", i, block.NumberU64())
  426. }
  427. }
  428. }
  429. }
  430. // Tests that chain reorganizations handle transaction removals and reinsertions.
  431. func TestChainTxReorgs(t *testing.T) {
  432. params.MinGasLimit = big.NewInt(125000) // Minimum the gas limit may ever be.
  433. params.GenesisGasLimit = big.NewInt(3141592) // Gas limit of the Genesis block.
  434. var (
  435. key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291")
  436. key2, _ = crypto.HexToECDSA("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a")
  437. key3, _ = crypto.HexToECDSA("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee")
  438. addr1 = crypto.PubkeyToAddress(key1.PublicKey)
  439. addr2 = crypto.PubkeyToAddress(key2.PublicKey)
  440. addr3 = crypto.PubkeyToAddress(key3.PublicKey)
  441. db, _ = ethdb.NewMemDatabase()
  442. )
  443. genesis := WriteGenesisBlockForTesting(db,
  444. GenesisAccount{addr1, big.NewInt(1000000)},
  445. GenesisAccount{addr2, big.NewInt(1000000)},
  446. GenesisAccount{addr3, big.NewInt(1000000)},
  447. )
  448. // Create two transactions shared between the chains:
  449. // - postponed: transaction included at a later block in the forked chain
  450. // - swapped: transaction included at the same block number in the forked chain
  451. postponed, _ := types.NewTransaction(0, addr1, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key1)
  452. swapped, _ := types.NewTransaction(1, addr1, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key1)
  453. // Create two transactions that will be dropped by the forked chain:
  454. // - pastDrop: transaction dropped retroactively from a past block
  455. // - freshDrop: transaction dropped exactly at the block where the reorg is detected
  456. var pastDrop, freshDrop *types.Transaction
  457. // Create three transactions that will be added in the forked chain:
  458. // - pastAdd: transaction added before the reorganiztion is detected
  459. // - freshAdd: transaction added at the exact block the reorg is detected
  460. // - futureAdd: transaction added after the reorg has already finished
  461. var pastAdd, freshAdd, futureAdd *types.Transaction
  462. chain := GenerateChain(genesis, db, 3, func(i int, gen *BlockGen) {
  463. switch i {
  464. case 0:
  465. pastDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key2)
  466. gen.AddTx(pastDrop) // This transaction will be dropped in the fork from below the split point
  467. gen.AddTx(postponed) // This transaction will be postponed till block #3 in the fork
  468. case 2:
  469. freshDrop, _ = types.NewTransaction(gen.TxNonce(addr2), addr2, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key2)
  470. gen.AddTx(freshDrop) // This transaction will be dropped in the fork from exactly at the split point
  471. gen.AddTx(swapped) // This transaction will be swapped out at the exact height
  472. gen.OffsetTime(9) // Lower the block difficulty to simulate a weaker chain
  473. }
  474. })
  475. // Import the chain. This runs all block validation rules.
  476. evmux := &event.TypeMux{}
  477. chainman, _ := NewChainManager(db, FakePow{}, evmux)
  478. chainman.SetProcessor(NewBlockProcessor(db, FakePow{}, chainman, evmux))
  479. if i, err := chainman.InsertChain(chain); err != nil {
  480. t.Fatalf("failed to insert original chain[%d]: %v", i, err)
  481. }
  482. // overwrite the old chain
  483. chain = GenerateChain(genesis, db, 5, func(i int, gen *BlockGen) {
  484. switch i {
  485. case 0:
  486. pastAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key3)
  487. gen.AddTx(pastAdd) // This transaction needs to be injected during reorg
  488. case 2:
  489. gen.AddTx(postponed) // This transaction was postponed from block #1 in the original chain
  490. gen.AddTx(swapped) // This transaction was swapped from the exact current spot in the original chain
  491. freshAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key3)
  492. gen.AddTx(freshAdd) // This transaction will be added exactly at reorg time
  493. case 3:
  494. futureAdd, _ = types.NewTransaction(gen.TxNonce(addr3), addr3, big.NewInt(1000), params.TxGas, nil, nil).SignECDSA(key3)
  495. gen.AddTx(futureAdd) // This transaction will be added after a full reorg
  496. }
  497. })
  498. if _, err := chainman.InsertChain(chain); err != nil {
  499. t.Fatalf("failed to insert forked chain: %v", err)
  500. }
  501. // removed tx
  502. for i, tx := range (types.Transactions{pastDrop, freshDrop}) {
  503. if GetTransaction(db, tx.Hash()) != nil {
  504. t.Errorf("drop %d: tx found while shouldn't have been", i)
  505. }
  506. if GetReceipt(db, tx.Hash()) != nil {
  507. t.Errorf("drop %d: receipt found while shouldn't have been", i)
  508. }
  509. }
  510. // added tx
  511. for i, tx := range (types.Transactions{pastAdd, freshAdd, futureAdd}) {
  512. if GetTransaction(db, tx.Hash()) == nil {
  513. t.Errorf("add %d: expected tx to be found", i)
  514. }
  515. if GetReceipt(db, tx.Hash()) == nil {
  516. t.Errorf("add %d: expected receipt to be found", i)
  517. }
  518. }
  519. // shared tx
  520. for i, tx := range (types.Transactions{postponed, swapped}) {
  521. if GetTransaction(db, tx.Hash()) == nil {
  522. t.Errorf("share %d: expected tx to be found", i)
  523. }
  524. if GetReceipt(db, tx.Hash()) == nil {
  525. t.Errorf("share %d: expected receipt to be found", i)
  526. }
  527. }
  528. }