@@ -30,8 +30,10 @@ import (
30
30
"github.com/ethereum/go-ethereum/common"
31
31
"github.com/ethereum/go-ethereum/core/state"
32
32
"github.com/ethereum/go-ethereum/core/types"
33
+ "github.com/ethereum/go-ethereum/crypto"
33
34
"github.com/ethereum/go-ethereum/ethdb"
34
35
"github.com/ethereum/go-ethereum/event"
36
+ "github.com/ethereum/go-ethereum/params"
35
37
"github.com/ethereum/go-ethereum/pow"
36
38
"github.com/ethereum/go-ethereum/rlp"
37
39
"github.com/hashicorp/golang-lru"
@@ -483,19 +485,115 @@ func TestInsertNonceError(t *testing.T) {
483
485
}
484
486
}
485
487
486
- /*
487
- func TestGenesisMismatch(t *testing.T) {
488
- db, _ := ethdb.NewMemDatabase()
489
- var mux event.TypeMux
490
- genesis := GenesisBlock(0, db)
491
- _, err := NewChainManager(genesis, db, db, db, thePow(), &mux)
492
- if err != nil {
493
- t.Error(err)
488
+ // Tests that chain reorganizations handle transaction removals and reinsertions.
489
+ func TestChainTxReorgs (t * testing.T ) {
490
+ params .MinGasLimit = big .NewInt (125000 ) // Minimum the gas limit may ever be.
491
+ params .GenesisGasLimit = big .NewInt (3141592 ) // Gas limit of the Genesis block.
492
+
493
+ var (
494
+ key1 , _ = crypto .HexToECDSA ("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291" )
495
+ key2 , _ = crypto .HexToECDSA ("8a1f9a8f95be41cd7ccb6168179afb4504aefe388d1e14474d32c45c72ce7b7a" )
496
+ key3 , _ = crypto .HexToECDSA ("49a7b37aa6f6645917e7b807e9d1c00d4fa71f18343b0d4122a4d2df64dd6fee" )
497
+ addr1 = crypto .PubkeyToAddress (key1 .PublicKey )
498
+ addr2 = crypto .PubkeyToAddress (key2 .PublicKey )
499
+ addr3 = crypto .PubkeyToAddress (key3 .PublicKey )
500
+ db , _ = ethdb .NewMemDatabase ()
501
+ )
502
+ genesis := WriteGenesisBlockForTesting (db ,
503
+ GenesisAccount {addr1 , big .NewInt (1000000 )},
504
+ GenesisAccount {addr2 , big .NewInt (1000000 )},
505
+ GenesisAccount {addr3 , big .NewInt (1000000 )},
506
+ )
507
+ // Create two transactions shared between the chains:
508
+ // - postponed: transaction included at a later block in the forked chain
509
+ // - swapped: transaction included at the same block number in the forked chain
510
+ postponed , _ := types .NewTransaction (0 , addr1 , big .NewInt (1000 ), params .TxGas , nil , nil ).SignECDSA (key1 )
511
+ swapped , _ := types .NewTransaction (1 , addr1 , big .NewInt (1000 ), params .TxGas , nil , nil ).SignECDSA (key1 )
512
+
513
+ // Create two transactions that will be dropped by the forked chain:
514
+ // - pastDrop: transaction dropped retroactively from a past block
515
+ // - freshDrop: transaction dropped exactly at the block where the reorg is detected
516
+ var pastDrop , freshDrop * types.Transaction
517
+
518
+ // Create three transactions that will be added in the forked chain:
519
+ // - pastAdd: transaction added before the reorganiztion is detected
520
+ // - freshAdd: transaction added at the exact block the reorg is detected
521
+ // - futureAdd: transaction added after the reorg has already finished
522
+ var pastAdd , freshAdd , futureAdd * types.Transaction
523
+
524
+ chain := GenerateChain (genesis , db , 3 , func (i int , gen * BlockGen ) {
525
+ switch i {
526
+ case 0 :
527
+ pastDrop , _ = types .NewTransaction (gen .TxNonce (addr2 ), addr2 , big .NewInt (1000 ), params .TxGas , nil , nil ).SignECDSA (key2 )
528
+
529
+ gen .AddTx (pastDrop ) // This transaction will be dropped in the fork from below the split point
530
+ gen .AddTx (postponed ) // This transaction will be postponed till block #3 in the fork
531
+
532
+ case 2 :
533
+ freshDrop , _ = types .NewTransaction (gen .TxNonce (addr2 ), addr2 , big .NewInt (1000 ), params .TxGas , nil , nil ).SignECDSA (key2 )
534
+
535
+ gen .AddTx (freshDrop ) // This transaction will be dropped in the fork from exactly at the split point
536
+ gen .AddTx (swapped ) // This transaction will be swapped out at the exact height
537
+
538
+ gen .OffsetTime (9 ) // Lower the block difficulty to simulate a weaker chain
539
+ }
540
+ })
541
+ // Import the chain. This runs all block validation rules.
542
+ evmux := & event.TypeMux {}
543
+ chainman , _ := NewChainManager (db , FakePow {}, evmux )
544
+ chainman .SetProcessor (NewBlockProcessor (db , FakePow {}, chainman , evmux ))
545
+ if i , err := chainman .InsertChain (chain ); err != nil {
546
+ t .Fatalf ("failed to insert original chain[%d]: %v" , i , err )
547
+ }
548
+
549
+ // overwrite the old chain
550
+ chain = GenerateChain (genesis , db , 5 , func (i int , gen * BlockGen ) {
551
+ switch i {
552
+ case 0 :
553
+ pastAdd , _ = types .NewTransaction (gen .TxNonce (addr3 ), addr3 , big .NewInt (1000 ), params .TxGas , nil , nil ).SignECDSA (key3 )
554
+ gen .AddTx (pastAdd ) // This transaction needs to be injected during reorg
555
+
556
+ case 2 :
557
+ gen .AddTx (postponed ) // This transaction was postponed from block #1 in the original chain
558
+ gen .AddTx (swapped ) // This transaction was swapped from the exact current spot in the original chain
559
+
560
+ freshAdd , _ = types .NewTransaction (gen .TxNonce (addr3 ), addr3 , big .NewInt (1000 ), params .TxGas , nil , nil ).SignECDSA (key3 )
561
+ gen .AddTx (freshAdd ) // This transaction will be added exactly at reorg time
562
+
563
+ case 3 :
564
+ futureAdd , _ = types .NewTransaction (gen .TxNonce (addr3 ), addr3 , big .NewInt (1000 ), params .TxGas , nil , nil ).SignECDSA (key3 )
565
+ gen .AddTx (futureAdd ) // This transaction will be added after a full reorg
566
+ }
567
+ })
568
+ if _ , err := chainman .InsertChain (chain ); err != nil {
569
+ t .Fatalf ("failed to insert forked chain: %v" , err )
494
570
}
495
- genesis = GenesisBlock(1, db)
496
- _, err = NewChainManager(genesis, db, db, db, thePow(), &mux)
497
- if err == nil {
498
- t.Error("expected genesis mismatch error")
571
+
572
+ // removed tx
573
+ for i , tx := range (types.Transactions {pastDrop , freshDrop }) {
574
+ if GetTransaction (db , tx .Hash ()) != nil {
575
+ t .Errorf ("drop %d: tx found while shouldn't have been" , i )
576
+ }
577
+ if GetReceipt (db , tx .Hash ()) != nil {
578
+ t .Errorf ("drop %d: receipt found while shouldn't have been" , i )
579
+ }
580
+ }
581
+ // added tx
582
+ for i , tx := range (types.Transactions {pastAdd , freshAdd , futureAdd }) {
583
+ if GetTransaction (db , tx .Hash ()) == nil {
584
+ t .Errorf ("add %d: expected tx to be found" , i )
585
+ }
586
+ if GetReceipt (db , tx .Hash ()) == nil {
587
+ t .Errorf ("add %d: expected receipt to be found" , i )
588
+ }
589
+ }
590
+ // shared tx
591
+ for i , tx := range (types.Transactions {postponed , swapped }) {
592
+ if GetTransaction (db , tx .Hash ()) == nil {
593
+ t .Errorf ("share %d: expected tx to be found" , i )
594
+ }
595
+ if GetReceipt (db , tx .Hash ()) == nil {
596
+ t .Errorf ("share %d: expected receipt to be found" , i )
597
+ }
499
598
}
500
599
}
501
- */
0 commit comments