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

meter and deduplicate included entitlement relations #2810

Merged
merged 3 commits into from
Sep 22, 2023
Merged
Show file tree
Hide file tree
Changes from 2 commits
Commits
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
1 change: 1 addition & 0 deletions runtime/common/memorykind.go
Original file line number Diff line number Diff line change
Expand Up @@ -242,6 +242,7 @@ const (
MemoryKindReferenceSemaType
MemoryKindEntitlementSemaType
MemoryKindEntitlementMapSemaType
MemoryKindEntitlementRelationSemaType
MemoryKindCapabilitySemaType

// ordered-map
Expand Down
15 changes: 8 additions & 7 deletions runtime/common/memorykind_string.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 10 additions & 9 deletions runtime/common/metering.go
Original file line number Diff line number Diff line change
Expand Up @@ -172,15 +172,16 @@ var (
EntitlementMapStaticTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindEntitlementMapStaticAccess)
// Sema types

VariableSizedSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindVariableSizedSemaType)
ConstantSizedSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindConstantSizedSemaType)
DictionarySemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindDictionarySemaType)
OptionalSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindOptionalSemaType)
IntersectionSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindIntersectionSemaType)
ReferenceSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindReferenceSemaType)
EntitlementSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindEntitlementSemaType)
EntitlementMapSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindEntitlementMapSemaType)
CapabilitySemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindCapabilitySemaType)
VariableSizedSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindVariableSizedSemaType)
ConstantSizedSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindConstantSizedSemaType)
DictionarySemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindDictionarySemaType)
OptionalSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindOptionalSemaType)
IntersectionSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindIntersectionSemaType)
ReferenceSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindReferenceSemaType)
EntitlementSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindEntitlementSemaType)
EntitlementMapSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindEntitlementMapSemaType)
EntitlementRelationSemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindEntitlementRelationSemaType)
CapabilitySemaTypeMemoryUsage = NewConstantMemoryUsage(MemoryKindCapabilitySemaType)

// Storage related memory usages

Expand Down
230 changes: 230 additions & 0 deletions runtime/entitlements_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1283,3 +1283,233 @@

require.NoError(t, err)
}

