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  }