github.com/onflow/flow-go@v0.33.17/fvm/context.go (about)

     1  package fvm
     2  
     3  import (
     4  	"math"
     5  
     6  	"github.com/rs/zerolog"
     7  	otelTrace "go.opentelemetry.io/otel/trace"
     8  
     9  	"github.com/onflow/flow-go/fvm/environment"
    10  	reusableRuntime "github.com/onflow/flow-go/fvm/runtime"
    11  	"github.com/onflow/flow-go/fvm/storage/derived"
    12  	"github.com/onflow/flow-go/fvm/storage/state"
    13  	"github.com/onflow/flow-go/fvm/tracing"
    14  	"github.com/onflow/flow-go/model/flow"
    15  	"github.com/onflow/flow-go/module"
    16  )
    17  
    18  const (
    19  	AccountKeyWeightThreshold = 1000
    20  
    21  	DefaultComputationLimit   = 100_000 // 100K
    22  	DefaultMemoryLimit        = math.MaxUint64
    23  	DefaultMaxInteractionSize = 20_000_000 // ~20MB
    24  )
    25  
    26  // A Context defines a set of execution parameters used by the virtual machine.
    27  type Context struct {
    28  	// DisableMemoryAndInteractionLimits will override memory and interaction
    29  	// limits and set them to MaxUint64, effectively disabling these limits.
    30  	DisableMemoryAndInteractionLimits bool
    31  	EVMEnabled                        bool
    32  	ComputationLimit                  uint64
    33  	MemoryLimit                       uint64
    34  	MaxStateKeySize                   uint64
    35  	MaxStateValueSize                 uint64
    36  	MaxStateInteractionSize           uint64
    37  
    38  	TransactionExecutorParams
    39  
    40  	DerivedBlockData *derived.DerivedBlockData
    41  
    42  	tracing.TracerSpan
    43  
    44  	environment.EnvironmentParams
    45  }
    46  
    47  // NewContext initializes a new execution context with the provided options.
    48  func NewContext(opts ...Option) Context {
    49  	return newContext(defaultContext(), opts...)
    50  }
    51  
    52  // NewContextFromParent spawns a child execution context with the provided options.
    53  func NewContextFromParent(parent Context, opts ...Option) Context {
    54  	return newContext(parent, opts...)
    55  }
    56  
    57  func newContext(ctx Context, opts ...Option) Context {
    58  	for _, applyOption := range opts {
    59  		ctx = applyOption(ctx)
    60  	}
    61  
    62  	return ctx
    63  }
    64  
    65  func defaultContext() Context {
    66  	return Context{
    67  		DisableMemoryAndInteractionLimits: false,
    68  		ComputationLimit:                  DefaultComputationLimit,
    69  		MemoryLimit:                       DefaultMemoryLimit,
    70  		MaxStateKeySize:                   state.DefaultMaxKeySize,
    71  		MaxStateValueSize:                 state.DefaultMaxValueSize,
    72  		MaxStateInteractionSize:           DefaultMaxInteractionSize,
    73  		TransactionExecutorParams:         DefaultTransactionExecutorParams(),
    74  		EnvironmentParams:                 environment.DefaultEnvironmentParams(),
    75  	}
    76  }
    77  
    78  // An Option sets a configuration parameter for a virtual machine context.
    79  type Option func(ctx Context) Context
    80  
    81  // WithChain sets the chain parameters for a virtual machine context.
    82  func WithChain(chain flow.Chain) Option {
    83  	return func(ctx Context) Context {
    84  		ctx.Chain = chain
    85  		return ctx
    86  	}
    87  }
    88  
    89  // WithGasLimit sets the computation limit for a virtual machine context.
    90  // @depricated, please use WithComputationLimit instead.
    91  func WithGasLimit(limit uint64) Option {
    92  	return func(ctx Context) Context {
    93  		ctx.ComputationLimit = limit
    94  		return ctx
    95  	}
    96  }
    97  
    98  // WithMemoryAndInteractionLimitsDisabled will override memory and interaction
    99  // limits and set them to MaxUint64, effectively disabling these limits.
   100  func WithMemoryAndInteractionLimitsDisabled() Option {
   101  	return func(ctx Context) Context {
   102  		ctx.DisableMemoryAndInteractionLimits = true
   103  		return ctx
   104  	}
   105  }
   106  
   107  // WithComputationLimit sets the computation limit for a virtual machine context.
   108  func WithComputationLimit(limit uint64) Option {
   109  	return func(ctx Context) Context {
   110  		ctx.ComputationLimit = limit
   111  		return ctx
   112  	}
   113  }
   114  
   115  // WithMemoryLimit sets the memory limit for a virtual machine context.
   116  func WithMemoryLimit(limit uint64) Option {
   117  	return func(ctx Context) Context {
   118  		ctx.MemoryLimit = limit
   119  		return ctx
   120  	}
   121  }
   122  
   123  // WithLogger sets the context logger
   124  func WithLogger(logger zerolog.Logger) Option {
   125  	return func(ctx Context) Context {
   126  		ctx.Logger = logger
   127  		return ctx
   128  	}
   129  }
   130  
   131  // WithMaxStateKeySize sets the byte size limit for ledger keys
   132  func WithMaxStateKeySize(limit uint64) Option {
   133  	return func(ctx Context) Context {
   134  		ctx.MaxStateKeySize = limit
   135  		return ctx
   136  	}
   137  }
   138  
   139  // WithMaxStateValueSize sets the byte size limit for ledger values
   140  func WithMaxStateValueSize(limit uint64) Option {
   141  	return func(ctx Context) Context {
   142  		ctx.MaxStateValueSize = limit
   143  		return ctx
   144  	}
   145  }
   146  
   147  // WithMaxStateInteractionSize sets the byte size limit for total interaction with ledger.
   148  // this prevents attacks such as reading all large registers
   149  func WithMaxStateInteractionSize(limit uint64) Option {
   150  	return func(ctx Context) Context {
   151  		ctx.MaxStateInteractionSize = limit
   152  		return ctx
   153  	}
   154  }
   155  
   156  // WithEventCollectionSizeLimit sets the event collection byte size limit for a virtual machine context.
   157  func WithEventCollectionSizeLimit(limit uint64) Option {
   158  	return func(ctx Context) Context {
   159  		ctx.EventCollectionByteSizeLimit = limit
   160  		return ctx
   161  	}
   162  }
   163  
   164  // WithEntropyProvider sets the entropy provider of a virtual machine context.
   165  //
   166  // The VM uses the input to provide entropy to the Cadence runtime randomness functions.
   167  func WithEntropyProvider(source environment.EntropyProvider) Option {
   168  	return func(ctx Context) Context {
   169  		ctx.EntropyProvider = source
   170  		return ctx
   171  	}
   172  }
   173  
   174  // WithBlockHeader sets the block header for a virtual machine context.
   175  //
   176  // The VM uses the header to provide current block information to the Cadence runtime.
   177  func WithBlockHeader(header *flow.Header) Option {
   178  	return func(ctx Context) Context {
   179  		ctx.BlockHeader = header
   180  		return ctx
   181  	}
   182  }
   183  
   184  // WithServiceEventCollectionEnabled enables service event collection
   185  func WithServiceEventCollectionEnabled() Option {
   186  	return func(ctx Context) Context {
   187  		ctx.ServiceEventCollectionEnabled = true
   188  		return ctx
   189  	}
   190  }
   191  
   192  // WithBlocks sets the block storage provider for a virtual machine context.
   193  //
   194  // The VM uses the block storage provider to provide historical block information to
   195  // the Cadence runtime.
   196  func WithBlocks(blocks environment.Blocks) Option {
   197  	return func(ctx Context) Context {
   198  		ctx.Blocks = blocks
   199  		return ctx
   200  	}
   201  }
   202  
   203  // WithMetricsReporter sets the metrics collector for a virtual machine context.
   204  //
   205  // A metrics collector is used to gather metrics reported by the Cadence runtime.
   206  func WithMetricsReporter(mr environment.MetricsReporter) Option {
   207  	return func(ctx Context) Context {
   208  		if mr != nil {
   209  			ctx.MetricsReporter = mr
   210  		}
   211  		return ctx
   212  	}
   213  }
   214  
   215  // WithTracer sets the tracer for a virtual machine context.
   216  func WithTracer(tr module.Tracer) Option {
   217  	return func(ctx Context) Context {
   218  		ctx.Tracer = tr
   219  		return ctx
   220  	}
   221  }
   222  
   223  // WithSpan sets the trace span for a virtual machine context.
   224  func WithSpan(span otelTrace.Span) Option {
   225  	return func(ctx Context) Context {
   226  		ctx.Span = span
   227  		return ctx
   228  	}
   229  }
   230  
   231  // WithExtensiveTracing sets the extensive tracing
   232  func WithExtensiveTracing() Option {
   233  	return func(ctx Context) Context {
   234  		ctx.ExtensiveTracing = true
   235  		return ctx
   236  	}
   237  }
   238  
   239  // WithServiceAccount enables or disables calls to the Flow service account.
   240  func WithServiceAccount(enabled bool) Option {
   241  	return func(ctx Context) Context {
   242  		ctx.ServiceAccountEnabled = enabled
   243  		return ctx
   244  	}
   245  }
   246  
   247  // WithRestrictContractRemoval enables or disables restricted contract removal for a
   248  // virtual machine context. Warning! this would be overridden with the flag stored on chain.
   249  // this is just a fallback value
   250  func WithContractRemovalRestricted(enabled bool) Option {
   251  	return func(ctx Context) Context {
   252  		ctx.RestrictContractRemoval = enabled
   253  		return ctx
   254  	}
   255  }
   256  
   257  // WithRestrictedContractDeployment enables or disables restricted contract deployment for a
   258  // virtual machine context. Warning! this would be overridden with the flag stored on chain.
   259  // this is just a fallback value
   260  func WithContractDeploymentRestricted(enabled bool) Option {
   261  	return func(ctx Context) Context {
   262  		ctx.RestrictContractDeployment = enabled
   263  		return ctx
   264  	}
   265  }
   266  
   267  // WithCadenceLogging enables or disables Cadence logging for a
   268  // virtual machine context.
   269  func WithCadenceLogging(enabled bool) Option {
   270  	return func(ctx Context) Context {
   271  		ctx.CadenceLoggingEnabled = enabled
   272  		return ctx
   273  	}
   274  }
   275  
   276  // WithAccountStorageLimit enables or disables checking if account storage used is
   277  // over its storage capacity
   278  func WithAccountStorageLimit(enabled bool) Option {
   279  	return func(ctx Context) Context {
   280  		ctx.LimitAccountStorage = enabled
   281  		return ctx
   282  	}
   283  }
   284  
   285  // WithAuthorizationCheckxEnabled enables or disables pre-execution
   286  // authorization checks.
   287  func WithAuthorizationChecksEnabled(enabled bool) Option {
   288  	return func(ctx Context) Context {
   289  		ctx.AuthorizationChecksEnabled = enabled
   290  		return ctx
   291  	}
   292  }
   293  
   294  // WithSequenceNumberCheckAndIncrementEnabled enables or disables pre-execution
   295  // sequence number check / increment.
   296  func WithSequenceNumberCheckAndIncrementEnabled(enabled bool) Option {
   297  	return func(ctx Context) Context {
   298  		ctx.SequenceNumberCheckAndIncrementEnabled = enabled
   299  		return ctx
   300  	}
   301  }
   302  
   303  // WithAccountKeyWeightThreshold sets the key weight threshold used for
   304  // authorization checks.  If the threshold is a negative number, signature
   305  // verification is skipped.
   306  //
   307  // Note: This is set only by tests
   308  func WithAccountKeyWeightThreshold(threshold int) Option {
   309  	return func(ctx Context) Context {
   310  		ctx.AccountKeyWeightThreshold = threshold
   311  		return ctx
   312  	}
   313  }
   314  
   315  // WithTransactionBodyExecutionEnabled enables or disables the transaction body
   316  // execution.
   317  //
   318  // Note: This is disabled only by tests
   319  func WithTransactionBodyExecutionEnabled(enabled bool) Option {
   320  	return func(ctx Context) Context {
   321  		ctx.TransactionBodyExecutionEnabled = enabled
   322  		return ctx
   323  	}
   324  }
   325  
   326  // WithTransactionFeesEnabled enables or disables deduction of transaction fees
   327  func WithTransactionFeesEnabled(enabled bool) Option {
   328  	return func(ctx Context) Context {
   329  		ctx.TransactionFeesEnabled = enabled
   330  		return ctx
   331  	}
   332  }
   333  
   334  // WithRandomSourceHistoryCallAllowed enables or disables calling the `entropy` function
   335  // within cadence
   336  func WithRandomSourceHistoryCallAllowed(allowed bool) Option {
   337  	return func(ctx Context) Context {
   338  		ctx.RandomSourceHistoryCallAllowed = allowed
   339  		return ctx
   340  	}
   341  }
   342  
   343  // WithReusableCadenceRuntimePool set the (shared) RedusableCadenceRuntimePool
   344  // use for creating the cadence runtime.
   345  func WithReusableCadenceRuntimePool(
   346  	pool reusableRuntime.ReusableCadenceRuntimePool,
   347  ) Option {
   348  	return func(ctx Context) Context {
   349  		ctx.ReusableCadenceRuntimePool = pool
   350  		return ctx
   351  	}
   352  }
   353  
   354  // WithDerivedBlockData sets the derived data cache storage to be used by the
   355  // transaction/script.
   356  func WithDerivedBlockData(derivedBlockData *derived.DerivedBlockData) Option {
   357  	return func(ctx Context) Context {
   358  		ctx.DerivedBlockData = derivedBlockData
   359  		return ctx
   360  	}
   361  }
   362  
   363  // WithEventEncoder sets events encoder to be used for encoding events emitted during execution
   364  func WithEventEncoder(encoder environment.EventEncoder) Option {
   365  	return func(ctx Context) Context {
   366  		ctx.EventEncoder = encoder
   367  		return ctx
   368  	}
   369  }
   370  
   371  // WithEVMEnabled enables access to the evm environment
   372  func WithEVMEnabled(enabled bool) Option {
   373  	return func(ctx Context) Context {
   374  		ctx.EVMEnabled = enabled
   375  		return ctx
   376  	}
   377  }