core: announce ChainSideEvent during reorg

Previously all blocks that were already in our chain were never re
announced as potential uncle block (e.g. ChainSideEvent). This is
problematic during mining where you want to gather as much possible
uncles as possible increasing the profit. This is now addressed in this
PR where during reorganisations of chains the old chain is regarded as
uncles.

Fixed #2298
This commit is contained in:
Jeffrey Wilcke
2016-03-07 18:11:52 +01:00
committed by Jeffrey Wilcke
parent d45f01d5f7
commit ba3fb9e6f4
2 changed files with 101 additions and 6 deletions

View File

@ -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):
}
}