mirror of
https://github.com/ethereum/go-ethereum.git
synced 2026-07-16 01:40:44 +00:00
parent
1fe81d541d
commit
beb6ff97d7
2 changed files with 1 additions and 122 deletions
|
|
@ -17,7 +17,6 @@
|
||||||
package core
|
package core
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"runtime"
|
|
||||||
"testing"
|
"testing"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
|
@ -77,123 +76,3 @@ func TestHeaderVerification(t *testing.T) {
|
||||||
chain.InsertChain(blocks[i : i+1])
|
chain.InsertChain(blocks[i : i+1])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Tests that concurrent header verification works, for both good and bad blocks.
|
|
||||||
func TestHeaderConcurrentVerification2(t *testing.T) { testHeaderConcurrentVerification(t, 2) }
|
|
||||||
func TestHeaderConcurrentVerification8(t *testing.T) { testHeaderConcurrentVerification(t, 8) }
|
|
||||||
func TestHeaderConcurrentVerification32(t *testing.T) { testHeaderConcurrentVerification(t, 32) }
|
|
||||||
|
|
||||||
func testHeaderConcurrentVerification(t *testing.T, threads int) {
|
|
||||||
// Create a simple chain to verify
|
|
||||||
var (
|
|
||||||
testdb = rawdb.NewMemoryDatabase()
|
|
||||||
gspec = &Genesis{Config: params.TestChainConfig}
|
|
||||||
genesis = gspec.MustCommit(testdb)
|
|
||||||
blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 8, nil)
|
|
||||||
)
|
|
||||||
headers := make([]*types.Header, len(blocks))
|
|
||||||
seals := make([]bool, len(blocks))
|
|
||||||
|
|
||||||
for i, block := range blocks {
|
|
||||||
headers[i] = block.Header()
|
|
||||||
seals[i] = true
|
|
||||||
}
|
|
||||||
// Set the number of threads to verify on
|
|
||||||
old := runtime.GOMAXPROCS(threads)
|
|
||||||
defer runtime.GOMAXPROCS(old)
|
|
||||||
|
|
||||||
// Run the header checker for the entire block chain at once both for a valid and
|
|
||||||
// also an invalid chain (enough if one arbitrary block is invalid).
|
|
||||||
for i, valid := range []bool{true, false} {
|
|
||||||
var results <-chan error
|
|
||||||
if valid {
|
|
||||||
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFaker(), vm.Config{})
|
|
||||||
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
|
|
||||||
chain.Stop()
|
|
||||||
} else {
|
|
||||||
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeFailer(uint64(len(headers)-1)), vm.Config{})
|
|
||||||
_, results = chain.engine.VerifyHeaders(chain, headers, seals)
|
|
||||||
chain.Stop()
|
|
||||||
}
|
|
||||||
// Wait for all the verification results
|
|
||||||
checks := make(map[int]error)
|
|
||||||
for j := 0; j < len(blocks); j++ {
|
|
||||||
select {
|
|
||||||
case result := <-results:
|
|
||||||
checks[j] = result
|
|
||||||
|
|
||||||
case <-time.After(time.Second):
|
|
||||||
t.Fatalf("test %d.%d: verification timeout", i, j)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check nonce check validity
|
|
||||||
for j := 0; j < len(blocks); j++ {
|
|
||||||
want := valid || (j < len(blocks)-2) // We chose the last-but-one nonce in the chain to fail
|
|
||||||
if (checks[j] == nil) != want {
|
|
||||||
t.Errorf("test %d.%d: validity mismatch: have %v, want %v", i, j, checks[j], want)
|
|
||||||
}
|
|
||||||
if !want {
|
|
||||||
// A few blocks after the first error may pass verification due to concurrent
|
|
||||||
// workers. We don't care about those in this test, just that the correct block
|
|
||||||
// errors out.
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Make sure no more data is returned
|
|
||||||
select {
|
|
||||||
case result := <-results:
|
|
||||||
t.Fatalf("test %d: unexpected result returned: %v", i, result)
|
|
||||||
case <-time.After(25 * time.Millisecond):
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Tests that aborting a header validation indeed prevents further checks from being
|
|
||||||
// run, as well as checks that no left-over goroutines are leaked.
|
|
||||||
func TestHeaderConcurrentAbortion2(t *testing.T) { testHeaderConcurrentAbortion(t, 2) }
|
|
||||||
func TestHeaderConcurrentAbortion8(t *testing.T) { testHeaderConcurrentAbortion(t, 8) }
|
|
||||||
func TestHeaderConcurrentAbortion32(t *testing.T) { testHeaderConcurrentAbortion(t, 32) }
|
|
||||||
|
|
||||||
func testHeaderConcurrentAbortion(t *testing.T, threads int) {
|
|
||||||
// Create a simple chain to verify
|
|
||||||
var (
|
|
||||||
testdb = rawdb.NewMemoryDatabase()
|
|
||||||
gspec = &Genesis{Config: params.TestChainConfig}
|
|
||||||
genesis = gspec.MustCommit(testdb)
|
|
||||||
blocks, _ = GenerateChain(params.TestChainConfig, genesis, ethash.NewFaker(), testdb, 1024, nil)
|
|
||||||
)
|
|
||||||
headers := make([]*types.Header, len(blocks))
|
|
||||||
seals := make([]bool, len(blocks))
|
|
||||||
|
|
||||||
for i, block := range blocks {
|
|
||||||
headers[i] = block.Header()
|
|
||||||
seals[i] = true
|
|
||||||
}
|
|
||||||
// Set the number of threads to verify on
|
|
||||||
old := runtime.GOMAXPROCS(threads)
|
|
||||||
defer runtime.GOMAXPROCS(old)
|
|
||||||
|
|
||||||
// Start the verifications and immediately abort
|
|
||||||
chain, _ := NewBlockChain(testdb, nil, params.TestChainConfig, ethash.NewFakeDelayer(time.Millisecond), vm.Config{})
|
|
||||||
defer chain.Stop()
|
|
||||||
abort, results := chain.engine.VerifyHeaders(chain, headers, seals)
|
|
||||||
close(abort)
|
|
||||||
|
|
||||||
// Deplete the results channel
|
|
||||||
verified := 0
|
|
||||||
for depleted := false; !depleted; {
|
|
||||||
select {
|
|
||||||
case result := <-results:
|
|
||||||
if result != nil {
|
|
||||||
t.Errorf("header %d: validation failed: %v", verified, result)
|
|
||||||
}
|
|
||||||
verified++
|
|
||||||
case <-time.After(50 * time.Millisecond):
|
|
||||||
depleted = true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Check that abortion was honored by not processing too many POWs
|
|
||||||
if verified > 2*threads {
|
|
||||||
t.Errorf("verification count too large: have %d, want below %d", verified, 2*threads)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -1092,7 +1092,7 @@ func testQueueTimeLimiting(t *testing.T, nolocals bool) {
|
||||||
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
|
t.Fatalf("pending transactions mismatched: have %d, want %d", pending, 2)
|
||||||
}
|
}
|
||||||
if queued != 2 {
|
if queued != 2 {
|
||||||
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 3)
|
t.Fatalf("queued transactions mismatched: have %d, want %d", queued, 2)
|
||||||
}
|
}
|
||||||
if err := validatePoolInternals(pool); err != nil {
|
if err := validatePoolInternals(pool); err != nil {
|
||||||
t.Fatalf("pool internal state corrupted: %v", err)
|
t.Fatalf("pool internal state corrupted: %v", err)
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue