|
|
|
@ -634,3 +634,65 @@ outer: |
|
|
|
|
t.Errorf("block broadcast to %d peers, expected %d", receivedCount, broadcastExpected) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Tests that a propagated malformed block (uncles or transactions don't match
|
|
|
|
|
// with the hashes in the header) gets discarded and not broadcast forward.
|
|
|
|
|
func TestBroadcastMalformedBlock(t *testing.T) { |
|
|
|
|
// Create a live node to test propagation with
|
|
|
|
|
var ( |
|
|
|
|
engine = ethash.NewFaker() |
|
|
|
|
db = rawdb.NewMemoryDatabase() |
|
|
|
|
config = ¶ms.ChainConfig{} |
|
|
|
|
gspec = &core.Genesis{Config: config} |
|
|
|
|
genesis = gspec.MustCommit(db) |
|
|
|
|
) |
|
|
|
|
blockchain, err := core.NewBlockChain(db, nil, config, engine, vm.Config{}, nil) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to create new blockchain: %v", err) |
|
|
|
|
} |
|
|
|
|
pm, err := NewProtocolManager(config, nil, downloader.FullSync, DefaultConfig.NetworkId, new(event.TypeMux), new(testTxPool), engine, blockchain, db, 1, nil) |
|
|
|
|
if err != nil { |
|
|
|
|
t.Fatalf("failed to start test protocol manager: %v", err) |
|
|
|
|
} |
|
|
|
|
pm.Start(2) |
|
|
|
|
defer pm.Stop() |
|
|
|
|
|
|
|
|
|
// Create two peers, one to send the malformed block with and one to check
|
|
|
|
|
// propagation
|
|
|
|
|
source, _ := newTestPeer("source", eth63, pm, true) |
|
|
|
|
defer source.close() |
|
|
|
|
|
|
|
|
|
sink, _ := newTestPeer("sink", eth63, pm, true) |
|
|
|
|
defer sink.close() |
|
|
|
|
|
|
|
|
|
// Create various combinations of malformed blocks
|
|
|
|
|
chain, _ := core.GenerateChain(gspec.Config, genesis, ethash.NewFaker(), db, 1, func(i int, gen *core.BlockGen) {}) |
|
|
|
|
|
|
|
|
|
malformedUncles := chain[0].Header() |
|
|
|
|
malformedUncles.UncleHash[0]++ |
|
|
|
|
malformedTransactions := chain[0].Header() |
|
|
|
|
malformedTransactions.TxHash[0]++ |
|
|
|
|
malformedEverything := chain[0].Header() |
|
|
|
|
malformedEverything.UncleHash[0]++ |
|
|
|
|
malformedEverything.TxHash[0]++ |
|
|
|
|
|
|
|
|
|
// Keep listening to broadcasts and notify if any arrives
|
|
|
|
|
notify := make(chan struct{}) |
|
|
|
|
go func() { |
|
|
|
|
if _, err := sink.app.ReadMsg(); err == nil { |
|
|
|
|
notify <- struct{}{} |
|
|
|
|
} |
|
|
|
|
}() |
|
|
|
|
// Try to broadcast all malformations and ensure they all get discarded
|
|
|
|
|
for _, header := range []*types.Header{malformedUncles, malformedTransactions, malformedEverything} { |
|
|
|
|
block := types.NewBlockWithHeader(header).WithBody(chain[0].Transactions(), chain[0].Uncles()) |
|
|
|
|
if err := p2p.Send(source.app, NewBlockMsg, []interface{}{block, big.NewInt(131136)}); err != nil { |
|
|
|
|
t.Fatalf("failed to broadcast block: %v", err) |
|
|
|
|
} |
|
|
|
|
select { |
|
|
|
|
case <-notify: |
|
|
|
|
t.Fatalf("malformed block forwarded") |
|
|
|
|
case <-time.After(100 * time.Millisecond): |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|