github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/engine/execution/computation/manager.go (about) 1 package computation 2 3 import ( 4 "context" 5 "fmt" 6 7 "github.com/onflow/cadence/runtime" 8 "github.com/rs/zerolog" 9 10 "github.com/onflow/flow-go/engine/execution" 11 "github.com/onflow/flow-go/engine/execution/computation/computer" 12 "github.com/onflow/flow-go/engine/execution/computation/query" 13 "github.com/onflow/flow-go/fvm" 14 reusableRuntime "github.com/onflow/flow-go/fvm/runtime" 15 "github.com/onflow/flow-go/fvm/storage/derived" 16 "github.com/onflow/flow-go/fvm/storage/snapshot" 17 "github.com/onflow/flow-go/model/flow" 18 "github.com/onflow/flow-go/module" 19 "github.com/onflow/flow-go/module/executiondatasync/provider" 20 "github.com/onflow/flow-go/module/mempool/entity" 21 "github.com/onflow/flow-go/state/protocol" 22 "github.com/onflow/flow-go/utils/logging" 23 ) 24 25 const ( 26 ReusableCadenceRuntimePoolSize = 1000 27 ) 28 29 type ComputationManager interface { 30 ExecuteScript( 31 ctx context.Context, 32 script []byte, 33 arguments [][]byte, 34 blockHeader *flow.Header, 35 snapshot snapshot.StorageSnapshot, 36 ) ( 37 []byte, 38 uint64, 39 error, 40 ) 41 42 ComputeBlock( 43 ctx context.Context, 44 parentBlockExecutionResultID flow.Identifier, 45 block *entity.ExecutableBlock, 46 snapshot snapshot.StorageSnapshot, 47 ) ( 48 *execution.ComputationResult, 49 error, 50 ) 51 52 GetAccount( 53 ctx context.Context, 54 addr flow.Address, 55 header *flow.Header, 56 snapshot snapshot.StorageSnapshot, 57 ) ( 58 *flow.Account, 59 error, 60 ) 61 } 62 63 type ComputationConfig struct { 64 query.QueryConfig 65 CadenceTracing bool 66 ExtensiveTracing bool 67 DerivedDataCacheSize uint 68 MaxConcurrency int 69 70 // When NewCustomVirtualMachine is nil, the manager will create a standard 71 // fvm virtual machine via fvm.NewVirtualMachine. Otherwise, the manager 72 // will create a virtual machine using this function. 73 // 74 // Note that this is primarily used for testing. 75 NewCustomVirtualMachine func() fvm.VM 76 } 77 78 // Manager manages computation and execution 79 type Manager struct { 80 log zerolog.Logger 81 vm fvm.VM 82 blockComputer computer.BlockComputer 83 queryExecutor query.Executor 84 derivedChainData *derived.DerivedChainData 85 } 86 87 var _ ComputationManager = &Manager{} 88 89 func New( 90 logger zerolog.Logger, 91 metrics module.ExecutionMetrics, 92 tracer module.Tracer, 93 me module.Local, 94 protoState protocol.State, 95 vmCtx fvm.Context, 96 committer computer.ViewCommitter, 97 executionDataProvider provider.Provider, 98 params ComputationConfig, 99 ) (*Manager, error) { 100 log := logger.With().Str("engine", "computation").Logger() 101 102 var vm fvm.VM 103 if params.NewCustomVirtualMachine != nil { 104 vm = params.NewCustomVirtualMachine() 105 } else { 106 vm = fvm.NewVirtualMachine() 107 } 108 109 chainID := vmCtx.Chain.ChainID() 110 options := DefaultFVMOptions(chainID, params.CadenceTracing, params.ExtensiveTracing) 111 vmCtx = fvm.NewContextFromParent(vmCtx, options...) 112 113 blockComputer, err := computer.NewBlockComputer( 114 vm, 115 vmCtx, 116 metrics, 117 tracer, 118 log.With().Str("component", "block_computer").Logger(), 119 committer, 120 me, 121 executionDataProvider, 122 nil, // TODO(ramtin): update me with proper consumers 123 protoState, 124 params.MaxConcurrency, 125 ) 126 127 if err != nil { 128 return nil, fmt.Errorf("cannot create block computer: %w", err) 129 } 130 131 derivedChainData, err := derived.NewDerivedChainData(params.DerivedDataCacheSize) 132 if err != nil { 133 return nil, fmt.Errorf("cannot create derived data cache: %w", err) 134 } 135 136 queryExecutor := query.NewQueryExecutor( 137 params.QueryConfig, 138 logger, 139 metrics, 140 vm, 141 vmCtx, 142 derivedChainData, 143 query.NewProtocolStateWrapper(protoState), 144 ) 145 146 e := Manager{ 147 log: log, 148 vm: vm, 149 blockComputer: blockComputer, 150 queryExecutor: queryExecutor, 151 derivedChainData: derivedChainData, 152 } 153 154 return &e, nil 155 } 156 157 func (e *Manager) VM() fvm.VM { 158 return e.vm 159 } 160 161 func (e *Manager) ComputeBlock( 162 ctx context.Context, 163 parentBlockExecutionResultID flow.Identifier, 164 block *entity.ExecutableBlock, 165 snapshot snapshot.StorageSnapshot, 166 ) (*execution.ComputationResult, error) { 167 168 e.log.Debug(). 169 Hex("block_id", logging.Entity(block.Block)). 170 Msg("received complete block") 171 172 derivedBlockData := e.derivedChainData.GetOrCreateDerivedBlockData( 173 block.ID(), 174 block.ParentID()) 175 176 result, err := e.blockComputer.ExecuteBlock( 177 ctx, 178 parentBlockExecutionResultID, 179 block, 180 snapshot, 181 derivedBlockData) 182 if err != nil { 183 return nil, fmt.Errorf("failed to execute block: %w", err) 184 } 185 186 e.log.Debug(). 187 Hex("block_id", logging.Entity(result.ExecutableBlock.Block)). 188 Msg("computed block result") 189 190 return result, nil 191 } 192 193 func (e *Manager) ExecuteScript( 194 ctx context.Context, 195 code []byte, 196 arguments [][]byte, 197 blockHeader *flow.Header, 198 snapshot snapshot.StorageSnapshot, 199 ) ([]byte, uint64, error) { 200 return e.queryExecutor.ExecuteScript(ctx, 201 code, 202 arguments, 203 blockHeader, 204 snapshot) 205 } 206 207 func (e *Manager) GetAccount( 208 ctx context.Context, 209 address flow.Address, 210 blockHeader *flow.Header, 211 snapshot snapshot.StorageSnapshot, 212 ) ( 213 *flow.Account, 214 error, 215 ) { 216 return e.queryExecutor.GetAccount( 217 ctx, 218 address, 219 blockHeader, 220 snapshot) 221 } 222 223 func (e *Manager) QueryExecutor() query.Executor { 224 return e.queryExecutor 225 } 226 227 func DefaultFVMOptions(chainID flow.ChainID, cadenceTracing bool, extensiveTracing bool) []fvm.Option { 228 options := []fvm.Option{ 229 fvm.WithChain(chainID.Chain()), 230 fvm.WithReusableCadenceRuntimePool( 231 reusableRuntime.NewReusableCadenceRuntimePool( 232 ReusableCadenceRuntimePoolSize, 233 runtime.Config{ 234 TracingEnabled: cadenceTracing, 235 AttachmentsEnabled: true, 236 }, 237 )), 238 fvm.WithEVMEnabled(true), 239 } 240 241 if extensiveTracing { 242 options = append(options, fvm.WithExtensiveTracing()) 243 } 244 245 return options 246 }