func TestRuntimeEntitlementMapIncludeDeduped(t *testing.T) {
t.Parallel()

storage := newTestLedger(nil, nil)

Check failure on line 1290 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Performance regression check

undefined: newTestLedger

Check failure on line 1290 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: newTestLedger

Check failure on line 1290 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: newTestLedger

Check failure on line 1290 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Test

undefined: newTestLedger
rt := newTestInterpreterRuntime()

Check failure on line 1291 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Performance regression check

undefined: newTestInterpreterRuntime

Check failure on line 1291 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: newTestInterpreterRuntime

Check failure on line 1291 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: newTestInterpreterRuntime

Check failure on line 1291 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Test

undefined: newTestInterpreterRuntime
accountCodes := map[Location][]byte{}

script := []byte(`
access(all) entitlement E
access(all) entitlement F

access(all) entitlement X
access(all) entitlement Y
access(all) entitlement mapping N1 {
E -> F
E -> E
E -> X
E -> Y
F -> F
F -> E
F -> X
F -> Y
X -> F
X -> E
X -> X
X -> Y
}
access(all) entitlement mapping N2{ include N1 }
access(all) entitlement mapping N3{ include N2 }
access(all) entitlement mapping N4{ include N3 }
access(all) entitlement mapping A {
include N1
include N2
include N3
include N4
}
access(all) entitlement mapping B {
include A
include N1
include N2
}
access(all) entitlement mapping C {
include A
include B
include N1
include N2
}
access(all) entitlement mapping D {
include A
include B
include C
include N1
include N2
}
access(all) entitlement mapping AA {
include A
include B
include C
include D
}
access(all) entitlement mapping BB {include AA}
access(all) entitlement mapping CC {include AA}
access(all) entitlement mapping DD {include AA}
access(all) entitlement mapping AAA {
include AA
include BB
include CC
include DD
}
access(all) entitlement mapping BBB {
include AAA
include AA
include BB
include CC
include DD
}
access(all) entitlement mapping CCC {
include AAA
include BBB
include AA
include BB
include CC
include DD
}
access(all) entitlement mapping DDD {
include AAA
include BBB
include CCC
include AA
include BB
include CC
include DD
}
access(all) entitlement mapping AAAA {
include AAA
include BBB
include CCC
include DDD
}
access(all) entitlement mapping BBBB {
include AAAA
include AAA
include BBB
include CCC
include DDD
}
access(all) entitlement mapping CCCC {
include AAAA
include BBBB
include AAA
include BBB
include CCC
include DDD
}
access(all) entitlement mapping DDDD {
include AAAA
include BBBB
include CCCC
include AAA
include BBB
include CCC
include DDD
}
access(all) entitlement mapping AAAAA {
include AAAA
include BBBB
include CCCC
include DDDD
}
access(all) entitlement mapping BBBBB {
include AAAAA
include AAAA
include BBBB
include CCCC
include DDDD
}
access(all) entitlement mapping CCCCC {
include AAAAA
include BBBBB
include AAAA
include BBBB
include CCCC
include DDDD
}
access(all) entitlement mapping DDDDD {
include AAAAA
include BBBBB
include CCCCC
include AAAA
include BBBB
include CCCC
include DDDD
}
access(all) entitlement mapping AAAAAA {
include AAAAA
include BBBBB
include CCCCC
include DDDDD
}
access(all) entitlement mapping BBBBBB { include AAAAAA}
access(all) entitlement mapping CCCCCC { include AAAAAA}
access(all) entitlement mapping DDDDDD { include AAAAAA}
access(all) entitlement mapping P1 {
include AAAAAA
include BBBBBB
include CCCCCC
include DDDDDD
}
access(all) entitlement mapping P2 { include P1 }
access(all) entitlement mapping P3 {
include P1
include P2
}
access(all) entitlement mapping P4 {
include P1
include P2
include P3
}

access(all) fun main() {}
`)

nextScriptLocation := newScriptLocationGenerator()

Check failure on line 1469 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Performance regression check

undefined: newScriptLocationGenerator

Check failure on line 1469 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: newScriptLocationGenerator

Check failure on line 1469 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: newScriptLocationGenerator

Check failure on line 1469 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Test

undefined: newScriptLocationGenerator

var totalRelations uint
var failed bool

runtimeInterface1 := &testRuntimeInterface{

Check failure on line 1474 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Performance regression check

undefined: testRuntimeInterface

Check failure on line 1474 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: testRuntimeInterface

Check failure on line 1474 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: testRuntimeInterface

Check failure on line 1474 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Test

undefined: testRuntimeInterface
storage: storage,
log: func(message string) {},
emitEvent: func(event cadence.Event) error {
return nil
},
resolveLocation: singleIdentifierLocationResolver(t),

Check failure on line 1480 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Performance regression check

undefined: singleIdentifierLocationResolver

Check failure on line 1480 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Lint

undefined: singleIdentifierLocationResolver (typecheck)

Check failure on line 1480 in runtime/entitlements_test.go

View workflow job for this annotation

GitHub Actions / Test

undefined: singleIdentifierLocationResolver
getSigningAccounts: func() ([]Address, error) {
return []Address{[8]byte{0, 0, 0, 0, 0, 0, 0, 1}}, nil
},
updateAccountContractCode: func(location common.AddressLocation, code []byte) error {
accountCodes[location] = code
return nil
},
getAccountContractCode: func(location common.AddressLocation) (code []byte, err error) {
code = accountCodes[location]
return code, nil
},
meterMemory: func(usage common.MemoryUsage) error {
if usage.Kind == common.MemoryKindEntitlementRelationSemaType {
totalRelations++
}
if totalRelations > 1000 {
failed = true
}
return nil
},
}

_, err := rt.ExecuteScript(
Script{
Source: script,
},
Context{
Interface: runtimeInterface1,
Location: nextScriptLocation(),
},
)

require.NoError(t, err)
require.False(t, failed)
}
5 changes: 1 addition & 4 deletions runtime/sema/check_interface_declaration.go
Original file line number Diff line number Diff line change
Expand Up @@ -542,10 +542,7 @@ func (checker *Checker) declareEntitlementMappingType(declaration *ast.Entitleme

entitlementRelations = append(
entitlementRelations,
EntitlementRelation{
Input: inputEntitlement,
Output: outputEntitlement,
},
NewEntitlementRelation(checker.memoryGauge, inputEntitlement, outputEntitlement),
)
}

Expand Down
20 changes: 19 additions & 1 deletion runtime/sema/type.go
Original file line number Diff line number Diff line change
Expand Up @@ -7841,6 +7841,18 @@ type EntitlementRelation struct {
Output *EntitlementType
}

func NewEntitlementRelation(
memoryGauge common.MemoryGauge,
input *EntitlementType,
output *EntitlementType,
) EntitlementRelation {
common.UseMemory(memoryGauge, common.EntitlementRelationSemaTypeMemoryUsage)
return EntitlementRelation{
Input: input,
Output: output,
}
}

type EntitlementMapType struct {
Location common.Location
containerType Type
Expand Down Expand Up @@ -8020,7 +8032,13 @@ func (t *EntitlementMapType) resolveEntitlementMappingInclusions(
checker.Elaboration.EntitlementMapTypeDeclaration(includedMapType),
visitedMaps,
)
t.Relations = append(t.Relations, includedMapType.Relations...)

for _, relation := range includedMapType.Relations {
if !slices.Contains(t.Relations, relation) {
common.UseMemory(checker.memoryGauge, common.EntitlementRelationSemaTypeMemoryUsage)
t.Relations = append(t.Relations, relation)
}
}
t.IncludesIdentity = t.IncludesIdentity || includedMapType.IncludesIdentity

includedMaps[includedMapType] = struct{}{}
Expand Down
Loading