From 2874423ff59983b2a5cb13539f64643877bacf99 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 17 Oct 2024 11:57:23 -0700 Subject: [PATCH 1/6] remove Crypto contract --- runtime/cmd/cmd.go | 7 - runtime/crypto_test.go | 82 ------ runtime/environment.go | 190 +++++-------- runtime/runtime_test.go | 2 - runtime/stdlib/contracts/crypto.cdc | 177 ------------ runtime/stdlib/contracts/crypto.go | 26 -- runtime/stdlib/contracts/crypto_test.cdc | 341 ----------------------- runtime/stdlib/crypto.go | 118 +------- runtime/stdlib/crypto_test.go | 31 --- runtime/stdlib/test.go | 11 - tools/analysis/analysis.go | 7 +- tools/analysis/analysis_test.go | 31 ++- tools/analysis/config.go | 2 + tools/analysis/programs.go | 34 ++- 14 files changed, 127 insertions(+), 932 deletions(-) delete mode 100644 runtime/stdlib/contracts/crypto.cdc delete mode 100644 runtime/stdlib/contracts/crypto.go delete mode 100644 runtime/stdlib/contracts/crypto_test.cdc delete mode 100644 runtime/stdlib/crypto_test.go diff --git a/runtime/cmd/cmd.go b/runtime/cmd/cmd.go index bbd43b2397..9cf8c372b4 100644 --- a/runtime/cmd/cmd.go +++ b/runtime/cmd/cmd.go @@ -97,13 +97,6 @@ func DefaultCheckerConfig( importedLocation common.Location, _ ast.Range, ) (sema.Import, error) { - if importedLocation == stdlib.CryptoCheckerLocation { - cryptoChecker := stdlib.CryptoChecker() - return sema.ElaborationImport{ - Elaboration: cryptoChecker.Elaboration, - }, nil - } - stringLocation, ok := importedLocation.(common.StringLocation) if !ok { return nil, &sema.CheckerError{ diff --git a/runtime/crypto_test.go b/runtime/crypto_test.go index 6cf6e1cec7..17a738511d 100644 --- a/runtime/crypto_test.go +++ b/runtime/crypto_test.go @@ -36,88 +36,6 @@ import ( . "github.com/onflow/cadence/runtime/tests/runtime_utils" ) -func TestRuntimeCrypto_verify(t *testing.T) { - - t.Parallel() - - runtime := NewTestInterpreterRuntime() - - script := []byte(` - import Crypto - - access(all) fun main(): Bool { - let publicKey = PublicKey( - publicKey: "0102".decodeHex(), - signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 - ) - - let keyList = Crypto.KeyList() - keyList.add( - publicKey, - hashAlgorithm: HashAlgorithm.SHA3_256, - weight: 1.0 - ) - - let signatureSet = [ - Crypto.KeyListSignature( - keyIndex: 0, - signature: "0304".decodeHex() - ) - ] - - return keyList.verify( - signatureSet: signatureSet, - signedData: "0506".decodeHex(), - domainSeparationTag: "foo" - ) - } - `) - - var called bool - - storage := NewTestLedger(nil, nil) - - runtimeInterface := &TestRuntimeInterface{ - Storage: storage, - OnVerifySignature: func( - signature []byte, - tag string, - signedData []byte, - publicKey []byte, - signatureAlgorithm SignatureAlgorithm, - hashAlgorithm HashAlgorithm, - ) (bool, error) { - called = true - assert.Equal(t, []byte{3, 4}, signature) - assert.Equal(t, "foo", tag) - assert.Equal(t, []byte{5, 6}, signedData) - assert.Equal(t, []byte{1, 2}, publicKey) - assert.Equal(t, SignatureAlgorithmECDSA_P256, signatureAlgorithm) - assert.Equal(t, HashAlgorithmSHA3_256, hashAlgorithm) - return true, nil - }, - } - addPublicKeyValidation(runtimeInterface, nil) - - result, err := runtime.ExecuteScript( - Script{ - Source: script, - }, - Context{ - Interface: runtimeInterface, - Location: common.ScriptLocation{}, - }, - ) - require.NoError(t, err) - - assert.Equal(t, - cadence.NewBool(true), - result, - ) - - assert.True(t, called) -} - func TestRuntimeHashAlgorithm_hash(t *testing.T) { t.Parallel() diff --git a/runtime/environment.go b/runtime/environment.go index 825e09a8a0..2cf7a87c2e 100644 --- a/runtime/environment.go +++ b/runtime/environment.go @@ -674,40 +674,29 @@ func (e *interpreterEnvironment) resolveImport( importRange ast.Range, ) (sema.Import, error) { - var elaboration *sema.Elaboration - switch importedLocation { - case stdlib.CryptoCheckerLocation: - cryptoChecker := stdlib.CryptoChecker() - elaboration = cryptoChecker.Elaboration - - default: - - // Check for cyclic imports - if e.checkedImports[importedLocation] { - return nil, &sema.CyclicImportsError{ - Location: importedLocation, - Range: importRange, - } - } else { - e.checkedImports[importedLocation] = true - defer delete(e.checkedImports, importedLocation) - } - - const getAndSetProgram = true - program, err := e.GetProgram( - importedLocation, - getAndSetProgram, - e.checkedImports, - ) - if err != nil { - return nil, err + // Check for cyclic imports + if e.checkedImports[importedLocation] { + return nil, &sema.CyclicImportsError{ + Location: importedLocation, + Range: importRange, } + } else { + e.checkedImports[importedLocation] = true + defer delete(e.checkedImports, importedLocation) + } - elaboration = program.Elaboration + const getAndSetProgram = true + program, err := e.GetProgram( + importedLocation, + getAndSetProgram, + e.checkedImports, + ) + if err != nil { + return nil, err } return sema.ElaborationImport{ - Elaboration: elaboration, + Elaboration: program.Elaboration, }, nil } @@ -1006,36 +995,30 @@ func (e *interpreterEnvironment) newInjectedCompositeFieldsHandler() interpreter compositeKind common.CompositeKind, ) map[string]interpreter.Value { - switch location { - case stdlib.CryptoCheckerLocation: - return nil + switch compositeKind { + case common.CompositeKindContract: + var address Address - default: - switch compositeKind { - case common.CompositeKindContract: - var address Address - - switch location := location.(type) { - case common.AddressLocation: - address = location.Address - default: - return nil - } + switch location := location.(type) { + case common.AddressLocation: + address = location.Address + default: + return nil + } - addressValue := interpreter.NewAddressValue( - inter, - address, - ) + addressValue := interpreter.NewAddressValue( + inter, + address, + ) - return map[string]interpreter.Value{ - sema.ContractAccountFieldName: stdlib.NewAccountReferenceValue( - inter, - e, - addressValue, - interpreter.FullyEntitledAccountAccess, - interpreter.EmptyLocationRange, - ), - } + return map[string]interpreter.Value{ + sema.ContractAccountFieldName: stdlib.NewAccountReferenceValue( + inter, + e, + addressValue, + interpreter.FullyEntitledAccountAccess, + interpreter.EmptyLocationRange, + ), } } @@ -1046,36 +1029,22 @@ func (e *interpreterEnvironment) newInjectedCompositeFieldsHandler() interpreter func (e *interpreterEnvironment) newImportLocationHandler() interpreter.ImportLocationHandlerFunc { return func(inter *interpreter.Interpreter, location common.Location) interpreter.Import { - switch location { - case stdlib.CryptoCheckerLocation: - cryptoChecker := stdlib.CryptoChecker() - program := interpreter.ProgramFromChecker(cryptoChecker) - subInterpreter, err := inter.NewSubInterpreter(program, location) - if err != nil { - panic(err) - } - return interpreter.InterpreterImport{ - Interpreter: subInterpreter, - } - - default: - const getAndSetProgram = true - program, err := e.GetProgram( - location, - getAndSetProgram, - importResolutionResults{}, - ) - if err != nil { - panic(err) - } + const getAndSetProgram = true + program, err := e.GetProgram( + location, + getAndSetProgram, + importResolutionResults{}, + ) + if err != nil { + panic(err) + } - subInterpreter, err := inter.NewSubInterpreter(program, location) - if err != nil { - panic(err) - } - return interpreter.InterpreterImport{ - Interpreter: subInterpreter, - } + subInterpreter, err := inter.NewSubInterpreter(program, location) + if err != nil { + panic(err) + } + return interpreter.InterpreterImport{ + Interpreter: subInterpreter, } } } @@ -1123,45 +1092,30 @@ func (e *interpreterEnvironment) newCompositeValueFunctionsHandler() interpreter func (e *interpreterEnvironment) loadContract( inter *interpreter.Interpreter, compositeType *sema.CompositeType, - constructorGenerator func(common.Address) *interpreter.HostFunctionValue, - invocationRange ast.Range, + _ func(common.Address) *interpreter.HostFunctionValue, + _ ast.Range, ) *interpreter.CompositeValue { - switch compositeType.Location { - case stdlib.CryptoCheckerLocation: - contract, err := stdlib.NewCryptoContract( - inter, - constructorGenerator(common.ZeroAddress), - invocationRange, - ) - if err != nil { - panic(err) - } - return contract - - default: - - var storedValue interpreter.Value + var storedValue interpreter.Value - switch location := compositeType.Location.(type) { - - case common.AddressLocation: - storageMap := e.storage.GetStorageMap( - location.Address, - StorageDomainContract, - false, - ) - if storageMap != nil { - storedValue = storageMap.ReadValue(inter, interpreter.StringStorageMapKey(location.Name)) - } - } - - if storedValue == nil { - panic(errors.NewDefaultUserError("failed to load contract: %s", compositeType.Location)) + switch location := compositeType.Location.(type) { + // TODO: support e.g. CryptoContractLocation + case common.AddressLocation: + storageMap := e.storage.GetStorageMap( + location.Address, + StorageDomainContract, + false, + ) + if storageMap != nil { + storedValue = storageMap.ReadValue(inter, interpreter.StringStorageMapKey(location.Name)) } + } - return storedValue.(*interpreter.CompositeValue) + if storedValue == nil { + panic(errors.NewDefaultUserError("failed to load contract: %s", compositeType.Location)) } + + return storedValue.(*interpreter.CompositeValue) } func (e *interpreterEnvironment) newOnFunctionInvocationHandler() func(_ *interpreter.Interpreter) { diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index d3f13fa003..cfd7fd69e8 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -7730,8 +7730,6 @@ func BenchmarkRuntimeScriptNoop(b *testing.B) { Environment: environment, } - require.NotNil(b, stdlib.CryptoChecker()) - runtime := NewTestInterpreterRuntime() b.ReportAllocs() diff --git a/runtime/stdlib/contracts/crypto.cdc b/runtime/stdlib/contracts/crypto.cdc deleted file mode 100644 index a8c50dcdfe..0000000000 --- a/runtime/stdlib/contracts/crypto.cdc +++ /dev/null @@ -1,177 +0,0 @@ - -access(all) contract Crypto { - - access(all) - fun hash(_ data: [UInt8], algorithm: HashAlgorithm): [UInt8] { - return algorithm.hash(data) - } - - access(all) - fun hashWithTag(_ data: [UInt8], tag: String, algorithm: HashAlgorithm): [UInt8] { - return algorithm.hashWithTag(data, tag: tag) - } - - access(all) - struct KeyListEntry { - - access(all) - let keyIndex: Int - - access(all) - let publicKey: PublicKey - - access(all) - let hashAlgorithm: HashAlgorithm - - access(all) - let weight: UFix64 - - access(all) - let isRevoked: Bool - - init( - keyIndex: Int, - publicKey: PublicKey, - hashAlgorithm: HashAlgorithm, - weight: UFix64, - isRevoked: Bool - ) { - self.keyIndex = keyIndex - self.publicKey = publicKey - self.hashAlgorithm = hashAlgorithm - self.weight = weight - self.isRevoked = isRevoked - } - } - - access(all) - struct KeyList { - - access(self) - let entries: [KeyListEntry] - - init() { - self.entries = [] - } - - /// Adds a new key with the given weight - access(all) - fun add( - _ publicKey: PublicKey, - hashAlgorithm: HashAlgorithm, - weight: UFix64 - ): KeyListEntry { - - let keyIndex = self.entries.length - let entry = KeyListEntry( - keyIndex: keyIndex, - publicKey: publicKey, - hashAlgorithm: hashAlgorithm, - weight: weight, - isRevoked: false - ) - self.entries.append(entry) - return entry - } - - /// Returns the key at the given index, if it exists. - /// Revoked keys are always returned, but they have the `isRevoked` field set to true - access(all) - fun get(keyIndex: Int): KeyListEntry? { - if keyIndex >= self.entries.length { - return nil - } - - return self.entries[keyIndex] - } - - /// Marks the key at the given index revoked, but does not delete it - access(all) - fun revoke(keyIndex: Int) { - if keyIndex >= self.entries.length { - return - } - - let currentEntry = self.entries[keyIndex] - self.entries[keyIndex] = KeyListEntry( - keyIndex: currentEntry.keyIndex, - publicKey: currentEntry.publicKey, - hashAlgorithm: currentEntry.hashAlgorithm, - weight: currentEntry.weight, - isRevoked: true - ) - } - - /// Returns true if the given signatures are valid for the given signed data - access(all) - fun verify( - signatureSet: [KeyListSignature], - signedData: [UInt8], - domainSeparationTag: String - ): Bool { - - var validWeights: UFix64 = 0.0 - - let seenKeyIndices: {Int: Bool} = {} - - for signature in signatureSet { - - // Ensure the key index is valid - - if signature.keyIndex >= self.entries.length { - return false - } - - // Ensure this key index has not already been seen - - if seenKeyIndices[signature.keyIndex] ?? false { - return false - } - - // Record the key index was seen - - seenKeyIndices[signature.keyIndex] = true - - // Get the actual key - - let key = self.entries[signature.keyIndex] - - // Ensure the key is not revoked - - if key.isRevoked { - return false - } - - // Ensure the signature is valid - - if !key.publicKey.verify( - signature: signature.signature, - signedData: signedData, - domainSeparationTag: domainSeparationTag, - hashAlgorithm:key.hashAlgorithm - ) { - return false - } - - validWeights = validWeights + key.weight - } - - return validWeights >= 1.0 - } - } - - access(all) - struct KeyListSignature { - - access(all) - let keyIndex: Int - - access(all) - let signature: [UInt8] - - init(keyIndex: Int, signature: [UInt8]) { - self.keyIndex = keyIndex - self.signature = signature - } - } -} diff --git a/runtime/stdlib/contracts/crypto.go b/runtime/stdlib/contracts/crypto.go deleted file mode 100644 index a64180f160..0000000000 --- a/runtime/stdlib/contracts/crypto.go +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Cadence - The resource-oriented smart contract programming language - * - * Copyright Flow Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package contracts - -import ( - _ "embed" -) - -//go:embed crypto.cdc -var Crypto []byte diff --git a/runtime/stdlib/contracts/crypto_test.cdc b/runtime/stdlib/contracts/crypto_test.cdc deleted file mode 100644 index d4e654287b..0000000000 --- a/runtime/stdlib/contracts/crypto_test.cdc +++ /dev/null @@ -1,341 +0,0 @@ -import Test -import Crypto from "crypto.cdc" - -access(all) -fun setup() { - let err = Test.deployContract( - name: "Crypto", - path: "crypto.cdc", - arguments: [] - ) - - Test.expect(err, Test.beNil()) -} - -access(all) -fun testCryptoHash() { - let hash = Crypto.hash([1, 2, 3], algorithm: HashAlgorithm.SHA3_256) - Test.assertEqual(32, hash.length) -} - -access(all) -fun testCryptoHashWithTag() { - let hash = Crypto.hashWithTag( - [1, 2, 3], - tag: "v0.1.tag", - algorithm: HashAlgorithm.SHA3_256 - ) - Test.assertEqual(32, hash.length) -} - -access(all) -fun testAddKeyToKeyList() { - let keyList = Crypto.KeyList() - - let publicKey = PublicKey( - publicKey: - "db04940e18ec414664ccfd31d5d2d4ece3985acb8cb17a2025b2f1673427267968e52e2bbf3599059649d4b2cce98fdb8a3048e68abf5abe3e710129e90696ca".decodeHex(), - signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 - ) - keyList.add( - publicKey, - hashAlgorithm: HashAlgorithm.SHA3_256, - weight: 1.0 - ) - - Test.assert(keyList.get(keyIndex: 0) != nil) -} - -access(all) -fun testGetKeyFromList() { - let keyList = Crypto.KeyList() - - let publicKey = PublicKey( - publicKey: - "db04940e18ec414664ccfd31d5d2d4ece3985acb8cb17a2025b2f1673427267968e52e2bbf3599059649d4b2cce98fdb8a3048e68abf5abe3e710129e90696ca".decodeHex(), - signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 - ) - keyList.add( - publicKey, - hashAlgorithm: HashAlgorithm.SHA3_256, - weight: 1.0 - ) - - Test.assert(keyList.get(keyIndex: 0) != nil) - Test.assert(keyList.get(keyIndex: 2) == nil) -} - -access(all) -fun testRevokeKeyFromList() { - let keyList = Crypto.KeyList() - - let publicKey = PublicKey( - publicKey: - "db04940e18ec414664ccfd31d5d2d4ece3985acb8cb17a2025b2f1673427267968e52e2bbf3599059649d4b2cce98fdb8a3048e68abf5abe3e710129e90696ca".decodeHex(), - signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 - ) - keyList.add( - publicKey, - hashAlgorithm: HashAlgorithm.SHA3_256, - weight: 0.5 - ) - - keyList.revoke(keyIndex: 0) - keyList.revoke(keyIndex: 2) - - Test.assert(keyList.get(keyIndex: 0)!.isRevoked) - Test.assert(keyList.get(keyIndex: 2) == nil) -} - -access(all) -fun testKeyListVerify() { - let keyList = Crypto.KeyList() - - let publicKeyA = PublicKey( - publicKey: - "db04940e18ec414664ccfd31d5d2d4ece3985acb8cb17a2025b2f1673427267968e52e2bbf3599059649d4b2cce98fdb8a3048e68abf5abe3e710129e90696ca".decodeHex(), - signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 - ) - - keyList.add( - publicKeyA, - hashAlgorithm: HashAlgorithm.SHA3_256, - weight: 0.5 - ) - - let publicKeyB = PublicKey( - publicKey: - "df9609ee588dd4a6f7789df8d56f03f545d4516f0c99b200d73b9a3afafc14de5d21a4fc7a2a2015719dc95c9e756cfa44f2a445151aaf42479e7120d83df956".decodeHex(), - signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 - ) - - keyList.add( - publicKeyB, - hashAlgorithm: HashAlgorithm.SHA3_256, - weight: 0.5 - ) - - let signatureSet = [ - Crypto.KeyListSignature( - keyIndex: 0, - signature: - "8870a8cbe6f44932ba59e0d15a706214cc4ad2538deb12c0cf718d86f32c47765462a92ce2da15d4a29eb4e2b6fa05d08c7db5d5b2a2cd8c2cb98ded73da31f6".decodeHex() - ), - Crypto.KeyListSignature( - keyIndex: 1, - signature: - "bbdc5591c3f937a730d4f6c0a6fde61a0a6ceaa531ccb367c3559335ab9734f4f2b9da8adbe371f1f7da913b5a3fdd96a871e04f078928ca89a83d841c72fadf".decodeHex() - ) - ] - - // "foo", encoded as UTF-8, in hex representation - let signedData = "666f6f".decodeHex() - - let isValid = keyList.verify( - signatureSet: signatureSet, - signedData: signedData, - domainSeparationTag: "FLOW-V0.0-user" - ) - - Test.assert(isValid) -} - -access(all) -fun testKeyListVerifyInsufficientWeights() { - let keyList = Crypto.KeyList() - - let publicKeyA = PublicKey( - publicKey: - "db04940e18ec414664ccfd31d5d2d4ece3985acb8cb17a2025b2f1673427267968e52e2bbf3599059649d4b2cce98fdb8a3048e68abf5abe3e710129e90696ca".decodeHex(), - signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 - ) - - keyList.add( - publicKeyA, - hashAlgorithm: HashAlgorithm.SHA3_256, - weight: 0.4 - ) - - let publicKeyB = PublicKey( - publicKey: - "df9609ee588dd4a6f7789df8d56f03f545d4516f0c99b200d73b9a3afafc14de5d21a4fc7a2a2015719dc95c9e756cfa44f2a445151aaf42479e7120d83df956".decodeHex(), - signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 - ) - - keyList.add( - publicKeyB, - hashAlgorithm: HashAlgorithm.SHA3_256, - weight: 0.5 - ) - - let signatureSet = [ - Crypto.KeyListSignature( - keyIndex: 0, - signature: - "8870a8cbe6f44932ba59e0d15a706214cc4ad2538deb12c0cf718d86f32c47765462a92ce2da15d4a29eb4e2b6fa05d08c7db5d5b2a2cd8c2cb98ded73da31f6".decodeHex() - ), - Crypto.KeyListSignature( - keyIndex: 1, - signature: - "bbdc5591c3f937a730d4f6c0a6fde61a0a6ceaa531ccb367c3559335ab9734f4f2b9da8adbe371f1f7da913b5a3fdd96a871e04f078928ca89a83d841c72fadf".decodeHex() - ) - ] - - // "foo", encoded as UTF-8, in hex representation - let signedData = "666f6f".decodeHex() - - let isValid = keyList.verify( - signatureSet: signatureSet, - signedData: signedData, - domainSeparationTag: "FLOW-V0.0-user" - ) - - Test.assert(!isValid) -} - -access(all) -fun testKeyListVerifyWithRevokedKey() { - let keyList = Crypto.KeyList() - - let publicKey = PublicKey( - publicKey: - "db04940e18ec414664ccfd31d5d2d4ece3985acb8cb17a2025b2f1673427267968e52e2bbf3599059649d4b2cce98fdb8a3048e68abf5abe3e710129e90696ca".decodeHex(), - signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 - ) - keyList.add( - publicKey, - hashAlgorithm: HashAlgorithm.SHA3_256, - weight: 0.5 - ) - - let signatureSet = [ - Crypto.KeyListSignature( - keyIndex: 0, - signature: - "8870a8cbe6f44932ba59e0d15a706214cc4ad2538deb12c0cf718d86f32c47765462a92ce2da15d4a29eb4e2b6fa05d08c7db5d5b2a2cd8c2cb98ded73da31f6".decodeHex() - ) - ] - - // "foo", encoded as UTF-8, in hex representation - let signedData = "666f6f".decodeHex() - - keyList.revoke(keyIndex: 0) - - let isValid = keyList.verify( - signatureSet: signatureSet, - signedData: signedData, - domainSeparationTag: "FLOW-V0.0-user" - ) - - Test.assert(!isValid) -} - -access(all) -fun testKeyListVerifyWithMissingSignature() { - let keyList = Crypto.KeyList() - - let publicKey = PublicKey( - publicKey: - "db04940e18ec414664ccfd31d5d2d4ece3985acb8cb17a2025b2f1673427267968e52e2bbf3599059649d4b2cce98fdb8a3048e68abf5abe3e710129e90696ca".decodeHex(), - signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 - ) - keyList.add( - publicKey, - hashAlgorithm: HashAlgorithm.SHA3_256, - weight: 0.5 - ) - - let signatureSet = [ - Crypto.KeyListSignature( - keyIndex: 1, - signature: - "8870a8cbe6f44932ba59e0d15a706214cc4ad2538deb12c0cf718d86f32c47765462a92ce2da15d4a29eb4e2b6fa05d08c7db5d5b2a2cd8c2cb98ded73da31f6".decodeHex() - ) - ] - - // "foo", encoded as UTF-8, in hex representation - let signedData = "666f6f".decodeHex() - - let isValid = keyList.verify( - signatureSet: signatureSet, - signedData: signedData, - domainSeparationTag: "FLOW-V0.0-user" - ) - - Test.assert(!isValid) -} - -access(all) -fun testKeyListVerifyDuplicateSignature() { - let keyList = Crypto.KeyList() - - let publicKey = PublicKey( - publicKey: - "db04940e18ec414664ccfd31d5d2d4ece3985acb8cb17a2025b2f1673427267968e52e2bbf3599059649d4b2cce98fdb8a3048e68abf5abe3e710129e90696ca".decodeHex(), - signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 - ) - keyList.add( - publicKey, - hashAlgorithm: HashAlgorithm.SHA3_256, - weight: 0.5 - ) - - let signatureSet = [ - Crypto.KeyListSignature( - keyIndex: 0, - signature: - "8870a8cbe6f44932ba59e0d15a706214cc4ad2538deb12c0cf718d86f32c47765462a92ce2da15d4a29eb4e2b6fa05d08c7db5d5b2a2cd8c2cb98ded73da31f6".decodeHex() - ), - Crypto.KeyListSignature( - keyIndex: 0, - signature: - "8870a8cbe6f44932ba59e0d15a706214cc4ad2538deb12c0cf718d86f32c47765462a92ce2da15d4a29eb4e2b6fa05d08c7db5d5b2a2cd8c2cb98ded73da31f6".decodeHex() - ) - ] - - // "foo", encoded as UTF-8, in hex representation - let signedData = "666f6f".decodeHex() - - let isValid = keyList.verify( - signatureSet: signatureSet, - signedData: signedData, - domainSeparationTag: "FLOW-V0.0-user" - ) - - Test.assert(!isValid) -} - -access(all) -fun testKeyListVerifyInvalidSignature() { - let keyList = Crypto.KeyList() - - let publicKey = PublicKey( - publicKey: - "db04940e18ec414664ccfd31d5d2d4ece3985acb8cb17a2025b2f1673427267968e52e2bbf3599059649d4b2cce98fdb8a3048e68abf5abe3e710129e90696ca".decodeHex(), - signatureAlgorithm: SignatureAlgorithm.ECDSA_P256 - ) - keyList.add( - publicKey, - hashAlgorithm: HashAlgorithm.SHA3_256, - weight: 0.5 - ) - - let signatureSet = [ - Crypto.KeyListSignature( - keyIndex: 0, - signature: - "db70a8cbe6f44932ba59e0d15a706214cc4ad2538deb12c0cf718d86f32c47765462a92ce2da15d4a29eb4e2b6fa05d08c7db5d5b2a2cd8c2cb98ded73da31f6".decodeHex() - ) - ] - - // "foo", encoded as UTF-8, in hex representation - let signedData = "666f6f".decodeHex() - - let isValid = keyList.verify( - signatureSet: signatureSet, - signedData: signedData, - domainSeparationTag: "FLOW-V0.0-user" - ) - - Test.assert(!isValid) -} diff --git a/runtime/stdlib/crypto.go b/runtime/stdlib/crypto.go index 585018540d..689de2e216 100644 --- a/runtime/stdlib/crypto.go +++ b/runtime/stdlib/crypto.go @@ -1,128 +1,12 @@ -/* - * Cadence - The resource-oriented smart contract programming language - * - * Copyright Flow Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - package stdlib import ( - "sync" - - "github.com/onflow/cadence/runtime/ast" "github.com/onflow/cadence/runtime/common" - "github.com/onflow/cadence/runtime/errors" - "github.com/onflow/cadence/runtime/parser" - "github.com/onflow/cadence/runtime/stdlib/contracts" - "github.com/onflow/cadence/runtime/interpreter" "github.com/onflow/cadence/runtime/sema" ) -const CryptoCheckerLocation = common.IdentifierLocation("Crypto") - -var cryptoOnce sync.Once - -// Deprecated: Use CryptoChecker instead -var cryptoChecker *sema.Checker - -// Deprecated: Use CryptoContractType instead -var cryptoContractType *sema.CompositeType - -// Deprecated: Use CryptoContractInitializerTypes -var cryptoContractInitializerTypes []sema.Type - -func CryptoChecker() *sema.Checker { - cryptoOnce.Do(initCrypto) - return cryptoChecker -} - -func CryptoContractType() *sema.CompositeType { - cryptoOnce.Do(initCrypto) - return cryptoContractType -} - -func CryptoContractInitializerTypes() []sema.Type { - cryptoOnce.Do(initCrypto) - return cryptoContractInitializerTypes -} - -func initCrypto() { - program, err := parser.ParseProgram( - nil, - contracts.Crypto, - parser.Config{}, - ) - if err != nil { - panic(err) - } - - cryptoChecker, err = sema.NewChecker( - program, - CryptoCheckerLocation, - nil, - &sema.Config{ - AccessCheckMode: sema.AccessCheckModeStrict, - }, - ) - if err != nil { - panic(err) - } - - err = cryptoChecker.Check() - if err != nil { - panic(err) - } - - variable, ok := cryptoChecker.Elaboration.GetGlobalType("Crypto") - if !ok { - panic(errors.NewUnreachableError()) - } - cryptoContractType = variable.Type.(*sema.CompositeType) - - cryptoContractInitializerTypes = make([]sema.Type, len(cryptoContractType.ConstructorParameters)) - for i, parameter := range cryptoContractType.ConstructorParameters { - cryptoContractInitializerTypes[i] = parameter.TypeAnnotation.Type - } -} - -func NewCryptoContract( - inter *interpreter.Interpreter, - constructor interpreter.FunctionValue, - invocationRange ast.Range, -) ( - *interpreter.CompositeValue, - error, -) { - initializerTypes := CryptoContractInitializerTypes() - value, err := inter.InvokeFunctionValue( - constructor, - nil, - initializerTypes, - initializerTypes, - CryptoContractType(), - invocationRange, - ) - if err != nil { - return nil, err - } - - compositeValue := value.(*interpreter.CompositeValue) - - return compositeValue, nil -} +const CryptoContractLocation = common.IdentifierLocation("Crypto") func cryptoAlgorithmEnumConstructorType[T sema.CryptoAlgorithm]( enumType *sema.CompositeType, diff --git a/runtime/stdlib/crypto_test.go b/runtime/stdlib/crypto_test.go deleted file mode 100644 index ff2dca5cf4..0000000000 --- a/runtime/stdlib/crypto_test.go +++ /dev/null @@ -1,31 +0,0 @@ -/* - * Cadence - The resource-oriented smart contract programming language - * - * Copyright Flow Foundation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package stdlib - -import ( - "testing" - - "github.com/stretchr/testify/require" - - "github.com/onflow/cadence/runtime/sema" -) - -func TestCryptoContract(t *testing.T) { - require.IsType(t, &sema.Checker{}, CryptoChecker()) -} diff --git a/runtime/stdlib/test.go b/runtime/stdlib/test.go index eb65c13985..0a7af89d5b 100644 --- a/runtime/stdlib/test.go +++ b/runtime/stdlib/test.go @@ -494,17 +494,6 @@ func NewTestInterpreterContractValueHandler( ) interpreter.ContractValue { switch compositeType.Location { - case CryptoCheckerLocation: - contract, err := NewCryptoContract( - inter, - constructorGenerator(common.ZeroAddress), - invocationRange, - ) - if err != nil { - panic(err) - } - return contract - case TestContractLocation: contract, err := GetTestContractType().NewTestContract( inter, diff --git a/tools/analysis/analysis.go b/tools/analysis/analysis.go index 4c5513a95a..d5ba872103 100644 --- a/tools/analysis/analysis.go +++ b/tools/analysis/analysis.go @@ -22,8 +22,11 @@ import ( "github.com/onflow/cadence/runtime/common" ) -func Load(config *Config, locations ...common.Location) (Programs, error) { - programs := make(Programs, len(locations)) +func Load(config *Config, locations ...common.Location) (*Programs, error) { + programs := &Programs{ + programs: make(map[common.Location]*Program, len(locations)), + cryptoContractElaboration: config.CryptoContractElaboration, + } for _, location := range locations { err := programs.Load(config, location) if err != nil { diff --git a/tools/analysis/analysis_test.go b/tools/analysis/analysis_test.go index d1321debf5..fb586a2e5f 100644 --- a/tools/analysis/analysis_test.go +++ b/tools/analysis/analysis_test.go @@ -89,8 +89,8 @@ func TestNeedSyntaxAndImport(t *testing.T) { programs, err := analysis.Load(config, txLocation) require.NoError(t, err) - require.NotNil(t, programs[txLocation]) - require.NotNil(t, programs[contractLocation]) + require.NotNil(t, programs.Get(txLocation)) + require.NotNil(t, programs.Get(contractLocation)) type locationRange struct { location common.Location @@ -99,7 +99,7 @@ func TestNeedSyntaxAndImport(t *testing.T) { var locationRanges []locationRange - for _, program := range programs { + for _, program := range programs.All() { require.NotNil(t, program.Program) require.NotNil(t, program.Checker) @@ -309,7 +309,10 @@ func TestHandledParserError(t *testing.T) { require.Equal(t, 1, handlerCalls) var parserError parser.Error - require.ErrorAs(t, programs[contractLocation].LoadError, &parserError) + require.ErrorAs(t, + programs.Get(contractLocation).LoadError, + &parserError, + ) } func TestHandledCheckerError(t *testing.T) { @@ -361,7 +364,10 @@ func TestHandledCheckerError(t *testing.T) { require.NoError(t, err) var checkerError *sema.CheckerError - require.ErrorAs(t, programs[contractLocation].LoadError, &checkerError) + require.ErrorAs(t, + programs.Get(contractLocation).LoadError, + &checkerError, + ) } // Tests that an error handled by the custom error handler is not returned @@ -429,12 +435,21 @@ func TestHandledLoadErrorImportedProgram(t *testing.T) { require.NoError(t, err) var checkerError *sema.CheckerError - require.ErrorAs(t, programs[contract1Location].LoadError, &checkerError) - require.ErrorAs(t, programs[contract2Location].LoadError, &checkerError) + require.ErrorAs(t, + programs.Get(contract1Location).LoadError, + &checkerError, + ) + require.ErrorAs(t, + programs.Get(contract2Location).LoadError, + &checkerError, + ) // Validate that parent checker receives the imported program error despite it being handled var importedProgramErr *sema.ImportedProgramError - require.ErrorAs(t, programs[contract1Location].LoadError, &importedProgramErr) + require.ErrorAs(t, + programs.Get(contract1Location).LoadError, + &importedProgramErr, + ) } func TestStdlib(t *testing.T) { diff --git a/tools/analysis/config.go b/tools/analysis/config.go index 3bf637f9f3..8e0386cf9b 100644 --- a/tools/analysis/config.go +++ b/tools/analysis/config.go @@ -45,6 +45,8 @@ type Config struct { HandleParserError func(err ParsingCheckingError, program *ast.Program) error // HandleCheckerError is called when a checker error occurs instead of returning it HandleCheckerError func(err ParsingCheckingError, checker *sema.Checker) error + // CryptoContractElaboration is the elaboration of the Crypto contract + CryptoContractElaboration *sema.Elaboration } func NewSimpleConfig( diff --git a/tools/analysis/programs.go b/tools/analysis/programs.go index 08ae11ae49..53bda6953b 100644 --- a/tools/analysis/programs.go +++ b/tools/analysis/programs.go @@ -26,11 +26,14 @@ import ( "github.com/onflow/cadence/runtime/stdlib" ) -type Programs map[common.Location]*Program +type Programs struct { + programs map[common.Location]*Program + cryptoContractElaboration *sema.Elaboration +} type importResolutionResults map[common.Location]bool -func (programs Programs) Load(config *Config, location common.Location) error { +func (programs *Programs) Load(config *Config, location common.Location) error { return programs.load( config, location, @@ -43,14 +46,14 @@ func (programs Programs) Load(config *Config, location common.Location) error { ) } -func (programs Programs) load( +func (programs *Programs) load( config *Config, location common.Location, importingLocation common.Location, importRange ast.Range, seenImports importResolutionResults, ) error { - if programs[location] != nil { + if programs.programs[location] != nil { return nil } @@ -104,7 +107,7 @@ func (programs Programs) load( } } - programs[location] = &Program{ + programs.programs[location] = &Program{ Location: location, Code: code, Program: program, @@ -115,7 +118,7 @@ func (programs Programs) load( return nil } -func (programs Programs) check( +func (programs *Programs) check( config *Config, program *ast.Program, location common.Location, @@ -153,9 +156,8 @@ func (programs Programs) check( var loadError error switch importedLocation { - case stdlib.CryptoCheckerLocation: - cryptoChecker := stdlib.CryptoChecker() - elaboration = cryptoChecker.Elaboration + case stdlib.CryptoContractLocation: + elaboration = programs.cryptoContractElaboration default: if seenImports[importedLocation] { @@ -172,7 +174,7 @@ func (programs Programs) check( return nil, err } - program := programs[importedLocation] + program := programs.programs[importedLocation] checker := program.Checker // If the imported program has a checker, use its elaboration for the import @@ -205,3 +207,15 @@ func (programs Programs) check( return checker, nil } + +func (programs *Programs) Get(location common.Location) *Program { + return programs.programs[location] +} + +func (programs *Programs) All() []*Program { + all := make([]*Program, 0, len(programs.programs)) + for _, program := range programs.programs { + all = append(all, program) + } + return all +} From 393e95547139475504f4dd91681b6b92c6405496 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 17 Oct 2024 16:49:48 -0700 Subject: [PATCH 2/6] call constructor for contracts loaded from identifier location, test --- runtime/environment.go | 36 +++++++++++---- runtime/runtime_test.go | 98 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 125 insertions(+), 9 deletions(-) diff --git a/runtime/environment.go b/runtime/environment.go index 2cf7a87c2e..89be3f8032 100644 --- a/runtime/environment.go +++ b/runtime/environment.go @@ -1092,14 +1092,32 @@ func (e *interpreterEnvironment) newCompositeValueFunctionsHandler() interpreter func (e *interpreterEnvironment) loadContract( inter *interpreter.Interpreter, compositeType *sema.CompositeType, - _ func(common.Address) *interpreter.HostFunctionValue, - _ ast.Range, + constructorGenerator func(common.Address) *interpreter.HostFunctionValue, + invocationRange ast.Range, ) *interpreter.CompositeValue { - var storedValue interpreter.Value + var contractValue interpreter.Value + + location := compositeType.Location + switch location := location.(type) { + case common.IdentifierLocation: + // Identifier locations are used for built-in contracts, + // and are not stored in storage + + constructorGenerator := constructorGenerator(common.ZeroAddress) + var err error + contractValue, err = inter.InvokeFunctionValue( + constructorGenerator, + nil, + nil, + nil, + compositeType, + invocationRange, + ) + if err != nil { + panic(err) + } - switch location := compositeType.Location.(type) { - // TODO: support e.g. CryptoContractLocation case common.AddressLocation: storageMap := e.storage.GetStorageMap( location.Address, @@ -1107,15 +1125,15 @@ func (e *interpreterEnvironment) loadContract( false, ) if storageMap != nil { - storedValue = storageMap.ReadValue(inter, interpreter.StringStorageMapKey(location.Name)) + contractValue = storageMap.ReadValue(inter, interpreter.StringStorageMapKey(location.Name)) } } - if storedValue == nil { - panic(errors.NewDefaultUserError("failed to load contract: %s", compositeType.Location)) + if contractValue == nil { + panic(errors.NewDefaultUserError("failed to load contract: %s", location)) } - return storedValue.(*interpreter.CompositeValue) + return contractValue.(*interpreter.CompositeValue) } func (e *interpreterEnvironment) newOnFunctionInvocationHandler() func(_ *interpreter.Interpreter) { diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index cfd7fd69e8..4e63c44413 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -11561,3 +11561,101 @@ func TestResultRedeclared(t *testing.T) { }) } +func TestRuntimeContractValueLocation(t *testing.T) { + + t.Parallel() + + signerAddress := common.MustBytesToAddress([]byte{0x42}) + + const fooContractName = "Foo" + fooIdentifierLocation := common.IdentifierLocation(fooContractName) + + fooContract := []byte(` + access(all) + contract Foo { + access(all) var answer: Int + + init() { + self.answer = 42 + } + } + `) + + accountCodes := map[Location][]byte{} + var events []cadence.Event + + runtimeInterface := &TestRuntimeInterface{ + Storage: NewTestLedger(nil, nil), + OnGetSigningAccounts: func() ([]Address, error) { + return []Address{signerAddress}, nil + }, + OnResolveLocation: func(identifiers []Identifier, location Location) ([]ResolvedLocation, error) { + assert.Empty(t, identifiers) + assert.Equal(t, fooIdentifierLocation, location) + + return []ResolvedLocation{ + { + Location: location, + Identifiers: identifiers, + }, + }, nil + }, + OnGetAccountContractCode: func(location common.AddressLocation) (code []byte, err error) { + return accountCodes[location], nil + }, + OnUpdateAccountContractCode: func(location common.AddressLocation, code []byte) error { + accountCodes[location] = code + return nil + }, + OnEmitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + OnGetCode: func(location Location) ([]byte, error) { + assert.Equal(t, fooIdentifierLocation, location) + return fooContract, nil + }, + } + + runtime := NewTestInterpreterRuntime() + + nextTransactionLocation := NewTransactionLocationGenerator() + nextScriptLocation := NewScriptLocationGenerator() + + // Deploy + + deploy := DeploymentTransaction(fooContractName, fooContract) + + err := runtime.ExecuteTransaction( + Script{ + Source: deploy, + }, + Context{ + Interface: runtimeInterface, + Location: nextTransactionLocation(), + }, + ) + require.NoError(t, err) + + // Test + + result, err := runtime.ExecuteScript( + Script{ + Source: []byte(` + import Foo + + access(all) + fun main(): Int { + return Foo.answer + } + `), + }, + Context{ + Interface: runtimeInterface, + Location: nextScriptLocation(), + }, + ) + require.NoError(t, err) + + assert.Equal(t, cadence.NewInt(42), result) +} From bc51dde5af18680803c8d2687d333b934802cc47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 17 Oct 2024 17:01:01 -0700 Subject: [PATCH 3/6] remove Flow CLI and testing from CI job --- .github/workflows/ci.yml | 6 ------ 1 file changed, 6 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 634088911f..c778cde165 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -39,18 +39,12 @@ jobs: go-version: ${{ env.GO_VERSION }} cache: true - - name: Install Flow CLI - run: sh -ci "$(curl -fsSL https://raw.githubusercontent.com/onflow/flow-cli/master/install.sh)" - - name: Build run: make -j8 build - name: Test run: make ci - - name: Cadence Testing Framework - run: cd runtime/stdlib/contracts && flow test --cover --covercode="contracts" crypto_test.cdc - - name: Upload coverage report uses: codecov/codecov-action@v2 with: From 02b9413c7a0e08624462238c986db157c5b752be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Fri, 18 Oct 2024 10:10:08 -0700 Subject: [PATCH 4/6] remove All function again, export field instead --- tools/analysis/analysis.go | 4 ++-- tools/analysis/analysis_test.go | 2 +- tools/analysis/programs.go | 22 +++++++--------------- 3 files changed, 10 insertions(+), 18 deletions(-) diff --git a/tools/analysis/analysis.go b/tools/analysis/analysis.go index 79ef89ed44..eb179774de 100644 --- a/tools/analysis/analysis.go +++ b/tools/analysis/analysis.go @@ -24,8 +24,8 @@ import ( func Load(config *Config, locations ...common.Location) (*Programs, error) { programs := &Programs{ - programs: make(map[common.Location]*Program, len(locations)), - cryptoContractElaboration: config.CryptoContractElaboration, + Programs: make(map[common.Location]*Program, len(locations)), + CryptoContractElaboration: config.CryptoContractElaboration, } for _, location := range locations { err := programs.Load(config, location) diff --git a/tools/analysis/analysis_test.go b/tools/analysis/analysis_test.go index 92c2f6e2c2..61e1d54ec4 100644 --- a/tools/analysis/analysis_test.go +++ b/tools/analysis/analysis_test.go @@ -99,7 +99,7 @@ func TestNeedSyntaxAndImport(t *testing.T) { var locationRanges []locationRange - for _, program := range programs.All() { + for _, program := range programs.Programs { require.NotNil(t, program.Program) require.NotNil(t, program.Checker) diff --git a/tools/analysis/programs.go b/tools/analysis/programs.go index 4adcb6e16f..58599bb589 100644 --- a/tools/analysis/programs.go +++ b/tools/analysis/programs.go @@ -27,8 +27,8 @@ import ( ) type Programs struct { - programs map[common.Location]*Program - cryptoContractElaboration *sema.Elaboration + Programs map[common.Location]*Program + CryptoContractElaboration *sema.Elaboration } type importResolutionResults map[common.Location]bool @@ -53,7 +53,7 @@ func (programs *Programs) load( importRange ast.Range, seenImports importResolutionResults, ) error { - if programs.programs[location] != nil { + if programs.Programs[location] != nil { return nil } @@ -107,7 +107,7 @@ func (programs *Programs) load( } } - programs.programs[location] = &Program{ + programs.Programs[location] = &Program{ Location: location, Code: code, Program: program, @@ -157,7 +157,7 @@ func (programs *Programs) check( switch importedLocation { case stdlib.CryptoContractLocation: - elaboration = programs.cryptoContractElaboration + elaboration = programs.CryptoContractElaboration default: if seenImports[importedLocation] { @@ -174,7 +174,7 @@ func (programs *Programs) check( return nil, err } - program := programs.programs[importedLocation] + program := programs.Programs[importedLocation] checker := program.Checker // If the imported program has a checker, use its elaboration for the import @@ -209,13 +209,5 @@ func (programs *Programs) check( } func (programs *Programs) Get(location common.Location) *Program { - return programs.programs[location] -} - -func (programs *Programs) All() []*Program { - all := make([]*Program, 0, len(programs.programs)) - for _, program := range programs.programs { - all = append(all, program) - } - return all + return programs.Programs[location] } From 2e72919b18ac6e217b9bfb7212203b386ca24e75 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Fri, 18 Oct 2024 10:33:27 -0700 Subject: [PATCH 5/6] revert 393e95547139475504f4dd91681b6b92c6405496: use resolve location to rewrite import --- runtime/environment.go | 32 ++++++++------------------------ tests/runtime_test.go | 13 ++++++++++--- 2 files changed, 18 insertions(+), 27 deletions(-) diff --git a/runtime/environment.go b/runtime/environment.go index ce0b5edae0..ff71d25c08 100644 --- a/runtime/environment.go +++ b/runtime/environment.go @@ -1092,40 +1092,24 @@ func (e *interpreterEnvironment) newCompositeValueFunctionsHandler() interpreter func (e *interpreterEnvironment) loadContract( inter *interpreter.Interpreter, compositeType *sema.CompositeType, - constructorGenerator func(common.Address) *interpreter.HostFunctionValue, - invocationRange ast.Range, + _ func(common.Address) *interpreter.HostFunctionValue, + _ ast.Range, ) *interpreter.CompositeValue { var contractValue interpreter.Value location := compositeType.Location - switch location := location.(type) { - case common.IdentifierLocation: - // Identifier locations are used for built-in contracts, - // and are not stored in storage - - constructorGenerator := constructorGenerator(common.ZeroAddress) - var err error - contractValue, err = inter.InvokeFunctionValue( - constructorGenerator, - nil, - nil, - nil, - compositeType, - invocationRange, - ) - if err != nil { - panic(err) - } - - case common.AddressLocation: + if addressLocation, ok := location.(common.AddressLocation); ok { storageMap := e.storage.GetStorageMap( - location.Address, + addressLocation.Address, StorageDomainContract, false, ) if storageMap != nil { - contractValue = storageMap.ReadValue(inter, interpreter.StringStorageMapKey(location.Name)) + contractValue = storageMap.ReadValue( + inter, + interpreter.StringStorageMapKey(addressLocation.Name), + ) } } diff --git a/tests/runtime_test.go b/tests/runtime_test.go index 12b16557cc..3a80d0c83d 100644 --- a/tests/runtime_test.go +++ b/tests/runtime_test.go @@ -11561,7 +11561,8 @@ func TestResultRedeclared(t *testing.T) { }) } -func TestRuntimeContractValueLocation(t *testing.T) { + +func TestRuntimeIdentifierLocationToAddressLocationRewrite(t *testing.T) { t.Parallel() @@ -11569,6 +11570,10 @@ func TestRuntimeContractValueLocation(t *testing.T) { const fooContractName = "Foo" fooIdentifierLocation := common.IdentifierLocation(fooContractName) + fooAddressLocation := common.AddressLocation{ + Address: signerAddress, + Name: fooContractName, + } fooContract := []byte(` access(all) @@ -11593,6 +11598,9 @@ func TestRuntimeContractValueLocation(t *testing.T) { assert.Empty(t, identifiers) assert.Equal(t, fooIdentifierLocation, location) + // NOTE: rewrite identifier location to address location + location = fooAddressLocation + return []ResolvedLocation{ { Location: location, @@ -11612,8 +11620,7 @@ func TestRuntimeContractValueLocation(t *testing.T) { return nil }, OnGetCode: func(location Location) ([]byte, error) { - assert.Equal(t, fooIdentifierLocation, location) - return fooContract, nil + return nil, errors.New("GetCode should not be called") }, } From 009255f04aeea462c45779b7fa7f93f581936254 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Fri, 18 Oct 2024 10:40:28 -0700 Subject: [PATCH 6/6] bring back license header --- stdlib/crypto.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/stdlib/crypto.go b/stdlib/crypto.go index 6728047285..c8838a474b 100644 --- a/stdlib/crypto.go +++ b/stdlib/crypto.go @@ -1,3 +1,21 @@ +/* + * Cadence - The resource-oriented smart contract programming language + * + * Copyright Flow Foundation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + package stdlib import (