@@ -291,86 +291,90 @@ func (hs *HeaderService) GetMerkleRootsConfirmations(
291291 return hs .repo .Headers .GetMerkleRootsConfirmations (request , hs .merkleCfg .MaxBlockHeightExcess )
292292}
293293
294- // LocateHeaders fetches headers for a number of blocks after the most recent known block
295- // in the best chain, based on the provided block locator and stop hash, and defaults to the
296- // genesis block if the locator is unknown.
297- func (hs * HeaderService ) LocateHeaders (locator domains.BlockLocator , hashStop * chainhash.Hash ) []wire.BlockHeader {
298- headers := hs .locateHeaders (locator , hashStop , wire .MaxBlockHeadersPerMsg )
299- return headers
294+ // LocateHeadersGetHeaders returns headers with given hashes.
295+ func (hs * HeaderService ) LocateHeadersGetHeaders (locators []* chainhash.Hash , hashstop * chainhash.Hash ) ([]* wire.BlockHeader , error ) {
296+ headers , err := hs .locateHeadersGetHeaders (locators , hashstop )
297+ if err != nil {
298+ return nil , err
299+ }
300+ return headers , nil
300301}
301302
302- func (hs * HeaderService ) locateHeaders (locator domains.BlockLocator , hashStop * chainhash.Hash , maxHeaders uint32 ) []wire.BlockHeader {
303- // Find the node after the first known block in the locator and the
304- // total number of nodes after it needed while respecting the stop hash
305- // and max entries.
306- node , total := hs .locateInventory (locator , hashStop , maxHeaders )
307- if total == 0 {
308- return nil
303+ func (hs * HeaderService ) locateHeadersGetHeaders (locators []* chainhash.Hash , hashstop * chainhash.Hash ) ([]* wire.BlockHeader , error ) {
304+
305+ if len (locators ) == 0 {
306+ return nil , errors .New ("no locators provided" )
309307 }
310308
311- // Populate and return the found headers.
312- headers := make ([]wire.BlockHeader , 0 , total )
313- for i := uint32 (0 ); i < total ; i ++ {
314- header := wire.BlockHeader {
315- Version : node .Version ,
316- PrevBlock : node .PreviousBlock ,
317- MerkleRoot : node .MerkleRoot ,
318- Timestamp : node .Timestamp ,
319- Bits : node .Bits ,
320- Nonce : node .Nonce ,
321- }
322- headers = append (headers , header )
323- node = hs .nodeByHeight (node .Height + 1 )
309+ hashes := make ([]string , len (locators ))
310+ for i , v := range locators {
311+ hashes [i ] = v .String ()
324312 }
325- return headers
326- }
327313
328- func (hs * HeaderService ) locateInventory (locator domains.BlockLocator , hashStop * chainhash.Hash , maxEntries uint32 ) (* domains.BlockHeader , uint32 ) {
329- // There are no block locators so a specific block is being requested
330- // as identified by the stop hash.
331- stopNode , _ := hs .GetHeaderByHash (hashStop .String ())
332- if len (locator ) == 0 {
333- if stopNode == nil {
334- // No blocks with the stop hash were found so there is
335- // nothing to do.
336- return nil , 0
314+ startHeight , err := hs .repo .Headers .GetHeadersStartHeight (hashes )
315+ if err != nil {
316+ return nil , fmt .Errorf ("error getting headers of locators: %v" , err )
317+ }
318+ var stopHeight int
319+ if hashstop .IsEqual (& chainhash.Hash {}) {
320+ stopHeight = startHeight + wire .MaxCFHeadersPerMsg
321+ } else {
322+ stopHeight , err = hs .repo .Headers .GetHeadersStopHeight (hashstop .String ())
323+ if err != nil {
324+ return nil , fmt .Errorf ("error getting hashstop height: %v" , err )
337325 }
338- return stopNode , 1
339326 }
340327
341- // Find the most recent locator block hash in the main chain. In the
342- // case none of the hashes in the locator are in the main chain, fall
343- // back to the genesis block.
344- startNode , _ := hs .repo .Headers .GetHeaderByHeight (0 )
345- for _ , hash := range locator {
346- node , _ := hs .GetHeaderByHash (hash .String ())
347- if node != nil && hs .Contains (node ) {
348- startNode = node
349- break
350- }
328+ if stopHeight == 0 {
329+ stopHeight = startHeight + wire .MaxCFHeadersPerMsg
351330 }
352331
353- // Start at the block after the most recently known block. When there
354- // is no next block it means the most recently known block is the tip of
355- // the best chain, so there is nothing more to do.
356- next := hs .Next (startNode )
357- if next == nil {
358- return nil , 0
332+ if stopHeight <= startHeight {
333+ return nil , errors .New ("hashStop is lower than first valid height" )
359334 }
360- startNode = next
361335
362- // Calculate how many entries are needed.
363- total := uint32 (( hs . GetTipHeight () - startNode . Height ) + 1 )
364- if stopNode != nil && hs . Contains ( stopNode ) &&
365- stopNode . Height >= startNode . Height {
336+ // Check if peer requested number of headers is higher than the maximum number of headers per message
337+ if wire . MaxCFHeadersPerMsg < stopHeight - startHeight {
338+ stopHeight = startHeight + wire . MaxCFHeadersPerMsg
339+ }
366340
367- total = uint32 ((stopNode .Height - startNode .Height ) + 1 )
341+ dbHeaders , err := hs .repo .Headers .GetHeadersByHeightRange (startHeight + 1 , stopHeight )
342+ if err != nil {
343+ return nil , fmt .Errorf ("error getting headers between heights: %v" , err )
344+ }
345+
346+ headers := make ([]* wire.BlockHeader , 0 , len (dbHeaders ))
347+ for _ , dbHeader := range dbHeaders {
348+ header := & wire.BlockHeader {
349+ Version : dbHeader .Version ,
350+ PrevBlock : dbHeader .PreviousBlock ,
351+ MerkleRoot : dbHeader .MerkleRoot ,
352+ Timestamp : dbHeader .Timestamp ,
353+ Bits : dbHeader .Bits ,
354+ Nonce : dbHeader .Nonce ,
355+ }
356+ headers = append (headers , header )
368357 }
369- if total > maxEntries {
370- total = maxEntries
358+
359+ return headers , nil
360+ }
361+
362+ // LocateHeaders fetches headers for a number of blocks after the most recent known block
363+ // in the best chain, based on the provided block locator and stop hash, and defaults to the
364+ // genesis block if the locator is unknown.
365+ func (hs * HeaderService ) LocateHeaders (locator domains.BlockLocator , hashStop * chainhash.Hash ) []wire.BlockHeader {
366+ headers , err := hs .locateHeadersGetHeaders (locator , hashStop )
367+ if err != nil {
368+ hs .log .Error ().Msg (err .Error ())
369+ return nil
370+ }
371+
372+ result := make ([]wire.BlockHeader , 0 , len (headers ))
373+ for _ , header := range headers {
374+ result = append (result , * header )
371375 }
372376
373- return startNode , total
377+ return result
374378}
375379
376380// Contains checks if given header is stored in db.
0 commit comments