github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/execution/ingestion/loader/unfinalized_loader.go (about) 1 package loader 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/rs/zerolog" 8 9 "github.com/onflow/flow-go/engine/execution/state" 10 "github.com/onflow/flow-go/model/flow" 11 "github.com/onflow/flow-go/state/protocol" 12 "github.com/onflow/flow-go/storage" 13 ) 14 15 type UnfinalizedLoader struct { 16 log zerolog.Logger 17 state protocol.State 18 headers storage.Headers 19 execState state.FinalizedExecutionState 20 } 21 22 // NewUnfinalizedLoader creates a new loader that loads all unfinalized and validated blocks 23 func NewUnfinalizedLoader( 24 log zerolog.Logger, 25 state protocol.State, 26 headers storage.Headers, 27 execState state.FinalizedExecutionState, 28 ) *UnfinalizedLoader { 29 return &UnfinalizedLoader{ 30 log: log.With().Str("component", "ingestion_engine_unfinalized_loader").Logger(), 31 state: state, 32 headers: headers, 33 execState: execState, 34 } 35 } 36 37 // LoadUnexecuted loads all unfinalized and validated blocks 38 // any error returned are exceptions 39 func (e *UnfinalizedLoader) LoadUnexecuted(ctx context.Context) ([]flow.Identifier, error) { 40 lastExecuted, err := e.execState.GetHighestFinalizedExecuted() 41 if err != nil { 42 return nil, fmt.Errorf("could not get highest finalized executed: %w", err) 43 } 44 45 // get finalized height 46 finalized := e.state.Final() 47 final, err := finalized.Head() 48 if err != nil { 49 return nil, fmt.Errorf("could not get finalized block: %w", err) 50 } 51 52 lg := e.log.With(). 53 Uint64("last_finalized", final.Height). 54 Uint64("last_finalized_executed", lastExecuted). 55 Logger() 56 57 lg.Info().Msgf("start loading unfinalized blocks") 58 59 // dynamically bootstrapped execution node will have highest finalized executed as sealed root, 60 // which is lower than finalized root. so we will reload blocks from 61 // [sealedRoot.Height + 1, finalizedRoot.Height] and execute them on startup. 62 unexecutedFinalized := make([]flow.Identifier, 0) 63 64 // starting from the first unexecuted block, go through each unexecuted and finalized block 65 // reload its block to execution queues 66 // loading finalized blocks 67 for height := lastExecuted + 1; height <= final.Height; height++ { 68 finalizedID, err := e.headers.BlockIDByHeight(height) 69 if err != nil { 70 return nil, fmt.Errorf("could not get header at height: %v, %w", height, err) 71 } 72 73 unexecutedFinalized = append(unexecutedFinalized, finalizedID) 74 } 75 76 // loaded all pending blocks 77 pendings, err := finalized.Descendants() 78 if err != nil { 79 return nil, fmt.Errorf("could not get descendants of finalized block: %w", err) 80 } 81 82 unexecuted := append(unexecutedFinalized, pendings...) 83 84 lg.Info(). 85 // Uint64("sealed_root_height", rootBlock.Height). 86 // Hex("sealed_root_id", logging.Entity(rootBlock)). 87 Int("total_finalized_unexecuted", len(unexecutedFinalized)). 88 Int("total_unexecuted", len(unexecuted)). 89 Msgf("finalized unexecuted blocks") 90 91 return unexecuted, nil 92 }