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