diff --git a/runtime/cmd/cmd.go b/runtime/cmd/cmd.go index bcba6c1a94..5a76ea8bfc 100644 --- a/runtime/cmd/cmd.go +++ b/runtime/cmd/cmd.go @@ -188,9 +188,9 @@ func PrepareInterpreter(filename string) (*interpreter.Interpreter, *sema.Checke inter, err := interpreter.NewInterpreter( checker, interpreter.WithPredefinedValues(valueDeclarations.ToValues()), - interpreter.WithUUIDHandler(func() uint64 { + interpreter.WithUUIDHandler(func() (uint64, error) { defer func() { uuid++ }() - return uuid + return uuid, nil }), ) must(err) diff --git a/runtime/contract_test.go b/runtime/contract_test.go index 8d5bd5fd95..66b1c15466 100644 --- a/runtime/contract_test.go +++ b/runtime/contract_test.go @@ -134,8 +134,8 @@ func TestRuntimeContract(t *testing.T) { runtimeInterface := &testRuntimeInterface{ storage: storage, - getSigningAccounts: func() []Address { - return []Address{signerAddress} + getSigningAccounts: func() ([]Address, error) { + return []Address{signerAddress}, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -471,8 +471,8 @@ func TestRuntimeImportMultipleContracts(t *testing.T) { runtimeInterface := &testRuntimeInterface{ storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{common.BytesToAddress([]byte{0x1})} + getSigningAccounts: func() ([]Address, error) { + return []Address{common.BytesToAddress([]byte{0x1})}, nil }, updateAccountContractCode: func(address Address, name string, code []byte) error { key := contractKey{ @@ -498,7 +498,7 @@ func TestRuntimeImportMultipleContracts(t *testing.T) { delete(deployedContracts, key) return nil }, - resolveLocation: func(identifiers []ast.Identifier, location ast.Location) (result []sema.ResolvedLocation) { + resolveLocation: func(identifiers []ast.Identifier, location ast.Location) (result []sema.ResolvedLocation, err error) { // Resolve each identifier as an address location @@ -519,7 +519,7 @@ func TestRuntimeImportMultipleContracts(t *testing.T) { log: func(message string) { loggedMessages = append(loggedMessages, message) }, - emitEvent: func(event cadence.Event) error{ + emitEvent: func(event cadence.Event) error { events = append(events, event) return nil }, diff --git a/runtime/crypto_test.go b/runtime/crypto_test.go index bd995cf1ac..2281aad0be 100644 --- a/runtime/crypto_test.go +++ b/runtime/crypto_test.go @@ -99,7 +99,7 @@ func TestRuntimeCrypto_verify(t *testing.T) { publicKey []byte, signatureAlgorithm string, hashAlgorithm string, - ) bool { + ) (bool, error) { called = true assert.Equal(t, []byte{3, 4}, signature) assert.Equal(t, "user", tag) @@ -107,7 +107,7 @@ func TestRuntimeCrypto_verify(t *testing.T) { assert.Equal(t, []byte{1, 2}, publicKey) assert.Equal(t, "ECDSA_P256", signatureAlgorithm) assert.Equal(t, "SHA3_256", hashAlgorithm) - return true + return true, nil }, } @@ -145,11 +145,11 @@ func TestRuntimeCrypto_hash(t *testing.T) { hash: func( data []byte, hashAlgorithm string, - ) []byte { + ) ([]byte, error) { called = true assert.Equal(t, []byte{1, 2, 3, 4}, data) assert.Equal(t, "SHA3_256", hashAlgorithm) - return []byte{5, 6, 7, 8} + return []byte{5, 6, 7, 8}, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) diff --git a/runtime/deferral_test.go b/runtime/deferral_test.go index 58ed373b6e..33cad28b97 100644 --- a/runtime/deferral_test.go +++ b/runtime/deferral_test.go @@ -138,8 +138,8 @@ func TestRuntimeStorageDeferredResourceDictionaryValues(t *testing.T) { return accountCode, nil }, storage: newTestStorage(onRead, onWrite), - getSigningAccounts: func() []Address { - return []Address{common.BytesToAddress(addressValue.Bytes())} + getSigningAccounts: func() ([]Address, error) { + return []Address{common.BytesToAddress(addressValue.Bytes())}, nil }, updateAccountContractCode: func(_ Address, _ string, code []byte) error { accountCode = code @@ -623,8 +623,8 @@ func TestRuntimeStorageDeferredResourceDictionaryValues_Nested(t *testing.T) { return accountCode, nil }, storage: newTestStorage(onRead, onWrite), - getSigningAccounts: func() []Address { - return []Address{common.BytesToAddress(addressValue.Bytes())} + getSigningAccounts: func() ([]Address, error) { + return []Address{common.BytesToAddress(addressValue.Bytes())}, nil }, updateAccountContractCode: func(_ Address, _ string, code []byte) error { accountCode = code @@ -856,11 +856,11 @@ func TestRuntimeStorageDeferredResourceDictionaryValues_DictionaryTransfer(t *te return accountCode, nil }, storage: newTestStorage(onRead, onWrite), - getSigningAccounts: func() []Address { + getSigningAccounts: func() ([]Address, error) { return []Address{ signer1, signer2, - } + }, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { @@ -1013,8 +1013,8 @@ func TestRuntimeStorageDeferredResourceDictionaryValues_Removal(t *testing.T) { return accountCode, nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{signer} + getSigningAccounts: func() ([]Address, error) { + return []Address{signer}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { @@ -1095,8 +1095,8 @@ func TestRuntimeStorageDeferredResourceDictionaryValues_Destruction(t *testing.T return accountCode, nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{signer} + getSigningAccounts: func() ([]Address, error) { + return []Address{signer}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { @@ -1211,8 +1211,8 @@ func TestRuntimeStorageDeferredResourceDictionaryValues_Insertion(t *testing.T) return accountCode, nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{signer} + getSigningAccounts: func() ([]Address, error) { + return []Address{signer}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { @@ -1330,8 +1330,8 @@ func TestRuntimeStorageDeferredResourceDictionaryValues_ValueTransferAndDestroy( return accountCode, nil }, storage: testStorage, - getSigningAccounts: func() []Address { - return signers + getSigningAccounts: func() ([]Address, error) { + return signers, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { diff --git a/runtime/interface.go b/runtime/interface.go index 44109a420e..399b060f06 100644 --- a/runtime/interface.go +++ b/runtime/interface.go @@ -41,7 +41,7 @@ type ResolvedLocation = sema.ResolvedLocation type Interface interface { // ResolveLocation resolves an import location. - ResolveLocation(identifiers []Identifier, location Location) []ResolvedLocation + ResolveLocation(identifiers []Identifier, location Location) ([]ResolvedLocation, error) // GetCode returns the code at a given location GetCode(location Location) ([]byte, error) // GetCachedProgram attempts to get a parsed program from a cache. @@ -65,26 +65,28 @@ type Interface interface { // RemoveAccountContractCode removes the code associated with an account contract. RemoveAccountContractCode(address Address, name string) (err error) // GetSigningAccounts returns the signing accounts. - GetSigningAccounts() []Address + GetSigningAccounts() ([]Address, error) // Log logs a string. - Log(string) + Log(string) error // EmitEvent is called when an event is emitted by the runtime. - EmitEvent(cadence.Event) (err error) + EmitEvent(cadence.Event) error // ValueExists returns true if the given key exists in the storage, owned by the given account. ValueExists(owner, key []byte) (exists bool, err error) // GenerateUUID is called to generate a UUID. - GenerateUUID() uint64 + GenerateUUID() (uint64, error) // GetComputationLimit returns the computation limit. A value <= 0 means there is no limit GetComputationLimit() uint64 + // SetComputationUsed reports the amount of computation used. + SetComputationUsed(used uint64) error // DecodeArgument decodes a transaction argument against the given type. DecodeArgument(argument []byte, argumentType cadence.Type) (cadence.Value, error) // GetCurrentBlockHeight returns the current block height. - GetCurrentBlockHeight() uint64 + GetCurrentBlockHeight() (uint64, error) // GetBlockAtHeight returns the block at the given height. GetBlockAtHeight(height uint64) (block Block, exists bool, err error) // UnsafeRandom returns a random uint64, where the process of random number derivation is not cryptographically // secure. - UnsafeRandom() uint64 + UnsafeRandom() (uint64, error) // VerifySignature returns true if the given signature was produced by signing the given tag + data // using the given public key, signature algorithm, and hash algorithm. VerifySignature( @@ -94,9 +96,9 @@ type Interface interface { publicKey []byte, signatureAlgorithm string, hashAlgorithm string, - ) bool + ) (bool, error) // Hash returns the digest of hashing the given data with using the given hash algorithm - Hash(data []byte, hashAlgorithm string) []byte + Hash(data []byte, hashAlgorithm string) ([]byte, error) // GetStorageUsed gets storage used in bytes by the address at the moment of the function call. GetStorageUsed(address Address) (value uint64, err error) // GetStorageCapacity gets storage capacity in bytes on the address. @@ -127,13 +129,13 @@ type EmptyRuntimeInterface struct{} var _ Interface = &EmptyRuntimeInterface{} -func (i *EmptyRuntimeInterface) ResolveLocation(identifiers []Identifier, location Location) []ResolvedLocation { +func (i *EmptyRuntimeInterface) ResolveLocation(identifiers []Identifier, location Location) ([]ResolvedLocation, error) { return []ResolvedLocation{ { Location: location, Identifiers: identifiers, }, - } + }, nil } func (i *EmptyRuntimeInterface) GetCode(_ Location) ([]byte, error) { @@ -188,38 +190,44 @@ func (i *EmptyRuntimeInterface) RemoveAccountContractCode(_ Address, _ string) ( return nil } -func (i *EmptyRuntimeInterface) GetSigningAccounts() []Address { - return nil +func (i *EmptyRuntimeInterface) GetSigningAccounts() ([]Address, error) { + return nil, nil } -func (i *EmptyRuntimeInterface) Log(_ string) {} +func (i *EmptyRuntimeInterface) Log(_ string) error { + return nil +} func (i *EmptyRuntimeInterface) EmitEvent(_ cadence.Event) error { return nil } -func (i *EmptyRuntimeInterface) GenerateUUID() uint64 { - return 0 +func (i *EmptyRuntimeInterface) GenerateUUID() (uint64, error) { + return 0, nil } func (i *EmptyRuntimeInterface) GetComputationLimit() uint64 { return 0 } +func (i *EmptyRuntimeInterface) SetComputationUsed(uint64) error { + return nil +} + func (i *EmptyRuntimeInterface) DecodeArgument(_ []byte, _ cadence.Type) (cadence.Value, error) { return nil, nil } -func (i *EmptyRuntimeInterface) GetCurrentBlockHeight() uint64 { - return 0 +func (i *EmptyRuntimeInterface) GetCurrentBlockHeight() (uint64, error) { + return 0, nil } func (i *EmptyRuntimeInterface) GetBlockAtHeight(_ uint64) (block Block, exists bool, err error) { return } -func (i *EmptyRuntimeInterface) UnsafeRandom() uint64 { - return 0 +func (i *EmptyRuntimeInterface) UnsafeRandom() (uint64, error) { + return 0, nil } func (i *EmptyRuntimeInterface) VerifySignature( @@ -229,21 +237,21 @@ func (i *EmptyRuntimeInterface) VerifySignature( _ []byte, _ string, _ string, -) bool { - return false +) (bool, error) { + return false, nil } func (i *EmptyRuntimeInterface) Hash( _ []byte, _ string, -) []byte { - return nil +) ([]byte, error) { + return nil, nil } -func (i EmptyRuntimeInterface) GetStorageUsed(_ Address) (uint64,error) { +func (i EmptyRuntimeInterface) GetStorageUsed(_ Address) (uint64, error) { return 0, nil } -func (i EmptyRuntimeInterface) GetStorageCapacity(_ Address) (uint64,error) { +func (i EmptyRuntimeInterface) GetStorageCapacity(_ Address) (uint64, error) { return 0, nil } diff --git a/runtime/interpreter/errors.go b/runtime/interpreter/errors.go index aec8486424..80aeb84cf2 100644 --- a/runtime/interpreter/errors.go +++ b/runtime/interpreter/errors.go @@ -196,7 +196,7 @@ func (e DestroyedCompositeError) Error() string { } // ForceAssignmentToNonNilResourceError - +// type ForceAssignmentToNonNilResourceError struct { LocationRange } @@ -206,7 +206,7 @@ func (e ForceAssignmentToNonNilResourceError) Error() string { } // ForceNilError - +// type ForceNilError struct { LocationRange } @@ -216,7 +216,7 @@ func (e ForceNilError) Error() string { } // TypeMismatchError - +// type TypeMismatchError struct { ExpectedType sema.Type LocationRange @@ -230,7 +230,7 @@ func (e TypeMismatchError) Error() string { } // InvalidPathDomainError - +// type InvalidPathDomainError struct { ActualDomain common.PathDomain ExpectedDomains []common.PathDomain @@ -257,7 +257,7 @@ func (e InvalidPathDomainError) SecondaryError() string { } // OverwriteError - +// type OverwriteError struct { Address AddressValue Path PathValue @@ -273,7 +273,7 @@ func (e OverwriteError) Error() string { } // CyclicLinkError - +// type CyclicLinkError struct { Address AddressValue Paths []PathValue @@ -298,7 +298,7 @@ func (e CyclicLinkError) Error() string { } // ArrayIndexOutOfBoundsError - +// type ArrayIndexOutOfBoundsError struct { Index int MaxIndex int @@ -312,3 +312,23 @@ func (e ArrayIndexOutOfBoundsError) Error() string { e.MaxIndex, ) } + +// EventEmissionUnavailableError +// +type EventEmissionUnavailableError struct { + LocationRange +} + +func (e EventEmissionUnavailableError) Error() string { + return "cannot emit event: unavailable" +} + +// UUIDUnavailableError +// +type UUIDUnavailableError struct { + LocationRange +} + +func (e UUIDUnavailableError) Error() string { + return "cannot get UUID: unavailable" +} diff --git a/runtime/interpreter/interpreter.go b/runtime/interpreter/interpreter.go index 96da865d33..fe721d24ff 100644 --- a/runtime/interpreter/interpreter.go +++ b/runtime/interpreter/interpreter.go @@ -78,7 +78,7 @@ type OnEventEmittedFunc func( inter *Interpreter, event *CompositeValue, eventType *sema.CompositeType, -) +) error // OnStatementFunc is a function that is triggered when a statement is about to be executed. // @@ -160,7 +160,7 @@ type ImportLocationHandlerFunc func( ) Import // UUIDHandlerFunc is a function that handles the generation of UUIDs. -type UUIDHandlerFunc func() uint64 +type UUIDHandlerFunc func() (uint64, error) // CompositeTypeCode contains the the "prepared" / "callable" "code" // for the functions and the destructor of a composite @@ -2557,7 +2557,18 @@ func (interpreter *Interpreter) declareNonEnumCompositeValue( fields := map[string]Value{} if declaration.CompositeKind == common.CompositeKindResource { - uuid := interpreter.uuidHandler() + + if interpreter.uuidHandler == nil { + panic(UUIDUnavailableError{ + LocationRange: invocation.LocationRange, + }) + } + + uuid, err := interpreter.uuidHandler() + if err != nil { + panic(err) + } + fields[sema.ResourceUUIDFieldName] = UInt64Value(uuid) } @@ -3489,7 +3500,16 @@ func (interpreter *Interpreter) VisitEmitStatement(statement *ast.EmitStatement) eventType := interpreter.Checker.Elaboration.EmitStatementEventTypes[statement] - interpreter.onEventEmitted(interpreter, event, eventType) + if interpreter.onEventEmitted == nil { + panic(EventEmissionUnavailableError{ + LocationRange: interpreter.locationRange(statement), + }) + } + + err := interpreter.onEventEmitted(interpreter, event, eventType) + if err != nil { + panic(err) + } // NOTE: no result, so it does *not* act like a return-statement return Done{} diff --git a/runtime/repl.go b/runtime/repl.go index f0200f6bfb..c464dc68fd 100644 --- a/runtime/repl.go +++ b/runtime/repl.go @@ -69,9 +69,9 @@ func NewREPL(onError func(error), onResult func(interpreter.Value), checkerOptio inter, err := interpreter.NewInterpreter( checker, interpreter.WithPredefinedValues(values), - interpreter.WithUUIDHandler(func() uint64 { + interpreter.WithUUIDHandler(func() (uint64, error) { defer func() { uuid++ }() - return uuid + return uuid, nil }), ) if err != nil { diff --git a/runtime/runtime.go b/runtime/runtime.go index d0e904b8b6..84aac01ff4 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -313,9 +313,11 @@ func (r *interpreterRuntime) ExecuteTransaction( var authorizers []Address wrapPanic(func() { - authorizers = runtimeInterface.GetSigningAccounts() + authorizers, err = runtimeInterface.GetSigningAccounts() }) - + if err != nil { + return newError(err) + } // check parameter count argumentCount := len(arguments) @@ -540,35 +542,44 @@ func (r *interpreterRuntime) parseAndCheckProgram( sema.WithPredeclaredValues(valueDeclarations), sema.WithPredeclaredTypes(typeDeclarations), sema.WithValidTopLevelDeclarationsHandler(validTopLevelDeclarations), - sema.WithLocationHandler(runtimeInterface.ResolveLocation), - sema.WithImportHandler(func(checker *sema.Checker, location ast.Location) (sema.Import, *sema.CheckerError) { - switch location { - case stdlib.CryptoChecker.Location: - return sema.CheckerImport{ - Checker: stdlib.CryptoChecker, - }, nil - - default: - var program *ast.Program - var err error - checker, checkerErr := checker.EnsureLoaded(location, func() *ast.Program { - program, err = importResolver(location) - return program + sema.WithLocationHandler( + func(identifiers []Identifier, location Location) (res []ResolvedLocation, err error) { + wrapPanic(func() { + res, err = runtimeInterface.ResolveLocation(identifiers, location) }) - // TODO: improve - if err != nil { - return nil, &sema.CheckerError{ - Errors: []error{err}, + return + }, + ), + sema.WithImportHandler( + func(checker *sema.Checker, location ast.Location) (sema.Import, *sema.CheckerError) { + switch location { + case stdlib.CryptoChecker.Location: + return sema.CheckerImport{ + Checker: stdlib.CryptoChecker, + }, nil + + default: + var program *ast.Program + var err error + checker, checkerErr := checker.EnsureLoaded(location, func() *ast.Program { + program, err = importResolver(location) + return program + }) + // TODO: improve + if err != nil { + return nil, &sema.CheckerError{ + Errors: []error{err}, + } } + if checkerErr != nil { + return nil, checkerErr + } + return sema.CheckerImport{ + Checker: checker, + }, nil } - if checkerErr != nil { - return nil, checkerErr - } - return sema.CheckerImport{ - Checker: checker, - }, nil - } - }), + }, + ), sema.WithCheckHandler(func(location ast.Location, check func()) { reportMetric( func() { @@ -619,8 +630,8 @@ func (r *interpreterRuntime) newInterpreter( inter *interpreter.Interpreter, eventValue *interpreter.CompositeValue, eventType *sema.CompositeType, - ) { - r.emitEvent(inter, runtimeInterface, eventValue, eventType) + ) error { + return r.emitEvent(inter, runtimeInterface, eventValue, eventType) }, ), interpreter.WithStorageKeyHandler( @@ -631,9 +642,9 @@ func (r *interpreterRuntime) newInterpreter( interpreter.WithInjectedCompositeFieldsHandler( r.injectedCompositeFieldsHandler(runtimeInterface, runtimeStorage), ), - interpreter.WithUUIDHandler(func() (uuid uint64) { + interpreter.WithUUIDHandler(func() (uuid uint64, err error) { wrapPanic(func() { - uuid = runtimeInterface.GenerateUUID() + uuid, err = runtimeInterface.GenerateUUID() }) return }), @@ -781,6 +792,13 @@ func (r *interpreterRuntime) meteringInterpreterOptions(runtimeInterface Interfa return } + var err error + wrapPanic(func() { + err = runtimeInterface.SetComputationUsed(used) + }) + if err != nil { + panic(err) + } panic(ComputationLimitExceededError{ Limit: limit, }) @@ -901,7 +919,7 @@ func (r *interpreterRuntime) emitEvent( runtimeInterface Interface, event *interpreter.CompositeValue, eventType *sema.CompositeType, -) { +) error { fields := make([]exportableValue, len(eventType.ConstructorParameters)) for i, parameter := range eventType.ConstructorParameters { @@ -918,9 +936,7 @@ func (r *interpreterRuntime) emitEvent( wrapPanic(func() { err = runtimeInterface.EmitEvent(exportedEvent) }) - if err != nil { - panic(err) - } + return err } func (r *interpreterRuntime) emitAccountEvent( @@ -1304,18 +1320,26 @@ func (r *interpreterRuntime) newGetAccountFunction(runtimeInterface Interface) i func (r *interpreterRuntime) newLogFunction(runtimeInterface Interface) interpreter.HostFunction { return func(invocation interpreter.Invocation) trampoline.Trampoline { message := fmt.Sprint(invocation.Arguments[0]) + var err error wrapPanic(func() { - runtimeInterface.Log(message) + err = runtimeInterface.Log(message) }) + if err != nil { + panic(err) + } result := interpreter.VoidValue{} return trampoline.Done{Result: result} } } -func (r *interpreterRuntime) getCurrentBlockHeight(runtimeInterface Interface) (currentBlockHeight uint64) { +func (r *interpreterRuntime) getCurrentBlockHeight(runtimeInterface Interface) (currentBlockHeight uint64, err error) { + var er error wrapPanic(func() { - currentBlockHeight = runtimeInterface.GetCurrentBlockHeight() + currentBlockHeight, er = runtimeInterface.GetCurrentBlockHeight() }) + if er != nil { + return 0, newError(er) + } return } @@ -1343,7 +1367,14 @@ func (r *interpreterRuntime) getBlockAtHeight(height uint64, runtimeInterface In func (r *interpreterRuntime) newGetCurrentBlockFunction(runtimeInterface Interface) interpreter.HostFunction { return func(invocation interpreter.Invocation) trampoline.Trampoline { - height := r.getCurrentBlockHeight(runtimeInterface) + var height uint64 + var err error + wrapPanic(func() { + height, err = r.getCurrentBlockHeight(runtimeInterface) + }) + if err != nil { + panic(err) + } block, err := r.getBlockAtHeight(height, runtimeInterface) if err != nil { panic(err) @@ -1372,9 +1403,13 @@ func (r *interpreterRuntime) newGetBlockFunction(runtimeInterface Interface) int func (r *interpreterRuntime) newUnsafeRandomFunction(runtimeInterface Interface) interpreter.HostFunction { return func(invocation interpreter.Invocation) trampoline.Trampoline { var rand uint64 + var err error wrapPanic(func() { - rand = runtimeInterface.UnsafeRandom() + rand, err = runtimeInterface.UnsafeRandom() }) + if err != nil { + panic(err) + } return trampoline.Done{Result: interpreter.UInt64Value(rand)} } } diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index e5095ceeef..038400968d 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -87,7 +87,7 @@ func newTestStorage( } type testRuntimeInterface struct { - resolveLocation func(identifiers []Identifier, location Location) []ResolvedLocation + resolveLocation func(identifiers []Identifier, location Location) ([]ResolvedLocation, error) getCode func(_ Location) ([]byte, error) getCachedProgram func(Location) (*ast.Program, error) cacheProgram func(Location, *ast.Program) error @@ -98,10 +98,10 @@ type testRuntimeInterface struct { updateAccountContractCode func(address Address, name string, code []byte) error getAccountContractCode func(address Address, name string) (code []byte, err error) removeAccountContractCode func(address Address, name string) (err error) - getSigningAccounts func() []Address + getSigningAccounts func() ([]Address, error) log func(string) emitEvent func(cadence.Event) error - generateUUID func() uint64 + generateUUID func() (uint64, error) computationLimit uint64 decodeArgument func(b []byte, t cadence.Type) (cadence.Value, error) programParsed func(location ast.Location, duration time.Duration) @@ -109,7 +109,7 @@ type testRuntimeInterface struct { programInterpreted func(location ast.Location, duration time.Duration) valueEncoded func(duration time.Duration) valueDecoded func(duration time.Duration) - unsafeRandom func() uint64 + unsafeRandom func() (uint64, error) verifySignature func( signature []byte, tag string, @@ -117,8 +117,8 @@ type testRuntimeInterface struct { publicKey []byte, signatureAlgorithm string, hashAlgorithm string, - ) bool - hash func(data []byte, hashAlgorithm string) []byte + ) (bool, error) + hash func(data []byte, hashAlgorithm string) ([]byte, error) setCadenceValue func(owner Address, key string, value cadence.Value) (err error) getStorageUsed func(_ Address) (uint64, error) getStorageCapacity func(_ Address) (uint64, error) @@ -126,14 +126,14 @@ type testRuntimeInterface struct { var _ Interface = &testRuntimeInterface{} -func (i *testRuntimeInterface) ResolveLocation(identifiers []Identifier, location Location) []ResolvedLocation { +func (i *testRuntimeInterface) ResolveLocation(identifiers []Identifier, location Location) ([]ResolvedLocation, error) { if i.resolveLocation == nil { return []ResolvedLocation{ { Location: location, Identifiers: identifiers, }, - } + }, nil } return i.resolveLocation(identifiers, location) } @@ -195,24 +195,25 @@ func (i *testRuntimeInterface) RemoveAccountContractCode(address Address, name s return i.removeAccountContractCode(address, name) } -func (i *testRuntimeInterface) GetSigningAccounts() []Address { +func (i *testRuntimeInterface) GetSigningAccounts() ([]Address, error) { if i.getSigningAccounts == nil { - return nil + return nil, nil } return i.getSigningAccounts() } -func (i *testRuntimeInterface) Log(message string) { +func (i *testRuntimeInterface) Log(message string) error { i.log(message) + return nil } func (i *testRuntimeInterface) EmitEvent(event cadence.Event) error { return i.emitEvent(event) } -func (i *testRuntimeInterface) GenerateUUID() uint64 { +func (i *testRuntimeInterface) GenerateUUID() (uint64, error) { if i.generateUUID == nil { - return 0 + return 0, nil } return i.generateUUID() } @@ -221,6 +222,10 @@ func (i *testRuntimeInterface) GetComputationLimit() uint64 { return i.computationLimit } +func (i *testRuntimeInterface) SetComputationUsed(uint64) error { + return nil +} + func (i *testRuntimeInterface) DecodeArgument(b []byte, t cadence.Type) (cadence.Value, error) { return i.decodeArgument(b, t) } @@ -260,8 +265,8 @@ func (i *testRuntimeInterface) ValueDecoded(duration time.Duration) { i.valueDecoded(duration) } -func (i *testRuntimeInterface) GetCurrentBlockHeight() uint64 { - return 1 +func (i *testRuntimeInterface) GetCurrentBlockHeight() (uint64, error) { + return 1, nil } func (i *testRuntimeInterface) GetBlockAtHeight(height uint64) (block Block, exists bool, err error) { @@ -285,9 +290,9 @@ func (i *testRuntimeInterface) GetBlockAtHeight(height uint64) (block Block, exi return block, true, nil } -func (i *testRuntimeInterface) UnsafeRandom() uint64 { +func (i *testRuntimeInterface) UnsafeRandom() (uint64, error) { if i.unsafeRandom == nil { - return 0 + return 0, nil } return i.unsafeRandom() } @@ -299,9 +304,9 @@ func (i *testRuntimeInterface) VerifySignature( publicKey []byte, signatureAlgorithm string, hashAlgorithm string, -) bool { +) (bool, error) { if i.verifySignature == nil { - return false + return false, nil } return i.verifySignature( signature, @@ -313,9 +318,9 @@ func (i *testRuntimeInterface) VerifySignature( ) } -func (i *testRuntimeInterface) Hash(data []byte, hashAlgorithm string) []byte { +func (i *testRuntimeInterface) Hash(data []byte, hashAlgorithm string) ([]byte, error) { if i.hash == nil { - return nil + return nil, nil } return i.hash(data, hashAlgorithm) } @@ -508,8 +513,8 @@ func TestRuntimeInvalidTransactionArgumentAccount(t *testing.T) { `) runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, } @@ -536,10 +541,10 @@ func TestRuntimeTransactionWithAccount(t *testing.T) { var loggedMessage string runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { + getSigningAccounts: func() ([]Address, error) { return []Address{ common.BytesToAddress([]byte{42}), - } + }, nil }, log: func(message string) { loggedMessage = message @@ -822,7 +827,7 @@ func TestRuntimeTransactionWithArguments(t *testing.T) { var loggedMessages []string runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { return tt.authorizers }, + getSigningAccounts: func() ([]Address, error) { return tt.authorizers, nil }, decodeArgument: func(b []byte, t cadence.Type) (cadence.Value, error) { return jsoncdc.Decode(b) }, @@ -1272,8 +1277,8 @@ func TestRuntimeStorage(t *testing.T) { } }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -1367,8 +1372,8 @@ func TestRuntimeStorageMultipleTransactionsResourceWithArray(t *testing.T) { } }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -1443,8 +1448,8 @@ func TestRuntimeStorageMultipleTransactionsResourceFunction(t *testing.T) { } }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -1519,8 +1524,8 @@ func TestRuntimeStorageMultipleTransactionsResourceField(t *testing.T) { } }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -1596,8 +1601,8 @@ func TestRuntimeCompositeFunctionInvocationFromImportingProgram(t *testing.T) { } }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, } @@ -1663,8 +1668,8 @@ func TestRuntimeResourceContractUseThroughReference(t *testing.T) { } }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -1738,8 +1743,8 @@ func TestRuntimeResourceContractUseThroughLink(t *testing.T) { } }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -1827,8 +1832,8 @@ func TestRuntimeResourceContractWithInterface(t *testing.T) { } }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -1896,8 +1901,8 @@ func TestScriptReturnTypeNotReturnableError(t *testing.T) { runtime := NewInterpreterRuntime() runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, } @@ -1978,8 +1983,8 @@ func TestScriptParameterTypeNotStorableError(t *testing.T) { `) runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, } @@ -2002,8 +2007,8 @@ func TestRuntimeSyntaxError(t *testing.T) { `) runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, } @@ -2069,8 +2074,8 @@ func TestRuntimeStorageChanges(t *testing.T) { } }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -2107,8 +2112,8 @@ func TestRuntimeAccountAddress(t *testing.T) { address := common.BytesToAddress([]byte{42}) runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { - return []Address{address} + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -2142,8 +2147,8 @@ func TestRuntimePublicAccountAddress(t *testing.T) { address := interpreter.NewAddressValueFromBytes([]byte{0x42}) runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { - return nil + getSigningAccounts: func() ([]Address, error) { + return nil, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -2217,8 +2222,8 @@ func TestRuntimeAccountPublishAndAccess(t *testing.T) { } }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{address} + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -2254,8 +2259,8 @@ func TestRuntimeTransaction_CreateAccount(t *testing.T) { runtimeInterface := &testRuntimeInterface{ storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, createAccount: func(payer Address) (address Address, err error) { return Address{42}, nil @@ -2341,8 +2346,8 @@ func TestRuntimeTransaction_AddPublicKey(t *testing.T) { runtimeInterface := &testRuntimeInterface{ storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, createAccount: func(payer Address) (address Address, err error) { return Address{42}, nil @@ -2540,8 +2545,8 @@ func TestRuntimeTransactionWithContractDeployment(t *testing.T) { runtimeInterface := &testRuntimeInterface{ storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { return accountCode, nil @@ -2624,8 +2629,8 @@ func TestRuntimeContractAccount(t *testing.T) { return accountCode, nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{common.BytesToAddress(addressValue.Bytes())} + getSigningAccounts: func() ([]Address, error) { + return []Address{common.BytesToAddress(addressValue.Bytes())}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { @@ -2711,8 +2716,8 @@ func TestRuntimeContractNestedResource(t *testing.T) { return accountCode, nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{addressValue} + getSigningAccounts: func() ([]Address, error) { + return []Address{addressValue}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { @@ -2722,7 +2727,7 @@ func TestRuntimeContractNestedResource(t *testing.T) { accountCode = code return nil }, - emitEvent: func(event cadence.Event) error {return nil}, + emitEvent: func(event cadence.Event) error { return nil }, log: func(message string) { loggedMessage = message }, @@ -2907,8 +2912,8 @@ func TestRuntimeFungibleTokenUpdateAccountCode(t *testing.T) { return accountCodes[key], nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{signerAccount} + getSigningAccounts: func() ([]Address, error) { + return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(address Address, name string) (code []byte, err error) { @@ -3031,8 +3036,8 @@ func TestRuntimeFungibleTokenCreateAccount(t *testing.T) { createAccount: func(payer Address) (address Address, err error) { return address2Value, nil }, - getSigningAccounts: func() []Address { - return []Address{signerAccount} + getSigningAccounts: func() ([]Address, error) { + return []Address{signerAccount}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(address Address, name string) (code []byte, err error) { @@ -3173,8 +3178,8 @@ func TestRuntimeInvokeStoredInterfaceFunction(t *testing.T) { nextAccount++ return result.ToAddress(), nil }, - getSigningAccounts: func() []Address { - return []Address{{0x1}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{0x1}}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(address Address, name string) (code []byte, err error) { @@ -3279,8 +3284,8 @@ func TestRuntimeBlock(t *testing.T) { var loggedMessages []string runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { - return nil + getSigningAccounts: func() ([]Address, error) { + return nil, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -3327,8 +3332,8 @@ func TestUnsafeRandom(t *testing.T) { var loggedMessages []string runtimeInterface := &testRuntimeInterface{ - unsafeRandom: func() uint64 { - return 7558174677681708339 + unsafeRandom: func() (uint64, error) { + return 7558174677681708339, nil }, log: func(message string) { loggedMessages = append(loggedMessages, message) @@ -3362,8 +3367,8 @@ func TestRuntimeTransactionTopLevelDeclarations(t *testing.T) { `) runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { - return nil + getSigningAccounts: func() ([]Address, error) { + return nil, nil }, } @@ -3383,8 +3388,8 @@ func TestRuntimeTransactionTopLevelDeclarations(t *testing.T) { `) runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { - return nil + getSigningAccounts: func() ([]Address, error) { + return nil, nil }, } @@ -3444,8 +3449,8 @@ func TestRuntimeStoreIntegerTypes(t *testing.T) { return accountCode, nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{addressValue.ToAddress()} + getSigningAccounts: func() ([]Address, error) { + return []Address{addressValue.ToAddress()}, nil }, getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { return accountCode, nil @@ -3553,8 +3558,8 @@ func TestInterpretResourceOwnerFieldUseComposite(t *testing.T) { return accountCodes[key], nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{address} + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(address Address, name string) (code []byte, err error) { @@ -3709,8 +3714,8 @@ func TestInterpretResourceOwnerFieldUseArray(t *testing.T) { return accountCodes[key], nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{address} + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil }, getAccountContractCode: func(address Address, name string) (code []byte, err error) { location := AddressLocation{ @@ -3870,8 +3875,8 @@ func TestInterpretResourceOwnerFieldUseDictionary(t *testing.T) { return accountCodes[key], nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{address} + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(address Address, name string) (code []byte, err error) { @@ -3891,7 +3896,7 @@ func TestInterpretResourceOwnerFieldUseDictionary(t *testing.T) { accountCodes[key] = code return nil }, - emitEvent: func(event cadence.Event) error{ + emitEvent: func(event cadence.Event) error { events = append(events, event) return nil }, @@ -4001,8 +4006,8 @@ func TestRuntimeComputationLimit(t *testing.T) { runtime := NewInterpreterRuntime() runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { - return nil + getSigningAccounts: func() ([]Address, error) { + return nil, nil }, computationLimit: computationLimit, } @@ -4096,8 +4101,8 @@ func TestRuntimeMetrics(t *testing.T) { runtimeInterface = &testRuntimeInterface{ storage: storage, - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, getCode: func(location Location) (bytes []byte, err error) { switch location { @@ -4268,8 +4273,8 @@ func TestRuntimeContractWriteback(t *testing.T) { return accountCode, nil }, storage: newTestStorage(nil, onWrite), - getSigningAccounts: func() []Address { - return []Address{common.BytesToAddress(addressValue.Bytes())} + getSigningAccounts: func() ([]Address, error) { + return []Address{common.BytesToAddress(addressValue.Bytes())}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { @@ -4279,7 +4284,7 @@ func TestRuntimeContractWriteback(t *testing.T) { accountCode = code return nil }, - emitEvent: func(event cadence.Event) error{ + emitEvent: func(event cadence.Event) error { events = append(events, event) return nil }, @@ -4366,8 +4371,8 @@ func TestRuntimeStorageWriteback(t *testing.T) { return accountCode, nil }, storage: newTestStorage(nil, onWrite), - getSigningAccounts: func() []Address { - return []Address{common.BytesToAddress(addressValue.Bytes())} + getSigningAccounts: func() ([]Address, error) { + return []Address{common.BytesToAddress(addressValue.Bytes())}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { @@ -4451,8 +4456,8 @@ func TestRuntimeExternalError(t *testing.T) { type logPanic struct{} runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { - return nil + getSigningAccounts: func() ([]Address, error) { + return nil, nil }, log: func(message string) { panic(logPanic{}) @@ -4538,8 +4543,8 @@ func TestRuntimeDeployCodeCaching(t *testing.T) { return cachedPrograms[location.ID()], nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return signerAddresses + getSigningAccounts: func() ([]Address, error) { + return signerAddresses, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(address Address, name string) (code []byte, err error) { @@ -4661,8 +4666,8 @@ func TestRuntimeUpdateCodeCaching(t *testing.T) { return cachedPrograms[location.ID()], nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return signerAddresses + getSigningAccounts: func() ([]Address, error) { + return signerAddresses, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(address Address, name string) (code []byte, err error) { @@ -4682,7 +4687,7 @@ func TestRuntimeUpdateCodeCaching(t *testing.T) { accountCodes[key] = code return nil }, - emitEvent: func(event cadence.Event) error{ + emitEvent: func(event cadence.Event) error { events = append(events, event) return nil }, @@ -4803,8 +4808,8 @@ func TestRuntimeNoCacheHitForToplevelPrograms(t *testing.T) { return cachedPrograms[location.ID()], nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return signerAddresses + getSigningAccounts: func() ([]Address, error) { + return signerAddresses, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(address Address, name string) (code []byte, err error) { @@ -4949,13 +4954,13 @@ func TestRuntimeTransaction_ContractUpdate(t *testing.T) { runtimeInterface := &testRuntimeInterface{ storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{common.BytesToAddress([]byte{0x42})} + getSigningAccounts: func() ([]Address, error) { + return []Address{common.BytesToAddress([]byte{0x42})}, nil }, getCode: func(_ Location) (bytes []byte, err error) { return accountCode, nil }, - resolveLocation: func(identifiers []Identifier, location Location) []ResolvedLocation { + resolveLocation: func(identifiers []Identifier, location Location) ([]ResolvedLocation, error) { require.Empty(t, identifiers) require.IsType(t, AddressLocation{}, location) @@ -4971,7 +4976,7 @@ func TestRuntimeTransaction_ContractUpdate(t *testing.T) { }, }, }, - } + }, nil }, getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { return accountCode, nil @@ -5103,8 +5108,8 @@ func TestRuntime(t *testing.T) { } } -func singleIdentifierLocationResolver(t *testing.T) func(identifiers []Identifier, location Location) []ResolvedLocation { - return func(identifiers []Identifier, location Location) []ResolvedLocation { +func singleIdentifierLocationResolver(t *testing.T) func(identifiers []Identifier, location Location) ([]ResolvedLocation, error) { + return func(identifiers []Identifier, location Location) ([]ResolvedLocation, error) { require.Len(t, identifiers, 1) require.IsType(t, AddressLocation{}, location) @@ -5116,7 +5121,7 @@ func singleIdentifierLocationResolver(t *testing.T) func(identifiers []Identifie }, Identifiers: identifiers, }, - } + }, nil } } @@ -5133,8 +5138,8 @@ func TestPanics(t *testing.T) { `) runtimeInterface := &testRuntimeInterface{ - getSigningAccounts: func() []Address { - return []Address{{42}} + getSigningAccounts: func() ([]Address, error) { + return []Address{{42}}, nil }, } diff --git a/runtime/sema/check_import_declaration.go b/runtime/sema/check_import_declaration.go index 4e46c6666d..3bca4230d8 100644 --- a/runtime/sema/check_import_declaration.go +++ b/runtime/sema/check_import_declaration.go @@ -50,7 +50,11 @@ func (checker *Checker) declareImportDeclaration(declaration *ast.ImportDeclarat EndPos: declaration.LocationPos, } - resolvedLocations := checker.resolveLocation(declaration.Identifiers, declaration.Location) + resolvedLocations, err := checker.resolveLocation(declaration.Identifiers, declaration.Location) + if err != nil { + checker.report(err) + return nil + } checker.Elaboration.ImportDeclarationsResolvedLocations[declaration] = resolvedLocations @@ -61,7 +65,7 @@ func (checker *Checker) declareImportDeclaration(declaration *ast.ImportDeclarat return nil } -func (checker *Checker) resolveLocation(identifiers []ast.Identifier, location ast.Location) []ResolvedLocation { +func (checker *Checker) resolveLocation(identifiers []ast.Identifier, location ast.Location) ([]ResolvedLocation, error) { // If no location handler is available, // default to resolving to a single location that declares all identifiers @@ -72,12 +76,11 @@ func (checker *Checker) resolveLocation(identifiers []ast.Identifier, location a Location: location, Identifiers: identifiers, }, - } + }, nil } // A location handler is available, // use it to resolve the location / identifiers - return checker.locationHandler(identifiers, location) } diff --git a/runtime/sema/checker.go b/runtime/sema/checker.go index 6de9a60990..e20a191e26 100644 --- a/runtime/sema/checker.go +++ b/runtime/sema/checker.go @@ -72,7 +72,7 @@ type ResolvedLocation struct { Identifiers []ast.Identifier } -type LocationHandlerFunc func(identifiers []ast.Identifier, location ast.Location) []ResolvedLocation +type LocationHandlerFunc func(identifiers []ast.Identifier, location ast.Location) ([]ResolvedLocation, error) type ImportHandlerFunc func(checker *Checker, location ast.Location) (Import, *CheckerError) diff --git a/runtime/stdlib/crypto.go b/runtime/stdlib/crypto.go index 25ceff0163..81701c7c7c 100644 --- a/runtime/stdlib/crypto.go +++ b/runtime/stdlib/crypto.go @@ -21,14 +21,14 @@ type CryptoSignatureVerifier interface { publicKey []byte, signatureAlgorithm string, hashAlgorithm string, - ) bool + ) (bool, error) } type CryptoHasher interface { Hash( data []byte, hashAlgorithm string, - ) []byte + ) ([]byte, error) } var CryptoChecker = func() *sema.Checker { @@ -107,13 +107,16 @@ func newCryptoContractVerifySignatureFunction(signatureVerifier CryptoSignatureV } hashAlgorithm := hashAlgorithmStringValue.Str - isValid := signatureVerifier.VerifySignature(signature, + isValid, err := signatureVerifier.VerifySignature(signature, tag, signedData, publicKey, signatureAlgorithm, hashAlgorithm, ) + if err != nil { + panic(err) + } return trampoline.Done{Result: interpreter.BoolValue(isValid)} }, @@ -153,7 +156,11 @@ func newCryptoContractHashFunction(hasher CryptoHasher) interpreter.FunctionValu } hashAlgorithm := hashAlgorithmStringValue.Str - digest := hasher.Hash(data, hashAlgorithm) + digest, err := hasher.Hash(data, hashAlgorithm) + if err != nil { + panic(err) + + } result := interpreter.ByteSliceToByteArrayValue(digest) diff --git a/runtime/storage_test.go b/runtime/storage_test.go index 2a8239cc1d..1586eb06f1 100644 --- a/runtime/storage_test.go +++ b/runtime/storage_test.go @@ -102,8 +102,8 @@ func TestRuntimeHighLevelStorage(t *testing.T) { return accountCode, nil }, storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { - return []Address{address} + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil }, resolveLocation: singleIdentifierLocationResolver(t), getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { @@ -258,8 +258,8 @@ func TestRuntimeMagic(t *testing.T) { runtimeInterface := &testRuntimeInterface{ storage: newTestStorage(nil, onWrite), - getSigningAccounts: func() []Address { - return []Address{address} + getSigningAccounts: func() ([]Address, error) { + return []Address{address}, nil }, } diff --git a/runtime/tests/checker/import_test.go b/runtime/tests/checker/import_test.go index f0ca09ee8a..5e38c22ecb 100644 --- a/runtime/tests/checker/import_test.go +++ b/runtime/tests/checker/import_test.go @@ -131,7 +131,7 @@ func TestCheckRepeatedImportResolution(t *testing.T) { ParseAndCheckOptions{ Options: []sema.Option{ sema.WithLocationHandler( - func(identifiers []ast.Identifier, location ast.Location) (result []sema.ResolvedLocation) { + func(identifiers []ast.Identifier, location ast.Location) (result []sema.ResolvedLocation, err error) { for _, identifier := range identifiers { result = append(result, sema.ResolvedLocation{ Location: ast.AddressLocation{ @@ -253,7 +253,7 @@ func TestCheckImportResolutionSplit(t *testing.T) { ParseAndCheckOptions{ Options: []sema.Option{ sema.WithLocationHandler( - func(identifiers []ast.Identifier, location ast.Location) (result []sema.ResolvedLocation) { + func(identifiers []ast.Identifier, location ast.Location) (result []sema.ResolvedLocation, err error) { for _, identifier := range identifiers { result = append(result, sema.ResolvedLocation{ Location: ast.AddressLocation{ diff --git a/runtime/tests/interpreter/import_test.go b/runtime/tests/interpreter/import_test.go index 167f8de3b8..b385dd1e42 100644 --- a/runtime/tests/interpreter/import_test.go +++ b/runtime/tests/interpreter/import_test.go @@ -183,7 +183,7 @@ func TestInterpretImportMultipleProgramsFromLocation(t *testing.T) { checker.ParseAndCheckOptions{ Options: []sema.Option{ sema.WithLocationHandler( - func(identifiers []ast.Identifier, location ast.Location) (result []sema.ResolvedLocation) { + func(identifiers []ast.Identifier, location ast.Location) (result []sema.ResolvedLocation, err error) { require.Equal(t, ast.AddressLocation{ diff --git a/runtime/tests/interpreter/interpreter_test.go b/runtime/tests/interpreter/interpreter_test.go index 78b1cba4d8..4086b4b2b9 100644 --- a/runtime/tests/interpreter/interpreter_test.go +++ b/runtime/tests/interpreter/interpreter_test.go @@ -77,9 +77,9 @@ func parseCheckAndInterpretWithOptions( interpreterOptions := append( []interpreter.Option{ - interpreter.WithUUIDHandler(func() uint64 { + interpreter.WithUUIDHandler(func() (uint64, error) { uuid++ - return uuid + return uuid, nil }), }, options.Options..., @@ -3714,8 +3714,8 @@ func TestInterpretInitializerWithInterfacePreCondition(t *testing.T) { } } - uuidHandler := interpreter.WithUUIDHandler(func() uint64 { - return 0 + uuidHandler := interpreter.WithUUIDHandler(func() (uint64, error) { + return 0, nil }) if compositeKind == common.CompositeKindContract { @@ -5701,8 +5701,9 @@ func TestInterpretEmitEvent(t *testing.T) { ) inter.SetOnEventEmittedHandler( - func(_ *interpreter.Interpreter, event *interpreter.CompositeValue, eventType *sema.CompositeType) { + func(_ *interpreter.Interpreter, event *interpreter.CompositeValue, eventType *sema.CompositeType) error { actualEvents = append(actualEvents, event) + return nil }, ) @@ -5901,8 +5902,9 @@ func TestInterpretEmitEventParameterTypes(t *testing.T) { var actualEvents []*interpreter.CompositeValue inter.SetOnEventEmittedHandler( - func(_ *interpreter.Interpreter, event *interpreter.CompositeValue, eventType *sema.CompositeType) { + func(_ *interpreter.Interpreter, event *interpreter.CompositeValue, eventType *sema.CompositeType) error { actualEvents = append(actualEvents, event) + return nil }, ) diff --git a/runtime/tests/interpreter/uuid_test.go b/runtime/tests/interpreter/uuid_test.go index 5ddfde88ca..6341ece3a4 100644 --- a/runtime/tests/interpreter/uuid_test.go +++ b/runtime/tests/interpreter/uuid_test.go @@ -93,9 +93,9 @@ func TestInterpretResourceUUID(t *testing.T) { inter, err := interpreter.NewInterpreter( importingChecker, interpreter.WithUUIDHandler( - func() uint64 { + func() (uint64, error) { defer func() { uuid++ }() - return uuid + return uuid, nil }, ), interpreter.WithImportLocationHandler( diff --git a/runtime/type_test.go b/runtime/type_test.go index 90e1be67ed..3f0b7f0025 100644 --- a/runtime/type_test.go +++ b/runtime/type_test.go @@ -54,10 +54,10 @@ func TestRuntimeTypeStorage(t *testing.T) { runtimeInterface := &testRuntimeInterface{ storage: newTestStorage(nil, nil), - getSigningAccounts: func() []Address { + getSigningAccounts: func() ([]Address, error) { return []Address{ common.BytesToAddress([]byte{42}), - } + }, nil }, log: func(message string) { loggedMessage = message