Skip to content

Commit

Permalink
Merge pull request #3110 from onflow/bastian/improve-migration
Browse files Browse the repository at this point in the history
  • Loading branch information
turbolent authored Feb 20, 2024
2 parents ba3e5e6 + cab2c8a commit e60051d
Show file tree
Hide file tree
Showing 10 changed files with 255 additions and 22 deletions.
6 changes: 4 additions & 2 deletions migrations/capcons/capabilitymigration.go
Original file line number Diff line number Diff line change
Expand Up @@ -86,9 +86,11 @@ func (m *CapabilityValueMigration) Migrate(
break
}

newBorrowType, ok := oldCapability.BorrowType.(*interpreter.ReferenceStaticType)
oldBorrowType := oldCapability.BorrowType

newBorrowType, ok := oldBorrowType.(*interpreter.ReferenceStaticType)
if !ok {
panic(errors.NewUnreachableError())
panic(errors.NewUnexpectedError("unexpected non-reference borrow type: %T", oldBorrowType))
}

// Convert the old AuthAccount type to the new fully-entitled Account type
Expand Down
24 changes: 15 additions & 9 deletions migrations/capcons/linkmigration.go
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,10 @@ func (m *LinkValueMigration) Migrate(

case interpreter.PathLinkValue: //nolint:staticcheck
var ok bool
borrowStaticType, ok = readValue.Type.(*interpreter.ReferenceStaticType)
borrowType := readValue.Type
borrowStaticType, ok = borrowType.(*interpreter.ReferenceStaticType)
if !ok {
panic(errors.NewUnreachableError())
panic(errors.NewUnexpectedError("unexpected non-reference borrow type: %T", borrowType))
}

case interpreter.AccountLinkValue: //nolint:staticcheck
Expand All @@ -106,12 +107,13 @@ func (m *LinkValueMigration) Migrate(
)

default:
panic(errors.NewUnreachableError())
panic(errors.NewUnexpectedError("unexpected value type: %T", value))
}

borrowType, ok := inter.MustConvertStaticToSemaType(borrowStaticType).(*sema.ReferenceType)
convertedBorrowStaticType := inter.MustConvertStaticToSemaType(borrowStaticType)
borrowType, ok := convertedBorrowStaticType.(*sema.ReferenceType)
if !ok {
panic(errors.NewUnreachableError())
panic(errors.NewUnexpectedError("unexpected non-reference borrow type: %T", borrowType))
}

// Get target
Expand Down Expand Up @@ -176,7 +178,7 @@ func (m *LinkValueMigration) Migrate(
)

default:
panic(errors.NewUnreachableError())
panic(errors.NewUnexpectedError("unexpected target type: %T", target))
}

