From 78bcd5598b8d76cdb38f12b5a1f5cebedf28705d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 8 Aug 2024 11:26:35 -0700 Subject: [PATCH 1/7] add migration which records capabilities with storage target --- migrations/capcons/migration_test.go | 130 ++++++++++++++++++++++ migrations/capcons/storagecapabilities.go | 28 +++++ migrations/capcons/storagecapmigration.go | 67 +++++++++++ 3 files changed, 225 insertions(+) create mode 100644 migrations/capcons/storagecapabilities.go create mode 100644 migrations/capcons/storagecapmigration.go diff --git a/migrations/capcons/migration_test.go b/migrations/capcons/migration_test.go index 531a9a60dd..5066aa249c 100644 --- a/migrations/capcons/migration_test.go +++ b/migrations/capcons/migration_test.go @@ -2793,3 +2793,133 @@ func TestCanSkipCapabilityValueMigration(t *testing.T) { test(ty, expected) } } + +func TestStorageCapMigration(t *testing.T) { + t.Parallel() + + // Equivalent to: getCapability(/storage/test) + capabilityValue := &interpreter.PathCapabilityValue{ //nolint:staticcheck + // NOTE: no borrow type + BorrowType: nil, + Path: interpreter.PathValue{ + Domain: common.PathDomainStorage, + Identifier: testPathIdentifier, + }, + Address: interpreter.AddressValue(testAddress), + } + + rt := NewTestInterpreterRuntime() + + var events []cadence.Event + + runtimeInterface := &TestRuntimeInterface{ + Storage: NewTestLedger(nil, nil), + OnGetSigningAccounts: func() ([]runtime.Address, error) { + return []runtime.Address{testAddress}, nil + }, + OnEmitEvent: func(event cadence.Event) error { + events = append(events, event) + return nil + }, + } + + nextTransactionLocation := NewTransactionLocationGenerator() + + // Setup + + setupTransactionLocation := nextTransactionLocation() + + environment := runtime.NewScriptInterpreterEnvironment(runtime.Config{}) + + // Inject the path capability value. + // + // We don't have a way to create a path capability value in a Cadence program anymore, + // so we have to inject it manually. + + environment.DeclareValue( + stdlib.StandardLibraryValue{ + Name: "cap", + Type: &sema.CapabilityType{}, + Kind: common.DeclarationKindConstant, + Value: capabilityValue, + }, + setupTransactionLocation, + ) + + // Save capability value into account + + // language=cadence + setupTx := ` + transaction { + prepare(signer: auth(SaveValue) &Account) { + signer.storage.save(cap, to: /storage/cap) + } + } + ` + + err := rt.ExecuteTransaction( + runtime.Script{ + Source: []byte(setupTx), + }, + runtime.Context{ + Interface: runtimeInterface, + Environment: environment, + Location: setupTransactionLocation, + }, + ) + require.NoError(t, err) + + // Migrate + + storage, inter, err := rt.Storage(runtime.Context{ + Interface: runtimeInterface, + }) + require.NoError(t, err) + + migration, err := migrations.NewStorageMigration(inter, storage, "test", testAddress) + require.NoError(t, err) + + reporter := &testMigrationReporter{} + + addressPaths := &AddressPaths{} + + migration.Migrate( + migration.NewValueMigrationsPathMigrator( + reporter, + &StorageCapMigration{ + AddressPaths: addressPaths, + }, + ), + ) + + err = migration.Commit() + require.NoError(t, err) + + // Assert + + require.Empty(t, reporter.migrations) + require.Empty(t, reporter.errors) + + err = storage.CheckHealth() + require.NoError(t, err) + + var actualAddressPaths []interpreter.AddressPath + + addressPaths.ForEach(func(addressPath interpreter.AddressPath) bool { + actualAddressPaths = append(actualAddressPaths, addressPath) + return true + }) + + assert.Equal(t, + []interpreter.AddressPath{ + { + Address: testAddress, + Path: interpreter.PathValue{ + Domain: common.PathDomainStorage, + Identifier: testPathIdentifier, + }, + }, + }, + actualAddressPaths, + ) +} diff --git a/migrations/capcons/storagecapabilities.go b/migrations/capcons/storagecapabilities.go new file mode 100644 index 0000000000..812005b218 --- /dev/null +++ b/migrations/capcons/storagecapabilities.go @@ -0,0 +1,28 @@ +package capcons + +import ( + "sync" + + "github.com/onflow/cadence/runtime/interpreter" +) + +type AddressPaths struct { + // set is a "set" of common.AddressPath (Go map of common.AddressPath ((address, path) pairs) to struct{}) + set sync.Map +} + +func (m *AddressPaths) Record( + addressPath interpreter.AddressPath, +) { + _, ok := m.set.Load(addressPath.Address) + if !ok { + m.set.Store(addressPath, struct{}{}) + } +} + +func (m *AddressPaths) ForEach(f func(addressPath interpreter.AddressPath) bool) { + m.set.Range(func(key, _ interface{}) bool { + addressPath := key.(interpreter.AddressPath) + return f(addressPath) + }) +} diff --git a/migrations/capcons/storagecapmigration.go b/migrations/capcons/storagecapmigration.go new file mode 100644 index 0000000000..17ba6a2476 --- /dev/null +++ b/migrations/capcons/storagecapmigration.go @@ -0,0 +1,67 @@ +/* + * 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 capcons + +import ( + "github.com/onflow/cadence/migrations" + "github.com/onflow/cadence/runtime/common" + "github.com/onflow/cadence/runtime/interpreter" +) + +// StorageCapMigration records path capabilities with storage domain target. +// It does not actually migrate any values. +type StorageCapMigration struct { + AddressPaths *AddressPaths +} + +var _ migrations.ValueMigration = &StorageCapMigration{} + +func (*StorageCapMigration) Name() string { + return "StorageCapMigration" +} + +func (*StorageCapMigration) Domains() map[string]struct{} { + return nil +} + +// Migrate records path capabilities with storage domain target. +// It does not actually migrate any values. +func (m *StorageCapMigration) Migrate( + _ interpreter.StorageKey, + _ interpreter.StorageMapKey, + value interpreter.Value, + _ *interpreter.Interpreter, + _ migrations.ValueMigrationPosition, +) ( + interpreter.Value, + error, +) { + // Record path capabilities with storage domain target + if pathCapabilityValue, ok := value.(*interpreter.PathCapabilityValue); ok && //nolint:staticcheck + pathCapabilityValue.Path.Domain == common.PathDomainStorage { + + m.AddressPaths.Record(pathCapabilityValue.AddressPath()) + } + + return nil, nil +} + +func (m *StorageCapMigration) CanSkip(valueType interpreter.StaticType) bool { + return CanSkipCapabilityValueMigration(valueType) +} From 682c484510df017eb2d8b2405219d1729cec6839 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 8 Aug 2024 11:49:01 -0700 Subject: [PATCH 2/7] also record borrow type --- migrations/capcons/migration_test.go | 50 ++++++++++++++++------- migrations/capcons/storagecapabilities.go | 44 ++++++++++++++------ migrations/capcons/storagecapmigration.go | 7 +++- 3 files changed, 73 insertions(+), 28 deletions(-) diff --git a/migrations/capcons/migration_test.go b/migrations/capcons/migration_test.go index 5066aa249c..b6c3e682c6 100644 --- a/migrations/capcons/migration_test.go +++ b/migrations/capcons/migration_test.go @@ -2797,10 +2797,15 @@ func TestCanSkipCapabilityValueMigration(t *testing.T) { func TestStorageCapMigration(t *testing.T) { t.Parallel() - // Equivalent to: getCapability(/storage/test) + testBorrowType := interpreter.NewReferenceStaticType( + nil, + interpreter.UnauthorizedAccess, + interpreter.PrimitiveStaticTypeString, + ) + + // Equivalent to: getCapability<&String>(/storage/test) capabilityValue := &interpreter.PathCapabilityValue{ //nolint:staticcheck - // NOTE: no borrow type - BorrowType: nil, + BorrowType: testBorrowType, Path: interpreter.PathValue{ Domain: common.PathDomainStorage, Identifier: testPathIdentifier, @@ -2881,13 +2886,13 @@ func TestStorageCapMigration(t *testing.T) { reporter := &testMigrationReporter{} - addressPaths := &AddressPaths{} + storageCapabilities := &StorageCapabilities{} migration.Migrate( migration.NewValueMigrationsPathMigrator( reporter, &StorageCapMigration{ - AddressPaths: addressPaths, + AddressPaths: storageCapabilities, }, ), ) @@ -2903,23 +2908,40 @@ func TestStorageCapMigration(t *testing.T) { err = storage.CheckHealth() require.NoError(t, err) - var actualAddressPaths []interpreter.AddressPath + type actual struct { + address common.Address + path interpreter.PathValue + borrowType interpreter.StaticType + } - addressPaths.ForEach(func(addressPath interpreter.AddressPath) bool { - actualAddressPaths = append(actualAddressPaths, addressPath) - return true - }) + var actuals []actual + + storageCapabilities.ForEach( + testAddress, + func(path interpreter.PathValue, borrowType interpreter.StaticType) bool { + actuals = append( + actuals, + actual{ + address: testAddress, + path: path, + borrowType: borrowType, + }, + ) + return true + }, + ) assert.Equal(t, - []interpreter.AddressPath{ + []actual{ { - Address: testAddress, - Path: interpreter.PathValue{ + address: testAddress, + path: interpreter.PathValue{ Domain: common.PathDomainStorage, Identifier: testPathIdentifier, }, + borrowType: testBorrowType, }, }, - actualAddressPaths, + actuals, ) } diff --git a/migrations/capcons/storagecapabilities.go b/migrations/capcons/storagecapabilities.go index 812005b218..65501e9d7b 100644 --- a/migrations/capcons/storagecapabilities.go +++ b/migrations/capcons/storagecapabilities.go @@ -3,26 +3,46 @@ package capcons import ( "sync" + "github.com/onflow/cadence/runtime/common" "github.com/onflow/cadence/runtime/interpreter" ) -type AddressPaths struct { - // set is a "set" of common.AddressPath (Go map of common.AddressPath ((address, path) pairs) to struct{}) - set sync.Map +// AccountStorageCapabilities maps path to borrow type +type AccountStorageCapabilities map[interpreter.PathValue]interpreter.StaticType + +type StorageCapabilities struct { + // accountStorageCapabilities maps common.Address to AccountStorageCapabilities + accountStorageCapabilities sync.Map } -func (m *AddressPaths) Record( +func (m *StorageCapabilities) Record( addressPath interpreter.AddressPath, + borrowType interpreter.StaticType, ) { - _, ok := m.set.Load(addressPath.Address) - if !ok { - m.set.Store(addressPath, struct{}{}) + var capabilityEntryMap AccountStorageCapabilities + rawCapabilityEntryMap, ok := m.accountStorageCapabilities.Load(addressPath.Address) + if ok { + capabilityEntryMap = rawCapabilityEntryMap.(AccountStorageCapabilities) + } else { + capabilityEntryMap = AccountStorageCapabilities{} + m.accountStorageCapabilities.Store(addressPath.Address, capabilityEntryMap) } + capabilityEntryMap[addressPath.Path] = borrowType } -func (m *AddressPaths) ForEach(f func(addressPath interpreter.AddressPath) bool) { - m.set.Range(func(key, _ interface{}) bool { - addressPath := key.(interpreter.AddressPath) - return f(addressPath) - }) +func (m *StorageCapabilities) ForEach( + address common.Address, + f func(path interpreter.PathValue, borrowType interpreter.StaticType) bool, +) { + rawCapabilityEntryMap, ok := m.accountStorageCapabilities.Load(address) + if !ok { + return + } + + capabilityEntryMap := rawCapabilityEntryMap.(AccountStorageCapabilities) + for path, borrowType := range capabilityEntryMap { + if !f(path, borrowType) { + return + } + } } diff --git a/migrations/capcons/storagecapmigration.go b/migrations/capcons/storagecapmigration.go index 17ba6a2476..f9c94967c4 100644 --- a/migrations/capcons/storagecapmigration.go +++ b/migrations/capcons/storagecapmigration.go @@ -27,7 +27,7 @@ import ( // StorageCapMigration records path capabilities with storage domain target. // It does not actually migrate any values. type StorageCapMigration struct { - AddressPaths *AddressPaths + AddressPaths *StorageCapabilities } var _ migrations.ValueMigration = &StorageCapMigration{} @@ -56,7 +56,10 @@ func (m *StorageCapMigration) Migrate( if pathCapabilityValue, ok := value.(*interpreter.PathCapabilityValue); ok && //nolint:staticcheck pathCapabilityValue.Path.Domain == common.PathDomainStorage { - m.AddressPaths.Record(pathCapabilityValue.AddressPath()) + m.AddressPaths.Record( + pathCapabilityValue.AddressPath(), + pathCapabilityValue.BorrowType, + ) } return nil, nil From fe1d93ca344d9d98e1216928c41fe9b6a43cff1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 8 Aug 2024 11:49:56 -0700 Subject: [PATCH 3/7] remove incorrect issuing of storage capability controllers invalid, because writes to other accounts --- migrations/capcons/capabilitymigration.go | 57 +++++------------------ migrations/capcons/migration_test.go | 3 -- 2 files changed, 11 insertions(+), 49 deletions(-) diff --git a/migrations/capcons/capabilitymigration.go b/migrations/capcons/capabilitymigration.go index d1a7f9c96d..21916bf231 100644 --- a/migrations/capcons/capabilitymigration.go +++ b/migrations/capcons/capabilitymigration.go @@ -24,7 +24,6 @@ import ( "github.com/onflow/cadence/runtime/errors" "github.com/onflow/cadence/runtime/interpreter" "github.com/onflow/cadence/runtime/sema" - "github.com/onflow/cadence/runtime/stdlib" ) type CapabilityMigrationReporter interface { @@ -44,7 +43,6 @@ type CapabilityMigrationReporter interface { // using the path to ID capability controller mapping generated by LinkValueMigration. type CapabilityValueMigration struct { CapabilityMapping *CapabilityMapping - IssueHandler stdlib.CapabilityControllerIssueHandler Reporter CapabilityMigrationReporter } @@ -70,7 +68,7 @@ func (m *CapabilityValueMigration) Migrate( storageKey interpreter.StorageKey, _ interpreter.StorageMapKey, value interpreter.Value, - inter *interpreter.Interpreter, + _ *interpreter.Interpreter, _ migrations.ValueMigrationPosition, ) ( interpreter.Value, @@ -79,7 +77,7 @@ func (m *CapabilityValueMigration) Migrate( // Migrate path capabilities to ID capabilities if pathCapabilityValue, ok := value.(*interpreter.PathCapabilityValue); ok { //nolint:staticcheck - return m.migratePathCapabilityValue(pathCapabilityValue, storageKey, inter) + return m.migratePathCapabilityValue(pathCapabilityValue, storageKey) } return nil, nil @@ -88,7 +86,6 @@ func (m *CapabilityValueMigration) Migrate( func (m *CapabilityValueMigration) migratePathCapabilityValue( oldCapability *interpreter.PathCapabilityValue, //nolint:staticcheck storageKey interpreter.StorageKey, - inter *interpreter.Interpreter, ) (interpreter.Value, error) { reporter := m.Reporter @@ -98,48 +95,16 @@ func (m *CapabilityValueMigration) migratePathCapabilityValue( var capabilityID interpreter.UInt64Value var controllerBorrowType sema.Type - targetPath := capabilityAddressPath.Path - - switch targetPath.Domain { - case common.PathDomainPublic, - common.PathDomainPrivate: - - var ok bool - capabilityID, controllerBorrowType, ok = m.CapabilityMapping.Get(capabilityAddressPath) - if !ok { - if reporter != nil { - reporter.MissingCapabilityID( - storageKey.Address, - capabilityAddressPath, - ) - } - return nil, nil + var ok bool + capabilityID, controllerBorrowType, ok = m.CapabilityMapping.Get(capabilityAddressPath) + if !ok { + if reporter != nil { + reporter.MissingCapabilityID( + storageKey.Address, + capabilityAddressPath, + ) } - - case common.PathDomainStorage: - // The capability may incorrectly target a storage path, - // due to an incorrect implementation of the link function in an early version of Cadence. - // This bug was fixed in https://github.com/onflow/cadence/pull/865, - // and subsequent capabilities created by the link function have correct targets, - // but networks may still have capabilities with incorrect targets. - // - // In this case, there is no corresponding capability controller in the mapping, - // so issue a new capability controller. - - borrowType := inter.MustConvertStaticToSemaType(oldCapability.BorrowType).(*sema.ReferenceType) - controllerBorrowType = borrowType - - capabilityID, _ = stdlib.IssueStorageCapabilityController( - inter, - interpreter.EmptyLocationRange, - m.IssueHandler, - common.Address(oldCapability.Address), - borrowType, - targetPath, - ) - - default: - panic(errors.NewUnexpectedError("unexpected capability target path: %s", targetPath)) + return nil, nil } oldBorrowType := oldCapability.BorrowType diff --git a/migrations/capcons/migration_test.go b/migrations/capcons/migration_test.go index b6c3e682c6..282792ece6 100644 --- a/migrations/capcons/migration_test.go +++ b/migrations/capcons/migration_test.go @@ -511,7 +511,6 @@ func testPathCapabilityValueMigration( reporter, &CapabilityValueMigration{ CapabilityMapping: capabilityMapping, - IssueHandler: handler, Reporter: reporter, }, ), @@ -2369,7 +2368,6 @@ func TestPublishedPathCapabilityValueMigration(t *testing.T) { reporter, &CapabilityValueMigration{ CapabilityMapping: capabilityMapping, - IssueHandler: handler, Reporter: reporter, }, ), @@ -2622,7 +2620,6 @@ func TestUntypedPathCapabilityValueMigration(t *testing.T) { reporter, &CapabilityValueMigration{ CapabilityMapping: capabilityMapping, - IssueHandler: handler, Reporter: reporter, }, ), From c044de6b97a3e14d108e2d4582954de9d496845f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 8 Aug 2024 12:02:14 -0700 Subject: [PATCH 4/7] make iteration deterministic --- migrations/capcons/migration_test.go | 24 +++++------ migrations/capcons/storagecapabilities.go | 52 +++++++++++++++-------- migrations/capcons/storagecapmigration.go | 4 +- 3 files changed, 48 insertions(+), 32 deletions(-) diff --git a/migrations/capcons/migration_test.go b/migrations/capcons/migration_test.go index 282792ece6..c955ea876d 100644 --- a/migrations/capcons/migration_test.go +++ b/migrations/capcons/migration_test.go @@ -2883,13 +2883,13 @@ func TestStorageCapMigration(t *testing.T) { reporter := &testMigrationReporter{} - storageCapabilities := &StorageCapabilities{} + storageDomainCapabilities := &AccountsCapabilities{} migration.Migrate( migration.NewValueMigrationsPathMigrator( reporter, &StorageCapMigration{ - AddressPaths: storageCapabilities, + StorageDomainCapabilities: storageDomainCapabilities, }, ), ) @@ -2907,21 +2907,19 @@ func TestStorageCapMigration(t *testing.T) { type actual struct { address common.Address - path interpreter.PathValue - borrowType interpreter.StaticType + capability AccountCapability } var actuals []actual - storageCapabilities.ForEach( + storageDomainCapabilities.ForEach( testAddress, - func(path interpreter.PathValue, borrowType interpreter.StaticType) bool { + func(accountCapability AccountCapability) bool { actuals = append( actuals, actual{ address: testAddress, - path: path, - borrowType: borrowType, + capability: accountCapability, }, ) return true @@ -2932,11 +2930,13 @@ func TestStorageCapMigration(t *testing.T) { []actual{ { address: testAddress, - path: interpreter.PathValue{ - Domain: common.PathDomainStorage, - Identifier: testPathIdentifier, + capability: AccountCapability{ + Path: interpreter.PathValue{ + Domain: common.PathDomainStorage, + Identifier: testPathIdentifier, + }, + BorrowType: testBorrowType, }, - borrowType: testBorrowType, }, }, actuals, diff --git a/migrations/capcons/storagecapabilities.go b/migrations/capcons/storagecapabilities.go index 65501e9d7b..8453fee3d3 100644 --- a/migrations/capcons/storagecapabilities.go +++ b/migrations/capcons/storagecapabilities.go @@ -7,41 +7,57 @@ import ( "github.com/onflow/cadence/runtime/interpreter" ) -// AccountStorageCapabilities maps path to borrow type -type AccountStorageCapabilities map[interpreter.PathValue]interpreter.StaticType +type AccountCapability struct { + Path interpreter.PathValue + BorrowType interpreter.StaticType +} + +type AccountCapabilities struct { + Capabilities []AccountCapability +} + +func (c *AccountCapabilities) Record(path interpreter.PathValue, borrowType interpreter.StaticType) { + c.Capabilities = append( + c.Capabilities, + AccountCapability{ + Path: path, + BorrowType: borrowType, + }, + ) +} -type StorageCapabilities struct { - // accountStorageCapabilities maps common.Address to AccountStorageCapabilities - accountStorageCapabilities sync.Map +type AccountsCapabilities struct { + // accountCapabilities maps common.Address to *AccountCapabilities + accountCapabilities sync.Map } -func (m *StorageCapabilities) Record( +func (m *AccountsCapabilities) Record( addressPath interpreter.AddressPath, borrowType interpreter.StaticType, ) { - var capabilityEntryMap AccountStorageCapabilities - rawCapabilityEntryMap, ok := m.accountStorageCapabilities.Load(addressPath.Address) + var accountCapabilities *AccountCapabilities + rawAccountCapabilities, ok := m.accountCapabilities.Load(addressPath.Address) if ok { - capabilityEntryMap = rawCapabilityEntryMap.(AccountStorageCapabilities) + accountCapabilities = rawAccountCapabilities.(*AccountCapabilities) } else { - capabilityEntryMap = AccountStorageCapabilities{} - m.accountStorageCapabilities.Store(addressPath.Address, capabilityEntryMap) + accountCapabilities = &AccountCapabilities{} + m.accountCapabilities.Store(addressPath.Address, accountCapabilities) } - capabilityEntryMap[addressPath.Path] = borrowType + accountCapabilities.Record(addressPath.Path, borrowType) } -func (m *StorageCapabilities) ForEach( +func (m *AccountsCapabilities) ForEach( address common.Address, - f func(path interpreter.PathValue, borrowType interpreter.StaticType) bool, + f func(AccountCapability) bool, ) { - rawCapabilityEntryMap, ok := m.accountStorageCapabilities.Load(address) + rawAccountCapabilities, ok := m.accountCapabilities.Load(address) if !ok { return } - capabilityEntryMap := rawCapabilityEntryMap.(AccountStorageCapabilities) - for path, borrowType := range capabilityEntryMap { - if !f(path, borrowType) { + accountCapabilities := rawAccountCapabilities.(*AccountCapabilities) + for _, accountCapability := range accountCapabilities.Capabilities { + if !f(accountCapability) { return } } diff --git a/migrations/capcons/storagecapmigration.go b/migrations/capcons/storagecapmigration.go index f9c94967c4..3f0fb6dff3 100644 --- a/migrations/capcons/storagecapmigration.go +++ b/migrations/capcons/storagecapmigration.go @@ -27,7 +27,7 @@ import ( // StorageCapMigration records path capabilities with storage domain target. // It does not actually migrate any values. type StorageCapMigration struct { - AddressPaths *StorageCapabilities + StorageDomainCapabilities *AccountsCapabilities } var _ migrations.ValueMigration = &StorageCapMigration{} @@ -56,7 +56,7 @@ func (m *StorageCapMigration) Migrate( if pathCapabilityValue, ok := value.(*interpreter.PathCapabilityValue); ok && //nolint:staticcheck pathCapabilityValue.Path.Domain == common.PathDomainStorage { - m.AddressPaths.Record( + m.StorageDomainCapabilities.Record( pathCapabilityValue.AddressPath(), pathCapabilityValue.BorrowType, ) From 622118de394e272396eddffe29a054a7c16f283f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 8 Aug 2024 12:03:29 -0700 Subject: [PATCH 5/7] rename --- migrations/capcons/{storagecapabilities.go => capabilities.go} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename migrations/capcons/{storagecapabilities.go => capabilities.go} (100%) diff --git a/migrations/capcons/storagecapabilities.go b/migrations/capcons/capabilities.go similarity index 100% rename from migrations/capcons/storagecapabilities.go rename to migrations/capcons/capabilities.go From dbc07d38600affb09f2449cb5bbdc77ead182703 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 8 Aug 2024 12:17:19 -0700 Subject: [PATCH 6/7] issue account capabilities --- migrations/capcons/capabilities.go | 8 ++++++ migrations/capcons/migration_test.go | 22 ++++++++++++++++ migrations/capcons/storagecapmigration.go | 31 +++++++++++++++++++++++ 3 files changed, 61 insertions(+) diff --git a/migrations/capcons/capabilities.go b/migrations/capcons/capabilities.go index 8453fee3d3..be6fc30fc7 100644 --- a/migrations/capcons/capabilities.go +++ b/migrations/capcons/capabilities.go @@ -62,3 +62,11 @@ func (m *AccountsCapabilities) ForEach( } } } + +func (m *AccountsCapabilities) Get(address common.Address) *AccountCapabilities { + rawAccountCapabilities, ok := m.accountCapabilities.Load(address) + if !ok { + return nil + } + return rawAccountCapabilities.(*AccountCapabilities) +} diff --git a/migrations/capcons/migration_test.go b/migrations/capcons/migration_test.go index c955ea876d..22d3a8eaee 100644 --- a/migrations/capcons/migration_test.go +++ b/migrations/capcons/migration_test.go @@ -494,6 +494,28 @@ func testPathCapabilityValueMigration( handler := &testCapConHandler{} + storageDomainCapabilities := &AccountsCapabilities{} + + migration.Migrate( + migration.NewValueMigrationsPathMigrator( + reporter, + &StorageCapMigration{ + StorageDomainCapabilities: storageDomainCapabilities, + }, + ), + ) + + storageCapabilities := storageDomainCapabilities.Get(testAddress) + if storageCapabilities != nil { + IssueAccountCapabilities( + inter, + testAddress, + storageCapabilities, + handler, + capabilityMapping, + ) + } + migration.Migrate( migration.NewValueMigrationsPathMigrator( reporter, diff --git a/migrations/capcons/storagecapmigration.go b/migrations/capcons/storagecapmigration.go index 3f0fb6dff3..ff13157962 100644 --- a/migrations/capcons/storagecapmigration.go +++ b/migrations/capcons/storagecapmigration.go @@ -22,6 +22,8 @@ import ( "github.com/onflow/cadence/migrations" "github.com/onflow/cadence/runtime/common" "github.com/onflow/cadence/runtime/interpreter" + "github.com/onflow/cadence/runtime/sema" + "github.com/onflow/cadence/runtime/stdlib" ) // StorageCapMigration records path capabilities with storage domain target. @@ -68,3 +70,32 @@ func (m *StorageCapMigration) Migrate( func (m *StorageCapMigration) CanSkip(valueType interpreter.StaticType) bool { return CanSkipCapabilityValueMigration(valueType) } + +func IssueAccountCapabilities( + inter *interpreter.Interpreter, + address common.Address, + capabilities *AccountCapabilities, + handler stdlib.CapabilityControllerIssueHandler, + mapping *CapabilityMapping, +) { + + for _, capability := range capabilities.Capabilities { + borrowType := inter.MustConvertStaticToSemaType(capability.BorrowType).(*sema.ReferenceType) + + capabilityID, _ := stdlib.IssueStorageCapabilityController( + inter, + interpreter.EmptyLocationRange, + handler, + address, + borrowType, + capability.Path, + ) + + addressPath := interpreter.AddressPath{ + Address: address, + Path: capability.Path, + } + + mapping.Record(addressPath, capabilityID, borrowType) + } +} From 0ed223437bc90576d84dc42f504830e18548f713 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 8 Aug 2024 12:18:52 -0700 Subject: [PATCH 7/7] add copyright header --- migrations/capcons/capabilities.go | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/migrations/capcons/capabilities.go b/migrations/capcons/capabilities.go index be6fc30fc7..e6805386e7 100644 --- a/migrations/capcons/capabilities.go +++ b/migrations/capcons/capabilities.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 capcons import (