Skip to content

Commit

Permalink
Merge pull request #3205 from onflow/bastian/3192-authaccount-type-lo…
Browse files Browse the repository at this point in the history
…ading
  • Loading branch information
turbolent authored Apr 3, 2024
2 parents a0dd6cf + 490fcc3 commit 936b087
Show file tree
Hide file tree
Showing 3 changed files with 206 additions and 0 deletions.
12 changes: 12 additions & 0 deletions migrations/statictypes/statictype_migration.go
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,18 @@ func (m *StaticTypeMigration) maybeConvertStaticType(staticType, parentType inte
convertedType = compositeTypeConverter(staticType)
}

// Convert built-in types in composite type form to primitive type
if convertedType == nil && staticType.Location == nil {
primitiveStaticType := interpreter.PrimitiveStaticTypeFromTypeID(staticType.TypeID)
if primitiveStaticType != interpreter.PrimitiveStaticTypeUnknown {
convertedPrimitiveStaticType := m.maybeConvertStaticType(primitiveStaticType, parentType)
if convertedPrimitiveStaticType != nil {
return convertedPrimitiveStaticType
}
return primitiveStaticType
}
}

// Interface types need to be placed in intersection types.
// If the composite type was converted to an interface type,
// and if the parent type is not an intersection type,
Expand Down
123 changes: 123 additions & 0 deletions migrations/statictypes/statictype_migration_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,84 @@ func TestStaticTypeMigration(t *testing.T) {
)
})

t.Run("TypeValue with reference to AuthAccount (as primitive)", func(t *testing.T) {
t.Parallel()

staticTypeMigration := NewStaticTypeMigration()

actual := migrate(t,
staticTypeMigration,
interpreter.NewUnmeteredTypeValue(
interpreter.NewDictionaryStaticType(nil,
interpreter.PrimitiveStaticTypeAddress,
interpreter.NewCapabilityStaticType(nil,
interpreter.NewReferenceStaticType(
nil,
interpreter.UnauthorizedAccess,
interpreter.PrimitiveStaticTypeAuthAccount, //nolint:staticcheck
),
),
),
),
true,
)
assert.Equal(t,
interpreter.NewUnmeteredTypeValue(
interpreter.NewDictionaryStaticType(nil,
interpreter.PrimitiveStaticTypeAddress,
interpreter.NewCapabilityStaticType(nil,
// NOTE: NOT reference to reference type
authAccountReferenceType,
),
),
),
actual,
)
})

t.Run("TypeValue with reference to AuthAccount (as composite)", func(t *testing.T) {
t.Parallel()

staticTypeMigration := NewStaticTypeMigration()

authAccountTypeID := interpreter.PrimitiveStaticTypeAuthAccount.ID() //nolint:staticcheck

actual := migrate(t,
staticTypeMigration,
interpreter.NewUnmeteredTypeValue(
interpreter.NewDictionaryStaticType(nil,
interpreter.PrimitiveStaticTypeAddress,
interpreter.NewCapabilityStaticType(nil,
interpreter.NewReferenceStaticType(
nil,
interpreter.UnauthorizedAccess,
// NOTE: AuthAccount as composite type
interpreter.NewCompositeStaticType(
nil,
nil,
string(authAccountTypeID),
authAccountTypeID,
),
),
),
),
),
true,
)
assert.Equal(t,
interpreter.NewUnmeteredTypeValue(
interpreter.NewDictionaryStaticType(nil,
interpreter.PrimitiveStaticTypeAddress,
interpreter.NewCapabilityStaticType(nil,
// NOTE: NOT reference to reference type
authAccountReferenceType,
),
),
),
actual,
)
})

t.Run("PathCapabilityValue with nil borrow type", func(t *testing.T) {
t.Parallel()

Expand Down Expand Up @@ -718,6 +796,51 @@ func TestStaticTypeMigration(t *testing.T) {

assert.Equal(t, expected, actual)
})

t.Run(
"composite types of (non-deprecated) built-in types are converted to primitive static types",
func(t *testing.T) {
t.Parallel()

test := func(t *testing.T, ty interpreter.PrimitiveStaticType) {

typeID := ty.ID()

t.Run(string(typeID), func(t *testing.T) {
t.Parallel()

staticTypeMigration := NewStaticTypeMigration()

actual := migrate(t,
staticTypeMigration,
interpreter.NewUnmeteredTypeValue(
// NOTE: AuthAccount as composite type
interpreter.NewCompositeStaticType(
nil,
nil,
string(typeID),
typeID,
),
),
true,
)
assert.Equal(t,
interpreter.NewUnmeteredTypeValue(ty),
actual,
)
})
}

for ty := interpreter.PrimitiveStaticTypeUnknown + 1; ty < interpreter.PrimitiveStaticType_Count; ty++ {
if !ty.IsDefined() || ty.IsDeprecated() { //nolint:staticcheck
continue
}

test(t, ty)
}
},
)

}

