github.com/onflow/flow-go@v0.33.17/fvm/evm/testutils/backend.go (about)

     1  package testutils
     2  
     3  import (
     4  	"encoding/binary"
     5  	"fmt"
     6  	"math"
     7  	"testing"
     8  
     9  	"github.com/onflow/atree"
    10  	"github.com/onflow/cadence"
    11  	jsoncdc "github.com/onflow/cadence/encoding/json"
    12  	"github.com/onflow/cadence/runtime/common"
    13  	"github.com/stretchr/testify/require"
    14  	"golang.org/x/exp/maps"
    15  
    16  	"github.com/onflow/flow-go/fvm/environment"
    17  	"github.com/onflow/flow-go/fvm/meter"
    18  	"github.com/onflow/flow-go/model/flow"
    19  )
    20  
    21  var TestFlowEVMRootAddress = flow.BytesToAddress([]byte("FlowEVM"))
    22  var TestComputationLimit = uint(math.MaxUint64 - 1)
    23  
    24  func RunWithTestFlowEVMRootAddress(t testing.TB, backend atree.Ledger, f func(flow.Address)) {
    25  	as := environment.NewAccountStatus()
    26  	err := backend.SetValue(TestFlowEVMRootAddress[:], []byte(flow.AccountStatusKey), as.ToBytes())
    27  	require.NoError(t, err)
    28  	f(TestFlowEVMRootAddress)
    29  }
    30  
    31  func RunWithTestBackend(t testing.TB, f func(*TestBackend)) {
    32  	tb := &TestBackend{
    33  		TestValueStore:   GetSimpleValueStore(),
    34  		testEventEmitter: getSimpleEventEmitter(),
    35  		testMeter:        getSimpleMeter(),
    36  	}
    37  	f(tb)
    38  }
    39  
    40  func ConvertToCadence(data []byte) []cadence.Value {
    41  	ret := make([]cadence.Value, len(data))
    42  	for i, v := range data {
    43  		ret[i] = cadence.UInt8(v)
    44  	}
    45  	return ret
    46  }
    47  
    48  func fullKey(owner, key []byte) string {
    49  	return string(owner) + "~" + string(key)
    50  }
    51  
    52  func GetSimpleValueStore() *TestValueStore {
    53  	data := make(map[string][]byte)
    54  	allocator := make(map[string]uint64)
    55  	bytesRead := 0
    56  	bytesWritten := 0
    57  	return &TestValueStore{
    58  		GetValueFunc: func(owner, key []byte) ([]byte, error) {
    59  			fk := fullKey(owner, key)
    60  			value := data[fk]
    61  			bytesRead += len(fk) + len(value)
    62  			return value, nil
    63  		},
    64  		SetValueFunc: func(owner, key, value []byte) error {
    65  			fk := fullKey(owner, key)
    66  			data[fk] = value
    67  			bytesWritten += len(fk) + len(value)
    68  			return nil
    69  		},
    70  		ValueExistsFunc: func(owner, key []byte) (bool, error) {
    71  			fk := fullKey(owner, key)
    72  			value := data[fk]
    73  			bytesRead += len(fk) + len(value)
    74  			return len(value) > 0, nil
    75  		},
    76  		AllocateStorageIndexFunc: func(owner []byte) (atree.StorageIndex, error) {
    77  			index := allocator[string(owner)]
    78  			var data [8]byte
    79  			allocator[string(owner)] = index + 1
    80  			binary.BigEndian.PutUint64(data[:], index)
    81  			bytesRead += len(owner) + 8
    82  			bytesWritten += len(owner) + 8
    83  			return atree.StorageIndex(data), nil
    84  		},
    85  		TotalStorageSizeFunc: func() int {
    86  			size := 0
    87  			for key, item := range data {
    88  				size += len(item) + len([]byte(key))
    89  			}
    90  			for key := range allocator {
    91  				size += len(key) + 8
    92  			}
    93  			return size
    94  		},
    95  		TotalBytesReadFunc: func() int {
    96  			return bytesRead
    97  		},
    98  		TotalBytesWrittenFunc: func() int {
    99  			return bytesWritten
   100  		},
   101  		TotalStorageItemsFunc: func() int {
   102  			return len(maps.Keys(data)) + len(maps.Keys(allocator))
   103  		},
   104  		ResetStatsFunc: func() {
   105  			bytesRead = 0
   106  			bytesWritten = 0
   107  		},
   108  	}
   109  }
   110  
   111  func getSimpleEventEmitter() *testEventEmitter {
   112  	events := make(flow.EventsList, 0)
   113  	return &testEventEmitter{
   114  		emitEvent: func(event cadence.Event) error {
   115  			payload, err := jsoncdc.Encode(event)
   116  			if err != nil {
   117  				return err
   118  			}
   119  
   120  			events = append(events, flow.Event{Type: flow.EventType(event.EventType.QualifiedIdentifier), Payload: payload})
   121  			return nil
   122  		},
   123  		events: func() flow.EventsList {
   124  			return events
   125  		},
   126  		reset: func() {
   127  			events = make(flow.EventsList, 0)
   128  		},
   129  	}
   130  }
   131  
   132  func getSimpleMeter() *testMeter {
   133  	computationLimit := TestComputationLimit
   134  	compUsed := uint(0)
   135  	return &testMeter{
   136  		meterComputation: func(kind common.ComputationKind, intensity uint) error {
   137  			compUsed += intensity
   138  			if compUsed > computationLimit {
   139  				return fmt.Errorf("computation limit has hit %d", computationLimit)
   140  			}
   141  			return nil
   142  		},
   143  		hasComputationCapacity: func(kind common.ComputationKind, intensity uint) bool {
   144  			return compUsed+intensity < computationLimit
   145  		},
   146  		computationUsed: func() (uint64, error) {
   147  			return uint64(compUsed), nil
   148  		},
   149  	}
   150  }
   151  
   152  type TestBackend struct {
   153  	*TestValueStore
   154  	*testMeter
   155  	*testEventEmitter
   156  }
   157  
   158  func (tb *TestBackend) TotalStorageSize() int {
   159  	if tb.TotalStorageSizeFunc == nil {
   160  		panic("method not set")
   161  	}
   162  	return tb.TotalStorageSizeFunc()
   163  }
   164  
   165  func (tb *TestBackend) DropEvents() {
   166  	if tb.reset == nil {
   167  		panic("method not set")
   168  	}
   169  	tb.reset()
   170  }
   171  
   172  type TestValueStore struct {
   173  	GetValueFunc             func(owner, key []byte) ([]byte, error)
   174  	SetValueFunc             func(owner, key, value []byte) error
   175  	ValueExistsFunc          func(owner, key []byte) (bool, error)
   176  	AllocateStorageIndexFunc func(owner []byte) (atree.StorageIndex, error)
   177  	TotalStorageSizeFunc     func() int
   178  	TotalBytesReadFunc       func() int
   179  	TotalBytesWrittenFunc    func() int
   180  	TotalStorageItemsFunc    func() int
   181  	ResetStatsFunc           func()
   182  }
   183  
   184  var _ environment.ValueStore = &TestValueStore{}
   185  
   186  func (vs *TestValueStore) GetValue(owner, key []byte) ([]byte, error) {
   187  	if vs.GetValueFunc == nil {
   188  		panic("method not set")
   189  	}
   190  	return vs.GetValueFunc(owner, key)
   191  }
   192  
   193  func (vs *TestValueStore) SetValue(owner, key, value []byte) error {
   194  	if vs.SetValueFunc == nil {
   195  		panic("method not set")
   196  	}
   197  	return vs.SetValueFunc(owner, key, value)
   198  }
   199  
   200  func (vs *TestValueStore) ValueExists(owner, key []byte) (bool, error) {
   201  	if vs.ValueExistsFunc == nil {
   202  		panic("method not set")
   203  	}
   204  	return vs.ValueExistsFunc(owner, key)
   205  }
   206  
   207  func (vs *TestValueStore) AllocateStorageIndex(owner []byte) (atree.StorageIndex, error) {
   208  	if vs.AllocateStorageIndexFunc == nil {
   209  		panic("method not set")
   210  	}
   211  	return vs.AllocateStorageIndexFunc(owner)
   212  }
   213  
   214  func (vs *TestValueStore) TotalBytesRead() int {
   215  	if vs.TotalBytesReadFunc == nil {
   216  		panic("method not set")
   217  	}
   218  	return vs.TotalBytesReadFunc()
   219  }
   220  
   221  func (vs *TestValueStore) TotalBytesWritten() int {
   222  	if vs.TotalBytesWrittenFunc == nil {
   223  		panic("method not set")
   224  	}
   225  	return vs.TotalBytesWrittenFunc()
   226  }
   227  
   228  func (vs *TestValueStore) TotalStorageSize() int {
   229  	if vs.TotalStorageSizeFunc == nil {
   230  		panic("method not set")
   231  	}
   232  	return vs.TotalStorageSizeFunc()
   233  }
   234  
   235  func (vs *TestValueStore) TotalStorageItems() int {
   236  	if vs.TotalStorageItemsFunc == nil {
   237  		panic("method not set")
   238  	}
   239  	return vs.TotalStorageItemsFunc()
   240  }
   241  
   242  func (vs *TestValueStore) ResetStats() {
   243  	if vs.ResetStatsFunc == nil {
   244  		panic("method not set")
   245  	}
   246  	vs.ResetStatsFunc()
   247  }
   248  
   249  type testMeter struct {
   250  	meterComputation       func(common.ComputationKind, uint) error
   251  	hasComputationCapacity func(common.ComputationKind, uint) bool
   252  	computationUsed        func() (uint64, error)
   253  	computationIntensities func() meter.MeteredComputationIntensities
   254  
   255  	meterMemory func(usage common.MemoryUsage) error
   256  	memoryUsed  func() (uint64, error)
   257  
   258  	meterEmittedEvent      func(byteSize uint64) error
   259  	totalEmittedEventBytes func() uint64
   260  
   261  	interactionUsed func() (uint64, error)
   262  }
   263  
   264  var _ environment.Meter = &testMeter{}
   265  
   266  func (m *testMeter) MeterComputation(
   267  	kind common.ComputationKind,
   268  	intensity uint,
   269  ) error {
   270  	if m.meterComputation == nil {
   271  		panic("method not set")
   272  	}
   273  	return m.meterComputation(kind, intensity)
   274  }
   275  
   276  func (m *testMeter) ComputationAvailable(
   277  	kind common.ComputationKind,
   278  	intensity uint,
   279  ) bool {
   280  	if m.hasComputationCapacity == nil {
   281  		panic("method not set")
   282  	}
   283  	return m.hasComputationCapacity(kind, intensity)
   284  }
   285  
   286  func (m *testMeter) ComputationIntensities() meter.MeteredComputationIntensities {
   287  	if m.computationIntensities == nil {
   288  		panic("method not set")
   289  	}
   290  	return m.computationIntensities()
   291  }
   292  
   293  func (m *testMeter) ComputationUsed() (uint64, error) {
   294  	if m.computationUsed == nil {
   295  		panic("method not set")
   296  	}
   297  	return m.computationUsed()
   298  }
   299  
   300  func (m *testMeter) MeterMemory(usage common.MemoryUsage) error {
   301  	if m.meterMemory == nil {
   302  		panic("method not set")
   303  	}
   304  	return m.meterMemory(usage)
   305  }
   306  
   307  func (m *testMeter) MemoryUsed() (uint64, error) {
   308  	if m.memoryUsed == nil {
   309  		panic("method not set")
   310  	}
   311  	return m.memoryUsed()
   312  }
   313  
   314  func (m *testMeter) InteractionUsed() (uint64, error) {
   315  	if m.interactionUsed == nil {
   316  		panic("method not set")
   317  	}
   318  	return m.interactionUsed()
   319  }
   320  
   321  func (m *testMeter) MeterEmittedEvent(byteSize uint64) error {
   322  	if m.meterEmittedEvent == nil {
   323  		panic("method not set")
   324  	}
   325  	return m.meterEmittedEvent(byteSize)
   326  }
   327  
   328  func (m *testMeter) TotalEmittedEventBytes() uint64 {
   329  	if m.totalEmittedEventBytes == nil {
   330  		panic("method not set")
   331  	}
   332  	return m.totalEmittedEventBytes()
   333  }
   334  
   335  type testEventEmitter struct {
   336  	emitEvent              func(event cadence.Event) error
   337  	events                 func() flow.EventsList
   338  	serviceEvents          func() flow.EventsList
   339  	convertedServiceEvents func() flow.ServiceEventList
   340  	reset                  func()
   341  }
   342  
   343  var _ environment.EventEmitter = &testEventEmitter{}
   344  
   345  func (vs *testEventEmitter) EmitEvent(event cadence.Event) error {
   346  	if vs.emitEvent == nil {
   347  		panic("method not set")
   348  	}
   349  	return vs.emitEvent(event)
   350  }
   351  
   352  func (vs *testEventEmitter) Events() flow.EventsList {
   353  	if vs.events == nil {
   354  		panic("method not set")
   355  	}
   356  	return vs.events()
   357  }
   358  
   359  func (vs *testEventEmitter) ServiceEvents() flow.EventsList {
   360  	if vs.serviceEvents == nil {
   361  		panic("method not set")
   362  	}
   363  	return vs.serviceEvents()
   364  }
   365  
   366  func (vs *testEventEmitter) ConvertedServiceEvents() flow.ServiceEventList {
   367  	if vs.convertedServiceEvents == nil {
   368  		panic("method not set")
   369  	}
   370  	return vs.convertedServiceEvents()
   371  }
   372  
   373  func (vs *testEventEmitter) Reset() {
   374  	if vs.reset == nil {
   375  		panic("method not set")
   376  	}
   377  	vs.reset()
   378  }