github.com/onflow/flow-go@v0.33.17/fvm/evm/testutils/cadence.go (about) 1 package testutils 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "encoding/hex" 7 "errors" 8 "fmt" 9 "strconv" 10 "strings" 11 "sync/atomic" 12 "testing" 13 "time" 14 15 "github.com/onflow/atree" 16 "github.com/onflow/cadence" 17 "github.com/onflow/cadence/encoding/json" 18 "github.com/onflow/cadence/runtime" 19 "github.com/onflow/cadence/runtime/common" 20 "github.com/onflow/cadence/runtime/interpreter" 21 "github.com/onflow/cadence/runtime/sema" 22 cadenceStdlib "github.com/onflow/cadence/runtime/stdlib" 23 "github.com/stretchr/testify/require" 24 "go.opentelemetry.io/otel/attribute" 25 ) 26 27 // TODO: replace with Cadence runtime testing utils once available https://github.com/onflow/cadence/pull/2800 28 29 func SingleIdentifierLocationResolver(t testing.TB) func( 30 identifiers []runtime.Identifier, 31 location runtime.Location, 32 ) ( 33 []runtime.ResolvedLocation, 34 error, 35 ) { 36 return func(identifiers []runtime.Identifier, location runtime.Location) ([]runtime.ResolvedLocation, error) { 37 require.Len(t, identifiers, 1) 38 require.IsType(t, common.AddressLocation{}, location) 39 40 return []runtime.ResolvedLocation{ 41 { 42 Location: common.AddressLocation{ 43 Address: location.(common.AddressLocation).Address, 44 Name: identifiers[0].Identifier, 45 }, 46 Identifiers: identifiers, 47 }, 48 }, nil 49 } 50 } 51 52 func newLocationGenerator[T ~[32]byte]() func() T { 53 var count uint64 54 return func() T { 55 t := T{} 56 newCount := atomic.AddUint64(&count, 1) 57 binary.LittleEndian.PutUint64(t[:], newCount) 58 return t 59 } 60 } 61 62 func NewTransactionLocationGenerator() func() common.TransactionLocation { 63 return newLocationGenerator[common.TransactionLocation]() 64 } 65 66 func NewScriptLocationGenerator() func() common.ScriptLocation { 67 return newLocationGenerator[common.ScriptLocation]() 68 } 69 70 func EncodeArgs(argValues []cadence.Value) [][]byte { 71 args := make([][]byte, len(argValues)) 72 for i, arg := range argValues { 73 var err error 74 args[i], err = json.Encode(arg) 75 if err != nil { 76 panic(fmt.Errorf("broken test: invalid argument: %w", err)) 77 } 78 } 79 return args 80 } 81 82 type TestLedger struct { 83 StoredValues map[string][]byte 84 OnValueExists func(owner, key []byte) (exists bool, err error) 85 OnGetValue func(owner, key []byte) (value []byte, err error) 86 OnSetValue func(owner, key, value []byte) (err error) 87 OnAllocateStorageIndex func(owner []byte) (atree.StorageIndex, error) 88 } 89 90 var _ atree.Ledger = TestLedger{} 91 92 func (s TestLedger) GetValue(owner, key []byte) (value []byte, err error) { 93 return s.OnGetValue(owner, key) 94 } 95 96 func (s TestLedger) SetValue(owner, key, value []byte) (err error) { 97 return s.OnSetValue(owner, key, value) 98 } 99 100 func (s TestLedger) ValueExists(owner, key []byte) (exists bool, err error) { 101 return s.OnValueExists(owner, key) 102 } 103 104 func (s TestLedger) AllocateStorageIndex(owner []byte) (atree.StorageIndex, error) { 105 return s.OnAllocateStorageIndex(owner) 106 } 107 108 func (s TestLedger) Dump() { 109 // Only used for testing/debugging purposes 110 for key, data := range s.StoredValues { //nolint:maprange 111 fmt.Printf("%s:\n", strconv.Quote(key)) 112 fmt.Printf("%s\n", hex.Dump(data)) 113 println() 114 } 115 } 116 117 func NewTestLedger( 118 onRead func(owner, key, value []byte), 119 onWrite func(owner, key, value []byte), 120 ) TestLedger { 121 122 storageKey := func(owner, key string) string { 123 return strings.Join([]string{owner, key}, "|") 124 } 125 126 storedValues := map[string][]byte{} 127 128 storageIndices := map[string]uint64{} 129 130 return TestLedger{ 131 StoredValues: storedValues, 132 OnValueExists: func(owner, key []byte) (bool, error) { 133 value := storedValues[storageKey(string(owner), string(key))] 134 return len(value) > 0, nil 135 }, 136 OnGetValue: func(owner, key []byte) (value []byte, err error) { 137 value = storedValues[storageKey(string(owner), string(key))] 138 if onRead != nil { 139 onRead(owner, key, value) 140 } 141 return value, nil 142 }, 143 OnSetValue: func(owner, key, value []byte) (err error) { 144 storedValues[storageKey(string(owner), string(key))] = value 145 if onWrite != nil { 146 onWrite(owner, key, value) 147 } 148 return nil 149 }, 150 OnAllocateStorageIndex: func(owner []byte) (result atree.StorageIndex, err error) { 151 index := storageIndices[string(owner)] + 1 152 storageIndices[string(owner)] = index 153 binary.BigEndian.PutUint64(result[:], index) 154 return 155 }, 156 } 157 } 158 159 type TestRuntimeInterface struct { 160 Storage atree.Ledger 161 162 OnResolveLocation func( 163 identifiers []runtime.Identifier, 164 location runtime.Location, 165 ) ( 166 []runtime.ResolvedLocation, 167 error, 168 ) 169 OnGetCode func(_ runtime.Location) ([]byte, error) 170 OnGetAndSetProgram func( 171 location runtime.Location, 172 load func() (*interpreter.Program, error), 173 ) (*interpreter.Program, error) 174 OnSetInterpreterSharedState func(state *interpreter.SharedState) 175 OnGetInterpreterSharedState func() *interpreter.SharedState 176 OnCreateAccount func(payer runtime.Address) (address runtime.Address, err error) 177 OnAddEncodedAccountKey func(address runtime.Address, publicKey []byte) error 178 OnRemoveEncodedAccountKey func(address runtime.Address, index int) (publicKey []byte, err error) 179 OnAddAccountKey func( 180 address runtime.Address, 181 publicKey *cadenceStdlib.PublicKey, 182 hashAlgo runtime.HashAlgorithm, 183 weight int, 184 ) (*cadenceStdlib.AccountKey, error) 185 OnGetAccountKey func(address runtime.Address, index int) (*cadenceStdlib.AccountKey, error) 186 OnRemoveAccountKey func(address runtime.Address, index int) (*cadenceStdlib.AccountKey, error) 187 OnAccountKeysCount func(address runtime.Address) (uint64, error) 188 OnUpdateAccountContractCode func(location common.AddressLocation, code []byte) error 189 OnGetAccountContractCode func(location common.AddressLocation) (code []byte, err error) 190 OnRemoveAccountContractCode func(location common.AddressLocation) (err error) 191 OnGetSigningAccounts func() ([]runtime.Address, error) 192 OnProgramLog func(string) 193 OnEmitEvent func(cadence.Event) error 194 OnResourceOwnerChanged func( 195 interpreter *interpreter.Interpreter, 196 resource *interpreter.CompositeValue, 197 oldAddress common.Address, 198 newAddress common.Address, 199 ) 200 OnGenerateUUID func() (uint64, error) 201 OnMeterComputation func(compKind common.ComputationKind, intensity uint) error 202 OnDecodeArgument func(b []byte, t cadence.Type) (cadence.Value, error) 203 OnProgramParsed func(location runtime.Location, duration time.Duration) 204 OnProgramChecked func(location runtime.Location, duration time.Duration) 205 OnProgramInterpreted func(location runtime.Location, duration time.Duration) 206 OnReadRandom func([]byte) error 207 OnVerifySignature func( 208 signature []byte, 209 tag string, 210 signedData []byte, 211 publicKey []byte, 212 signatureAlgorithm runtime.SignatureAlgorithm, 213 hashAlgorithm runtime.HashAlgorithm, 214 ) (bool, error) 215 OnHash func( 216 data []byte, 217 tag string, 218 hashAlgorithm runtime.HashAlgorithm, 219 ) ([]byte, error) 220 OnSetCadenceValue func(owner runtime.Address, key string, value cadence.Value) (err error) 221 OnGetAccountBalance func(_ runtime.Address) (uint64, error) 222 OnGetAccountAvailableBalance func(_ runtime.Address) (uint64, error) 223 OnGetStorageUsed func(_ runtime.Address) (uint64, error) 224 OnGetStorageCapacity func(_ runtime.Address) (uint64, error) 225 Programs map[runtime.Location]*interpreter.Program 226 OnImplementationDebugLog func(message string) error 227 OnValidatePublicKey func(publicKey *cadenceStdlib.PublicKey) error 228 OnBLSVerifyPOP func(pk *cadenceStdlib.PublicKey, s []byte) (bool, error) 229 OnBLSAggregateSignatures func(sigs [][]byte) ([]byte, error) 230 OnBLSAggregatePublicKeys func(keys []*cadenceStdlib.PublicKey) (*cadenceStdlib.PublicKey, error) 231 OnGetAccountContractNames func(address runtime.Address) ([]string, error) 232 OnRecordTrace func( 233 operation string, 234 location runtime.Location, 235 duration time.Duration, 236 attrs []attribute.KeyValue, 237 ) 238 OnMeterMemory func(usage common.MemoryUsage) error 239 OnComputationUsed func() (uint64, error) 240 OnMemoryUsed func() (uint64, error) 241 OnInteractionUsed func() (uint64, error) 242 OnGenerateAccountID func(address common.Address) (uint64, error) 243 244 lastUUID uint64 245 accountIDs map[common.Address]uint64 246 updatedContractCode bool 247 } 248 249 // TestRuntimeInterface should implement Interface 250 var _ runtime.Interface = &TestRuntimeInterface{} 251 252 func (i *TestRuntimeInterface) ResolveLocation( 253 identifiers []runtime.Identifier, 254 location runtime.Location, 255 ) ([]runtime.ResolvedLocation, error) { 256 if i.OnResolveLocation == nil { 257 return []runtime.ResolvedLocation{ 258 { 259 Location: location, 260 Identifiers: identifiers, 261 }, 262 }, nil 263 } 264 return i.OnResolveLocation(identifiers, location) 265 } 266 267 func (i *TestRuntimeInterface) GetCode(location runtime.Location) ([]byte, error) { 268 if i.OnGetCode == nil { 269 return nil, nil 270 } 271 return i.OnGetCode(location) 272 } 273 274 func (i *TestRuntimeInterface) GetOrLoadProgram( 275 location runtime.Location, 276 load func() (*interpreter.Program, error), 277 ) ( 278 program *interpreter.Program, 279 err error, 280 ) { 281 if i.OnGetAndSetProgram == nil { 282 if i.Programs == nil { 283 i.Programs = map[runtime.Location]*interpreter.Program{} 284 } 285 286 var ok bool 287 program, ok = i.Programs[location] 288 if ok { 289 return 290 } 291 292 program, err = load() 293 294 // NOTE: important: still set empty program, 295 // even if error occurred 296 297 i.Programs[location] = program 298 299 return 300 } 301 302 return i.OnGetAndSetProgram(location, load) 303 } 304 305 func (i *TestRuntimeInterface) SetInterpreterSharedState(state *interpreter.SharedState) { 306 if i.OnSetInterpreterSharedState == nil { 307 return 308 } 309 310 i.OnSetInterpreterSharedState(state) 311 } 312 313 func (i *TestRuntimeInterface) GetInterpreterSharedState() *interpreter.SharedState { 314 if i.OnGetInterpreterSharedState == nil { 315 return nil 316 } 317 318 return i.OnGetInterpreterSharedState() 319 } 320 321 func (i *TestRuntimeInterface) ValueExists(owner, key []byte) (exists bool, err error) { 322 return i.Storage.ValueExists(owner, key) 323 } 324 325 func (i *TestRuntimeInterface) GetValue(owner, key []byte) (value []byte, err error) { 326 return i.Storage.GetValue(owner, key) 327 } 328 329 func (i *TestRuntimeInterface) SetValue(owner, key, value []byte) (err error) { 330 return i.Storage.SetValue(owner, key, value) 331 } 332 333 func (i *TestRuntimeInterface) AllocateStorageIndex(owner []byte) (atree.StorageIndex, error) { 334 return i.Storage.AllocateStorageIndex(owner) 335 } 336 337 func (i *TestRuntimeInterface) CreateAccount(payer runtime.Address) (address runtime.Address, err error) { 338 if i.OnCreateAccount == nil { 339 panic("must specify TestRuntimeInterface.OnCreateAccount") 340 } 341 return i.OnCreateAccount(payer) 342 } 343 344 func (i *TestRuntimeInterface) AddEncodedAccountKey(address runtime.Address, publicKey []byte) error { 345 if i.OnAddEncodedAccountKey == nil { 346 panic("must specify TestRuntimeInterface.OnAddEncodedAccountKey") 347 } 348 return i.OnAddEncodedAccountKey(address, publicKey) 349 } 350 351 func (i *TestRuntimeInterface) RevokeEncodedAccountKey(address runtime.Address, index int) ([]byte, error) { 352 if i.OnRemoveEncodedAccountKey == nil { 353 panic("must specify TestRuntimeInterface.OnRemoveEncodedAccountKey") 354 } 355 return i.OnRemoveEncodedAccountKey(address, index) 356 } 357 358 func (i *TestRuntimeInterface) AddAccountKey( 359 address runtime.Address, 360 publicKey *cadenceStdlib.PublicKey, 361 hashAlgo runtime.HashAlgorithm, 362 weight int, 363 ) (*cadenceStdlib.AccountKey, error) { 364 if i.OnAddAccountKey == nil { 365 panic("must specify TestRuntimeInterface.OnAddAccountKey") 366 } 367 return i.OnAddAccountKey(address, publicKey, hashAlgo, weight) 368 } 369 370 func (i *TestRuntimeInterface) GetAccountKey(address runtime.Address, index int) (*cadenceStdlib.AccountKey, error) { 371 if i.OnGetAccountKey == nil { 372 panic("must specify TestRuntimeInterface.OnGetAccountKey") 373 } 374 return i.OnGetAccountKey(address, index) 375 } 376 377 func (i *TestRuntimeInterface) AccountKeysCount(address runtime.Address) (uint64, error) { 378 if i.OnAccountKeysCount == nil { 379 panic("must specify TestRuntimeInterface.OnAccountKeysCount") 380 } 381 return i.OnAccountKeysCount(address) 382 } 383 384 func (i *TestRuntimeInterface) RevokeAccountKey(address runtime.Address, index int) (*cadenceStdlib.AccountKey, error) { 385 if i.OnRemoveAccountKey == nil { 386 panic("must specify TestRuntimeInterface.OnRemoveAccountKey") 387 } 388 return i.OnRemoveAccountKey(address, index) 389 } 390 391 func (i *TestRuntimeInterface) UpdateAccountContractCode(location common.AddressLocation, code []byte) (err error) { 392 if i.OnUpdateAccountContractCode == nil { 393 panic("must specify TestRuntimeInterface.OnUpdateAccountContractCode") 394 } 395 396 err = i.OnUpdateAccountContractCode(location, code) 397 if err != nil { 398 return err 399 } 400 401 i.updatedContractCode = true 402 403 return nil 404 } 405 406 func (i *TestRuntimeInterface) GetAccountContractCode(location common.AddressLocation) (code []byte, err error) { 407 if i.OnGetAccountContractCode == nil { 408 panic("must specify TestRuntimeInterface.OnGetAccountContractCode") 409 } 410 return i.OnGetAccountContractCode(location) 411 } 412 413 func (i *TestRuntimeInterface) RemoveAccountContractCode(location common.AddressLocation) (err error) { 414 if i.OnRemoveAccountContractCode == nil { 415 panic("must specify TestRuntimeInterface.OnRemoveAccountContractCode") 416 } 417 return i.OnRemoveAccountContractCode(location) 418 } 419 420 func (i *TestRuntimeInterface) GetSigningAccounts() ([]runtime.Address, error) { 421 if i.OnGetSigningAccounts == nil { 422 return nil, nil 423 } 424 return i.OnGetSigningAccounts() 425 } 426 427 func (i *TestRuntimeInterface) ProgramLog(message string) error { 428 i.OnProgramLog(message) 429 return nil 430 } 431 432 func (i *TestRuntimeInterface) EmitEvent(event cadence.Event) error { 433 return i.OnEmitEvent(event) 434 } 435 436 func (i *TestRuntimeInterface) ResourceOwnerChanged( 437 interpreter *interpreter.Interpreter, 438 resource *interpreter.CompositeValue, 439 oldOwner common.Address, 440 newOwner common.Address, 441 ) { 442 if i.OnResourceOwnerChanged != nil { 443 i.OnResourceOwnerChanged( 444 interpreter, 445 resource, 446 oldOwner, 447 newOwner, 448 ) 449 } 450 } 451 452 func (i *TestRuntimeInterface) GenerateUUID() (uint64, error) { 453 if i.OnGenerateUUID == nil { 454 i.lastUUID++ 455 return i.lastUUID, nil 456 } 457 return i.OnGenerateUUID() 458 } 459 460 func (i *TestRuntimeInterface) MeterComputation(compKind common.ComputationKind, intensity uint) error { 461 if i.OnMeterComputation == nil { 462 return nil 463 } 464 return i.OnMeterComputation(compKind, intensity) 465 } 466 467 func (i *TestRuntimeInterface) DecodeArgument(b []byte, t cadence.Type) (cadence.Value, error) { 468 if i.OnDecodeArgument == nil { 469 panic("must specify TestRuntimeInterface.OnDecodeArgument") 470 } 471 return i.OnDecodeArgument(b, t) 472 } 473 474 func (i *TestRuntimeInterface) ProgramParsed(location runtime.Location, duration time.Duration) { 475 if i.OnProgramParsed == nil { 476 return 477 } 478 i.OnProgramParsed(location, duration) 479 } 480 481 func (i *TestRuntimeInterface) ProgramChecked(location runtime.Location, duration time.Duration) { 482 if i.OnProgramChecked == nil { 483 return 484 } 485 i.OnProgramChecked(location, duration) 486 } 487 488 func (i *TestRuntimeInterface) ProgramInterpreted(location runtime.Location, duration time.Duration) { 489 if i.OnProgramInterpreted == nil { 490 return 491 } 492 i.OnProgramInterpreted(location, duration) 493 } 494 495 func (i *TestRuntimeInterface) GetCurrentBlockHeight() (uint64, error) { 496 return 1, nil 497 } 498 499 func (i *TestRuntimeInterface) GetBlockAtHeight(height uint64) (block cadenceStdlib.Block, exists bool, err error) { 500 501 buf := new(bytes.Buffer) 502 err = binary.Write(buf, binary.BigEndian, height) 503 if err != nil { 504 panic(err) 505 } 506 507 encoded := buf.Bytes() 508 var hash cadenceStdlib.BlockHash 509 copy(hash[sema.BlockTypeIdFieldType.Size-int64(len(encoded)):], encoded) 510 511 block = cadenceStdlib.Block{ 512 Height: height, 513 View: height, 514 Hash: hash, 515 Timestamp: time.Unix(int64(height), 0).UnixNano(), 516 } 517 return block, true, nil 518 } 519 520 func (i *TestRuntimeInterface) ReadRandom(buffer []byte) error { 521 if i.OnReadRandom == nil { 522 return nil 523 } 524 return i.OnReadRandom(buffer) 525 } 526 527 func (i *TestRuntimeInterface) VerifySignature( 528 signature []byte, 529 tag string, 530 signedData []byte, 531 publicKey []byte, 532 signatureAlgorithm runtime.SignatureAlgorithm, 533 hashAlgorithm runtime.HashAlgorithm, 534 ) (bool, error) { 535 if i.OnVerifySignature == nil { 536 return false, nil 537 } 538 return i.OnVerifySignature( 539 signature, 540 tag, 541 signedData, 542 publicKey, 543 signatureAlgorithm, 544 hashAlgorithm, 545 ) 546 } 547 548 func (i *TestRuntimeInterface) Hash(data []byte, tag string, hashAlgorithm runtime.HashAlgorithm) ([]byte, error) { 549 if i.OnHash == nil { 550 return nil, nil 551 } 552 return i.OnHash(data, tag, hashAlgorithm) 553 } 554 555 func (i *TestRuntimeInterface) SetCadenceValue(owner common.Address, key string, value cadence.Value) (err error) { 556 if i.OnSetCadenceValue == nil { 557 panic("must specify TestRuntimeInterface.OnSetCadenceValue") 558 } 559 return i.OnSetCadenceValue(owner, key, value) 560 } 561 562 func (i *TestRuntimeInterface) GetAccountBalance(address runtime.Address) (uint64, error) { 563 if i.OnGetAccountBalance == nil { 564 panic("must specify TestRuntimeInterface.OnGetAccountBalance") 565 } 566 return i.OnGetAccountBalance(address) 567 } 568 569 func (i *TestRuntimeInterface) GetAccountAvailableBalance(address runtime.Address) (uint64, error) { 570 if i.OnGetAccountAvailableBalance == nil { 571 panic("must specify TestRuntimeInterface.OnGetAccountAvailableBalance") 572 } 573 return i.OnGetAccountAvailableBalance(address) 574 } 575 576 func (i *TestRuntimeInterface) GetStorageUsed(address runtime.Address) (uint64, error) { 577 if i.OnGetStorageUsed == nil { 578 panic("must specify TestRuntimeInterface.OnGetStorageUsed") 579 } 580 return i.OnGetStorageUsed(address) 581 } 582 583 func (i *TestRuntimeInterface) GetStorageCapacity(address runtime.Address) (uint64, error) { 584 if i.OnGetStorageCapacity == nil { 585 panic("must specify TestRuntimeInterface.OnGetStorageCapacity") 586 } 587 return i.OnGetStorageCapacity(address) 588 } 589 590 func (i *TestRuntimeInterface) ImplementationDebugLog(message string) error { 591 if i.OnImplementationDebugLog == nil { 592 return nil 593 } 594 return i.OnImplementationDebugLog(message) 595 } 596 597 func (i *TestRuntimeInterface) ValidatePublicKey(key *cadenceStdlib.PublicKey) error { 598 if i.OnValidatePublicKey == nil { 599 return errors.New("mock defaults to public key validation failure") 600 } 601 602 return i.OnValidatePublicKey(key) 603 } 604 605 func (i *TestRuntimeInterface) BLSVerifyPOP(key *cadenceStdlib.PublicKey, s []byte) (bool, error) { 606 if i.OnBLSVerifyPOP == nil { 607 return false, nil 608 } 609 610 return i.OnBLSVerifyPOP(key, s) 611 } 612 613 func (i *TestRuntimeInterface) BLSAggregateSignatures(sigs [][]byte) ([]byte, error) { 614 if i.OnBLSAggregateSignatures == nil { 615 return []byte{}, nil 616 } 617 618 return i.OnBLSAggregateSignatures(sigs) 619 } 620 621 func (i *TestRuntimeInterface) BLSAggregatePublicKeys(keys []*cadenceStdlib.PublicKey) (*cadenceStdlib.PublicKey, error) { 622 if i.OnBLSAggregatePublicKeys == nil { 623 return nil, nil 624 } 625 626 return i.OnBLSAggregatePublicKeys(keys) 627 } 628 629 func (i *TestRuntimeInterface) GetAccountContractNames(address runtime.Address) ([]string, error) { 630 if i.OnGetAccountContractNames == nil { 631 return []string{}, nil 632 } 633 634 return i.OnGetAccountContractNames(address) 635 } 636 637 func (i *TestRuntimeInterface) GenerateAccountID(address common.Address) (uint64, error) { 638 if i.OnGenerateAccountID == nil { 639 if i.accountIDs == nil { 640 i.accountIDs = map[common.Address]uint64{} 641 } 642 i.accountIDs[address]++ 643 return i.accountIDs[address], nil 644 } 645 646 return i.OnGenerateAccountID(address) 647 } 648 649 func (i *TestRuntimeInterface) RecordTrace( 650 operation string, 651 location runtime.Location, 652 duration time.Duration, 653 attrs []attribute.KeyValue, 654 ) { 655 if i.OnRecordTrace == nil { 656 return 657 } 658 i.OnRecordTrace(operation, location, duration, attrs) 659 } 660 661 func (i *TestRuntimeInterface) MeterMemory(usage common.MemoryUsage) error { 662 if i.OnMeterMemory == nil { 663 return nil 664 } 665 666 return i.OnMeterMemory(usage) 667 } 668 669 func (i *TestRuntimeInterface) ComputationUsed() (uint64, error) { 670 if i.OnComputationUsed == nil { 671 return 0, nil 672 } 673 674 return i.OnComputationUsed() 675 } 676 677 func (i *TestRuntimeInterface) MemoryUsed() (uint64, error) { 678 if i.OnMemoryUsed == nil { 679 return 0, nil 680 } 681 682 return i.OnMemoryUsed() 683 } 684 685 func (i *TestRuntimeInterface) InteractionUsed() (uint64, error) { 686 if i.OnInteractionUsed == nil { 687 return 0, nil 688 } 689 690 return i.OnInteractionUsed() 691 }