17
17
package eth
18
18
19
19
import (
20
+ "bytes"
20
21
"encoding/json"
21
22
"errors"
22
23
"fmt"
@@ -88,6 +89,8 @@ type ProtocolManager struct {
88
89
txsSub event.Subscription
89
90
minedBlockSub * event.TypeMuxSubscription
90
91
92
+ whitelist map [uint64 ]common.Hash
93
+
91
94
// channels for fetcher, syncer, txsyncLoop
92
95
newPeerCh chan * peer
93
96
txsyncCh chan * txsync
@@ -101,7 +104,7 @@ type ProtocolManager struct {
101
104
102
105
// NewProtocolManager returns a new Ethereum sub protocol manager. The Ethereum sub protocol manages peers capable
103
106
// with the Ethereum network.
104
- func NewProtocolManager (config * params.ChainConfig , mode downloader.SyncMode , networkID uint64 , mux * event.TypeMux , txpool txPool , engine consensus.Engine , blockchain * core.BlockChain , chaindb ethdb.Database ) (* ProtocolManager , error ) {
107
+ func NewProtocolManager (config * params.ChainConfig , mode downloader.SyncMode , networkID uint64 , mux * event.TypeMux , txpool txPool , engine consensus.Engine , blockchain * core.BlockChain , chaindb ethdb.Database , whitelist map [ uint64 ]common. Hash ) (* ProtocolManager , error ) {
105
108
// Create the protocol manager with the base fields
106
109
manager := & ProtocolManager {
107
110
networkID : networkID ,
@@ -110,6 +113,7 @@ func NewProtocolManager(config *params.ChainConfig, mode downloader.SyncMode, ne
110
113
blockchain : blockchain ,
111
114
chainconfig : config ,
112
115
peers : newPeerSet (),
116
+ whitelist : whitelist ,
113
117
newPeerCh : make (chan * peer ),
114
118
noMorePeers : make (chan struct {}),
115
119
txsyncCh : make (chan * txsync ),
@@ -307,6 +311,16 @@ func (pm *ProtocolManager) handle(p *peer) error {
307
311
}
308
312
}()
309
313
}
314
+
315
+ // If we have any explicit whitelist block hashes, request them
316
+ for bn := range pm .whitelist {
317
+ p .Log ().Debug ("Requesting whitelist block" , "number" , bn )
318
+ if err := p .RequestHeadersByNumber (bn , 1 , 0 , false ); err != nil {
319
+ p .Log ().Error ("whitelist request failed" , "err" , err , "number" , bn , "peer" , p .id )
320
+ return err
321
+ }
322
+ }
323
+
310
324
// main loop. handle incoming messages.
311
325
for {
312
326
if err := pm .handleMsg (p ); err != nil {
@@ -452,6 +466,16 @@ func (pm *ProtocolManager) handleMsg(p *peer) error {
452
466
// Filter out any explicitly requested headers, deliver the rest to the downloader
453
467
filter := len (headers ) == 1
454
468
if filter {
469
+ // Check for any responses not matching our whitelist
470
+ if expected , ok := pm .whitelist [headers [0 ].Number .Uint64 ()]; ok {
471
+ actual := headers [0 ].Hash ()
472
+ if ! bytes .Equal (expected .Bytes (), actual .Bytes ()) {
473
+ p .Log ().Info ("Dropping peer with non-matching whitelist block" , "number" , headers [0 ].Number .Uint64 (), "hash" , actual , "expected" , expected )
474
+ return errors .New ("whitelist block mismatch" )
475
+ }
476
+ p .Log ().Debug ("Whitelist block verified" , "number" , headers [0 ].Number .Uint64 (), "hash" , expected )
477
+ }
478
+
455
479
// If it's a potential DAO fork check, validate against the rules
456
480
if p .forkDrop != nil && pm .chainconfig .DAOForkBlock .Cmp (headers [0 ].Number ) == 0 {
457
481
// Disable the fork drop timer
0 commit comments