func TestMigratingNestedContainers(t *testing.T) {
Expand Down
71 changes: 71 additions & 0 deletions runtime/interpreter/primitivestatictype.go
Original file line number Diff line number Diff line change
Expand Up @@ -394,6 +394,9 @@ func (t PrimitiveStaticType) elementSize() uint {
PrimitiveStaticTypeAccountKey:
// These types are deprecated, and only exist for migration purposes
return UnknownElementSize

case PrimitiveStaticTypeUnknown:
case PrimitiveStaticType_Count:
}

panic(errors.NewUnexpectedError("missing case for %s", t))
Expand Down Expand Up @@ -422,6 +425,35 @@ func (t PrimitiveStaticType) MeteredString(memoryGauge common.MemoryGauge) strin
}

func (t PrimitiveStaticType) ID() TypeID {

// Handle deprecated types specially, because they do not have a sema type equivalent anymore
switch t {
case PrimitiveStaticTypeAuthAccount: //nolint:staticcheck
return "AuthAccount"
case PrimitiveStaticTypePublicAccount: //nolint:staticcheck
return "PublicAccount"
case PrimitiveStaticTypeAuthAccountContracts: //nolint:staticcheck
return "AuthAccount.Contracts"
case PrimitiveStaticTypePublicAccountContracts: //nolint:staticcheck
return "PublicAccount.Contracts"
case PrimitiveStaticTypeAuthAccountKeys: //nolint:staticcheck
return "AuthAccount.Keys"
case PrimitiveStaticTypePublicAccountKeys: //nolint:staticcheck
return "PublicAccount.Keys"
case PrimitiveStaticTypeAuthAccountInbox: //nolint:staticcheck
return "AuthAccount.Inbox"
case PrimitiveStaticTypeAuthAccountStorageCapabilities: //nolint:staticcheck
return "AuthAccount.StorageCapabilities"
case PrimitiveStaticTypeAuthAccountAccountCapabilities: //nolint:staticcheck
return "AuthAccount.AccountCapabilities"
case PrimitiveStaticTypeAuthAccountCapabilities: //nolint:staticcheck
return "AuthAccount.Capabilities"
case PrimitiveStaticTypePublicAccountCapabilities: //nolint:staticcheck
return "PublicAccount.Capabilities"
case PrimitiveStaticTypeAccountKey: //nolint:staticcheck
return "AccountKey"
}

return t.SemaType().ID()
}

Expand Down Expand Up @@ -654,6 +686,21 @@ func (t PrimitiveStaticType) SemaType() sema.Type {
case PrimitiveStaticTypePublicAccount: //nolint:staticcheck
// deprecated, but needed for migration purposes
return sema.AccountReferenceType

case PrimitiveStaticTypeAuthAccountContracts:
case PrimitiveStaticTypePublicAccountContracts:
case PrimitiveStaticTypeAuthAccountKeys:
case PrimitiveStaticTypePublicAccountKeys:
case PrimitiveStaticTypeAccountKey:
case PrimitiveStaticTypeAuthAccountInbox:
case PrimitiveStaticTypeAuthAccountStorageCapabilities:
case PrimitiveStaticTypeAuthAccountAccountCapabilities:
case PrimitiveStaticTypeAuthAccountCapabilities:
case PrimitiveStaticTypePublicAccountCapabilities:
panic(errors.NewUnexpectedError("cannot convert deprecated type %s", t))

case PrimitiveStaticTypeUnknown:
case PrimitiveStaticType_Count:
}

if t.IsDeprecated() {
Expand Down Expand Up @@ -919,3 +966,27 @@ func ConvertSemaToPrimitiveStaticType(

return NewPrimitiveStaticType(memoryGauge, typ)
}

var primitiveStaticTypesByTypeID = map[TypeID]PrimitiveStaticType{}

func init() {
// Check all defined primitive static types,
// and construct a type ID to primitive static type mapping
for ty := PrimitiveStaticTypeUnknown + 1; ty < PrimitiveStaticType_Count; ty++ {
if !ty.IsDefined() {
continue
}

_ = ty.elementSize()

primitiveStaticTypesByTypeID[ty.ID()] = ty
}
}

func PrimitiveStaticTypeFromTypeID(typeID TypeID) PrimitiveStaticType {
ty, ok := primitiveStaticTypesByTypeID[typeID]
if !ok {
return PrimitiveStaticTypeUnknown
}
return ty
}

0 comments on commit 936b087

Please sign in to comment.