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

     1  package cluster
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/onflow/flow-go/model/flow"
     7  	"github.com/onflow/flow-go/state/cluster"
     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 cluster.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 get finalized header: %w", err)
    27  	}
    28  	pendingIDs, err := finalizedSnapshot.Pending() // find IDs of all blocks descending from the finalized block
    29  	if err != nil {
    30  		return nil, nil, fmt.Errorf("could not get pending children: %w", err)
    31  	}
    32  
    33  	pending := make([]*flow.Header, 0, len(pendingIDs))
    34  	for _, pendingID := range pendingIDs {
    35  		header, err := headers.ByBlockID(pendingID)
    36  		if err != nil {
    37  			return nil, nil, fmt.Errorf("could not find pending child: %w", err)
    38  		}
    39  		pending = append(pending, header)
    40  	}
    41  
    42  	return finalizedBlock, pending, nil
    43  }