github.com/onflow/flow-go@v0.33.17/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 := e.execState.GetHighestFinalizedExecuted() 41 42 // get finalized height 43 finalized := e.state.Final() 44 final, err := finalized.Head() 45 if err != nil { 46 return nil, fmt.Errorf("could not get finalized block: %w", err) 47 } 48 49 lg := e.log.With(). 50 Uint64("last_finalized", final.Height). 51 Uint64("last_finalized_executed", lastExecuted). 52 Logger() 53 54 lg.Info().Msgf("start loading unfinalized blocks") 55 56 // dynamically bootstrapped execution node will have highest finalized executed as sealed root, 57 // which is lower than finalized root. so we will reload blocks from 58 // [sealedRoot.Height + 1, finalizedRoot.Height] and execute them on startup. 59 unexecutedFinalized := make([]flow.Identifier, 0) 60 61 // starting from the first unexecuted block, go through each unexecuted and finalized block 62 // reload its block to execution queues 63 // loading finalized blocks 64 for height := lastExecuted + 1; height <= final.Height; height++ { 65 finalizedID, err := e.headers.BlockIDByHeight(height) 66 if err != nil { 67 return nil, fmt.Errorf("could not get header at height: %v, %w", height, err) 68 } 69 70 unexecutedFinalized = append(unexecutedFinalized, finalizedID) 71 } 72 73 // loaded all pending blocks 74 pendings, err := finalized.Descendants() 75 if err != nil { 76 return nil, fmt.Errorf("could not get descendants of finalized block: %w", err) 77 } 78 79 unexecuted := append(unexecutedFinalized, pendings...) 80 81 lg.Info(). 82 // Uint64("sealed_root_height", rootBlock.Height). 83 // Hex("sealed_root_id", logging.Entity(rootBlock)). 84 Int("total_finalized_unexecuted", len(unexecutedFinalized)). 85 Int("total_unexecuted", len(unexecuted)). 86 Msgf("finalized unexecuted blocks") 87 88 return unexecuted, nil 89 }