github.com/annchain/OG@v0.0.9/og/fetcher/fetcher.go (about)

     1  // Copyright 2015 The go-ethereum Authors
     2  // This file is part of the go-ethereum library.
     3  //
     4  // The go-ethereum library is free software: you can redistribute it and/or modify
     5  // it under the terms of the GNU Lesser General Public License as published by
     6  // the Free Software Foundation, either version 3 of the License, or
     7  // (at your option) any later version.
     8  //
     9  // The go-ethereum library is distributed in the hope that it will be useful,
    10  // but WITHOUT ANY WARRANTY; without even the implied warranty of
    11  // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    12  // GNU Lesser General Public License for more details.
    13  //
    14  // You should have received a copy of the GNU Lesser General Public License
    15  // along with the go-ethereum library. If not, see <http://www.gnu.org/licenses/>.
    16  
    17  // Package fetcher contains the sequencer announcement based synchronisation.
    18  package fetcher
    19  
    20  import (
    21  	"errors"
    22  	"github.com/annchain/OG/arefactor/common/goroutine"
    23  	types2 "github.com/annchain/OG/arefactor/og/types"
    24  	"github.com/annchain/OG/og/protocol/dagmessage"
    25  	"github.com/annchain/OG/og/types"
    26  	"github.com/annchain/OG/og/types/archive"
    27  
    28  	"math/rand"
    29  	"time"
    30  
    31  	"gopkg.in/karalabe/cookiejar.v2/collections/prque"
    32  )
    33  
    34  const (
    35  	arriveTimeout  = 500 * time.Millisecond // Time allowance before an announced sequencer is explicitly requested
    36  	gatherSlack    = 100 * time.Millisecond // Interval used to collate almost-expired announces with fetches
    37  	fetchTimeout   = 5 * time.Second        // Maximum allotted time to return an explicitly requested sequencer
    38  	maxUncleDist   = 7                      // Maximum allowed backward distance from the chain head
    39  	maxQueueDist   = 32                     // Maximum allowed distance from the chain head to queue
    40  	hashLimit      = 256                    // Maximum number of unique sequencers a peer may have announced
    41  	sequencerLimit = 64                     // Maximum number of unique sequencers a peer may have delivered
    42  )
    43  
    44  var (
    45  	errTerminated = errors.New("terminated")
    46  )
    47  
    48  // sequencerRetrievalFn is a callback type for retrieving a sequencer from the local chain.
    49  type sequencerRetrievalFn func(types2.Hash) *types.Sequencer
    50  
    51  // headerRequesterFn is a callback type for sending a header retrieval request.
    52  type headerRequesterFn func(peerId string, hash types2.Hash) error
    53  
    54  // bodyRequesterFn is a callback type for sending a body retrieval request.
    55  type bodyRequesterFn func(peerId string, hashs types2.Hashes) error
    56  
    57  // chainHeightFn is a callback type to retrieve the current chain height.
    58  type chainHeightFn func() uint64
    59  
    60  // chainInsertFn is a callback type to insert a batch of sequencers into the local chain.
    61  type chainInsertFn func(seq *types.Sequencer, txs types.Txis) error
    62  
    63  // peerDropFn is a callback type for dropping a peer detected as malicious.
    64  type peerDropFn func(id string)
    65  
    66  // announce is the hash notification of the availability of a new sequencer in the
    67  // network.
    68  type announce struct {
    69  	hash   types2.Hash                 // Hash of the sequencer being announced
    70  	number uint64                      // Number of the sequencer being announced (0 = unknown | old protocol)
    71  	header *dagmessage.SequencerHeader // Header of the sequencer partially reassembled (new protocol)
    72  	time   time.Time                   // Timestamp of the announcement
    73  
    74  	origin string // Identifier of the peer originating the notification
    75  
    76  	fetchHeader headerRequesterFn // Fetcher function to retrieve the header of an announced sequencer
    77  	fetchBodies bodyRequesterFn   // Fetcher function to retrieve the body of an announced sequencer
    78  }
    79  
    80  // headerFilterTask represents a batch of headers needing fetcher filtering.
    81  type headerFilterTask struct {
    82  	peer    string                        // The source peer of sequencer headers
    83  	headers []*dagmessage.SequencerHeader // Collection of headers to filter
    84  	time    time.Time                     // Arrival time of the headers
    85  }
    86  
    87  // bodyFilterTask represents a batch of sequencer bodies (transactions and uncles)
    88  // needing fetcher filtering.
    89  type bodyFilterTask struct {
    90  	peer         string       // The source peer of sequencer bodies
    91  	transactions []types.Txis // Collection of transactions per sequencer bodies
    92  	sequencers   []*types.Sequencer
    93  	time         time.Time // Arrival time of the sequencers' contents
    94  }
    95  
    96  // inject represents a schedules import operation.
    97  type inject struct {
    98  	origin    string
    99  	sequencer *types.Sequencer
   100  }
   101  
   102  // Fetcher is responsible for accumulating sequencer announcements from various peers
   103  // and scheduling them for retrieval.
   104  type Fetcher struct {
   105  	// Various event channels
   106  	notify chan *announce
   107  	inject chan *inject
   108  
   109  	sequencerFilter chan chan []*types.Sequencer
   110  	headerFilter    chan chan *headerFilterTask
   111  	bodyFilter      chan chan *bodyFilterTask
   112  
   113  	done chan types2.Hash
   114  	quit chan struct{}
   115  
   116  	// Announce states
   117  	announces  map[string]int              // Per peer announce counts to prevent memory exhaustion
   118  	announced  map[types2.Hash][]*announce // Announced sequencers, scheduled for fetching
   119  	fetching   map[types2.Hash]*announce   // Announced sequencers, currently fetching
   120  	fetched    map[types2.Hash][]*announce // sequencers with headers fetched, scheduled for body retrieval
   121  	completing map[types2.Hash]*announce   // sequencers with headers, currently body-completing
   122  
   123  	// sequencer cache
   124  	queue  *prque.Prque            // Queue containing the import operations (sequencer number sorted)
   125  	queues map[string]int          // Per peer sequencer counts to prevent memory exhaustion
   126  	queued map[types2.Hash]*inject // Set of already queued sequencers (to dedupe imports)
   127  
   128  	getsequencer sequencerRetrievalFn
   129  
   130  	chainHeight chainHeightFn // Retrieves the current chain's height
   131  	insertChain chainInsertFn // Injects a batch of sequencers into the chain
   132  	dropPeer    peerDropFn    // Drops a peer for misbehaving
   133  
   134  	// Testing hooks
   135  	announceChangeHook func(types2.Hash, bool)          // Method to call upon adding or deleting a hash from the announce list
   136  	queueChangeHook    func(types2.Hash, bool)          // Method to call upon adding or deleting a sequencer from the import queue
   137  	fetchingHook       func(types2.Hashes)              // Method to call upon starting a sequencer (eth/61) or header (eth/62) fetch
   138  	completingHook     func(types2.Hashes)              // Method to call upon starting a sequencer body fetch (eth/62)
   139  	importedHook       func(sequencer *types.Sequencer) // Method to call upon successful sequencer import (both eth/61 and eth/62)
   140  }
   141  
   142  // New creates a sequencer fetcher to retrieve sequencers based on hash announcements.
   143  func New(getsequencer sequencerRetrievalFn, chainHeight chainHeightFn, insertChain chainInsertFn, dropPeer peerDropFn) *Fetcher {
   144  	return &Fetcher{
   145  		notify:          make(chan *announce),
   146  		inject:          make(chan *inject),
   147  		sequencerFilter: make(chan chan []*types.Sequencer),
   148  		headerFilter:    make(chan chan *headerFilterTask),
   149  		bodyFilter:      make(chan chan *bodyFilterTask),
   150  		done:            make(chan types2.Hash),
   151  		quit:            make(chan struct{}),
   152  		announces:       make(map[string]int),
   153  		announced:       make(map[types2.Hash][]*announce),
   154  		fetching:        make(map[types2.Hash]*announce),
   155  		fetched:         make(map[types2.Hash][]*announce),
   156  		completing:      make(map[types2.Hash]*announce),
   157  		queue:           prque.New(),
   158  		queues:          make(map[string]int),
   159  		queued:          make(map[types2.Hash]*inject),
   160  		getsequencer:    getsequencer,
   161  		chainHeight:     chainHeight,
   162  		insertChain:     insertChain,
   163  		dropPeer:        dropPeer,
   164  	}
   165  }
   166  
   167  // Start boots up the announcement based synchroniser, accepting and processing
   168  // hash notifications and sequencer fetches until termination requested.
   169  func (f *Fetcher) Start() {
   170  	goroutine.New(f.loop)
   171  }
   172  
   173  // Stop terminates the announcement based synchroniser, canceling all pending
   174  // operations.
   175  func (f *Fetcher) Stop() {
   176  	close(f.quit)
   177  }
   178  
   179  // Notify announces the fetcher of the potential availability of a new sequencer in
   180  // the network.
   181  func (f *Fetcher) Notify(peer string, hash types2.Hash, number uint64, time time.Time,
   182  	headerFetcher headerRequesterFn, bodyFetcher bodyRequesterFn) error {
   183  	sequencer := &announce{
   184  		hash:        hash,
   185  		number:      number,
   186  		time:        time,
   187  		origin:      peer,
   188  		fetchHeader: headerFetcher,
   189  		fetchBodies: bodyFetcher,
   190  	}
   191  	select {
   192  	case f.notify <- sequencer:
   193  		return nil
   194  	case <-f.quit:
   195  		return errTerminated
   196  	}
   197  }
   198  
   199  // Enqueue tries to fill gaps the the fetcher's future import queue.
   200  func (f *Fetcher) Enqueue(peer string, sequencer *types.Sequencer) error {
   201  	op := &inject{
   202  		origin:    peer,
   203  		sequencer: sequencer,
   204  	}
   205  	select {
   206  	case f.inject <- op:
   207  		return nil
   208  	case <-f.quit:
   209  		return errTerminated
   210  	}
   211  }
   212  
   213  // FilterHeaders extracts all the headers that were explicitly requested by the fetcher,
   214  // returning those that should be handled differently.
   215  func (f *Fetcher) FilterHeaders(peer string, headers dagmessage.SequencerHeaders, time time.Time) []*dagmessage.SequencerHeader {
   216  	log.WithField("peer", peer).WithField("headers", headers).Trace(
   217  		"Filtering headers")
   218  
   219  	// Send the filter channel to the fetcher
   220  	filter := make(chan *headerFilterTask)
   221  
   222  	select {
   223  	case f.headerFilter <- filter:
   224  	case <-f.quit:
   225  		return nil
   226  	}
   227  	// Request the filtering of the header list
   228  	select {
   229  	case filter <- &headerFilterTask{peer: peer, headers: headers, time: time}:
   230  	case <-f.quit:
   231  		return nil
   232  	}
   233  	// Retrieve the headers remaining after filtering
   234  	select {
   235  	case task := <-filter:
   236  		return task.headers
   237  	case <-f.quit:
   238  		return nil
   239  	}
   240  }
   241  
   242  // FilterBodies extracts all the sequencer bodies that were explicitly requested by
   243  // the fetcher, returning those that should be handled differently.
   244  func (f *Fetcher) FilterBodies(peer string, transactions []types.Txis, sequencers archive.Sequencers, time time.Time) []types.Txis {
   245  	log.WithField("txs", len(transactions)).WithField("sequencers ", sequencers).WithField(
   246  		"peer", peer).Trace("Filtering bodies")
   247  
   248  	// Send the filter channel to the fetcher
   249  	filter := make(chan *bodyFilterTask)
   250  
   251  	select {
   252  	case f.bodyFilter <- filter:
   253  	case <-f.quit:
   254  		return nil
   255  	}
   256  	// Request the filtering of the body list
   257  	select {
   258  	case filter <- &bodyFilterTask{peer: peer, transactions: transactions, sequencers: sequencers, time: time}:
   259  	case <-f.quit:
   260  		return nil
   261  	}
   262  	// Retrieve the bodies remaining after filtering
   263  	select {
   264  	case task := <-filter:
   265  		return task.transactions
   266  	case <-f.quit:
   267  		return nil
   268  	}
   269  }
   270  
   271  // Loop is the main fetcher loop, checking and processing various notification
   272  // events.
   273  func (f *Fetcher) loop() {
   274  	// Iterate the sequencer fetching until a quit is requested
   275  	fetchTimer := time.NewTimer(0)
   276  	completeTimer := time.NewTimer(0)
   277  
   278  	for {
   279  		// Clean up any expired sequencer fetches
   280  		for hash, announce := range f.fetching {
   281  			if time.Since(announce.time) > fetchTimeout {
   282  				f.forgetHash(hash)
   283  			}
   284  		}
   285  		// Import any queued sequencers that could potentially fit
   286  		height := f.chainHeight()
   287  		for !f.queue.Empty() {
   288  			op := f.queue.PopItem().(*inject)
   289  			hash := op.sequencer.GetHash()
   290  			if f.queueChangeHook != nil {
   291  				f.queueChangeHook(hash, false)
   292  			}
   293  			// If too high up the chain or phase, continue later
   294  			number := op.sequencer.Number()
   295  			if number > height+1 {
   296  				f.queue.Push(op, -float32(number))
   297  				if f.queueChangeHook != nil {
   298  					f.queueChangeHook(hash, true)
   299  				}
   300  				break
   301  			}
   302  			// Otherwise if fresh and still unknown, try and import
   303  			if number+maxUncleDist < height || f.getsequencer(hash) != nil {
   304  				f.forgetsequencer(hash)
   305  				continue
   306  			}
   307  			//todo
   308  			f.insert(op.origin, op.sequencer, nil)
   309  		}
   310  		// Wait for an outside event to occur
   311  		select {
   312  		case <-f.quit:
   313  			// Fetcher terminating, abort all operations
   314  			return
   315  
   316  		case notification := <-f.notify:
   317  			// A sequencer was announced, make sure the peer isn't DOSing us
   318  			propAnnounceInMeter.Mark(1)
   319  
   320  			count := f.announces[notification.origin] + 1
   321  			if count > hashLimit {
   322  				log.WithField("peer", notification.origin).WithField(
   323  					"limit", hashLimit).Debug("Sender exceeded outstanding announces")
   324  				propAnnounceDOSMeter.Mark(1)
   325  				break
   326  			}
   327  			// If we have a valid sequencer number, check that it's potentially useful
   328  			if notification.number > 0 {
   329  				if dist := int64(notification.number) - int64(f.chainHeight()); dist < -maxUncleDist || dist > maxQueueDist {
   330  					log.WithField("peer", notification.origin).WithField("number", notification.number).WithField(
   331  						"hash", notification.hash).WithField("distance", dist).Debug("Sender discarded announcement")
   332  					propAnnounceDropMeter.Mark(1)
   333  					break
   334  				}
   335  			}
   336  			// All is well, schedule the announce if sequencer's not yet downloading
   337  			if _, ok := f.fetching[notification.hash]; ok {
   338  				break
   339  			}
   340  			if _, ok := f.completing[notification.hash]; ok {
   341  				break
   342  			}
   343  			f.announces[notification.origin] = count
   344  			f.announced[notification.hash] = append(f.announced[notification.hash], notification)
   345  			if f.announceChangeHook != nil && len(f.announced[notification.hash]) == 1 {
   346  				f.announceChangeHook(notification.hash, true)
   347  			}
   348  			if len(f.announced) == 1 {
   349  				f.rescheduleFetch(fetchTimer)
   350  			}
   351  
   352  		case op := <-f.inject:
   353  			// A direct sequencer insertion was requested, try and fill any pending gaps
   354  			propBroadcastInMeter.Mark(1)
   355  			f.enqueue(op.origin, op.sequencer)
   356  
   357  		case hash := <-f.done:
   358  			// A pending import finished, remove all traces of the notification
   359  			f.forgetHash(hash)
   360  			f.forgetsequencer(hash)
   361  
   362  		case <-fetchTimer.C:
   363  			// At least one sequencer's timer ran out, check for needing retrieval
   364  			request := make(map[string]types2.Hashes)
   365  
   366  			for hash, announces := range f.announced {
   367  				if time.Since(announces[0].time) > arriveTimeout-gatherSlack {
   368  					// Pick a random peer to retrieve from, reset all others
   369  					announce := announces[rand.Intn(len(announces))]
   370  					f.forgetHash(hash)
   371  
   372  					// If the sequencer still didn't arrive, queue for fetching
   373  					if f.getsequencer(hash) == nil {
   374  						request[announce.origin] = append(request[announce.origin], hash)
   375  						f.fetching[hash] = announce
   376  					}
   377  				}
   378  			}
   379  			// Send out all sequencer header requests
   380  			for peer, hashes := range request {
   381  				log.WithField("peer", peer).WithField("list", hashes).Trace(
   382  					"Fetching scheduled headers")
   383  
   384  				// Create a closure of the fetch and schedule in on a new thread
   385  				fetchHeader, hashes := f.fetching[hashes[0]].fetchHeader, hashes
   386  				function := func() {
   387  					defer goroutine.DumpStack(true)
   388  					if f.fetchingHook != nil {
   389  						f.fetchingHook(hashes)
   390  					}
   391  					for _, hash := range hashes {
   392  						headerFetchMeter.Mark(1)
   393  						fetchHeader(peer, hash) // Suboptimal, but protocol doesn't allow batch header retrievals
   394  					}
   395  				}
   396  				goroutine.New(function)
   397  			}
   398  			// Schedule the next fetch if sequencers are still pending
   399  			f.rescheduleFetch(fetchTimer)
   400  
   401  		case <-completeTimer.C:
   402  			// At least one header's timer ran out, retrieve everything
   403  			request := make(map[string]types2.Hashes)
   404  
   405  			for hash, announces := range f.fetched {
   406  				// Pick a random peer to retrieve from, reset all others
   407  				announce := announces[rand.Intn(len(announces))]
   408  				f.forgetHash(hash)
   409  
   410  				// If the sequencer still didn't arrive, queue for completion
   411  				if f.getsequencer(hash) == nil {
   412  					request[announce.origin] = append(request[announce.origin], hash)
   413  					f.completing[hash] = announce
   414  				}
   415  			}
   416  			// Send out all sequencer body requests
   417  			for peer, hashes := range request {
   418  				log.WithField("peer", peer).WithField("list", hashes).Trace(
   419  					"Fetching scheduled bodies")
   420  
   421  				// Create a closure of the fetch and schedule in on a new thread
   422  				if f.completingHook != nil {
   423  					f.completingHook(hashes)
   424  				}
   425  				bodyFetchMeter.Mark(int64(len(hashes)))
   426  				function := func() { f.completing[hashes[0]].fetchBodies(peer, hashes) }
   427  				goroutine.New(function)
   428  			}
   429  			// Schedule the next fetch if sequencers are still pending
   430  			f.rescheduleComplete(completeTimer)
   431  
   432  		case filter := <-f.headerFilter:
   433  			// Headers arrived from a remote peer. Extract those that were explicitly
   434  			// requested by the fetcher, and return everything else so it's delivered
   435  			// to other parts of the system.
   436  			var task *headerFilterTask
   437  			select {
   438  			case task = <-filter:
   439  			case <-f.quit:
   440  				return
   441  			}
   442  			headerFilterInMeter.Mark(int64(len(task.headers)))
   443  
   444  			// Split the batch of headers into unknown ones (to return to the caller),
   445  			// known incomplete ones (requiring body retrievals) and completed sequencers.
   446  			unknown, incomplete, complete := []*dagmessage.SequencerHeader{}, []*announce{}, []*types.Sequencer{}
   447  			for _, header := range task.headers {
   448  				hash := header.GetHash()
   449  
   450  				// Filter fetcher-requested headers from other synchronisation algorithms
   451  				if announce := f.fetching[hash]; announce != nil && announce.origin == task.peer && f.fetched[hash] == nil && f.completing[hash] == nil && f.queued[hash] == nil {
   452  					// If the delivered header does not match the promised number, drop the announcer
   453  					if header.SequencerId() != announce.number {
   454  						log.WithField("peer", announce.origin).WithField("hash", header.GetHash()).WithField("announced", announce.number).WithField(
   455  							"provided", header.SequencerId()).Debug("Invalid sequencer number fetched")
   456  						f.dropPeer(announce.origin)
   457  						f.forgetHash(hash)
   458  						continue
   459  					}
   460  					// Only keep if not imported by other means
   461  					if f.getsequencer(hash) == nil {
   462  						announce.header = header
   463  						announce.time = task.time
   464  
   465  						// Otherwise add to the list of sequencers needing completion
   466  						incomplete = append(incomplete, announce)
   467  					} else {
   468  						log.WithField("peer", announce.origin).WithField("hash", header.GetHash()).WithField(
   469  							"number", header.SequencerId()).Debug("quencer already imported, discarding header")
   470  
   471  						f.forgetHash(hash)
   472  					}
   473  				} else {
   474  					// Fetcher doesn't know about it, add to the return list
   475  					unknown = append(unknown, header)
   476  				}
   477  			}
   478  			headerFilterOutMeter.Mark(int64(len(unknown)))
   479  			select {
   480  			case filter <- &headerFilterTask{headers: unknown, time: task.time}:
   481  			case <-f.quit:
   482  				return
   483  			}
   484  			// Schedule the retrieved headers for body completion
   485  			for _, announce := range incomplete {
   486  				hash := announce.header.GetHash()
   487  				if _, ok := f.completing[hash]; ok {
   488  					continue
   489  				}
   490  				f.fetched[hash] = append(f.fetched[hash], announce)
   491  				if len(f.fetched) == 1 {
   492  					f.rescheduleComplete(completeTimer)
   493  				}
   494  			}
   495  			// Schedule the header-only sequencers for import
   496  			for _, sequencer := range complete {
   497  				if announce := f.completing[sequencer.GetHash()]; announce != nil {
   498  					f.enqueue(announce.origin, sequencer)
   499  				}
   500  			}
   501  
   502  		case filter := <-f.bodyFilter:
   503  			// sequencer bodies arrived, extract any explicitly requested sequencers, return the rest
   504  			var task *bodyFilterTask
   505  			select {
   506  			case task = <-filter:
   507  			case <-f.quit:
   508  				return
   509  			}
   510  			bodyFilterInMeter.Mark(int64(len(task.transactions)))
   511  			sequencers := []*types.Sequencer{}
   512  			bodyFilterOutMeter.Mark(int64(len(task.transactions)))
   513  			select {
   514  			case filter <- task:
   515  			case <-f.quit:
   516  				return
   517  			}
   518  			// Schedule the retrieved sequencers for ordered import
   519  			for _, sequencer := range sequencers {
   520  				if announce := f.completing[sequencer.GetHash()]; announce != nil {
   521  					f.enqueue(announce.origin, sequencer)
   522  				}
   523  			}
   524  		}
   525  	}
   526  }
   527  
   528  // rescheduleFetch resets the specified fetch timer to the next announce timeout.
   529  func (f *Fetcher) rescheduleFetch(fetch *time.Timer) {
   530  	// Short circuit if no sequencers are announced
   531  	if len(f.announced) == 0 {
   532  		return
   533  	}
   534  	// Otherwise find the earliest expiring announcement
   535  	earliest := time.Now()
   536  	for _, announces := range f.announced {
   537  		if earliest.After(announces[0].time) {
   538  			earliest = announces[0].time
   539  		}
   540  	}
   541  	fetch.Reset(arriveTimeout - time.Since(earliest))
   542  }
   543  
   544  // rescheduleComplete resets the specified completion timer to the next fetch timeout.
   545  func (f *Fetcher) rescheduleComplete(complete *time.Timer) {
   546  	// Short circuit if no headers are fetched
   547  	if len(f.fetched) == 0 {
   548  		return
   549  	}
   550  	// Otherwise find the earliest expiring announcement
   551  	earliest := time.Now()
   552  	for _, announces := range f.fetched {
   553  		if earliest.After(announces[0].time) {
   554  			earliest = announces[0].time
   555  		}
   556  	}
   557  	complete.Reset(gatherSlack - time.Since(earliest))
   558  }
   559  
   560  // enqueue schedules a new future import operation, if the sequencer to be imported
   561  // has not yet been seen.
   562  func (f *Fetcher) enqueue(peer string, sequencer *types.Sequencer) {
   563  	hash := sequencer.GetHash()
   564  
   565  	// Ensure the peer isn't DOSing us
   566  	count := f.queues[peer] + 1
   567  	if count > sequencerLimit {
   568  		log.WithField("peer", peer).WithField("number", sequencer.Number()).WithField("hash", hash).WithField(
   569  			"limit", sequencerLimit).Debug("Discarded propagated sequencer, exceeded allowance")
   570  		propBroadcastDOSMeter.Mark(1)
   571  		f.forgetHash(hash)
   572  		return
   573  	}
   574  	// Discard any past or too distant sequencers
   575  	if dist := int64(sequencer.Number()) - int64(f.chainHeight()); dist < -maxUncleDist || dist > maxQueueDist {
   576  		log.WithField("peer", peer).WithField("number", sequencer.Number()).WithField("hash", hash).WithField("distance", dist)
   577  		propBroadcastDropMeter.Mark(1)
   578  		f.forgetHash(hash)
   579  		return
   580  	}
   581  	// Schedule the sequencer for future importing
   582  	if _, ok := f.queued[hash]; !ok {
   583  		op := &inject{
   584  			origin:    peer,
   585  			sequencer: sequencer,
   586  		}
   587  		f.queues[peer] = count
   588  		f.queued[hash] = op
   589  		f.queue.Push(op, -float32(sequencer.Number()))
   590  		if f.queueChangeHook != nil {
   591  			f.queueChangeHook(op.sequencer.GetHash(), true)
   592  		}
   593  		log.WithField("peer", peer).WithField("Number", sequencer.Number()).WithField("hash", hash).WithField(
   594  			"queued", f.queue.Size()).Debug("Queued propagated sequencer")
   595  	}
   596  }
   597  
   598  // insert spawns a new goroutine to run a sequencer insertion into the chain. If the
   599  // sequencer's number is at the same height as the current import phase, it updates
   600  // the phase states accordingly.
   601  func (f *Fetcher) insert(peer string, sequencer *types.Sequencer, txs types.Txis) {
   602  	hash := sequencer.GetHash()
   603  
   604  	// Run the import on a new thread
   605  	log.WithField("peer", peer).WithField("number", sequencer.Number()).WithField(
   606  		"hash", hash).Debug("Importing propagated sequencer")
   607  	function := func() {
   608  		defer func() { f.done <- hash }()
   609  
   610  		// Run the actual import and log any issues
   611  		if err := f.insertChain(sequencer, txs); err != nil {
   612  			log.WithField("peer", peer).WithField("number", sequencer.Number()).WithField(
   613  				"hash", hash).WithError(err).Debug("Propagated sequencer import failed")
   614  			return
   615  		}
   616  
   617  		// Invoke the testing hook if needed
   618  		if f.importedHook != nil {
   619  			f.importedHook(sequencer)
   620  		}
   621  	}
   622  	goroutine.New(function)
   623  }
   624  
   625  // forgetHash removes all traces of a sequencer announcement from the fetcher's
   626  // internal state.
   627  func (f *Fetcher) forgetHash(hash types2.Hash) {
   628  	// Remove all pending announces and decrement DOS counters
   629  	for _, announce := range f.announced[hash] {
   630  		f.announces[announce.origin]--
   631  		if f.announces[announce.origin] == 0 {
   632  			delete(f.announces, announce.origin)
   633  		}
   634  	}
   635  	delete(f.announced, hash)
   636  	if f.announceChangeHook != nil {
   637  		f.announceChangeHook(hash, false)
   638  	}
   639  	// Remove any pending fetches and decrement the DOS counters
   640  	if announce := f.fetching[hash]; announce != nil {
   641  		f.announces[announce.origin]--
   642  		if f.announces[announce.origin] == 0 {
   643  			delete(f.announces, announce.origin)
   644  		}
   645  		delete(f.fetching, hash)
   646  	}
   647  
   648  	// Remove any pending completion requests and decrement the DOS counters
   649  	for _, announce := range f.fetched[hash] {
   650  		f.announces[announce.origin]--
   651  		if f.announces[announce.origin] == 0 {
   652  			delete(f.announces, announce.origin)
   653  		}
   654  	}
   655  	delete(f.fetched, hash)
   656  
   657  	// Remove any pending completions and decrement the DOS counters
   658  	if announce := f.completing[hash]; announce != nil {
   659  		f.announces[announce.origin]--
   660  		if f.announces[announce.origin] == 0 {
   661  			delete(f.announces, announce.origin)
   662  		}
   663  		delete(f.completing, hash)
   664  	}
   665  }
   666  
   667  // forgetsequencer removes all traces of a queued sequencer from the fetcher's internal
   668  // state.
   669  func (f *Fetcher) forgetsequencer(hash types2.Hash) {
   670  	if insert := f.queued[hash]; insert != nil {
   671  		f.queues[insert.origin]--
   672  		if f.queues[insert.origin] == 0 {
   673  			delete(f.queues, insert.origin)
   674  		}
   675  		delete(f.queued, hash)
   676  	}
   677  }