Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Entitlements Migration #2951

Merged
merged 56 commits into from
Jan 16, 2024
Merged
Show file tree
Hide file tree
Changes from 38 commits
Commits
Show all changes
56 commits
Select commit Hold shift + click to select a range
c046e28
include interface conformances when computing supported entitlements …
dsainati1 Aug 1, 2023
a42e1dd
compute entitled types
dsainati1 Aug 3, 2023
9f317a5
Merge branch 'sainati/interface-inherited-entitlement-sets' into sain…
dsainati1 Aug 3, 2023
dbc8038
tests for convert to entitled type
dsainati1 Aug 3, 2023
e5f4d47
add todo
dsainati1 Aug 3, 2023
63c6550
basic conversion of values
dsainati1 Aug 7, 2023
0791955
tests for arrays and dicts of references
dsainati1 Aug 7, 2023
1c0e20d
add test for capability values
dsainati1 Aug 8, 2023
b031af9
convert runtime type values
dsainati1 Aug 8, 2023
bfed26b
make TypeValue a pointer type
dsainati1 Aug 9, 2023
bb65048
fix tests
dsainati1 Aug 9, 2023
f5be50c
Merge branch 'feature/stable-cadence' of github.com:onflow/cadence in…
dsainati1 Aug 9, 2023
02bc9d5
Merge branch 'sainati/entitlement-sets' of github.com:onflow/cadence …
dsainati1 Aug 9, 2023
fa70004
removed old capability value
dsainati1 Aug 9, 2023
ba63ef1
add entitlements migration
dsainati1 Nov 16, 2023
a2f63c1
Merge branch 'sainati/supported-entitlements-interface' of github.com…
dsainati1 Nov 16, 2023
4ecf451
add implementation and tests for ConvertEntitledType
dsainati1 Nov 16, 2023
6916901
Merge branch 'sainati/convert-entitled-value' of github.com:onflow/ca…
dsainati1 Nov 16, 2023
7533eef
add tests for array and dict values
dsainati1 Nov 17, 2023
6caeeec
convert array and dict types
dsainati1 Nov 17, 2023
4e72efc
scaffolding for capabilities and storagereferences
dsainati1 Nov 20, 2023
332646a
Merge branch 'feature/stable-cadence' of github.com:onflow/cadence in…
dsainati1 Nov 20, 2023
be44520
support for migrating legacy intersection types
dsainati1 Nov 21, 2023
26688cc
test for simple migration
dsainati1 Nov 21, 2023
22aab6f
Merge branch 'supun/generalized-migration' of https://github.com/onfl…
SupunS Nov 21, 2023
c9a78f5
add test for full update flow
dsainati1 Nov 27, 2023
6193e44
improve test
dsainati1 Nov 27, 2023
f201835
also walk container static types when removing restricted types
dsainati1 Dec 1, 2023
c465ab0
fix test
dsainati1 Dec 4, 2023
c2c0098
Merge branch 'master' of github.com:onflow/cadence into sainati/entit…
dsainati1 Dec 11, 2023
6aaa023
update convertValue to create a new value
dsainati1 Dec 11, 2023
e867648
adjust tests
dsainati1 Dec 12, 2023
af22600
add test for array of values
dsainati1 Dec 13, 2023
591471d
broken commit for testing
dsainati1 Dec 13, 2023
cb3d934
add new test
dsainati1 Dec 13, 2023
cf9f801
return nil for unchanged values
dsainati1 Dec 13, 2023
e0958b3
Merge branch 'test-migration-branch' of github.com:onflow/cadence int…
dsainati1 Dec 13, 2023
600eafc
fix comment
dsainati1 Dec 13, 2023
59e9af8
respond to review
dsainati1 Dec 13, 2023
9ebd416
revert change of TypeValue to pointer type
dsainati1 Dec 15, 2023
0afbaea
remove unnecessary formatting changes
dsainati1 Dec 15, 2023
f187329
remove unnecessary formatting changes
dsainati1 Dec 15, 2023
fb88f49
Update migrations/migration.go
dsainati1 Dec 20, 2023
444ad83
Merge branch 'master' of github.com:onflow/cadence into sainati/entit…
dsainati1 Jan 2, 2024
1413852
Merge branch 'master' of github.com:onflow/cadence into sainati/entit…
dsainati1 Jan 5, 2024
c46d84e
don't create new wrapper types when inner type does not change
dsainati1 Jan 5, 2024
f5f26f6
add comment
dsainati1 Jan 5, 2024
de138fa
add test for typeValue keys
dsainati1 Jan 5, 2024
1df8f05
Merge branch 'master' of github.com:onflow/cadence into sainati/entit…
dsainati1 Jan 10, 2024
757dacb
Merge branch 'master' into sainati/entitlements-migration
turbolent Jan 12, 2024
8d75305
Merge branch 'master' of github.com:onflow/cadence into sainati/entit…
dsainati1 Jan 12, 2024
c2bb44d
fix compile
dsainati1 Jan 12, 2024
63f5cde
Merge branch 'sainati/entitlements-migration' of github.com:onflow/ca…
dsainati1 Jan 12, 2024
96c87d5
Update migrations/migration.go
dsainati1 Jan 16, 2024
4a4ba6b
fix lint
dsainati1 Jan 16, 2024
aabab60
fix lint
dsainati1 Jan 16, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
87 changes: 87 additions & 0 deletions migrations/account_storage.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
/*
* Cadence - The resource-oriented smart contract programming language
*
* Copyright Dapper Labs, Inc.
*
* 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 migrations

import (
"github.com/onflow/cadence/runtime"
"github.com/onflow/cadence/runtime/common"
"github.com/onflow/cadence/runtime/interpreter"
)

type AccountStorage struct {
storage *runtime.Storage
address common.Address
}

// NewAccountStorage constructs an `AccountStorage` for a given account.
func NewAccountStorage(storage *runtime.Storage, address common.Address) AccountStorage {
return AccountStorage{
storage: storage,
address: address,
}
}

// ForEachValue iterates over the values in the account.
// The `valueConverter takes a function to be applied to each value.
// It returns the converted, if a new value was created during conversion.
func (i *AccountStorage) ForEachValue(
inter *interpreter.Interpreter,
domains []common.PathDomain,
valueConverter func(
value interpreter.Value,
address common.Address,
domain common.PathDomain,
key string,
) interpreter.Value,
) {
for _, domain := range domains {
storageMap := i.storage.GetStorageMap(i.address, domain.Identifier(), false)
if storageMap == nil || storageMap.Count() == 0 {
continue
}

iterator := storageMap.Iterator(inter)

// Read the keys first, so the iteration wouldn't be affected
// by the modification of the storage values.
var keys []string
for key, _ := iterator.Next(); key != nil; key, _ = iterator.Next() {
identifier := string(key.(interpreter.StringAtreeValue))
keys = append(keys, identifier)
}

for _, key := range keys {
storageKey := interpreter.StringStorageMapKey(key)

value := storageMap.ReadValue(nil, storageKey)

newValue := valueConverter(value, i.address, domain, key)
if newValue == nil {
continue
}

// If the converter returns a new value, then replace the existing value with the new one.
storageMap.SetValue(
inter,
storageKey,
newValue,
)
}
}
}
49 changes: 49 additions & 0 deletions migrations/account_type/dummy_static_type.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
/*
* Cadence - The resource-oriented smart contract programming language
*
* Copyright Dapper Labs, Inc.
*
* 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 account_type

import (
"github.com/onflow/cadence/runtime/common"
"github.com/onflow/cadence/runtime/interpreter"
)

// dummyStaticType is just a wrapper for `interpreter.PrimitiveStaticType`
// with an overridden `ID` function.
// This is only for testing the migration, so that a type-value with a deprecated primitive type
// (e.g: `PrimitiveStaticTypePublicAccount`) is insertable as a dictionary key (to populate the storage).
// i.e: To make hashing function works, which requires `ID()` method.
// Currently, this is not possible, since the `ID` function of `interpreter.PrimitiveStaticType`
// of deprecated types no longer work, as it relies on the `sema.Type`,
// but the corresponding `sema.Type` for the deprecated primitive types are no longer available.
type dummyStaticType struct {
interpreter.PrimitiveStaticType
}

func (t dummyStaticType) ID() common.TypeID {
return common.TypeID(t.String())
}

func (t dummyStaticType) Equal(other interpreter.StaticType) bool {
otherDummyType, ok := other.(dummyStaticType)
if !ok {
return false
}

return t == otherDummyType
}
192 changes: 192 additions & 0 deletions migrations/account_type/migration.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
/*
* Cadence - The resource-oriented smart contract programming language
*
* Copyright Dapper Labs, Inc.
*
* 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 account_type

import (
"github.com/onflow/cadence/migrations"
"github.com/onflow/cadence/runtime/common"
"github.com/onflow/cadence/runtime/interpreter"
"github.com/onflow/cadence/runtime/sema"
)

type AccountTypeMigration struct{}

var _ migrations.Migration = AccountTypeMigration{}

func NewAccountTypeMigration() AccountTypeMigration {
return AccountTypeMigration{}
}

func (AccountTypeMigration) Name() string {
return "AccountTypeMigration"
}

// Migrate migrates `AuthAccount` and `PublicAccount` types inside `TypeValue`s,
// to the account reference type (&Account).
func (AccountTypeMigration) Migrate(value interpreter.Value) (newValue interpreter.Value) {
if typeValue, ok := value.(*interpreter.TypeValue); ok {
convertedType := maybeConvertAccountType(typeValue.Type)
if convertedType == nil {
return
}

return interpreter.NewTypeValue(nil, convertedType)
}

return nil
}

func maybeConvertAccountType(staticType interpreter.StaticType) interpreter.StaticType {
switch staticType := staticType.(type) {
case *interpreter.ConstantSizedStaticType:
convertedType := maybeConvertAccountType(staticType.Type)
if convertedType != nil {
return interpreter.NewConstantSizedStaticType(nil, convertedType, staticType.Size)
}

case *interpreter.VariableSizedStaticType:
convertedType := maybeConvertAccountType(staticType.Type)
if convertedType != nil {
return interpreter.NewVariableSizedStaticType(nil, convertedType)
}

case *interpreter.DictionaryStaticType:
convertedKeyType := maybeConvertAccountType(staticType.KeyType)
convertedValueType := maybeConvertAccountType(staticType.ValueType)
if convertedKeyType != nil && convertedValueType != nil {
return interpreter.NewDictionaryStaticType(nil, convertedKeyType, convertedValueType)
}
if convertedKeyType != nil {
return interpreter.NewDictionaryStaticType(nil, convertedKeyType, staticType.ValueType)
}
if convertedValueType != nil {
return interpreter.NewDictionaryStaticType(nil, staticType.KeyType, convertedValueType)
}

case *interpreter.CapabilityStaticType:
convertedBorrowType := maybeConvertAccountType(staticType.BorrowType)
if convertedBorrowType != nil {
return interpreter.NewCapabilityStaticType(nil, convertedBorrowType)
}

case *interpreter.IntersectionStaticType:
// Nothing to do. Inner types can only be interfaces.

case *interpreter.OptionalStaticType:
convertedInnerType := maybeConvertAccountType(staticType.Type)
if convertedInnerType != nil {
return interpreter.NewOptionalStaticType(nil, convertedInnerType)
}

case *interpreter.ReferenceStaticType:
// TODO: Reference of references must not be allowed?
convertedReferencedType := maybeConvertAccountType(staticType.ReferencedType)
if convertedReferencedType != nil {
switch convertedReferencedType {

// If the converted type is already an account reference, then return as-is.
// i.e: Do not create reference to a reference.
case authAccountReferenceType,
unauthorizedAccountReferenceType:
return convertedReferencedType

default:
return interpreter.NewReferenceStaticType(nil, staticType.Authorization, convertedReferencedType)
}
}

case interpreter.FunctionStaticType:
// Non-storable

case *interpreter.CompositeStaticType,
*interpreter.InterfaceStaticType:
// Nothing to do

case dummyStaticType:
// This is for testing the migration.
// i.e: wrapper was only to make it possible to use as a dictionary-key.
// Ignore the wrapper, and continue with the inner type.
return maybeConvertAccountType(staticType.PrimitiveStaticType)

default:
// Is it safe to do so?
switch staticType {
case interpreter.PrimitiveStaticTypePublicAccount: //nolint:staticcheck
return unauthorizedAccountReferenceType
case interpreter.PrimitiveStaticTypeAuthAccount: //nolint:staticcheck
return authAccountReferenceType

case interpreter.PrimitiveStaticTypeAuthAccountCapabilities, //nolint:staticcheck
interpreter.PrimitiveStaticTypePublicAccountCapabilities: //nolint:staticcheck
return interpreter.PrimitiveStaticTypeAccount_Capabilities

case interpreter.PrimitiveStaticTypeAuthAccountAccountCapabilities: //nolint:staticcheck
return interpreter.PrimitiveStaticTypeAccount_AccountCapabilities

case interpreter.PrimitiveStaticTypeAuthAccountStorageCapabilities: //nolint:staticcheck
return interpreter.PrimitiveStaticTypeAccount_StorageCapabilities

case interpreter.PrimitiveStaticTypeAuthAccountContracts, //nolint:staticcheck
interpreter.PrimitiveStaticTypePublicAccountContracts: //nolint:staticcheck
return interpreter.PrimitiveStaticTypeAccount_Contracts

case interpreter.PrimitiveStaticTypeAuthAccountKeys, //nolint:staticcheck
interpreter.PrimitiveStaticTypePublicAccountKeys: //nolint:staticcheck
return interpreter.PrimitiveStaticTypeAccount_Keys

case interpreter.PrimitiveStaticTypeAuthAccountInbox: //nolint:staticcheck
return interpreter.PrimitiveStaticTypeAccount_Inbox

case interpreter.PrimitiveStaticTypeAccountKey: //nolint:staticcheck
return interpreter.AccountKeyStaticType
}
}

return nil
}

var authAccountEntitlements = []common.TypeID{
sema.StorageType.ID(),
sema.ContractsType.ID(),
sema.KeysType.ID(),
sema.InboxType.ID(),
sema.CapabilitiesType.ID(),
}

var authAccountReferenceType = func() *interpreter.ReferenceStaticType {
auth := interpreter.NewEntitlementSetAuthorization(
nil,
func() []common.TypeID {
return authAccountEntitlements
},
len(authAccountEntitlements),
sema.Conjunction,
)
return interpreter.NewReferenceStaticType(
nil,
auth,
interpreter.PrimitiveStaticTypeAccount,
)
}()

var unauthorizedAccountReferenceType = interpreter.NewReferenceStaticType(
nil,
interpreter.UnauthorizedAccess,
interpreter.PrimitiveStaticTypeAccount,
)
Loading