github.com/onflow/flow-go@v0.33.17/fvm/environment/meter.go (about) 1 package environment 2 3 import ( 4 "context" 5 6 "github.com/onflow/cadence/runtime/common" 7 8 "github.com/onflow/flow-go/fvm/errors" 9 "github.com/onflow/flow-go/fvm/meter" 10 "github.com/onflow/flow-go/fvm/storage/state" 11 ) 12 13 const ( 14 // [2_000, 3_000) reserved for the FVM 15 ComputationKindHash = 2001 + iota 16 ComputationKindVerifySignature 17 ComputationKindAddAccountKey 18 ComputationKindAddEncodedAccountKey 19 ComputationKindAllocateStorageIndex 20 ComputationKindCreateAccount 21 ComputationKindEmitEvent 22 ComputationKindGenerateUUID 23 ComputationKindGetAccountAvailableBalance 24 ComputationKindGetAccountBalance 25 ComputationKindGetAccountContractCode 26 ComputationKindGetAccountContractNames 27 ComputationKindGetAccountKey 28 ComputationKindGetBlockAtHeight 29 ComputationKindGetCode 30 ComputationKindGetCurrentBlockHeight 31 _ 32 ComputationKindGetStorageCapacity 33 ComputationKindGetStorageUsed 34 ComputationKindGetValue 35 ComputationKindRemoveAccountContractCode 36 ComputationKindResolveLocation 37 ComputationKindRevokeAccountKey 38 ComputationKindRevokeEncodedAccountKey 39 _ 40 ComputationKindSetValue 41 ComputationKindUpdateAccountContractCode 42 ComputationKindValidatePublicKey 43 ComputationKindValueExists 44 ComputationKindAccountKeysCount 45 ComputationKindBLSVerifyPOP 46 ComputationKindBLSAggregateSignatures 47 ComputationKindBLSAggregatePublicKeys 48 ComputationKindGetOrLoadProgram 49 ComputationKindGenerateAccountLocalID 50 ComputationKindGetRandomSourceHistory 51 ComputationKindEVMGasUsage 52 ComputationKindRLPEncoding 53 ComputationKindRLPDecoding 54 ComputationKindEncodeEvent 55 _ 56 ComputationKindEVMEncodeABI 57 ComputationKindEVMDecodeABI 58 ) 59 60 type Meter interface { 61 MeterComputation(common.ComputationKind, uint) error 62 ComputationUsed() (uint64, error) 63 ComputationIntensities() meter.MeteredComputationIntensities 64 ComputationAvailable(common.ComputationKind, uint) bool 65 66 MeterMemory(usage common.MemoryUsage) error 67 MemoryUsed() (uint64, error) 68 69 MeterEmittedEvent(byteSize uint64) error 70 TotalEmittedEventBytes() uint64 71 72 InteractionUsed() (uint64, error) 73 } 74 75 type meterImpl struct { 76 txnState state.NestedTransactionPreparer 77 } 78 79 func NewMeter(txnState state.NestedTransactionPreparer) Meter { 80 return &meterImpl{ 81 txnState: txnState, 82 } 83 } 84 85 func (meter *meterImpl) MeterComputation( 86 kind common.ComputationKind, 87 intensity uint, 88 ) error { 89 return meter.txnState.MeterComputation(kind, intensity) 90 } 91 92 func (meter *meterImpl) ComputationIntensities() meter.MeteredComputationIntensities { 93 return meter.txnState.ComputationIntensities() 94 } 95 96 func (meter *meterImpl) ComputationAvailable( 97 kind common.ComputationKind, 98 intensity uint, 99 ) bool { 100 return meter.txnState.ComputationAvailable(kind, intensity) 101 } 102 103 func (meter *meterImpl) ComputationUsed() (uint64, error) { 104 return meter.txnState.TotalComputationUsed(), nil 105 } 106 107 func (meter *meterImpl) MeterMemory(usage common.MemoryUsage) error { 108 return meter.txnState.MeterMemory(usage.Kind, uint(usage.Amount)) 109 } 110 111 func (meter *meterImpl) MemoryUsed() (uint64, error) { 112 return meter.txnState.TotalMemoryEstimate(), nil 113 } 114 115 func (meter *meterImpl) InteractionUsed() (uint64, error) { 116 return meter.txnState.InteractionUsed(), nil 117 } 118 119 func (meter *meterImpl) MeterEmittedEvent(byteSize uint64) error { 120 return meter.txnState.MeterEmittedEvent(byteSize) 121 } 122 123 func (meter *meterImpl) TotalEmittedEventBytes() uint64 { 124 return meter.txnState.TotalEmittedEventBytes() 125 } 126 127 type cancellableMeter struct { 128 meterImpl 129 130 ctx context.Context 131 } 132 133 func NewCancellableMeter( 134 ctx context.Context, 135 txnState state.NestedTransactionPreparer, 136 ) Meter { 137 return &cancellableMeter{ 138 meterImpl: meterImpl{ 139 txnState: txnState, 140 }, 141 ctx: ctx, 142 } 143 } 144 145 func (meter *cancellableMeter) MeterComputation( 146 kind common.ComputationKind, 147 intensity uint, 148 ) error { 149 // this method is called on every unit of operation, so 150 // checking the context here is the most likely would capture 151 // timeouts or cancellation as soon as they happen, though 152 // we might revisit this when optimizing script execution 153 // by only checking on specific kind of Meter calls. 154 // 155 // in the future this context check should be done inside the cadence 156 select { 157 case <-meter.ctx.Done(): 158 err := meter.ctx.Err() 159 if errors.Is(err, context.DeadlineExceeded) { 160 return errors.NewScriptExecutionTimedOutError() 161 } 162 return errors.NewScriptExecutionCancelledError(err) 163 default: 164 // do nothing 165 } 166 167 return meter.meterImpl.MeterComputation(kind, intensity) 168 }