|
|
|
@ -32,6 +32,7 @@ import ( |
|
|
|
|
"github.com/ethereum/go-ethereum/core/vm" |
|
|
|
|
"github.com/ethereum/go-ethereum/crypto" |
|
|
|
|
"github.com/ethereum/go-ethereum/ethdb" |
|
|
|
|
"github.com/ethereum/go-ethereum/ethdb/memorydb" |
|
|
|
|
"github.com/ethereum/go-ethereum/params" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
@ -867,7 +868,6 @@ func TestChainTxReorgs(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestLogReorgs(t *testing.T) { |
|
|
|
|
|
|
|
|
|
var ( |
|
|
|
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") |
|
|
|
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey) |
|
|
|
@ -913,6 +913,213 @@ func TestLogReorgs(t *testing.T) { |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestLogRebirth(t *testing.T) { |
|
|
|
|
var ( |
|
|
|
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") |
|
|
|
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey) |
|
|
|
|
db = memorydb.New() |
|
|
|
|
|
|
|
|
|
// this code generates a log
|
|
|
|
|
code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") |
|
|
|
|
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} |
|
|
|
|
genesis = gspec.MustCommit(db) |
|
|
|
|
signer = types.NewEIP155Signer(gspec.Config.ChainID) |
|
|
|
|
newLogCh = make(chan bool) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// listenNewLog checks whether the received logs number is equal with expected.
|
|
|
|
|
listenNewLog := func(sink chan []*types.Log, expect int) { |
|
|
|
|
cnt := 0 |
|
|
|
|
for { |
|
|
|
|
select { |
|
|
|
|
case logs := <-sink: |
|
|
|
|
cnt += len(logs) |
|
|
|
|
case <-time.NewTimer(5 * time.Second).C: |
|
|
|
|
// new logs timeout
|
|
|
|
|
newLogCh <- false |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if cnt == expect { |
|
|
|
|
break |
|
|
|
|
} else if cnt > expect { |
|
|
|
|
// redundant logs received
|
|
|
|
|
newLogCh <- false |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
select { |
|
|
|
|
case <-sink: |
|
|
|
|
// redundant logs received
|
|
|
|
|
newLogCh <- false |
|
|
|
|
case <-time.NewTimer(100 * time.Millisecond).C: |
|
|
|
|
newLogCh <- true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) |
|
|
|
|
defer blockchain.Stop() |
|
|
|
|
|
|
|
|
|
logsCh := make(chan []*types.Log) |
|
|
|
|
blockchain.SubscribeLogsEvent(logsCh) |
|
|
|
|
|
|
|
|
|
rmLogsCh := make(chan RemovedLogsEvent) |
|
|
|
|
blockchain.SubscribeRemovedLogsEvent(rmLogsCh) |
|
|
|
|
|
|
|
|
|
chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { |
|
|
|
|
if i == 1 { |
|
|
|
|
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to create tx: %v", err) |
|
|
|
|
} |
|
|
|
|
gen.AddTx(tx) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
// Spawn a goroutine to receive log events
|
|
|
|
|
go listenNewLog(logsCh, 1) |
|
|
|
|
if _, err := blockchain.InsertChain(chain); err != nil { |
|
|
|
|
t.Fatalf("failed to insert chain: %v", err) |
|
|
|
|
} |
|
|
|
|
if !<-newLogCh { |
|
|
|
|
t.Fatalf("failed to receive new log event") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Generate long reorg chain
|
|
|
|
|
forkChain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { |
|
|
|
|
if i == 1 { |
|
|
|
|
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to create tx: %v", err) |
|
|
|
|
} |
|
|
|
|
gen.AddTx(tx) |
|
|
|
|
// Higher block difficulty
|
|
|
|
|
gen.OffsetTime(-9) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
|
|
|
|
|
// Spawn a goroutine to receive log events
|
|
|
|
|
go listenNewLog(logsCh, 1) |
|
|
|
|
if _, err := blockchain.InsertChain(forkChain); err != nil { |
|
|
|
|
t.Fatalf("failed to insert forked chain: %v", err) |
|
|
|
|
} |
|
|
|
|
if !<-newLogCh { |
|
|
|
|
t.Fatalf("failed to receive new log event") |
|
|
|
|
} |
|
|
|
|
// Ensure removedLog events received
|
|
|
|
|
select { |
|
|
|
|
case ev := <-rmLogsCh: |
|
|
|
|
if len(ev.Logs) == 0 { |
|
|
|
|
t.Error("expected logs") |
|
|
|
|
} |
|
|
|
|
case <-time.NewTimer(1 * time.Second).C: |
|
|
|
|
t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
newBlocks, _ := GenerateChain(params.TestChainConfig, chain[len(chain)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) |
|
|
|
|
go listenNewLog(logsCh, 1) |
|
|
|
|
if _, err := blockchain.InsertChain(newBlocks); err != nil { |
|
|
|
|
t.Fatalf("failed to insert forked chain: %v", err) |
|
|
|
|
} |
|
|
|
|
// Ensure removedLog events received
|
|
|
|
|
select { |
|
|
|
|
case ev := <-rmLogsCh: |
|
|
|
|
if len(ev.Logs) == 0 { |
|
|
|
|
t.Error("expected logs") |
|
|
|
|
} |
|
|
|
|
case <-time.NewTimer(1 * time.Second).C: |
|
|
|
|
t.Fatal("Timeout. There is no RemovedLogsEvent has been sent.") |
|
|
|
|
} |
|
|
|
|
// Rebirth logs should omit a newLogEvent
|
|
|
|
|
if !<-newLogCh { |
|
|
|
|
t.Fatalf("failed to receive new log event") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestSideLogRebirth(t *testing.T) { |
|
|
|
|
var ( |
|
|
|
|
key1, _ = crypto.HexToECDSA("b71c71a67e1177ad4e901695e1b4b9ee17ae16c6668d313eac2f96dbcda3f291") |
|
|
|
|
addr1 = crypto.PubkeyToAddress(key1.PublicKey) |
|
|
|
|
db = memorydb.New() |
|
|
|
|
|
|
|
|
|
// this code generates a log
|
|
|
|
|
code = common.Hex2Bytes("60606040525b7f24ec1d3ff24c2f6ff210738839dbc339cd45a5294d85c79361016243157aae7b60405180905060405180910390a15b600a8060416000396000f360606040526008565b00") |
|
|
|
|
gspec = &Genesis{Config: params.TestChainConfig, Alloc: GenesisAlloc{addr1: {Balance: big.NewInt(10000000000000)}}} |
|
|
|
|
genesis = gspec.MustCommit(db) |
|
|
|
|
signer = types.NewEIP155Signer(gspec.Config.ChainID) |
|
|
|
|
newLogCh = make(chan bool) |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
// listenNewLog checks whether the received logs number is equal with expected.
|
|
|
|
|
listenNewLog := func(sink chan []*types.Log, expect int) { |
|
|
|
|
cnt := 0 |
|
|
|
|
for { |
|
|
|
|
select { |
|
|
|
|
case logs := <-sink: |
|
|
|
|
cnt += len(logs) |
|
|
|
|
case <-time.NewTimer(5 * time.Second).C: |
|
|
|
|
// new logs timeout
|
|
|
|
|
newLogCh <- false |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
if cnt == expect { |
|
|
|
|
break |
|
|
|
|
} else if cnt > expect { |
|
|
|
|
// redundant logs received
|
|
|
|
|
newLogCh <- false |
|
|
|
|
return |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
select { |
|
|
|
|
case <-sink: |
|
|
|
|
// redundant logs received
|
|
|
|
|
newLogCh <- false |
|
|
|
|
case <-time.NewTimer(100 * time.Millisecond).C: |
|
|
|
|
newLogCh <- true |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
blockchain, _ := NewBlockChain(db, nil, gspec.Config, ethash.NewFaker(), vm.Config{}, nil) |
|
|
|
|
defer blockchain.Stop() |
|
|
|
|
|
|
|
|
|
logsCh := make(chan []*types.Log) |
|
|
|
|
blockchain.SubscribeLogsEvent(logsCh) |
|
|
|
|
|
|
|
|
|
chain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { |
|
|
|
|
if i == 1 { |
|
|
|
|
// Higher block difficulty
|
|
|
|
|
gen.OffsetTime(-9) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
if _, err := blockchain.InsertChain(chain); err != nil { |
|
|
|
|
t.Fatalf("failed to insert forked chain: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Generate side chain with lower difficulty
|
|
|
|
|
sideChain, _ := GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), db, 2, func(i int, gen *BlockGen) { |
|
|
|
|
if i == 1 { |
|
|
|
|
tx, err := types.SignTx(types.NewContractCreation(gen.TxNonce(addr1), new(big.Int), 1000000, new(big.Int), code), signer, key1) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to create tx: %v", err) |
|
|
|
|
} |
|
|
|
|
gen.AddTx(tx) |
|
|
|
|
} |
|
|
|
|
}) |
|
|
|
|
if _, err := blockchain.InsertChain(sideChain); err != nil { |
|
|
|
|
t.Fatalf("failed to insert forked chain: %v", err) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Generate a new block based on side chain
|
|
|
|
|
newBlocks, _ := GenerateChain(params.TestChainConfig, sideChain[len(sideChain)-1], ethash.NewFaker(), db, 1, func(i int, gen *BlockGen) {}) |
|
|
|
|
go listenNewLog(logsCh, 1) |
|
|
|
|
if _, err := blockchain.InsertChain(newBlocks); err != nil { |
|
|
|
|
t.Fatalf("failed to insert forked chain: %v", err) |
|
|
|
|
} |
|
|
|
|
// Rebirth logs should omit a newLogEvent
|
|
|
|
|
if !<-newLogCh { |
|
|
|
|
t.Fatalf("failed to receive new log event") |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func TestReorgSideEvent(t *testing.T) { |
|
|
|
|
var ( |
|
|
|
|
db = rawdb.NewMemoryDatabase() |
|
|
|
|