github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/consensus/recovery/protocol/state.go (about)

     1  package protocol
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/flow-go/model/flow"
     7  	"github.com/onflow/flow-go/state/protocol"
     8  	"github.com/onflow/flow-go/storage"
     9  )
    10  
    11  // FindLatest returns:
    12  //   - [first value] latest finalized header
    13  //   - [second value] all known descendants (i.e. pending blocks)
    14  //   - No errors expected during normal operations.
    15  //
    16  // All returned blocks have been verified by the compliance layer, i.e. they are guaranteed to be valid.
    17  // The descendants are listed in ancestor-first order, i.e. for any block B = descendants[i], B's parent
    18  // must be included at an index _smaller_ than i, unless B's parent is the latest finalized block.
    19  //
    20  // Note: this is an expensive method, which is intended to help recover from a crash, e.g. help to
    21  // re-built the in-memory consensus state.
    22  func FindLatest(state protocol.State, headers storage.Headers) (*flow.Header, []*flow.Header, error) {
    23  	finalizedSnapshot := state.Final()              // state snapshot at latest finalized block
    24  	finalizedBlock, err := finalizedSnapshot.Head() // header of latest finalized block
    25  	if err != nil {
    26  		return nil, nil, fmt.Errorf("could not find finalized block")
    27  	}
    28  	pendingIDs, err := finalizedSnapshot.Descendants() // find IDs of all blocks descending from the finalized block
    29  	if err != nil {
    30  		return nil, nil, fmt.Errorf("could not find pending block")
    31  	}
    32  
    33  	// retrieve the headers for each of the pending blocks
    34  	pending := make([]*flow.Header, 0, len(pendingIDs))
    35  	for _, pendingID := range pendingIDs {
    36  		pendingHeader, err := headers.ByBlockID(pendingID)
    37  		if err != nil {
    38  			return nil, nil, fmt.Errorf("could not find pending block by ID: %w", err)
    39  		}
    40  		pending = append(pending, pendingHeader)
    41  	}
    42  
    43  	return finalizedBlock, pending, nil
    44  }