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