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