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 }