@@ -18,6 +18,7 @@ package catchup
1818
1919import (
2020 "context"
21+ "errors"
2122 "fmt"
2223 "sync"
2324 "sync/atomic"
@@ -155,8 +156,19 @@ func (s *Service) SynchronizingTime() time.Duration {
155156 return time .Duration (timeInNS - startNS )
156157}
157158
159+ // errLedgerAlreadyHasBlock is returned by innerFetch in case the local ledger already has the requested block.
160+ var errLedgerAlreadyHasBlock = errors .New ("ledger already has block" )
161+
158162// function scope to make a bunch of defer statements better
159163func (s * Service ) innerFetch (r basics.Round , peer network.Peer ) (blk * bookkeeping.Block , cert * agreement.Certificate , ddur time.Duration , err error ) {
164+ ledgerWaitCh := s .ledger .Wait (r )
165+ select {
166+ case <- ledgerWaitCh :
167+ // if our ledger already have this block, no need to attempt to fetch it.
168+ return nil , nil , time .Duration (0 ), errLedgerAlreadyHasBlock
169+ default :
170+ }
171+
160172 ctx , cf := context .WithCancel (s .ctx )
161173 fetcher := makeUniversalBlockFetcher (s .log , s .net , s .cfg )
162174 defer cf ()
@@ -165,7 +177,7 @@ func (s *Service) innerFetch(r basics.Round, peer network.Peer) (blk *bookkeepin
165177 go func () {
166178 select {
167179 case <- stopWaitingForLedgerRound :
168- case <- s . ledger . Wait ( r ) :
180+ case <- ledgerWaitCh :
169181 cf ()
170182 }
171183 }()
@@ -218,6 +230,10 @@ func (s *Service) fetchAndWrite(r basics.Round, prevFetchCompleteChan chan bool,
218230 block , cert , blockDownloadDuration , err := s .innerFetch (r , peer )
219231
220232 if err != nil {
233+ if err == errLedgerAlreadyHasBlock {
234+ // ledger already has the block, no need to request this block from anyone.
235+ return true
236+ }
221237 s .log .Debugf ("fetchAndWrite(%v): Could not fetch: %v (attempt %d)" , r , err , i )
222238 peerSelector .rankPeer (psp , peerRankDownloadFailed )
223239 // we've just failed to retrieve a block; wait until the previous block is fetched before trying again
0 commit comments