|
|
|
@ -25,6 +25,7 @@ import ( |
|
|
|
|
"runtime" |
|
|
|
|
"strconv" |
|
|
|
|
"testing" |
|
|
|
|
"time" |
|
|
|
|
|
|
|
|
|
"github.com/ethereum/ethash" |
|
|
|
|
"github.com/ethereum/go-ethereum/common" |
|
|
|
@ -1006,3 +1007,82 @@ func TestLogReorgs(t *testing.T) { |
|
|
|
|
t.Error("expected logs") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestReorgSideEvent(t *testing.T) { |
|
|
|
|
var ( |
|
|
|
|
db, _ = ethdb.NewMemDatabase() |
|
|
|
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") |
|
|
|
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey) |
|
|
|
|
genesis = WriteGenesisBlockForTesting(db, GenesisAccount{addr1, big.NewInt(10000000000000)}) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
evmux := &event.TypeMux{} |
|
|
|
|
blockchain, _ := NewBlockChain(db, FakePow{}, evmux) |
|
|
|
|
|
|
|
|
|
chain, _ := GenerateChain(genesis, db, 3, func(i int, gen *BlockGen) { |
|
|
|
|
if i == 2 { |
|
|
|
|
gen.OffsetTime(9) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
if _, err := blockchain.InsertChain(chain); err != nil { |
|
|
|
|
t.Fatalf("failed to insert chain: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
replacementBlocks, _ := GenerateChain(genesis, db, 4, func(i int, gen *BlockGen) { |
|
|
|
|
tx, err := types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), big.NewInt(1000000), new(big.Int), nil).SignECDSA(key1) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to create tx: %v", err) |
|
|
|
|
} |
|
|
|
|
gen.AddTx(tx) |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
subs := evmux.Subscribe(ChainSideEvent{}) |
|
|
|
|
if _, err := blockchain.InsertChain(replacementBlocks); err != nil { |
|
|
|
|
t.Fatalf("failed to insert chain: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// first two block of the secondary chain are for a brief moment considered
|
|
|
|
|
// side chains because up to that point the first one is considered the
|
|
|
|
|
// heavier chain.
|
|
|
|
|
expectedSideHashes := map[common.Hash]bool{ |
|
|
|
|
replacementBlocks[0].Hash(): true, |
|
|
|
|
replacementBlocks[1].Hash(): true, |
|
|
|
|
chain[0].Hash(): true, |
|
|
|
|
chain[1].Hash(): true, |
|
|
|
|
chain[2].Hash(): true, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
i := 0 |
|
|
|
|
|
|
|
|
|
const timeoutDura = 10 * time.Second |
|
|
|
|
timeout := time.NewTimer(timeoutDura) |
|
|
|
|
done: |
|
|
|
|
for { |
|
|
|
|
select { |
|
|
|
|
case ev := <-subs.Chan(): |
|
|
|
|
block := ev.Data.(ChainSideEvent).Block |
|
|
|
|
if _, ok := expectedSideHashes[block.Hash()]; !ok { |
|
|
|
|
t.Errorf("%d: didn't expect %x to be in side chain", i, block.Hash()) |
|
|
|
|
} |
|
|
|
|
i++ |
|
|
|
|
|
|
|
|
|
if i == len(expectedSideHashes) { |
|
|
|
|
timeout.Stop() |
|
|
|
|
|
|
|
|
|
break done |
|
|
|
|
} |
|
|
|
|
timeout.Reset(timeoutDura) |
|
|
|
|
|
|
|
|
|
case <-timeout.C: |
|
|
|
|
t.Fatal("Timeout. Possibly not all blocks were triggered for sideevent") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// make sure no more events are fired
|
|
|
|
|
select { |
|
|
|
|
case e := <-subs.Chan(): |
|
|
|
|
t.Errorf("unexectped event fired: %v", e) |
|
|
|
|
case <-time.After(250 * time.Millisecond): |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|