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 }