github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/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  	_ // removed, DO NOT REUSE
    39  	_ // removed, DO NOT REUSE
    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  // MainnetExecutionEffortWeights are the execution effort weights as they are
    61  // on mainnet from 18.8.2022
    62  var MainnetExecutionEffortWeights = meter.ExecutionEffortWeights{
    63  	common.ComputationKindStatement:          1569,
    64  	common.ComputationKindLoop:               1569,
    65  	common.ComputationKindFunctionInvocation: 1569,
    66  	ComputationKindGetValue:                  808,
    67  	ComputationKindCreateAccount:             2837670,
    68  	ComputationKindSetValue:                  765,
    69  }
    70  
    71  type Meter interface {
    72  	MeterComputation(common.ComputationKind, uint) error
    73  	ComputationUsed() (uint64, error)
    74  	ComputationIntensities() meter.MeteredComputationIntensities
    75  	ComputationAvailable(common.ComputationKind, uint) bool
    76  
    77  	MeterMemory(usage common.MemoryUsage) error
    78  	MemoryUsed() (uint64, error)
    79  
    80  	MeterEmittedEvent(byteSize uint64) error
    81  	TotalEmittedEventBytes() uint64
    82  
    83  	InteractionUsed() (uint64, error)
    84  }
    85  
    86  type meterImpl struct {
    87  	txnState state.NestedTransactionPreparer
    88  }
    89  
    90  func NewMeter(txnState state.NestedTransactionPreparer) Meter {
    91  	return &meterImpl{
    92  		txnState: txnState,
    93  	}
    94  }
    95  
    96  func (meter *meterImpl) MeterComputation(
    97  	kind common.ComputationKind,
    98  	intensity uint,
    99  ) error {
   100  	return meter.txnState.MeterComputation(kind, intensity)
   101  }
   102  
   103  func (meter *meterImpl) ComputationIntensities() meter.MeteredComputationIntensities {
   104  	return meter.txnState.ComputationIntensities()
   105  }
   106  
   107  func (meter *meterImpl) ComputationAvailable(
   108  	kind common.ComputationKind,
   109  	intensity uint,
   110  ) bool {
   111  	return meter.txnState.ComputationAvailable(kind, intensity)
   112  }
   113  
   114  func (meter *meterImpl) ComputationUsed() (uint64, error) {
   115  	return meter.txnState.TotalComputationUsed(), nil
   116  }
   117  
   118  func (meter *meterImpl) MeterMemory(usage common.MemoryUsage) error {
   119  	return meter.txnState.MeterMemory(usage.Kind, uint(usage.Amount))
   120  }
   121  
   122  func (meter *meterImpl) MemoryUsed() (uint64, error) {
   123  	return meter.txnState.TotalMemoryEstimate(), nil
   124  }
   125  
   126  func (meter *meterImpl) InteractionUsed() (uint64, error) {
   127  	return meter.txnState.InteractionUsed(), nil
   128  }
   129  
   130  func (meter *meterImpl) MeterEmittedEvent(byteSize uint64) error {
   131  	return meter.txnState.MeterEmittedEvent(byteSize)
   132  }
   133  
   134  func (meter *meterImpl) TotalEmittedEventBytes() uint64 {
   135  	return meter.txnState.TotalEmittedEventBytes()
   136  }
   137  
   138  type cancellableMeter struct {
   139  	meterImpl
   140  
   141  	ctx context.Context
   142  }
   143  
   144  func NewCancellableMeter(
   145  	ctx context.Context,
   146  	txnState state.NestedTransactionPreparer,
   147  ) Meter {
   148  	return &cancellableMeter{
   149  		meterImpl: meterImpl{
   150  			txnState: txnState,
   151  		},
   152  		ctx: ctx,
   153  	}
   154  }
   155  
   156  func (meter *cancellableMeter) MeterComputation(
   157  	kind common.ComputationKind,
   158  	intensity uint,
   159  ) error {
   160  	// this method is called on every unit of operation, so
   161  	// checking the context here is the most likely would capture
   162  	// timeouts or cancellation as soon as they happen, though
   163  	// we might revisit this when optimizing script execution
   164  	// by only checking on specific kind of Meter calls.
   165  	//
   166  	// in the future this context check should be done inside the cadence
   167  	select {
   168  	case <-meter.ctx.Done():
   169  		err := meter.ctx.Err()
   170  		if errors.Is(err, context.DeadlineExceeded) {
   171  			return errors.NewScriptExecutionTimedOutError()
   172  		}
   173  		return errors.NewScriptExecutionCancelledError(err)
   174  	default:
   175  		// do nothing
   176  	}
   177  
   178  	return meter.meterImpl.MeterComputation(kind, intensity)
   179  }