github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/fvm/meter/meter_test.go (about)

     1  package meter_test
     2  
     3  import (
     4  	"fmt"
     5  	"math"
     6  	"testing"
     7  
     8  	"github.com/stretchr/testify/assert"
     9  	"github.com/stretchr/testify/require"
    10  
    11  	"github.com/onflow/cadence/runtime/common"
    12  
    13  	"github.com/onflow/flow-go/fvm/errors"
    14  	"github.com/onflow/flow-go/fvm/meter"
    15  	"github.com/onflow/flow-go/model/flow"
    16  )
    17  
    18  func TestWeightedComputationMetering(t *testing.T) {
    19  
    20  	t.Run("get limits", func(t *testing.T) {
    21  		m := meter.NewMeter(
    22  			meter.DefaultParameters().
    23  				WithComputationLimit(1).
    24  				WithMemoryLimit(2),
    25  		)
    26  		require.Equal(t, uint(1), m.TotalComputationLimit())
    27  		require.Equal(t, uint64(2), m.TotalMemoryLimit())
    28  	})
    29  
    30  	t.Run("get limits max", func(t *testing.T) {
    31  		m := meter.NewMeter(
    32  			meter.DefaultParameters().
    33  				WithComputationLimit(math.MaxUint32).
    34  				WithMemoryLimit(math.MaxUint32),
    35  		)
    36  		require.Equal(t, uint(math.MaxUint32), m.TotalComputationLimit())
    37  		require.Equal(t, uint64(math.MaxUint32), m.TotalMemoryLimit())
    38  	})
    39  
    40  	t.Run("meter computation and memory", func(t *testing.T) {
    41  		m := meter.NewMeter(
    42  			meter.DefaultParameters().
    43  				WithComputationLimit(10).
    44  				WithComputationWeights(
    45  					map[common.ComputationKind]uint64{0: 1 << meter.MeterExecutionInternalPrecisionBytes}).
    46  				WithMemoryLimit(10).
    47  				WithMemoryWeights(map[common.MemoryKind]uint64{0: 1}),
    48  		)
    49  
    50  		err := m.MeterComputation(0, 1)
    51  		require.NoError(t, err)
    52  		require.Equal(t, uint64(1), m.TotalComputationUsed())
    53  
    54  		err = m.MeterComputation(0, 2)
    55  		require.NoError(t, err)
    56  		require.Equal(t, uint64(1+2), m.TotalComputationUsed())
    57  
    58  		err = m.MeterComputation(0, 8)
    59  		require.Error(t, err)
    60  		require.True(t, errors.IsComputationLimitExceededError(err))
    61  		require.Equal(t, err.Error(), errors.NewComputationLimitExceededError(10).Error())
    62  
    63  		err = m.MeterMemory(0, 2)
    64  		require.NoError(t, err)
    65  		require.Equal(t, uint64(2), m.TotalMemoryEstimate())
    66  
    67  		err = m.MeterMemory(0, 3)
    68  		require.NoError(t, err)
    69  		require.Equal(t, uint64(2+3), m.TotalMemoryEstimate())
    70  
    71  		err = m.MeterMemory(0, 8)
    72  		require.Error(t, err)
    73  		require.True(t, errors.IsMemoryLimitExceededError(err))
    74  		require.Equal(t, err.Error(), errors.NewMemoryLimitExceededError(10).Error())
    75  	})
    76  
    77  	t.Run("meter computation and memory with weights", func(t *testing.T) {
    78  		m := meter.NewMeter(
    79  			meter.DefaultParameters().
    80  				WithComputationLimit(100).
    81  				WithComputationWeights(
    82  					map[common.ComputationKind]uint64{0: 13 << meter.MeterExecutionInternalPrecisionBytes}).
    83  				WithMemoryLimit(100).
    84  				WithMemoryWeights(map[common.MemoryKind]uint64{0: 17}),
    85  		)
    86  
    87  		err := m.MeterComputation(0, 1)
    88  		require.NoError(t, err)
    89  		require.Equal(t, uint64(13), m.TotalComputationUsed())
    90  		require.Equal(t, uint(1), m.ComputationIntensities()[0])
    91  
    92  		err = m.MeterMemory(0, 2)
    93  		require.NoError(t, err)
    94  		require.Equal(t, uint64(34), m.TotalMemoryEstimate())
    95  		require.Equal(t, uint(2), m.MemoryIntensities()[0])
    96  	})
    97  
    98  	t.Run("meter computation with weights lower than MeterInternalPrecisionBytes", func(t *testing.T) {
    99  		m := meter.NewMeter(
   100  			meter.DefaultParameters().
   101  				WithComputationLimit(100).
   102  				WithComputationWeights(map[common.ComputationKind]uint64{0: 1}).
   103  				WithMemoryLimit(100).
   104  				WithMemoryWeights(map[common.MemoryKind]uint64{0: 1}),
   105  		)
   106  
   107  		internalPrecisionMinusOne := uint((1 << meter.MeterExecutionInternalPrecisionBytes) - 1)
   108  
   109  		err := m.MeterComputation(0, internalPrecisionMinusOne)
   110  		require.NoError(t, err)
   111  		require.Equal(t, uint64(0), m.TotalComputationUsed())
   112  		require.Equal(t, internalPrecisionMinusOne, m.ComputationIntensities()[0])
   113  
   114  		err = m.MeterComputation(0, 1)
   115  		require.NoError(t, err)
   116  		require.Equal(t, uint64(1), m.TotalComputationUsed())
   117  		require.Equal(t, uint(1<<meter.MeterExecutionInternalPrecisionBytes), m.ComputationIntensities()[0])
   118  	})
   119  
   120  	t.Run("check computation capacity", func(t *testing.T) {
   121  		m := meter.NewMeter(
   122  			meter.DefaultParameters().
   123  				WithComputationLimit(10).
   124  				WithComputationWeights(
   125  					map[common.ComputationKind]uint64{0: 1 << meter.MeterExecutionInternalPrecisionBytes}),
   126  		)
   127  
   128  		hasCapacity := m.ComputationAvailable(0, 1)
   129  		require.True(t, hasCapacity)
   130  
   131  		err := m.MeterComputation(0, 1)
   132  		require.NoError(t, err)
   133  		require.Equal(t, uint64(1), m.TotalComputationUsed())
   134  
   135  		require.True(t, m.ComputationAvailable(0, 9))
   136  		require.False(t, m.ComputationAvailable(0, 10))
   137  
   138  		// test a type without a weight (default zero)
   139  		require.True(t, m.ComputationAvailable(1, 10))
   140  	})
   141  
   142  	t.Run("merge meters", func(t *testing.T) {
   143  		compKind := common.ComputationKind(0)
   144  		m := meter.NewMeter(
   145  			meter.DefaultParameters().
   146  				WithComputationLimit(9).
   147  				WithComputationWeights(
   148  					map[common.ComputationKind]uint64{0: 1 << meter.MeterExecutionInternalPrecisionBytes}).
   149  				WithMemoryLimit(0).
   150  				WithMemoryWeights(map[common.MemoryKind]uint64{0: 1}),
   151  		)
   152  
   153  		err := m.MeterComputation(compKind, 1)
   154  		require.NoError(t, err)
   155  
   156  		child1 := meter.NewMeter(m.MeterParameters)
   157  		err = child1.MeterComputation(compKind, 2)
   158  		require.NoError(t, err)
   159  
   160  		child2 := meter.NewMeter(m.MeterParameters)
   161  		err = child2.MeterComputation(compKind, 3)
   162  		require.NoError(t, err)
   163  
   164  		child3 := meter.NewMeter(m.MeterParameters)
   165  		err = child3.MeterComputation(compKind, 4)
   166  		require.NoError(t, err)
   167  
   168  		m.MergeMeter(child1)
   169  		require.Equal(t, uint64(1+2), m.TotalComputationUsed())
   170  		require.Equal(t, uint(1+2), m.ComputationIntensities()[compKind])
   171  
   172  		m.MergeMeter(child2)
   173  		require.Equal(t, uint64(1+2+3), m.TotalComputationUsed())
   174  		require.Equal(t, uint(1+2+3), m.ComputationIntensities()[compKind])
   175  
   176  		// merge hits limit, but is accepted.
   177  		m.MergeMeter(child3)
   178  		require.Equal(t, uint64(1+2+3+4), m.TotalComputationUsed())
   179  		require.Equal(t, uint(1+2+3+4), m.ComputationIntensities()[compKind])
   180  
   181  		// error after merge (hitting limit)
   182  		err = m.MeterComputation(compKind, 0)
   183  		require.Error(t, err)
   184  		require.True(t, errors.IsComputationLimitExceededError(err))
   185  		require.Equal(t, err.Error(), errors.NewComputationLimitExceededError(9).Error())
   186  	})
   187  
   188  	t.Run("merge meters - ignore limits", func(t *testing.T) {
   189  		compKind := common.ComputationKind(0)
   190  		m := meter.NewMeter(
   191  			meter.DefaultParameters().
   192  				WithComputationLimit(9).
   193  				WithMemoryLimit(0).
   194  				WithComputationWeights(map[common.ComputationKind]uint64{0: 1 << meter.MeterExecutionInternalPrecisionBytes}),
   195  		)
   196  
   197  		err := m.MeterComputation(compKind, 1)
   198  		require.NoError(t, err)
   199  
   200  		child := meter.NewMeter(m.MeterParameters)
   201  		err = child.MeterComputation(compKind, 1)
   202  		require.NoError(t, err)
   203  
   204  		// hitting limit and ignoring it
   205  		m.MergeMeter(child)
   206  		require.Equal(t, uint64(1+1), m.TotalComputationUsed())
   207  		require.Equal(t, uint(1+1), m.ComputationIntensities()[compKind])
   208  	})
   209  
   210  	t.Run("merge meters - large values - computation", func(t *testing.T) {
   211  		m := meter.NewMeter(
   212  			meter.DefaultParameters().
   213  				WithComputationLimit(math.MaxUint32).
   214  				WithComputationWeights(map[common.ComputationKind]uint64{
   215  					0: math.MaxUint32 << meter.MeterExecutionInternalPrecisionBytes,
   216  				}),
   217  		)
   218  
   219  		err := m.MeterComputation(0, 1)
   220  		require.NoError(t, err)
   221  
   222  		child1 := meter.NewMeter(m.MeterParameters)
   223  		err = child1.MeterComputation(0, 1)
   224  		require.NoError(t, err)
   225  
   226  		m.MergeMeter(child1)
   227  
   228  		err = m.MeterComputation(0, 0)
   229  		require.True(t, errors.IsComputationLimitExceededError(err))
   230  	})
   231  
   232  	t.Run("merge meters - large values - memory", func(t *testing.T) {
   233  		m := meter.NewMeter(
   234  			meter.DefaultParameters().
   235  				WithMemoryLimit(math.MaxUint32).
   236  				WithMemoryWeights(map[common.MemoryKind]uint64{
   237  					0: math.MaxUint32,
   238  				}),
   239  		)
   240  
   241  		err := m.MeterMemory(0, 1)
   242  		require.NoError(t, err)
   243  
   244  		child1 := meter.NewMeter(m.MeterParameters)
   245  		err = child1.MeterMemory(0, 1)
   246  		require.NoError(t, err)
   247  
   248  		m.MergeMeter(child1)
   249  
   250  		err = m.MeterMemory(0, 0)
   251  		require.Error(t, err)
   252  		require.True(t, errors.IsMemoryLimitExceededError(err))
   253  		require.Equal(t, err.Error(), errors.NewMemoryLimitExceededError(math.MaxUint32).Error())
   254  	})
   255  
   256  	t.Run("add intensity - test limits - computation", func(t *testing.T) {
   257  		var m *meter.Meter
   258  		reset := func() {
   259  			m = meter.NewMeter(
   260  				meter.DefaultParameters().
   261  					WithComputationLimit(math.MaxUint32).
   262  					WithComputationWeights(map[common.ComputationKind]uint64{
   263  						0: 0,
   264  						1: 1,
   265  						2: 1 << meter.MeterExecutionInternalPrecisionBytes,
   266  						3: math.MaxUint64,
   267  					}),
   268  			)
   269  		}
   270  
   271  		reset()
   272  		err := m.MeterComputation(0, 1)
   273  		require.NoError(t, err)
   274  		require.Equal(t, uint64(0), m.TotalComputationUsed())
   275  		reset()
   276  		err = m.MeterComputation(0, 1<<meter.MeterExecutionInternalPrecisionBytes)
   277  		require.NoError(t, err)
   278  		require.Equal(t, uint64(0), m.TotalComputationUsed())
   279  		reset()
   280  		err = m.MeterComputation(0, math.MaxUint32)
   281  		require.NoError(t, err)
   282  		require.Equal(t, uint64(0), m.TotalComputationUsed())
   283  
   284  		reset()
   285  		err = m.MeterComputation(1, 1)
   286  		require.NoError(t, err)
   287  		require.Equal(t, uint64(0), m.TotalComputationUsed())
   288  		reset()
   289  		err = m.MeterComputation(1, 1<<meter.MeterExecutionInternalPrecisionBytes)
   290  		require.NoError(t, err)
   291  		require.Equal(t, uint64(1), m.TotalComputationUsed())
   292  		reset()
   293  		err = m.MeterComputation(1, math.MaxUint32)
   294  		require.NoError(t, err)
   295  		require.Equal(t, uint64(1<<16-1), m.TotalComputationUsed())
   296  
   297  		reset()
   298  		err = m.MeterComputation(2, 1)
   299  		require.NoError(t, err)
   300  		require.Equal(t, uint64(1), m.TotalComputationUsed())
   301  		reset()
   302  		err = m.MeterComputation(2, 1<<meter.MeterExecutionInternalPrecisionBytes)
   303  		require.NoError(t, err)
   304  		require.Equal(t, uint64(1<<16), m.TotalComputationUsed())
   305  		reset()
   306  		err = m.MeterComputation(2, math.MaxUint32)
   307  		require.NoError(t, err)
   308  		require.Equal(t, uint64(math.MaxUint32), m.TotalComputationUsed())
   309  
   310  		reset()
   311  		err = m.MeterComputation(3, 1)
   312  		require.True(t, errors.IsComputationLimitExceededError(err))
   313  		reset()
   314  		err = m.MeterComputation(3, 1<<meter.MeterExecutionInternalPrecisionBytes)
   315  		require.True(t, errors.IsComputationLimitExceededError(err))
   316  		reset()
   317  		err = m.MeterComputation(3, math.MaxUint32)
   318  		require.True(t, errors.IsComputationLimitExceededError(err))
   319  	})
   320  
   321  	t.Run("add intensity - test limits - memory", func(t *testing.T) {
   322  		var m *meter.Meter
   323  		reset := func() {
   324  			m = meter.NewMeter(
   325  				meter.DefaultParameters().
   326  					WithMemoryLimit(math.MaxUint32).
   327  					WithMemoryWeights(map[common.MemoryKind]uint64{
   328  						0: 0,
   329  						1: 1,
   330  						2: 2,
   331  						3: math.MaxUint64,
   332  					}),
   333  			)
   334  		}
   335  
   336  		reset()
   337  		err := m.MeterMemory(0, 1)
   338  		require.NoError(t, err)
   339  		require.Equal(t, uint64(0), m.TotalMemoryEstimate())
   340  		reset()
   341  		err = m.MeterMemory(0, 1)
   342  		require.NoError(t, err)
   343  		require.Equal(t, uint64(0), m.TotalMemoryEstimate())
   344  		reset()
   345  		err = m.MeterMemory(0, math.MaxUint32)
   346  		require.NoError(t, err)
   347  		require.Equal(t, uint64(0), m.TotalMemoryEstimate())
   348  
   349  		reset()
   350  		err = m.MeterMemory(1, 1)
   351  		require.NoError(t, err)
   352  		require.Equal(t, uint64(1), m.TotalMemoryEstimate())
   353  		reset()
   354  		err = m.MeterMemory(1, 1)
   355  		require.NoError(t, err)
   356  		require.Equal(t, uint64(1), m.TotalMemoryEstimate())
   357  		reset()
   358  		err = m.MeterMemory(1, math.MaxUint32)
   359  		require.NoError(t, err)
   360  		require.Equal(t, uint64(math.MaxUint32), m.TotalMemoryEstimate())
   361  
   362  		reset()
   363  		err = m.MeterMemory(2, 1)
   364  		require.NoError(t, err)
   365  		require.Equal(t, uint64(2), m.TotalMemoryEstimate())
   366  		reset()
   367  		err = m.MeterMemory(2, 1)
   368  		require.NoError(t, err)
   369  		require.Equal(t, uint64(2), m.TotalMemoryEstimate())
   370  		reset()
   371  		err = m.MeterMemory(2, math.MaxUint32)
   372  		require.True(t, errors.IsMemoryLimitExceededError(err))
   373  
   374  		reset()
   375  		err = m.MeterMemory(3, 1)
   376  		require.True(t, errors.IsMemoryLimitExceededError(err))
   377  		reset()
   378  		err = m.MeterMemory(3, 1)
   379  		require.True(t, errors.IsMemoryLimitExceededError(err))
   380  		reset()
   381  		err = m.MeterMemory(3, math.MaxUint32)
   382  		require.True(t, errors.IsMemoryLimitExceededError(err))
   383  	})
   384  }
   385  
   386  func TestMemoryWeights(t *testing.T) {
   387  	for kind := common.MemoryKindUnknown + 1; kind < common.MemoryKindLast; kind++ {
   388  		weight, ok := meter.DefaultMemoryWeights[kind]
   389  		if !assert.True(t, ok, fmt.Sprintf("missing weight for memory kind '%s'", kind.String())) {
   390  			continue
   391  		}
   392  		assert.Greater(
   393  			t,
   394  			weight,
   395  			uint64(0),
   396  			fmt.Sprintf(
   397  				"weight for memory kind '%s' is not a positive integer: %d",
   398  				kind.String(),
   399  				weight,
   400  			),
   401  		)
   402  	}
   403  }
   404  
   405  func TestStorageLimits(t *testing.T) {
   406  	t.Run("metering storage read - within limit", func(t *testing.T) {
   407  		meter1 := meter.NewMeter(
   408  			meter.DefaultParameters(),
   409  		)
   410  
   411  		key1 := flow.NewRegisterID(flow.EmptyAddress, "1")
   412  		val1 := []byte{0x1, 0x2, 0x3}
   413  		size1 := meter.GetStorageKeyValueSizeForTesting(key1, val1)
   414  
   415  		// first read of key1
   416  		err := meter1.MeterStorageRead(key1, val1, false)
   417  		require.NoError(t, err)
   418  		require.Equal(t, meter1.TotalBytesReadFromStorage(), size1)
   419  
   420  		// second read of key1
   421  		err = meter1.MeterStorageRead(key1, val1, false)
   422  		require.NoError(t, err)
   423  		require.Equal(t, meter1.TotalBytesReadFromStorage(), size1)
   424  
   425  		// first read of key2
   426  		key2 := flow.NewRegisterID(flow.EmptyAddress, "2")
   427  		val2 := []byte{0x3, 0x2, 0x1}
   428  		size2 := meter.GetStorageKeyValueSizeForTesting(key2, val2)
   429  
   430  		err = meter1.MeterStorageRead(key2, val2, false)
   431  		require.NoError(t, err)
   432  		require.Equal(t, meter1.TotalBytesReadFromStorage(), size1+size2)
   433  	})
   434  
   435  	t.Run("metering storage written - within limit", func(t *testing.T) {
   436  		meter1 := meter.NewMeter(
   437  			meter.DefaultParameters(),
   438  		)
   439  
   440  		key1 := flow.NewRegisterID(flow.EmptyAddress, "1")
   441  		val1 := []byte{0x1, 0x2, 0x3}
   442  		val2 := []byte{0x1, 0x2, 0x3, 0x4}
   443  
   444  		// first write of key1
   445  		err := meter1.MeterStorageWrite(key1, val1, false)
   446  		require.NoError(t, err)
   447  		require.Equal(t, meter1.TotalBytesWrittenToStorage(), meter.GetStorageKeyValueSizeForTesting(key1, val1))
   448  
   449  		// second write of key1 with val2
   450  		err = meter1.MeterStorageWrite(key1, val2, false)
   451  		require.NoError(t, err)
   452  		require.Equal(t, meter1.TotalBytesWrittenToStorage(), meter.GetStorageKeyValueSizeForTesting(key1, val2))
   453  
   454  		// first write of key2
   455  		key2 := flow.NewRegisterID(flow.EmptyAddress, "2")
   456  		err = meter1.MeterStorageWrite(key2, val2, false)
   457  		require.NoError(t, err)
   458  		require.Equal(t, meter1.TotalBytesWrittenToStorage(),
   459  			meter.GetStorageKeyValueSizeForTesting(key1, val2)+meter.GetStorageKeyValueSizeForTesting(key2, val2))
   460  	})
   461  
   462  	t.Run("metering storage read - exceeding limit - not enforced", func(t *testing.T) {
   463  		meter1 := meter.NewMeter(
   464  			meter.DefaultParameters().WithStorageInteractionLimit(1),
   465  		)
   466  
   467  		key1 := flow.NewRegisterID(flow.EmptyAddress, "1")
   468  		val1 := []byte{0x1, 0x2, 0x3}
   469  
   470  		err := meter1.MeterStorageRead(key1, val1, false /* not enforced */)
   471  		require.NoError(t, err)
   472  		require.Equal(t, meter1.TotalBytesReadFromStorage(), meter.GetStorageKeyValueSizeForTesting(key1, val1))
   473  	})
   474  
   475  	t.Run("metering storage read - exceeding limit - enforced", func(t *testing.T) {
   476  		testLimit := uint64(1)
   477  		meter1 := meter.NewMeter(
   478  			meter.DefaultParameters().WithStorageInteractionLimit(testLimit),
   479  		)
   480  
   481  		key1 := flow.NewRegisterID(flow.EmptyAddress, "1")
   482  		val1 := []byte{0x1, 0x2, 0x3}
   483  
   484  		err := meter1.MeterStorageRead(key1, val1, true /* enforced */)
   485  
   486  		ledgerInteractionLimitExceedError := errors.NewLedgerInteractionLimitExceededError(
   487  			meter.GetStorageKeyValueSizeForTesting(key1, val1),
   488  			testLimit,
   489  		)
   490  		require.ErrorAs(t, err, &ledgerInteractionLimitExceedError)
   491  	})
   492  
   493  	t.Run("metering storage written - exceeding limit - not enforced", func(t *testing.T) {
   494  		testLimit := uint64(1)
   495  		meter1 := meter.NewMeter(
   496  			meter.DefaultParameters().WithStorageInteractionLimit(testLimit),
   497  		)
   498  
   499  		key1 := flow.NewRegisterID(flow.EmptyAddress, "1")
   500  		val1 := []byte{0x1, 0x2, 0x3}
   501  
   502  		err := meter1.MeterStorageWrite(key1, val1, false /* not enforced */)
   503  		require.NoError(t, err)
   504  	})
   505  
   506  	t.Run("metering storage written - exceeding limit - enforced", func(t *testing.T) {
   507  		testLimit := uint64(1)
   508  		meter1 := meter.NewMeter(
   509  			meter.DefaultParameters().WithStorageInteractionLimit(testLimit),
   510  		)
   511  
   512  		key1 := flow.NewRegisterID(flow.EmptyAddress, "1")
   513  		val1 := []byte{0x1, 0x2, 0x3}
   514  
   515  		err := meter1.MeterStorageWrite(key1, val1, true /* enforced */)
   516  
   517  		ledgerInteractionLimitExceedError := errors.NewLedgerInteractionLimitExceededError(
   518  			meter.GetStorageKeyValueSizeForTesting(key1, val1),
   519  			testLimit,
   520  		)
   521  		require.ErrorAs(t, err, &ledgerInteractionLimitExceedError)
   522  	})
   523  
   524  	t.Run("metering storage read and written - within limit", func(t *testing.T) {
   525  		meter1 := meter.NewMeter(
   526  			meter.DefaultParameters(),
   527  		)
   528  
   529  		key1 := flow.NewRegisterID(flow.EmptyAddress, "1")
   530  		key2 := flow.NewRegisterID(flow.EmptyAddress, "2")
   531  		val1 := []byte{0x1, 0x2, 0x3}
   532  		val2 := []byte{0x1, 0x2, 0x3, 0x4}
   533  		size1 := meter.GetStorageKeyValueSizeForTesting(key1, val1)
   534  		size2 := meter.GetStorageKeyValueSizeForTesting(key2, val2)
   535  
   536  		// read of key1
   537  		err := meter1.MeterStorageRead(key1, val1, false)
   538  		require.NoError(t, err)
   539  		require.Equal(t, meter1.TotalBytesReadFromStorage(), size1)
   540  		require.Equal(t, meter1.TotalBytesOfStorageInteractions(), size1)
   541  
   542  		// write of key2
   543  		err = meter1.MeterStorageWrite(key2, val2, false)
   544  		require.NoError(t, err)
   545  		require.Equal(t, meter1.TotalBytesWrittenToStorage(), size2)
   546  		require.Equal(t, meter1.TotalBytesOfStorageInteractions(), size1+size2)
   547  	})
   548  
   549  	t.Run("metering storage read and written - exceeding limit - not enforced", func(t *testing.T) {
   550  		key1 := flow.NewRegisterID(flow.EmptyAddress, "1")
   551  		key2 := flow.NewRegisterID(flow.EmptyAddress, "2")
   552  		val1 := []byte{0x1, 0x2, 0x3}
   553  		val2 := []byte{0x1, 0x2, 0x3, 0x4}
   554  		size1 := meter.GetStorageKeyValueSizeForTesting(key1, val1)
   555  		size2 := meter.GetStorageKeyValueSizeForTesting(key2, val2)
   556  
   557  		meter1 := meter.NewMeter(
   558  			meter.DefaultParameters().WithStorageInteractionLimit(size1 + size2 - 1),
   559  		)
   560  
   561  		// read of key1
   562  		err := meter1.MeterStorageRead(key1, val1, false)
   563  		require.NoError(t, err)
   564  		require.Equal(t, meter1.TotalBytesReadFromStorage(), size1)
   565  		require.Equal(t, meter1.TotalBytesOfStorageInteractions(), size1)
   566  
   567  		// write of key2
   568  		err = meter1.MeterStorageWrite(key2, val2, false)
   569  		require.NoError(t, err)
   570  		require.Equal(t, meter1.TotalBytesWrittenToStorage(), size2)
   571  		require.Equal(t, meter1.TotalBytesOfStorageInteractions(), size1+size2)
   572  	})
   573  
   574  	t.Run("metering storage read and written - exceeding limit - enforced", func(t *testing.T) {
   575  		key1 := flow.NewRegisterID(flow.EmptyAddress, "1")
   576  		key2 := flow.NewRegisterID(flow.EmptyAddress, "2")
   577  		val1 := []byte{0x1, 0x2, 0x3}
   578  		val2 := []byte{0x1, 0x2, 0x3, 0x4}
   579  		size1 := meter.GetStorageKeyValueSizeForTesting(key1, val1)
   580  		size2 := meter.GetStorageKeyValueSizeForTesting(key2, val2)
   581  		testLimit := size1 + size2 - 1
   582  		meter1 := meter.NewMeter(
   583  			meter.DefaultParameters().WithStorageInteractionLimit(testLimit),
   584  		)
   585  
   586  		// read of key1
   587  		err := meter1.MeterStorageRead(key1, val1, true)
   588  		require.NoError(t, err)
   589  		require.Equal(t, meter1.TotalBytesReadFromStorage(), size1)
   590  		require.Equal(t, meter1.TotalBytesOfStorageInteractions(), size1)
   591  
   592  		// write of key2
   593  		err = meter1.MeterStorageWrite(key2, val2, true)
   594  		ledgerInteractionLimitExceedError := errors.NewLedgerInteractionLimitExceededError(
   595  			size1+size2,
   596  			testLimit,
   597  		)
   598  		require.ErrorAs(t, err, &ledgerInteractionLimitExceedError)
   599  	})
   600  
   601  	t.Run("merge storage metering", func(t *testing.T) {
   602  		// meter 1
   603  		meter1 := meter.NewMeter(
   604  			meter.DefaultParameters(),
   605  		)
   606  		readKey1 := flow.NewRegisterID(flow.EmptyAddress, "r1")
   607  		readVal1 := []byte{0x1, 0x2, 0x3}
   608  		readSize1 := meter.GetStorageKeyValueSizeForTesting(readKey1, readVal1)
   609  		err := meter1.MeterStorageRead(readKey1, readVal1, false)
   610  		require.NoError(t, err)
   611  
   612  		writeKey1 := flow.NewRegisterID(flow.EmptyAddress, "w1")
   613  		writeVal1 := []byte{0x1, 0x2, 0x3, 0x4}
   614  		writeSize1 := meter.GetStorageKeyValueSizeForTesting(writeKey1, writeVal1)
   615  		err = meter1.MeterStorageWrite(writeKey1, writeVal1, false)
   616  		require.NoError(t, err)
   617  
   618  		// meter 2
   619  		meter2 := meter.NewMeter(
   620  			meter.DefaultParameters(),
   621  		)
   622  
   623  		writeKey2 := flow.NewRegisterID(flow.EmptyAddress, "w2")
   624  		writeVal2 := []byte{0x1, 0x2, 0x3, 0x4, 0x5}
   625  		writeSize2 := meter.GetStorageKeyValueSizeForTesting(writeKey2, writeVal2)
   626  
   627  		err = meter1.MeterStorageRead(readKey1, readVal1, false)
   628  		require.NoError(t, err)
   629  
   630  		err = meter1.MeterStorageWrite(writeKey1, writeVal1, false)
   631  		require.NoError(t, err)
   632  
   633  		// read the same key value as meter1
   634  		err = meter2.MeterStorageRead(readKey1, readVal1, false)
   635  		require.NoError(t, err)
   636  
   637  		err = meter2.MeterStorageWrite(writeKey2, writeVal2, false)
   638  		require.NoError(t, err)
   639  
   640  		// merge
   641  		meter1.MergeMeter(meter2)
   642  
   643  		require.Equal(t, meter1.TotalBytesOfStorageInteractions(), readSize1+writeSize1+writeSize2)
   644  		require.Equal(t, meter1.TotalBytesReadFromStorage(), readSize1)
   645  		require.Equal(t, meter1.TotalBytesWrittenToStorage(), writeSize1+writeSize2)
   646  
   647  		reads, writes := meter1.GetStorageRWSizeMapForTesting()
   648  		readKey1Val, ok := reads[readKey1]
   649  		require.True(t, ok)
   650  		require.Equal(t, readKey1Val, readSize1) // meter merge only takes child values for rw bookkeeping
   651  
   652  		writeKey1Val, ok := writes[writeKey1]
   653  		require.True(t, ok)
   654  		require.Equal(t, writeKey1Val, writeSize1)
   655  
   656  		writeKey2Val, ok := writes[writeKey2]
   657  		require.True(t, ok)
   658  		require.Equal(t, writeKey2Val, writeSize2)
   659  	})
   660  }
   661  
   662  func TestEventLimits(t *testing.T) {
   663  	t.Run("metering event emit - within limit", func(t *testing.T) {
   664  		meter1 := meter.NewMeter(
   665  			meter.DefaultParameters(),
   666  		)
   667  
   668  		testSize1, testSize2 := uint64(123), uint64(234)
   669  
   670  		err := meter1.MeterEmittedEvent(testSize1)
   671  		require.NoError(t, err)
   672  		require.Equal(t, testSize1, meter1.TotalEmittedEventBytes())
   673  
   674  		err = meter1.MeterEmittedEvent(testSize2)
   675  		require.NoError(t, err)
   676  		require.Equal(t, testSize1+testSize2, meter1.TotalEmittedEventBytes())
   677  	})
   678  
   679  	t.Run("metering event emit - exceeding limit", func(t *testing.T) {
   680  		testSize1, testSize2 := uint64(123), uint64(234)
   681  		testEventLimit := testSize1 + testSize2 - 1 // make it fail at 2nd meter
   682  		meter1 := meter.NewMeter(
   683  			meter.DefaultParameters().WithEventEmitByteLimit(testEventLimit),
   684  		)
   685  
   686  		err := meter1.MeterEmittedEvent(testSize1)
   687  		require.NoError(t, err)
   688  		require.Equal(t, testSize1, meter1.TotalEmittedEventBytes())
   689  
   690  		err = meter1.MeterEmittedEvent(testSize2)
   691  		eventLimitExceededError := errors.NewEventLimitExceededError(
   692  			testSize1+testSize2,
   693  			testEventLimit)
   694  		require.ErrorAs(t, err, &eventLimitExceededError)
   695  	})
   696  
   697  	t.Run("merge event metering", func(t *testing.T) {
   698  		// meter 1
   699  		meter1 := meter.NewMeter(
   700  			meter.DefaultParameters(),
   701  		)
   702  		testSize1 := uint64(123)
   703  		err := meter1.MeterEmittedEvent(testSize1)
   704  		require.NoError(t, err)
   705  
   706  		// meter 2
   707  		meter2 := meter.NewMeter(
   708  			meter.DefaultParameters(),
   709  		)
   710  		testSize2 := uint64(234)
   711  		err = meter2.MeterEmittedEvent(testSize2)
   712  		require.NoError(t, err)
   713  
   714  		// merge
   715  		meter1.MergeMeter(meter2)
   716  		require.Equal(t, testSize1+testSize2, meter1.TotalEmittedEventBytes())
   717  	})
   718  }