// Record new capability ID in source path mapping.
Expand Down Expand Up @@ -310,9 +312,13 @@ func (m *LinkValueMigration) getPathCapabilityFinalTarget(
// so it's possible that a capability value is encountered when determining the final target,
// when a part of the full link chain was already previously migrated.

capabilityBorrowType, ok := inter.MustConvertStaticToSemaType(value.BorrowType).(*sema.ReferenceType)
convertedBorrowType := inter.MustConvertStaticToSemaType(value.BorrowType)
capabilityBorrowType, ok := convertedBorrowType.(*sema.ReferenceType)
if !ok {
panic(errors.NewUnreachableError())
panic(errors.NewUnexpectedError(
"unexpected non-reference borrow type: %T",
convertedBorrowType,
))
}

// Do not borrow final target (i.e. do not require target to exist),
Expand Down Expand Up @@ -349,7 +355,7 @@ func (m *LinkValueMigration) getPathCapabilityFinalTarget(
}

default:
panic(errors.NewUnreachableError())
panic(errors.NewUnexpectedError("unexpected value type: %T", value))
}
}
}
Expand Down
35 changes: 34 additions & 1 deletion migrations/entitlements/migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -909,6 +909,11 @@ func TestConvertToEntitledValue(t *testing.T) {
),
Name: "[Type]",
},
{
Input: interpreter.NewTypeValue(inter, nil),
Output: interpreter.NewTypeValue(inter, nil),
Name: "Type(nil)",
},
{
Input: interpreter.NewDictionaryValue(
inter,
Expand Down Expand Up @@ -1041,6 +1046,19 @@ func TestConvertToEntitledValue(t *testing.T) {
},
Name: "PathCapability<&S>",
},
{
Input: &interpreter.PathCapabilityValue{ //nolint:staticcheck
Address: interpreter.NewAddressValue(inter, testAddress),
Path: testPathValue,
BorrowType: nil,
},
Output: &interpreter.PathCapabilityValue{ //nolint:staticcheck
Address: interpreter.NewAddressValue(inter, testAddress),
Path: testPathValue,
BorrowType: nil,
},
Name: "PathCapability<nil>",
},
{
Input: interpreter.NewCapabilityValue(
inter,
Expand Down Expand Up @@ -1276,6 +1294,21 @@ func TestConvertToEntitledValue(t *testing.T) {
}
return true

case interpreter.TypeValue:
// TypeValue considers missing type "unknown"/"invalid",
// and "unknown"/"invalid" type values unequal.
// However, we want to consider those equal here for testing/asserting purposes
other, ok := output.(interpreter.TypeValue)
if !ok {
return false
}

if other.Type == nil {
return v.Type == nil
} else {
return other.Type.Equal(v.Type)
}

case *interpreter.EphemeralReferenceValue:
otherReference, ok := output.(*interpreter.EphemeralReferenceValue)
if !ok || !v.Authorization.Equal(otherReference.Authorization) {
Expand Down Expand Up @@ -1304,7 +1337,7 @@ func TestConvertToEntitledValue(t *testing.T) {
convertedValue := convertEntireTestValue(inter, storage, testAddress, test.Input)
switch convertedValue := convertedValue.(type) {
case interpreter.EquatableValue:
require.True(t, referencePeekingEqual(convertedValue, test.Output))
require.True(t, referencePeekingEqual(convertedValue, test.Output), "expected: %s\nactual: %s", test.Output, convertedValue)
default:
require.Equal(t, convertedValue, test.Output)
}
Expand Down
7 changes: 4 additions & 3 deletions migrations/legacy_primitivestatic_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@ type LegacyPrimitiveStaticType struct {
var _ interpreter.StaticType = LegacyPrimitiveStaticType{}

func (t LegacyPrimitiveStaticType) ID() common.TypeID {
switch t.PrimitiveStaticType {
primitiveStaticType := t.PrimitiveStaticType

switch primitiveStaticType {
case interpreter.PrimitiveStaticTypeAuthAccount: //nolint:staticcheck
return "AuthAccount"
case interpreter.PrimitiveStaticTypePublicAccount: //nolint:staticcheck
Expand All @@ -59,7 +61,6 @@ func (t LegacyPrimitiveStaticType) ID() common.TypeID {
case interpreter.PrimitiveStaticTypeAccountKey: //nolint:staticcheck
return "AccountKey"
default:
panic(errors.NewUnreachableError())

panic(errors.NewUnexpectedError("unexpected non-legacy primitive static type: %s", primitiveStaticType))
}
}
15 changes: 12 additions & 3 deletions migrations/migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -306,7 +306,10 @@ func (m *StorageMigration) MigrateNestedValue(
)

if _, ok := oldValue.(*interpreter.SomeValue); !ok {
panic(errors.NewUnreachableError())
panic(errors.NewUnexpectedError(
"failed to remove old value for migrated key: %s",
existingKey,
))
}

keyToSet = newKey
Expand Down Expand Up @@ -372,8 +375,14 @@ func (m *StorageMigration) MigrateNestedValue(
// is the same as the owner of the old value
if ownedValue, ok := value.(interpreter.OwnedValue); ok {
if ownedConvertedValue, ok := convertedValue.(interpreter.OwnedValue); ok {
if ownedConvertedValue.GetOwner() != ownedValue.GetOwner() {
panic(errors.NewUnreachableError())
convertedOwner := ownedConvertedValue.GetOwner()
originalOwner := ownedValue.GetOwner()
if convertedOwner != originalOwner {
panic(errors.NewUnexpectedError(
"migrated value has different owner: expected %s, got %s",
originalOwner,
convertedOwner,
))
}
}
}
Expand Down
8 changes: 7 additions & 1 deletion migrations/statictypes/account_type_migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@ type testReporter struct {
interpreter.StorageKey
interpreter.StorageMapKey
}]struct{}
errors []error
}

func newTestReporter() *testReporter {
Expand Down Expand Up @@ -72,8 +73,9 @@ func (t *testReporter) Error(
_ interpreter.StorageKey,
_ interpreter.StorageMapKey,
_ string,
_ error,
err error,
) {
t.errors = append(t.errors, err)
}

func TestAccountTypeInTypeValueMigration(t *testing.T) {
Expand Down Expand Up @@ -424,6 +426,8 @@ func TestAccountTypeInTypeValueMigration(t *testing.T) {
err = migration.Commit()
require.NoError(t, err)

require.Empty(t, reporter.errors)

// Check reported migrated paths
for identifier, test := range testCases {
key := struct {
Expand Down Expand Up @@ -1080,6 +1084,8 @@ func TestAccountTypeRehash(t *testing.T) {
err := migration.Commit()
require.NoError(t, err)

require.Empty(t, reporter.errors)

require.Equal(t,
map[struct {
interpreter.StorageKey
Expand Down
2 changes: 2 additions & 0 deletions migrations/statictypes/composite_type_migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,6 +172,8 @@ func TestCompositeAndInterfaceTypeMigration(t *testing.T) {
err = migration.Commit()
require.NoError(t, err)

require.Empty(t, reporter.errors)

// Check reported migrated paths
for identifier, test := range testCases {
key := struct {
Expand Down
12 changes: 12 additions & 0 deletions migrations/statictypes/intersection_type_migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -443,6 +443,8 @@ func TestIntersectionTypeMigration(t *testing.T) {
err = migration.Commit()
require.NoError(t, err)

require.Empty(t, reporter.errors)

// Check reported migrated paths
for identifier, test := range testCases {
key := struct {
Expand Down Expand Up @@ -611,6 +613,8 @@ func TestIntersectionTypeRehash(t *testing.T) {
err := migration.Commit()
require.NoError(t, err)

require.Empty(t, reporter.errors)

require.Equal(t,
map[struct {
interpreter.StorageKey
Expand Down Expand Up @@ -775,6 +779,8 @@ func TestRehashNestedIntersectionType(t *testing.T) {
err := migration.Commit()
require.NoError(t, err)

require.Empty(t, reporter.errors)

require.Equal(t,
map[struct {
interpreter.StorageKey
Expand Down Expand Up @@ -914,6 +920,8 @@ func TestRehashNestedIntersectionType(t *testing.T) {
err := migration.Commit()
require.NoError(t, err)

require.Empty(t, reporter.errors)

require.Equal(t,
map[struct {
interpreter.StorageKey
Expand Down Expand Up @@ -1114,6 +1122,8 @@ func TestIntersectionTypeMigrationWithInterfaceTypeConverter(t *testing.T) {
err = migration.Commit()
require.NoError(t, err)

require.Empty(t, reporter.errors)

expectLegacyTypeConverted := convertCompositeType && legacyType != nil
expectInterfaceTypeConverted := convertInterfaceType && len(interfaceTypeQualifiedIdentifiers) > 0
expectMigration := len(interfaceTypeQualifiedIdentifiers) >= 2 ||
Expand Down Expand Up @@ -1282,6 +1292,8 @@ func TestIntersectionTypeMigrationWithTypeConverters(t *testing.T) {
err = migration.Commit()
require.NoError(t, err)

require.Empty(t, reporter.errors)

key := struct {
interpreter.StorageKey
interpreter.StorageMapKey
Expand Down
16 changes: 13 additions & 3 deletions migrations/statictypes/statictype_migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -66,7 +66,12 @@ func (m *StaticTypeMigration) Migrate(
) (newValue interpreter.Value, err error) {
switch value := value.(type) {
case interpreter.TypeValue:
convertedType := m.maybeConvertStaticType(value.Type, nil)
// Type is optional. nil represents "unknown"/"invalid" type
ty := value.Type
if ty == nil {
return
}
convertedType := m.maybeConvertStaticType(ty, nil)
if convertedType == nil {
return
}
Expand All @@ -80,7 +85,12 @@ func (m *StaticTypeMigration) Migrate(
return interpreter.NewUnmeteredCapabilityValue(value.ID, value.Address, convertedBorrowType), nil

case *interpreter.PathCapabilityValue: //nolint:staticcheck
convertedBorrowType := m.maybeConvertStaticType(value.BorrowType, nil)
// Type is optional
borrowType := value.BorrowType
if borrowType == nil {
return
}
convertedBorrowType := m.maybeConvertStaticType(borrowType, nil)
if convertedBorrowType == nil {
return
}
Expand Down Expand Up @@ -345,7 +355,7 @@ func (m *StaticTypeMigration) maybeConvertStaticType(staticType, parentType inte
}

default:
panic(errors.NewUnreachableError())
panic(errors.NewUnexpectedError("unexpected static type: %T", staticType))
}

return nil
Expand Down
Loading

0 comments on commit e60051d

Please sign in to comment.