From 2e9b2543863cfb5e9cec9a318591dc95322f8e1d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Mon, 28 Aug 2023 09:45:18 -0700 Subject: [PATCH 01/10] export CompositeType fields, so they can be set from other packages --- runtime/sema/crypto_algorithm_types.go | 8 ++++---- runtime/sema/type.go | 18 +++++++++--------- 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/runtime/sema/crypto_algorithm_types.go b/runtime/sema/crypto_algorithm_types.go index a061e71e2c..b74d326bff 100644 --- a/runtime/sema/crypto_algorithm_types.go +++ b/runtime/sema/crypto_algorithm_types.go @@ -278,10 +278,10 @@ func newNativeEnumType( membersConstructor func(enumType *CompositeType) []*Member, ) *CompositeType { ty := &CompositeType{ - Identifier: identifier, - EnumRawType: rawType, - Kind: common.CompositeKindEnum, - importable: true, + Identifier: identifier, + EnumRawType: rawType, + Kind: common.CompositeKindEnum, + ImportableBuiltin: true, } // Members of the enum type are *not* the enum cases! diff --git a/runtime/sema/type.go b/runtime/sema/type.go index a507a9d26b..3075f15d57 100644 --- a/runtime/sema/type.go +++ b/runtime/sema/type.go @@ -4277,9 +4277,9 @@ type CompositeType struct { effectiveInterfaceConformancesOnce sync.Once memberResolversOnce sync.Once ConstructorPurity FunctionPurity - hasComputedMembers bool + HasComputedMembers bool // Only applicable for native composite types - importable bool + ImportableBuiltin bool supportedEntitlements *EntitlementOrderedSet } @@ -4488,7 +4488,7 @@ func (*CompositeType) IsInvalidType() bool { } func (t *CompositeType) IsStorable(results map[*Member]bool) bool { - if t.hasComputedMembers { + if t.HasComputedMembers { return false } @@ -4524,7 +4524,7 @@ func (t *CompositeType) IsStorable(results map[*Member]bool) bool { func (t *CompositeType) IsImportable(results map[*Member]bool) bool { // Use the pre-determined flag for native types if t.Location == nil { - return t.importable + return t.ImportableBuiltin } // Only structures and enums can be imported @@ -7440,9 +7440,9 @@ const AccountKeyIsRevokedFieldName = "isRevoked" var AccountKeyType = func() *CompositeType { accountKeyType := &CompositeType{ - Identifier: AccountKeyTypeName, - Kind: common.CompositeKindStructure, - importable: false, + Identifier: AccountKeyTypeName, + Kind: common.CompositeKindStructure, + ImportableBuiltin: false, } const accountKeyKeyIndexFieldDocString = `The index of the account key` @@ -7523,8 +7523,8 @@ var PublicKeyType = func() *CompositeType { publicKeyType := &CompositeType{ Identifier: PublicKeyTypeName, Kind: common.CompositeKindStructure, - hasComputedMembers: true, - importable: true, + HasComputedMembers: true, + ImportableBuiltin: true, } var members = []*Member{ From 8007825c2fc48607ab2371348994c132bc4b8600 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Mon, 28 Aug 2023 09:49:45 -0700 Subject: [PATCH 02/10] add support for generating contracts and code in any package --- runtime/sema/gen/main.go | 200 ++++++++++++++++----- runtime/sema/gen/main_test.go | 2 +- runtime/sema/gen/testdata/nested.golden.go | 8 +- 3 files changed, 158 insertions(+), 52 deletions(-) diff --git a/runtime/sema/gen/main.go b/runtime/sema/gen/main.go index e2c223ce4d..97c2a77fed 100644 --- a/runtime/sema/gen/main.go +++ b/runtime/sema/gen/main.go @@ -19,6 +19,7 @@ package main import ( + "flag" "fmt" "go/token" "os" @@ -39,6 +40,10 @@ import ( "github.com/onflow/cadence/runtime/pretty" ) +const semaPath = "github.com/onflow/cadence/runtime/sema" + +var packagePathFlag = flag.String("p", semaPath, "package path") + const headerTemplate = `// Code generated from {{ . }}. DO NOT EDIT. /* * Cadence - The resource-oriented smart contract programming language @@ -325,7 +330,8 @@ func (g *generator) VisitCompositeDeclaration(decl *ast.CompositeDeclaration) (_ compositeKind := decl.CompositeKind switch compositeKind { case common.CompositeKindStructure, - common.CompositeKindResource: + common.CompositeKindResource, + common.CompositeKindContract: break default: panic(fmt.Sprintf("%s declarations are not supported", compositeKind.Name())) @@ -364,6 +370,15 @@ func (g *generator) VisitCompositeDeclaration(decl *ast.CompositeDeclaration) (_ // Otherwise, we have to generate a CompositeType canGenerateSimpleType := len(g.typeStack) == 1 + if canGenerateSimpleType { + switch compositeKind { + case common.CompositeKindStructure, + common.CompositeKindResource: + break + default: + canGenerateSimpleType = false + } + } for _, memberDeclaration := range decl.Members.Declarations() { ast.AcceptDeclaration[struct{}](memberDeclaration, g) @@ -375,13 +390,15 @@ func (g *generator) VisitCompositeDeclaration(decl *ast.CompositeDeclaration) (_ memberDeclaration, ) - switch memberDeclaration.(type) { - case *ast.FieldDeclaration, - *ast.FunctionDeclaration: - break + if canGenerateSimpleType { + switch memberDeclaration.(type) { + case *ast.FieldDeclaration, + *ast.FunctionDeclaration: + break - default: - canGenerateSimpleType = false + default: + canGenerateSimpleType = false + } } } @@ -528,7 +545,10 @@ func (g *generator) VisitCompositeDeclaration(decl *ast.CompositeDeclaration) (_ Tok: token.ASSIGN, Rhs: []dst.Expr{ &dst.CallExpr{ - Fun: dst.NewIdent("MembersAsMap"), + Fun: &dst.Ident{ + Name: "MembersAsMap", + Path: semaPath, + }, Args: []dst.Expr{ dst.NewIdent(membersVariableIdentifier), }, @@ -545,7 +565,10 @@ func (g *generator) VisitCompositeDeclaration(decl *ast.CompositeDeclaration) (_ Tok: token.ASSIGN, Rhs: []dst.Expr{ &dst.CallExpr{ - Fun: dst.NewIdent("MembersFieldNames"), + Fun: &dst.Ident{ + Name: "MembersFieldNames", + Path: semaPath, + }, Args: []dst.Expr{ dst.NewIdent(membersVariableIdentifier), }, @@ -642,7 +665,10 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("GenericType"), + Type: &dst.Ident{ + Name: "GenericType", + Path: semaPath, + }, Elts: []dst.Expr{ goKeyValue("TypeParameter", dst.NewIdent(typeParamVarName)), }, @@ -661,7 +687,10 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("CapabilityType"), + Type: &dst.Ident{ + Name: "CapabilityType", + Path: semaPath, + }, }, } default: @@ -683,7 +712,10 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("OptionalType"), + Type: &dst.Ident{ + Name: "OptionalType", + Path: semaPath, + }, Elts: []dst.Expr{ goKeyValue("Type", innerType), }, @@ -695,7 +727,10 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("ReferenceType"), + Type: &dst.Ident{ + Name: "ReferenceType", + Path: semaPath, + }, Elts: []dst.Expr{ goKeyValue("Type", borrowType), // TODO: add support for parsing entitlements @@ -709,7 +744,10 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("VariableSizedType"), + Type: &dst.Ident{ + Name: "VariableSizedType", + Path: semaPath, + }, Elts: []dst.Expr{ goKeyValue("Type", elementType), }, @@ -721,7 +759,10 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("ConstantSizedType"), + Type: &dst.Ident{ + Name: "ConstantSizedType", + Path: semaPath, + }, Elts: []dst.Expr{ goKeyValue("Type", elementType), goKeyValue( @@ -757,7 +798,10 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { } return &dst.CallExpr{ - Fun: dst.NewIdent("MustInstantiate"), + Fun: &dst.Ident{ + Name: "MustInstantiate", + Path: semaPath, + }, Args: argumentExprs, } @@ -778,7 +822,10 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { &dst.CompositeLit{ Type: &dst.ArrayType{ Elt: &dst.StarExpr{ - X: dst.NewIdent("InterfaceType"), + X: &dst.Ident{ + Name: "InterfaceType", + Path: semaPath, + }, }, }, Elts: intersectedTypes, @@ -790,7 +837,10 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("IntersectionType"), + Type: &dst.Ident{ + Name: "IntersectionType", + Path: semaPath, + }, Elts: elements, }, } @@ -843,7 +893,10 @@ func functionTypeExpr( typeParametersExpr = &dst.CompositeLit{ Type: &dst.ArrayType{ Elt: &dst.StarExpr{ - X: dst.NewIdent("TypeParameter"), + X: &dst.Ident{ + Name: "TypeParameter", + Path: semaPath, + }, }, }, Elts: typeParameterExprs, @@ -875,6 +928,7 @@ func functionTypeExpr( if parameter.Label == "_" { lit = &dst.Ident{ Name: "ArgumentLabelNotRequired", + Path: semaPath, } } else { lit = goStringLit(parameter.Label) @@ -915,7 +969,10 @@ func functionTypeExpr( parametersExpr = &dst.CompositeLit{ Type: &dst.ArrayType{ - Elt: dst.NewIdent("Parameter"), + Elt: &dst.Ident{ + Name: "Parameter", + Path: semaPath, + }, }, Elts: parameterExprs, } @@ -978,7 +1035,10 @@ func functionTypeExpr( return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("FunctionType"), + Type: &dst.Ident{ + Name: "FunctionType", + Path: semaPath, + }, Elts: compositeElements, }, } @@ -1328,7 +1388,10 @@ func simpleTypeLiteral(ty *typeDecl) dst.Expr { return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("SimpleType"), + Type: &dst.Ident{ + Name: "SimpleType", + Path: semaPath, + }, Elts: elements, }, } @@ -1344,7 +1407,10 @@ func simpleTypeMemberResolversFunc(fullTypeName string, declarations []ast.Decla returnStatement := &dst.ReturnStmt{ Results: []dst.Expr{ &dst.CallExpr{ - Fun: dst.NewIdent("MembersAsResolvers"), + Fun: &dst.Ident{ + Name: "MembersAsResolvers", + Path: semaPath, + }, Args: []dst.Expr{ membersExpr(fullTypeName, typeVarName, declarations), }, @@ -1431,14 +1497,24 @@ func membersExpr( return &dst.CompositeLit{ Type: &dst.ArrayType{ - Elt: &dst.StarExpr{X: dst.NewIdent("Member")}, + Elt: &dst.StarExpr{ + X: &dst.Ident{ + Name: "Member", + Path: semaPath, + }, + }, }, Elts: elements, } } func simpleType() *dst.StarExpr { - return &dst.StarExpr{X: dst.NewIdent("SimpleType")} + return &dst.StarExpr{ + X: &dst.Ident{ + Name: "SimpleType", + Path: semaPath, + }, + } } func accessExpr(access ast.Access) dst.Expr { @@ -1542,7 +1618,10 @@ func newDeclarationMember( } return &dst.CallExpr{ - Fun: dst.NewIdent("NewUnmeteredFieldMember"), + Fun: &dst.Ident{ + Name: "NewUnmeteredFieldMember", + Path: semaPath, + }, Args: args, } } @@ -1566,7 +1645,10 @@ func newDeclarationMember( } return &dst.CallExpr{ - Fun: dst.NewIdent("NewUnmeteredFunctionMember"), + Fun: &dst.Ident{ + Name: "NewUnmeteredFunctionMember", + Path: semaPath, + }, Args: args, } } @@ -1579,8 +1661,11 @@ func newDeclarationMember( func stringMemberResolverMapType() *dst.MapType { return &dst.MapType{ - Key: dst.NewIdent("string"), - Value: dst.NewIdent("MemberResolver"), + Key: dst.NewIdent("string"), + Value: &dst.Ident{ + Name: "MemberResolver", + Path: semaPath, + }, } } @@ -1590,8 +1675,8 @@ func compositeTypeExpr(ty *typeDecl) dst.Expr { // var t = &CompositeType{ // Identifier: FooTypeName, // Kind: common.CompositeKindStructure, - // importable: false, - // hasComputedMembers: true, + // ImportableBuiltin: false, + // HasComputedMembers: true, // } // // t.SetNestedType(FooBarTypeName, FooBarType) @@ -1644,7 +1729,10 @@ func compositeTypeExpr(ty *typeDecl) dst.Expr { List: []*dst.Field{ { Type: &dst.StarExpr{ - X: dst.NewIdent("CompositeType"), + X: &dst.Ident{ + Name: "CompositeType", + Path: semaPath, + }, }, }, }, @@ -1663,14 +1751,17 @@ func compositeTypeLiteral(ty *typeDecl) dst.Expr { elements := []dst.Expr{ goKeyValue("Identifier", typeNameVarIdent(ty.fullTypeName)), goKeyValue("Kind", kind), - goKeyValue("importable", goBoolLit(ty.importable)), - goKeyValue("hasComputedMembers", goBoolLit(true)), + goKeyValue("ImportableBuiltin", goBoolLit(ty.importable)), + goKeyValue("HasComputedMembers", goBoolLit(true)), } return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("CompositeType"), + Type: &dst.Ident{ + Name: "CompositeType", + Path: semaPath, + }, Elts: elements, }, } @@ -1678,7 +1769,10 @@ func compositeTypeLiteral(ty *typeDecl) dst.Expr { func typeAnnotationCallExpr(ty dst.Expr) *dst.CallExpr { return &dst.CallExpr{ - Fun: dst.NewIdent("NewTypeAnnotation"), + Fun: &dst.Ident{ + Name: "NewTypeAnnotation", + Path: semaPath, + }, Args: []dst.Expr{ ty, }, @@ -1699,7 +1793,10 @@ func typeParameterExpr(name string, typeBound dst.Expr) dst.Expr { return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("TypeParameter"), + Type: &dst.Ident{ + Name: "TypeParameter", + Path: semaPath, + }, Elts: elements, }, } @@ -1788,7 +1885,7 @@ func parseCadenceFile(path string) *ast.Program { return program } -func gen(inPath string, outFile *os.File) { +func gen(inPath string, outFile *os.File, packagePath string) { program := parseCadenceFile(inPath) var gen generator @@ -1799,21 +1896,27 @@ func gen(inPath string, outFile *os.File) { gen.generateTypeInit(program) - writeGoFile(inPath, outFile, gen.decls) + writeGoFile(inPath, outFile, gen.decls, packagePath) } -func writeGoFile(inPath string, outFile *os.File, decls []dst.Decl) { +func writeGoFile(inPath string, outFile *os.File, decls []dst.Decl, packagePath string) { err := parsedHeaderTemplate.Execute(outFile, inPath) if err != nil { panic(err) } - restorer := decorator.NewRestorerWithImports("sema", guess.RestorerResolver{}) + resolver := guess.New() + restorer := decorator.NewRestorerWithImports(packagePath, resolver) + + packageName, err := resolver.ResolvePackage(packagePath) + if err != nil { + panic(err) + } err = restorer.Fprint( outFile, &dst.File{ - Name: dst.NewIdent("sema"), + Name: dst.NewIdent(packageName), Decls: decls, }, ) @@ -1823,14 +1926,17 @@ func writeGoFile(inPath string, outFile *os.File, decls []dst.Decl) { } func main() { - if len(os.Args) < 2 { + flag.Parse() + argumentCount := flag.NArg() + + if argumentCount < 1 { panic("Missing path to input Cadence file") } - if len(os.Args) < 3 { + if argumentCount < 2 { panic("Missing path to output Go file") } - inPath := os.Args[1] - outPath := os.Args[2] + inPath := flag.Arg(0) + outPath := flag.Arg(1) outFile, err := os.Create(outPath) if err != nil { @@ -1838,5 +1944,5 @@ func main() { } defer outFile.Close() - gen(inPath, outFile) + gen(inPath, outFile, *packagePathFlag) } diff --git a/runtime/sema/gen/main_test.go b/runtime/sema/gen/main_test.go index 173adc1df1..1e8def123d 100644 --- a/runtime/sema/gen/main_test.go +++ b/runtime/sema/gen/main_test.go @@ -50,7 +50,7 @@ func TestFiles(t *testing.T) { require.NoError(t, err) defer outFile.Close() - gen(inputPath, outFile) + gen(inputPath, outFile, "github.com/onflow/cadence/runtime/sema") goldenPath := filepath.Join(testDataDirectory, testname+".golden.go") want, err := os.ReadFile(goldenPath) diff --git a/runtime/sema/gen/testdata/nested.golden.go b/runtime/sema/gen/testdata/nested.golden.go index 3f998c940a..73c94c99c1 100644 --- a/runtime/sema/gen/testdata/nested.golden.go +++ b/runtime/sema/gen/testdata/nested.golden.go @@ -62,8 +62,8 @@ var Foo_BarType = func() *CompositeType { var t = &CompositeType{ Identifier: Foo_BarTypeName, Kind: common.CompositeKindStructure, - importable: false, - hasComputedMembers: true, + ImportableBuiltin: false, + HasComputedMembers: true, } return t @@ -90,8 +90,8 @@ var FooType = func() *CompositeType { var t = &CompositeType{ Identifier: FooTypeName, Kind: common.CompositeKindStructure, - importable: false, - hasComputedMembers: true, + ImportableBuiltin: false, + HasComputedMembers: true, } t.SetNestedType(Foo_BarTypeName, Foo_BarType) From bb6b8ac416016ef0e18bc6dc0d29a6a6fffdcdf9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Mon, 28 Aug 2023 09:50:35 -0700 Subject: [PATCH 03/10] refactor BLS contract to use type code generator --- runtime/stdlib/bls.cdc | 22 +++++++ runtime/stdlib/bls.gen.go | 122 ++++++++++++++++++++++++++++++++++++ runtime/stdlib/bls.go | 105 ++++--------------------------- runtime/stdlib/builtin.go | 4 ++ runtime/stdlib/flow.go | 2 +- runtime/stdlib/publickey.go | 6 +- 6 files changed, 166 insertions(+), 95 deletions(-) create mode 100644 runtime/stdlib/bls.cdc create mode 100644 runtime/stdlib/bls.gen.go diff --git a/runtime/stdlib/bls.cdc b/runtime/stdlib/bls.cdc new file mode 100644 index 0000000000..da4c6284ff --- /dev/null +++ b/runtime/stdlib/bls.cdc @@ -0,0 +1,22 @@ +access(all) +contract BLS { + /// Aggregates multiple BLS signatures into one, + /// considering the proof of possession as a defense against rogue attacks. + /// + /// Signatures could be generated from the same or distinct messages, + /// they could also be the aggregation of other signatures. + /// The order of the signatures in the slice does not matter since the aggregation is commutative. + /// No subgroup membership check is performed on the input signatures. + /// The function returns nil if the array is empty or if decoding one of the signature fails. + access(all) + fun aggregateSignatures(_ signatures: [[UInt8]]): [UInt8]? + + + /// Aggregates multiple BLS public keys into one. + /// + /// The order of the public keys in the slice does not matter since the aggregation is commutative. + /// No subgroup membership check is performed on the input keys. + /// The function returns nil if the array is empty or any of the input keys is not a BLS key. + access(all) + fun aggregatePublicKeys(_ keys: [PublicKey]): PublicKey? +} diff --git a/runtime/stdlib/bls.gen.go b/runtime/stdlib/bls.gen.go new file mode 100644 index 0000000000..5fac48866e --- /dev/null +++ b/runtime/stdlib/bls.gen.go @@ -0,0 +1,122 @@ +// Code generated from bls.cdc. DO NOT EDIT. +/* + * 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 stdlib + +import ( + "github.com/onflow/cadence/runtime/ast" + "github.com/onflow/cadence/runtime/common" + "github.com/onflow/cadence/runtime/sema" +) + +const BLSTypeAggregateSignaturesFunctionName = "aggregateSignatures" + +var BLSTypeAggregateSignaturesFunctionType = &sema.FunctionType{ + Parameters: []sema.Parameter{ + { + Label: sema.ArgumentLabelNotRequired, + Identifier: "signatures", + TypeAnnotation: sema.NewTypeAnnotation(&sema.VariableSizedType{ + Type: &sema.VariableSizedType{ + Type: UInt8Type, + }, + }), + }, + }, + ReturnTypeAnnotation: sema.NewTypeAnnotation( + &sema.OptionalType{ + Type: &sema.VariableSizedType{ + Type: UInt8Type, + }, + }, + ), +} + +const BLSTypeAggregateSignaturesFunctionDocString = ` +Aggregates multiple BLS signatures into one, +considering the proof of possession as a defense against rogue attacks. + +Signatures could be generated from the same or distinct messages, +they could also be the aggregation of other signatures. +The order of the signatures in the slice does not matter since the aggregation is commutative. +No subgroup membership check is performed on the input signatures. +The function returns nil if the array is empty or if decoding one of the signature fails. +` + +const BLSTypeAggregatePublicKeysFunctionName = "aggregatePublicKeys" + +var BLSTypeAggregatePublicKeysFunctionType = &sema.FunctionType{ + Parameters: []sema.Parameter{ + { + Label: sema.ArgumentLabelNotRequired, + Identifier: "keys", + TypeAnnotation: sema.NewTypeAnnotation(&sema.VariableSizedType{ + Type: PublicKeyType, + }), + }, + }, + ReturnTypeAnnotation: sema.NewTypeAnnotation( + &sema.OptionalType{ + Type: PublicKeyType, + }, + ), +} + +const BLSTypeAggregatePublicKeysFunctionDocString = ` +Aggregates multiple BLS public keys into one. + +The order of the public keys in the slice does not matter since the aggregation is commutative. +No subgroup membership check is performed on the input keys. +The function returns nil if the array is empty or any of the input keys is not a BLS key. +` + +const BLSTypeName = "BLS" + +var BLSType = func() *sema.CompositeType { + var t = &sema.CompositeType{ + Identifier: BLSTypeName, + Kind: common.CompositeKindContract, + ImportableBuiltin: false, + HasComputedMembers: true, + } + + return t +}() + +func init() { + var members = []*sema.Member{ + sema.NewUnmeteredFunctionMember( + BLSType, + ast.AccessPublic, + BLSTypeAggregateSignaturesFunctionName, + BLSTypeAggregateSignaturesFunctionType, + BLSTypeAggregateSignaturesFunctionDocString, + ), + sema.NewUnmeteredFunctionMember( + BLSType, + ast.AccessPublic, + BLSTypeAggregatePublicKeysFunctionName, + BLSTypeAggregatePublicKeysFunctionType, + BLSTypeAggregatePublicKeysFunctionDocString, + ), + } + + BLSType.Members = sema.MembersAsMap(members) + BLSType.Fields = sema.MembersFieldNames(members) +} diff --git a/runtime/stdlib/bls.go b/runtime/stdlib/bls.go index f99591db2c..b1dd5999f6 100644 --- a/runtime/stdlib/bls.go +++ b/runtime/stdlib/bls.go @@ -18,6 +18,8 @@ package stdlib +//go:generate go run ../sema/gen -p stdlib bls.cdc bls.gen.go + import ( "github.com/onflow/cadence/runtime/common" "github.com/onflow/cadence/runtime/errors" @@ -25,89 +27,6 @@ import ( "github.com/onflow/cadence/runtime/sema" ) -var blsContractType = func() *sema.CompositeType { - ty := &sema.CompositeType{ - Identifier: "BLS", - Kind: common.CompositeKindContract, - } - - ty.Members = sema.MembersAsMap([]*sema.Member{ - sema.NewUnmeteredPublicFunctionMember( - ty, - blsAggregatePublicKeysFunctionName, - blsAggregatePublicKeysFunctionType, - blsAggregatePublicKeysFunctionDocString, - ), - sema.NewUnmeteredPublicFunctionMember( - ty, - blsAggregateSignaturesFunctionName, - blsAggregateSignaturesFunctionType, - blsAggregateSignaturesFunctionDocString, - ), - }) - return ty -}() - -var blsContractStaticType interpreter.StaticType = interpreter.ConvertSemaCompositeTypeToStaticCompositeType( - nil, - blsContractType, -) - -const blsAggregateSignaturesFunctionDocString = ` -Aggregates multiple BLS signatures into one, -considering the proof of possession as a defense against rogue attacks. - -Signatures could be generated from the same or distinct messages, -they could also be the aggregation of other signatures. -The order of the signatures in the slice does not matter since the aggregation is commutative. -No subgroup membership check is performed on the input signatures. -The function returns nil if the array is empty or if decoding one of the signature fails. -` - -const blsAggregateSignaturesFunctionName = "aggregateSignatures" - -var blsAggregateSignaturesFunctionType = sema.NewSimpleFunctionType( - sema.FunctionPurityView, - []sema.Parameter{ - { - Label: sema.ArgumentLabelNotRequired, - Identifier: "signatures", - TypeAnnotation: sema.ByteArrayArrayTypeAnnotation, - }, - }, - sema.NewTypeAnnotation( - &sema.OptionalType{ - Type: sema.ByteArrayType, - }, - ), -) - -const blsAggregatePublicKeysFunctionDocString = ` -Aggregates multiple BLS public keys into one. - -The order of the public keys in the slice does not matter since the aggregation is commutative. -No subgroup membership check is performed on the input keys. -The function returns nil if the array is empty or any of the input keys is not a BLS key. -` - -const blsAggregatePublicKeysFunctionName = "aggregatePublicKeys" - -var blsAggregatePublicKeysFunctionType = sema.NewSimpleFunctionType( - sema.FunctionPurityView, - []sema.Parameter{ - { - Label: sema.ArgumentLabelNotRequired, - Identifier: "keys", - TypeAnnotation: sema.PublicKeyArrayTypeAnnotation, - }, - }, - sema.NewTypeAnnotation( - &sema.OptionalType{ - Type: sema.PublicKeyType, - }, - ), -) - type BLSPublicKeyAggregator interface { PublicKeySignatureVerifier BLSPoPVerifier @@ -121,7 +40,7 @@ func newBLSAggregatePublicKeysFunction( ) *interpreter.HostFunctionValue { return interpreter.NewHostFunctionValue( gauge, - blsAggregatePublicKeysFunctionType, + BLSTypeAggregatePublicKeysFunctionType, func(invocation interpreter.Invocation) interpreter.Value { publicKeysValue, ok := invocation.Arguments[0].(*interpreter.ArrayValue) if !ok { @@ -193,7 +112,7 @@ func newBLSAggregateSignaturesFunction( ) *interpreter.HostFunctionValue { return interpreter.NewHostFunctionValue( gauge, - blsAggregateSignaturesFunctionType, + BLSTypeAggregateSignaturesFunctionType, func(invocation interpreter.Invocation) interpreter.Value { signaturesValue, ok := invocation.Arguments[0].(*interpreter.ArrayValue) if !ok { @@ -256,19 +175,21 @@ type BLSContractHandler interface { BLSSignatureAggregator } +var BLSTypeStaticType = interpreter.ConvertSemaToStaticType(nil, BLSType) + func NewBLSContract( gauge common.MemoryGauge, handler BLSContractHandler, ) StandardLibraryValue { - var blsContractFields = map[string]interpreter.Value{ - blsAggregatePublicKeysFunctionName: newBLSAggregatePublicKeysFunction(gauge, handler), - blsAggregateSignaturesFunctionName: newBLSAggregateSignaturesFunction(gauge, handler), + blsContractFields := map[string]interpreter.Value{ + BLSTypeAggregatePublicKeysFunctionName: newBLSAggregatePublicKeysFunction(gauge, handler), + BLSTypeAggregateSignaturesFunctionName: newBLSAggregateSignaturesFunction(gauge, handler), } - var blsContractValue = interpreter.NewSimpleCompositeValue( + blsContractValue := interpreter.NewSimpleCompositeValue( nil, - blsContractType.ID(), - blsContractStaticType, + BLSType.ID(), + BLSTypeStaticType, nil, blsContractFields, nil, @@ -278,7 +199,7 @@ func NewBLSContract( return StandardLibraryValue{ Name: "BLS", - Type: blsContractType, + Type: BLSType, Value: blsContractValue, Kind: common.DeclarationKindContract, } diff --git a/runtime/stdlib/builtin.go b/runtime/stdlib/builtin.go index d292eb1bef..d462a5f83d 100644 --- a/runtime/stdlib/builtin.go +++ b/runtime/stdlib/builtin.go @@ -18,6 +18,10 @@ package stdlib +import "github.com/onflow/cadence/runtime/sema" + +var UInt8Type = sema.UInt8Type + type StandardLibraryHandler interface { Logger UnsafeRandomGenerator diff --git a/runtime/stdlib/flow.go b/runtime/stdlib/flow.go index 47451caf56..f34cfd633a 100644 --- a/runtime/stdlib/flow.go +++ b/runtime/stdlib/flow.go @@ -193,7 +193,7 @@ var AccountEventCodeHashParameter = sema.Parameter{ var AccountEventPublicKeyParameterAsCompositeType = sema.Parameter{ Identifier: "publicKey", TypeAnnotation: sema.NewTypeAnnotation( - sema.PublicKeyType, + PublicKeyType, ), } diff --git a/runtime/stdlib/publickey.go b/runtime/stdlib/publickey.go index ef27bebc3a..5b02f4250d 100644 --- a/runtime/stdlib/publickey.go +++ b/runtime/stdlib/publickey.go @@ -25,6 +25,8 @@ import ( "github.com/onflow/cadence/runtime/sema" ) +var PublicKeyType = sema.PublicKeyType + const publicKeyConstructorFunctionDocString = ` Constructs a new public key ` @@ -258,7 +260,7 @@ func newPublicKeyVerifySignatureFunction( inter.ExpectType( publicKeyValue, - sema.PublicKeyType, + PublicKeyType, locationRange, ) @@ -328,7 +330,7 @@ func newPublicKeyVerifyPoPFunction( inter.ExpectType( publicKeyValue, - sema.PublicKeyType, + PublicKeyType, locationRange, ) From c6bbff3a2ceccbd632fd01d93fdacfb4b59b20b6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Mon, 28 Aug 2023 09:50:49 -0700 Subject: [PATCH 04/10] refactor RLP contract to use type code generator --- runtime/stdlib/rlp.cdc | 18 ++++++ runtime/stdlib/rlp.gen.go | 116 ++++++++++++++++++++++++++++++++++++++ runtime/stdlib/rlp.go | 94 +++++------------------------- 3 files changed, 147 insertions(+), 81 deletions(-) create mode 100644 runtime/stdlib/rlp.cdc create mode 100644 runtime/stdlib/rlp.gen.go diff --git a/runtime/stdlib/rlp.cdc b/runtime/stdlib/rlp.cdc new file mode 100644 index 0000000000..e5a3ac78ab --- /dev/null +++ b/runtime/stdlib/rlp.cdc @@ -0,0 +1,18 @@ +access(all) +contract RLP { + /// Decodes an RLP-encoded byte array (called string in the context of RLP). + /// The byte array should only contain of a single encoded value for a string; + /// if the encoded value type does not match, or it has trailing unnecessary bytes, the program aborts. + /// If any error is encountered while decoding, the program aborts. + access(all) + fun decodeString(_ input: [UInt8]): [UInt8] + + + /// Decodes an RLP-encoded list into an array of RLP-encoded items. + /// Note that this function does not recursively decode, so each element of the resulting array is RLP-encoded data. + /// The byte array should only contain of a single encoded value for a list; + /// if the encoded value type does not match, or it has trailing unnecessary bytes, the program aborts. + /// If any error is encountered while decoding, the program aborts. + access(all) + fun decodeList(_ input: [UInt8]): [[UInt8]] +} diff --git a/runtime/stdlib/rlp.gen.go b/runtime/stdlib/rlp.gen.go new file mode 100644 index 0000000000..b8585d55de --- /dev/null +++ b/runtime/stdlib/rlp.gen.go @@ -0,0 +1,116 @@ +// Code generated from rlp.cdc. DO NOT EDIT. +/* + * 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 stdlib + +import ( + "github.com/onflow/cadence/runtime/ast" + "github.com/onflow/cadence/runtime/common" + "github.com/onflow/cadence/runtime/sema" +) + +const RLPTypeDecodeStringFunctionName = "decodeString" + +var RLPTypeDecodeStringFunctionType = &sema.FunctionType{ + Parameters: []sema.Parameter{ + { + Label: sema.ArgumentLabelNotRequired, + Identifier: "input", + TypeAnnotation: sema.NewTypeAnnotation(&sema.VariableSizedType{ + Type: UInt8Type, + }), + }, + }, + ReturnTypeAnnotation: sema.NewTypeAnnotation( + &sema.VariableSizedType{ + Type: UInt8Type, + }, + ), +} + +const RLPTypeDecodeStringFunctionDocString = ` +Decodes an RLP-encoded byte array (called string in the context of RLP). +The byte array should only contain of a single encoded value for a string; +if the encoded value type does not match, or it has trailing unnecessary bytes, the program aborts. +If any error is encountered while decoding, the program aborts. +` + +const RLPTypeDecodeListFunctionName = "decodeList" + +var RLPTypeDecodeListFunctionType = &sema.FunctionType{ + Parameters: []sema.Parameter{ + { + Label: sema.ArgumentLabelNotRequired, + Identifier: "input", + TypeAnnotation: sema.NewTypeAnnotation(&sema.VariableSizedType{ + Type: UInt8Type, + }), + }, + }, + ReturnTypeAnnotation: sema.NewTypeAnnotation( + &sema.VariableSizedType{ + Type: &sema.VariableSizedType{ + Type: UInt8Type, + }, + }, + ), +} + +const RLPTypeDecodeListFunctionDocString = ` +Decodes an RLP-encoded list into an array of RLP-encoded items. +Note that this function does not recursively decode, so each element of the resulting array is RLP-encoded data. +The byte array should only contain of a single encoded value for a list; +if the encoded value type does not match, or it has trailing unnecessary bytes, the program aborts. +If any error is encountered while decoding, the program aborts. +` + +const RLPTypeName = "RLP" + +var RLPType = func() *sema.CompositeType { + var t = &sema.CompositeType{ + Identifier: RLPTypeName, + Kind: common.CompositeKindContract, + ImportableBuiltin: false, + HasComputedMembers: true, + } + + return t +}() + +func init() { + var members = []*sema.Member{ + sema.NewUnmeteredFunctionMember( + RLPType, + ast.AccessPublic, + RLPTypeDecodeStringFunctionName, + RLPTypeDecodeStringFunctionType, + RLPTypeDecodeStringFunctionDocString, + ), + sema.NewUnmeteredFunctionMember( + RLPType, + ast.AccessPublic, + RLPTypeDecodeListFunctionName, + RLPTypeDecodeListFunctionType, + RLPTypeDecodeListFunctionDocString, + ), + } + + RLPType.Members = sema.MembersAsMap(members) + RLPType.Fields = sema.MembersFieldNames(members) +} diff --git a/runtime/stdlib/rlp.go b/runtime/stdlib/rlp.go index 4743450d23..e36b7c66ba 100644 --- a/runtime/stdlib/rlp.go +++ b/runtime/stdlib/rlp.go @@ -18,67 +18,17 @@ package stdlib +//go:generate go run ../sema/gen -p stdlib rlp.cdc rlp.gen.go + import ( "fmt" "github.com/onflow/cadence/runtime/common" "github.com/onflow/cadence/runtime/errors" "github.com/onflow/cadence/runtime/interpreter" - "github.com/onflow/cadence/runtime/sema" "github.com/onflow/cadence/runtime/stdlib/rlp" ) -var rlpContractType = func() *sema.CompositeType { - ty := &sema.CompositeType{ - Identifier: "RLP", - Kind: common.CompositeKindContract, - } - - ty.Members = sema.MembersAsMap([]*sema.Member{ - sema.NewUnmeteredPublicFunctionMember( - ty, - rlpDecodeListFunctionName, - rlpDecodeListFunctionType, - rlpDecodeListFunctionDocString, - ), - sema.NewUnmeteredPublicFunctionMember( - ty, - rlpDecodeStringFunctionName, - rlpDecodeStringFunctionType, - rlpDecodeStringFunctionDocString, - ), - }) - return ty -}() - -var rlpContractStaticType interpreter.StaticType = interpreter.ConvertSemaCompositeTypeToStaticCompositeType( - nil, - rlpContractType, -) - -const rlpErrMsgInputContainsExtraBytes = "input data is expected to be RLP-encoded of a single string or a single list but it seems it contains extra trailing bytes." - -const rlpDecodeStringFunctionDocString = ` -Decodes an RLP-encoded byte array (called string in the context of RLP). -The byte array should only contain of a single encoded value for a string; -if the encoded value type does not match, or it has trailing unnecessary bytes, the program aborts. -If any error is encountered while decoding, the program aborts. -` - -const rlpDecodeStringFunctionName = "decodeString" - -var rlpDecodeStringFunctionType = sema.NewSimpleFunctionType( - sema.FunctionPurityView, - []sema.Parameter{ - { - Label: sema.ArgumentLabelNotRequired, - Identifier: "input", - TypeAnnotation: sema.ByteArrayTypeAnnotation, - }, - }, - sema.ByteArrayTypeAnnotation, -) - type RLPDecodeStringError struct { interpreter.LocationRange Msg string @@ -92,8 +42,10 @@ func (e RLPDecodeStringError) Error() string { return fmt.Sprintf("failed to RLP-decode string: %s", e.Msg) } +const rlpErrMsgInputContainsExtraBytes = "input data is expected to be RLP-encoded of a single string or a single list but it seems it contains extra trailing bytes." + var rlpDecodeStringFunction = interpreter.NewUnmeteredHostFunctionValue( - rlpDecodeStringFunctionType, + RLPTypeDecodeStringFunctionType, func(invocation interpreter.Invocation) interpreter.Value { input, ok := invocation.Arguments[0].(*interpreter.ArrayValue) if !ok { @@ -128,28 +80,6 @@ var rlpDecodeStringFunction = interpreter.NewUnmeteredHostFunctionValue( }, ) -const rlpDecodeListFunctionDocString = ` -Decodes an RLP-encoded list into an array of RLP-encoded items. -Note that this function does not recursively decode, so each element of the resulting array is RLP-encoded data. -The byte array should only contain of a single encoded value for a list; -if the encoded value type does not match, or it has trailing unnecessary bytes, the program aborts. -If any error is encountered while decoding, the program aborts. -` - -const rlpDecodeListFunctionName = "decodeList" - -var rlpDecodeListFunctionType = sema.NewSimpleFunctionType( - sema.FunctionPurityView, - []sema.Parameter{ - { - Label: sema.ArgumentLabelNotRequired, - Identifier: "input", - TypeAnnotation: sema.ByteArrayTypeAnnotation, - }, - }, - sema.ByteArrayArrayTypeAnnotation, -) - type RLPDecodeListError struct { interpreter.LocationRange Msg string @@ -164,7 +94,7 @@ func (e RLPDecodeListError) Error() string { } var rlpDecodeListFunction = interpreter.NewUnmeteredHostFunctionValue( - rlpDecodeListFunctionType, + RLPTypeDecodeListFunctionType, func(invocation interpreter.Invocation) interpreter.Value { input, ok := invocation.Arguments[0].(*interpreter.ArrayValue) if !ok { @@ -218,14 +148,16 @@ var rlpDecodeListFunction = interpreter.NewUnmeteredHostFunctionValue( ) var rlpContractFields = map[string]interpreter.Value{ - rlpDecodeListFunctionName: rlpDecodeListFunction, - rlpDecodeStringFunctionName: rlpDecodeStringFunction, + RLPTypeDecodeListFunctionName: rlpDecodeListFunction, + RLPTypeDecodeStringFunctionName: rlpDecodeStringFunction, } +var RLPTypeStaticType = interpreter.ConvertSemaToStaticType(nil, RLPType) + var rlpContractValue = interpreter.NewSimpleCompositeValue( nil, - rlpContractType.ID(), - rlpContractStaticType, + RLPType.ID(), + RLPTypeStaticType, nil, rlpContractFields, nil, @@ -235,7 +167,7 @@ var rlpContractValue = interpreter.NewSimpleCompositeValue( var RLPContract = StandardLibraryValue{ Name: "RLP", - Type: rlpContractType, + Type: RLPType, Value: rlpContractValue, Kind: common.DeclarationKindContract, } From 2aa04903e4b73f124b9a06c2f31b8991308dad4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 31 Aug 2023 14:19:45 -0700 Subject: [PATCH 05/10] re-generate type declarations --- runtime/sema/account.gen.go | 32 ++++++++++++++++---------------- runtime/stdlib/bls.gen.go | 4 ++-- runtime/stdlib/rlp.gen.go | 4 ++-- 3 files changed, 20 insertions(+), 20 deletions(-) diff --git a/runtime/sema/account.gen.go b/runtime/sema/account.gen.go index f67d7e18a8..09361d7e21 100644 --- a/runtime/sema/account.gen.go +++ b/runtime/sema/account.gen.go @@ -445,8 +445,8 @@ var Account_StorageType = func() *CompositeType { var t = &CompositeType{ Identifier: Account_StorageTypeName, Kind: common.CompositeKindStructure, - importable: false, - hasComputedMembers: true, + ImportableBuiltin: false, + HasComputedMembers: true, } return t @@ -731,8 +731,8 @@ var Account_ContractsType = func() *CompositeType { var t = &CompositeType{ Identifier: Account_ContractsTypeName, Kind: common.CompositeKindStructure, - importable: false, - hasComputedMembers: true, + ImportableBuiltin: false, + HasComputedMembers: true, } return t @@ -918,8 +918,8 @@ var Account_KeysType = func() *CompositeType { var t = &CompositeType{ Identifier: Account_KeysTypeName, Kind: common.CompositeKindStructure, - importable: false, - hasComputedMembers: true, + ImportableBuiltin: false, + HasComputedMembers: true, } return t @@ -1096,8 +1096,8 @@ var Account_InboxType = func() *CompositeType { var t = &CompositeType{ Identifier: Account_InboxTypeName, Kind: common.CompositeKindStructure, - importable: false, - hasComputedMembers: true, + ImportableBuiltin: false, + HasComputedMembers: true, } return t @@ -1291,8 +1291,8 @@ var Account_CapabilitiesType = func() *CompositeType { var t = &CompositeType{ Identifier: Account_CapabilitiesTypeName, Kind: common.CompositeKindStructure, - importable: false, - hasComputedMembers: true, + ImportableBuiltin: false, + HasComputedMembers: true, } return t @@ -1497,8 +1497,8 @@ var Account_StorageCapabilitiesType = func() *CompositeType { var t = &CompositeType{ Identifier: Account_StorageCapabilitiesTypeName, Kind: common.CompositeKindStructure, - importable: false, - hasComputedMembers: true, + ImportableBuiltin: false, + HasComputedMembers: true, } return t @@ -1669,8 +1669,8 @@ var Account_AccountCapabilitiesType = func() *CompositeType { var t = &CompositeType{ Identifier: Account_AccountCapabilitiesTypeName, Kind: common.CompositeKindStructure, - importable: false, - hasComputedMembers: true, + ImportableBuiltin: false, + HasComputedMembers: true, } return t @@ -1730,8 +1730,8 @@ var AccountType = func() *CompositeType { var t = &CompositeType{ Identifier: AccountTypeName, Kind: common.CompositeKindStructure, - importable: false, - hasComputedMembers: true, + ImportableBuiltin: false, + HasComputedMembers: true, } t.SetNestedType(Account_StorageTypeName, Account_StorageType) diff --git a/runtime/stdlib/bls.gen.go b/runtime/stdlib/bls.gen.go index 5fac48866e..eeaa7683f1 100644 --- a/runtime/stdlib/bls.gen.go +++ b/runtime/stdlib/bls.gen.go @@ -103,14 +103,14 @@ func init() { var members = []*sema.Member{ sema.NewUnmeteredFunctionMember( BLSType, - ast.AccessPublic, + PrimitiveAccess(ast.AccessAll), BLSTypeAggregateSignaturesFunctionName, BLSTypeAggregateSignaturesFunctionType, BLSTypeAggregateSignaturesFunctionDocString, ), sema.NewUnmeteredFunctionMember( BLSType, - ast.AccessPublic, + PrimitiveAccess(ast.AccessAll), BLSTypeAggregatePublicKeysFunctionName, BLSTypeAggregatePublicKeysFunctionType, BLSTypeAggregatePublicKeysFunctionDocString, diff --git a/runtime/stdlib/rlp.gen.go b/runtime/stdlib/rlp.gen.go index b8585d55de..979b9ef2d5 100644 --- a/runtime/stdlib/rlp.gen.go +++ b/runtime/stdlib/rlp.gen.go @@ -97,14 +97,14 @@ func init() { var members = []*sema.Member{ sema.NewUnmeteredFunctionMember( RLPType, - ast.AccessPublic, + PrimitiveAccess(ast.AccessAll), RLPTypeDecodeStringFunctionName, RLPTypeDecodeStringFunctionType, RLPTypeDecodeStringFunctionDocString, ), sema.NewUnmeteredFunctionMember( RLPType, - ast.AccessPublic, + PrimitiveAccess(ast.AccessAll), RLPTypeDecodeListFunctionName, RLPTypeDecodeListFunctionType, RLPTypeDecodeListFunctionDocString, From c44bb96b5fbdb89f49a33a2585bf438365e7aea2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 31 Aug 2023 14:20:04 -0700 Subject: [PATCH 06/10] make RLP and BLS functions view --- runtime/stdlib/bls.cdc | 4 ++-- runtime/stdlib/bls.gen.go | 2 ++ runtime/stdlib/rlp.cdc | 4 ++-- runtime/stdlib/rlp.gen.go | 2 ++ 4 files changed, 8 insertions(+), 4 deletions(-) diff --git a/runtime/stdlib/bls.cdc b/runtime/stdlib/bls.cdc index da4c6284ff..25e291bd12 100644 --- a/runtime/stdlib/bls.cdc +++ b/runtime/stdlib/bls.cdc @@ -9,7 +9,7 @@ contract BLS { /// No subgroup membership check is performed on the input signatures. /// The function returns nil if the array is empty or if decoding one of the signature fails. access(all) - fun aggregateSignatures(_ signatures: [[UInt8]]): [UInt8]? + view fun aggregateSignatures(_ signatures: [[UInt8]]): [UInt8]? /// Aggregates multiple BLS public keys into one. @@ -18,5 +18,5 @@ contract BLS { /// No subgroup membership check is performed on the input keys. /// The function returns nil if the array is empty or any of the input keys is not a BLS key. access(all) - fun aggregatePublicKeys(_ keys: [PublicKey]): PublicKey? + view fun aggregatePublicKeys(_ keys: [PublicKey]): PublicKey? } diff --git a/runtime/stdlib/bls.gen.go b/runtime/stdlib/bls.gen.go index eeaa7683f1..0aa312820f 100644 --- a/runtime/stdlib/bls.gen.go +++ b/runtime/stdlib/bls.gen.go @@ -28,6 +28,7 @@ import ( const BLSTypeAggregateSignaturesFunctionName = "aggregateSignatures" var BLSTypeAggregateSignaturesFunctionType = &sema.FunctionType{ + Purity: FunctionPurityView, Parameters: []sema.Parameter{ { Label: sema.ArgumentLabelNotRequired, @@ -62,6 +63,7 @@ The function returns nil if the array is empty or if decoding one of the signatu const BLSTypeAggregatePublicKeysFunctionName = "aggregatePublicKeys" var BLSTypeAggregatePublicKeysFunctionType = &sema.FunctionType{ + Purity: FunctionPurityView, Parameters: []sema.Parameter{ { Label: sema.ArgumentLabelNotRequired, diff --git a/runtime/stdlib/rlp.cdc b/runtime/stdlib/rlp.cdc index e5a3ac78ab..6102f9c4b9 100644 --- a/runtime/stdlib/rlp.cdc +++ b/runtime/stdlib/rlp.cdc @@ -5,7 +5,7 @@ contract RLP { /// if the encoded value type does not match, or it has trailing unnecessary bytes, the program aborts. /// If any error is encountered while decoding, the program aborts. access(all) - fun decodeString(_ input: [UInt8]): [UInt8] + view fun decodeString(_ input: [UInt8]): [UInt8] /// Decodes an RLP-encoded list into an array of RLP-encoded items. @@ -14,5 +14,5 @@ contract RLP { /// if the encoded value type does not match, or it has trailing unnecessary bytes, the program aborts. /// If any error is encountered while decoding, the program aborts. access(all) - fun decodeList(_ input: [UInt8]): [[UInt8]] + view fun decodeList(_ input: [UInt8]): [[UInt8]] } diff --git a/runtime/stdlib/rlp.gen.go b/runtime/stdlib/rlp.gen.go index 979b9ef2d5..47983e4027 100644 --- a/runtime/stdlib/rlp.gen.go +++ b/runtime/stdlib/rlp.gen.go @@ -28,6 +28,7 @@ import ( const RLPTypeDecodeStringFunctionName = "decodeString" var RLPTypeDecodeStringFunctionType = &sema.FunctionType{ + Purity: FunctionPurityView, Parameters: []sema.Parameter{ { Label: sema.ArgumentLabelNotRequired, @@ -54,6 +55,7 @@ If any error is encountered while decoding, the program aborts. const RLPTypeDecodeListFunctionName = "decodeList" var RLPTypeDecodeListFunctionType = &sema.FunctionType{ + Purity: FunctionPurityView, Parameters: []sema.Parameter{ { Label: sema.ArgumentLabelNotRequired, From f74550be068402f229010f8bc836cc64f564903a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 31 Aug 2023 14:46:45 -0700 Subject: [PATCH 07/10] add sema package path to recently added identifiers --- runtime/sema/gen/main.go | 63 +++++++++++++++++++++++++++++++--------- 1 file changed, 50 insertions(+), 13 deletions(-) diff --git a/runtime/sema/gen/main.go b/runtime/sema/gen/main.go index 97c2a77fed..9e07ce5530 100644 --- a/runtime/sema/gen/main.go +++ b/runtime/sema/gen/main.go @@ -41,6 +41,7 @@ import ( ) const semaPath = "github.com/onflow/cadence/runtime/sema" +const astPath = "github.com/onflow/cadence/runtime/ast" var packagePathFlag = flag.String("p", semaPath, "package path") @@ -734,7 +735,13 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { Elts: []dst.Expr{ goKeyValue("Type", borrowType), // TODO: add support for parsing entitlements - goKeyValue("Authorization", dst.NewIdent("UnauthorizedAccess")), + goKeyValue( + "Authorization", + &dst.Ident{ + Name: "UnauthorizedAccess", + Path: semaPath, + }, + ), }, }, } @@ -861,7 +868,10 @@ func functionTypeExpr( var purityExpr dst.Expr if t.PurityAnnotation == ast.FunctionPurityView { - purityExpr = dst.NewIdent("FunctionPurityView") + purityExpr = &dst.Ident{ + Name: "FunctionPurityView", + Path: semaPath, + } } // Type parameters @@ -1521,11 +1531,14 @@ func accessExpr(access ast.Access) dst.Expr { switch access := access.(type) { case ast.PrimitiveAccess: return &dst.CallExpr{ - Fun: dst.NewIdent("PrimitiveAccess"), + Fun: &dst.Ident{ + Name: "PrimitiveAccess", + Path: semaPath, + }, Args: []dst.Expr{ &dst.Ident{ Name: access.String(), - Path: "github.com/onflow/cadence/runtime/ast", + Path: astPath, }, }, } @@ -1544,9 +1557,15 @@ func accessExpr(access ast.Access) dst.Expr { switch access.EntitlementSet.Separator() { case ast.Conjunction: - setKind = dst.NewIdent("Conjunction") + setKind = &dst.Ident{ + Name: "Conjunction", + Path: semaPath, + } case ast.Disjunction: - setKind = dst.NewIdent("Disjunction") + setKind = &dst.Ident{ + Name: "Disjunction", + Path: semaPath, + } default: panic(errors.NewUnreachableError()) } @@ -1554,7 +1573,10 @@ func accessExpr(access ast.Access) dst.Expr { args := []dst.Expr{ &dst.CompositeLit{ Type: &dst.ArrayType{ - Elt: dst.NewIdent("Type"), + Elt: &dst.Ident{ + Name: "Type", + Path: semaPath, + }, }, Elts: entitlementExprs, }, @@ -1567,7 +1589,10 @@ func accessExpr(access ast.Access) dst.Expr { } return &dst.CallExpr{ - Fun: dst.NewIdent("newEntitlementAccess"), + Fun: &dst.Ident{ + Name: "newEntitlementAccess", + Path: semaPath, + }, Args: args, } @@ -1579,7 +1604,7 @@ func accessExpr(access ast.Access) dst.Expr { func variableKindIdent(variableKind ast.VariableKind) *dst.Ident { return &dst.Ident{ Name: variableKind.String(), - Path: "github.com/onflow/cadence/runtime/ast", + Path: astPath, } } @@ -1810,7 +1835,10 @@ func entitlementTypeLiteral(name string) dst.Expr { return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("EntitlementType"), + Type: &dst.Ident{ + Name: "EntitlementType", + Path: semaPath, + }, Elts: []dst.Expr{ goKeyValue("Identifier", goStringLit(name)), }, @@ -1839,7 +1867,10 @@ func entitlementMapTypeLiteral(name string, elements []ast.EntitlementMapElement } relationExpr := &dst.CompositeLit{ - Type: dst.NewIdent("EntitlementRelation"), + Type: &dst.Ident{ + Name: "EntitlementRelation", + Path: semaPath, + }, Elts: []dst.Expr{ goKeyValue("Input", typeExpr(relation.Input, nil)), goKeyValue("Output", typeExpr(relation.Output, nil)), @@ -1854,7 +1885,10 @@ func entitlementMapTypeLiteral(name string, elements []ast.EntitlementMapElement relationsExpr := &dst.CompositeLit{ Type: &dst.ArrayType{ - Elt: dst.NewIdent("EntitlementRelation"), + Elt: &dst.Ident{ + Name: "EntitlementRelation", + Path: semaPath, + }, }, Elts: relationExprs, } @@ -1862,7 +1896,10 @@ func entitlementMapTypeLiteral(name string, elements []ast.EntitlementMapElement return &dst.UnaryExpr{ Op: token.AND, X: &dst.CompositeLit{ - Type: dst.NewIdent("EntitlementMapType"), + Type: &dst.Ident{ + Name: "EntitlementMapType", + Path: semaPath, + }, Elts: []dst.Expr{ goKeyValue("Identifier", goStringLit(name)), goKeyValue("Relations", relationsExpr), From fbb765c52210b2af25189419d2bdabfee3cf6982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 31 Aug 2023 14:46:56 -0700 Subject: [PATCH 08/10] re-generate --- runtime/stdlib/bls.gen.go | 8 ++++---- runtime/stdlib/rlp.gen.go | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/runtime/stdlib/bls.gen.go b/runtime/stdlib/bls.gen.go index 0aa312820f..e88a5939fa 100644 --- a/runtime/stdlib/bls.gen.go +++ b/runtime/stdlib/bls.gen.go @@ -28,7 +28,7 @@ import ( const BLSTypeAggregateSignaturesFunctionName = "aggregateSignatures" var BLSTypeAggregateSignaturesFunctionType = &sema.FunctionType{ - Purity: FunctionPurityView, + Purity: sema.FunctionPurityView, Parameters: []sema.Parameter{ { Label: sema.ArgumentLabelNotRequired, @@ -63,7 +63,7 @@ The function returns nil if the array is empty or if decoding one of the signatu const BLSTypeAggregatePublicKeysFunctionName = "aggregatePublicKeys" var BLSTypeAggregatePublicKeysFunctionType = &sema.FunctionType{ - Purity: FunctionPurityView, + Purity: sema.FunctionPurityView, Parameters: []sema.Parameter{ { Label: sema.ArgumentLabelNotRequired, @@ -105,14 +105,14 @@ func init() { var members = []*sema.Member{ sema.NewUnmeteredFunctionMember( BLSType, - PrimitiveAccess(ast.AccessAll), + sema.PrimitiveAccess(ast.AccessAll), BLSTypeAggregateSignaturesFunctionName, BLSTypeAggregateSignaturesFunctionType, BLSTypeAggregateSignaturesFunctionDocString, ), sema.NewUnmeteredFunctionMember( BLSType, - PrimitiveAccess(ast.AccessAll), + sema.PrimitiveAccess(ast.AccessAll), BLSTypeAggregatePublicKeysFunctionName, BLSTypeAggregatePublicKeysFunctionType, BLSTypeAggregatePublicKeysFunctionDocString, diff --git a/runtime/stdlib/rlp.gen.go b/runtime/stdlib/rlp.gen.go index 47983e4027..44aac52a78 100644 --- a/runtime/stdlib/rlp.gen.go +++ b/runtime/stdlib/rlp.gen.go @@ -28,7 +28,7 @@ import ( const RLPTypeDecodeStringFunctionName = "decodeString" var RLPTypeDecodeStringFunctionType = &sema.FunctionType{ - Purity: FunctionPurityView, + Purity: sema.FunctionPurityView, Parameters: []sema.Parameter{ { Label: sema.ArgumentLabelNotRequired, @@ -55,7 +55,7 @@ If any error is encountered while decoding, the program aborts. const RLPTypeDecodeListFunctionName = "decodeList" var RLPTypeDecodeListFunctionType = &sema.FunctionType{ - Purity: FunctionPurityView, + Purity: sema.FunctionPurityView, Parameters: []sema.Parameter{ { Label: sema.ArgumentLabelNotRequired, @@ -99,14 +99,14 @@ func init() { var members = []*sema.Member{ sema.NewUnmeteredFunctionMember( RLPType, - PrimitiveAccess(ast.AccessAll), + sema.PrimitiveAccess(ast.AccessAll), RLPTypeDecodeStringFunctionName, RLPTypeDecodeStringFunctionType, RLPTypeDecodeStringFunctionDocString, ), sema.NewUnmeteredFunctionMember( RLPType, - PrimitiveAccess(ast.AccessAll), + sema.PrimitiveAccess(ast.AccessAll), RLPTypeDecodeListFunctionName, RLPTypeDecodeListFunctionType, RLPTypeDecodeListFunctionDocString, From 2ec180397f3fa69e5e7e20b1ad732e0e29ff153c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 31 Aug 2023 15:29:40 -0700 Subject: [PATCH 09/10] add support for dictionary types --- runtime/sema/gen/main.go | 17 +++++++++++++++++ runtime/sema/gen/testdata/fields.cdc | 3 +++ runtime/sema/gen/testdata/fields.golden.go | 19 +++++++++++++++++++ 3 files changed, 39 insertions(+) diff --git a/runtime/sema/gen/main.go b/runtime/sema/gen/main.go index 9e07ce5530..6b48943801 100644 --- a/runtime/sema/gen/main.go +++ b/runtime/sema/gen/main.go @@ -783,6 +783,23 @@ func typeExpr(t ast.Type, typeParams map[string]string) dst.Expr { }, } + case *ast.DictionaryType: + keyType := typeExpr(t.KeyType, typeParams) + valueType := typeExpr(t.ValueType, typeParams) + return &dst.UnaryExpr{ + Op: token.AND, + X: &dst.CompositeLit{ + Type: &dst.Ident{ + Name: "DictionaryType", + Path: semaPath, + }, + Elts: []dst.Expr{ + goKeyValue("KeyType", keyType), + goKeyValue("ValueType", valueType), + }, + }, + } + case *ast.FunctionType: return functionTypeExpr(t, nil, nil, typeParams) diff --git a/runtime/sema/gen/testdata/fields.cdc b/runtime/sema/gen/testdata/fields.cdc index 667f50b712..1cf74e4f96 100644 --- a/runtime/sema/gen/testdata/fields.cdc +++ b/runtime/sema/gen/testdata/fields.cdc @@ -14,6 +14,9 @@ access(all) struct Test { /// This is a test constant-sized integer array. access(all) let testConstInts: [UInt64; 2] + /// This is a test integer dictionary. + access(all) let testIntDict: {UInt64: Bool} + /// This is a test parameterized-type field. access(all) let testParam: Foo diff --git a/runtime/sema/gen/testdata/fields.golden.go b/runtime/sema/gen/testdata/fields.golden.go index 9fdabd602e..f4af42f973 100644 --- a/runtime/sema/gen/testdata/fields.golden.go +++ b/runtime/sema/gen/testdata/fields.golden.go @@ -71,6 +71,17 @@ const TestTypeTestConstIntsFieldDocString = ` This is a test constant-sized integer array. ` +const TestTypeTestIntDictFieldName = "testIntDict" + +var TestTypeTestIntDictFieldType = &DictionaryType{ + KeyType: UInt64Type, + ValueType: BoolType, +} + +const TestTypeTestIntDictFieldDocString = ` +This is a test integer dictionary. +` + const TestTypeTestParamFieldName = "testParam" var TestTypeTestParamFieldType = MustInstantiate( @@ -186,6 +197,14 @@ func init() { TestTypeTestConstIntsFieldType, TestTypeTestConstIntsFieldDocString, ), + NewUnmeteredFieldMember( + t, + PrimitiveAccess(ast.AccessAll), + ast.VariableKindConstant, + TestTypeTestIntDictFieldName, + TestTypeTestIntDictFieldType, + TestTypeTestIntDictFieldDocString, + ), NewUnmeteredFieldMember( t, PrimitiveAccess(ast.AccessAll), From 806368013a5166550ec7a1a1343209dbc03643fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Bastian=20M=C3=BCller?= Date: Thu, 31 Aug 2023 15:36:03 -0700 Subject: [PATCH 10/10] use existing name constants --- runtime/stdlib/bls.go | 4 ++-- runtime/stdlib/rlp.go | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/runtime/stdlib/bls.go b/runtime/stdlib/bls.go index b1dd5999f6..62cc7ad6ae 100644 --- a/runtime/stdlib/bls.go +++ b/runtime/stdlib/bls.go @@ -187,7 +187,7 @@ func NewBLSContract( } blsContractValue := interpreter.NewSimpleCompositeValue( - nil, + gauge, BLSType.ID(), BLSTypeStaticType, nil, @@ -198,7 +198,7 @@ func NewBLSContract( ) return StandardLibraryValue{ - Name: "BLS", + Name: BLSTypeName, Type: BLSType, Value: blsContractValue, Kind: common.DeclarationKindContract, diff --git a/runtime/stdlib/rlp.go b/runtime/stdlib/rlp.go index e36b7c66ba..a8c9faae3f 100644 --- a/runtime/stdlib/rlp.go +++ b/runtime/stdlib/rlp.go @@ -166,7 +166,7 @@ var rlpContractValue = interpreter.NewSimpleCompositeValue( ) var RLPContract = StandardLibraryValue{ - Name: "RLP", + Name: RLPTypeName, Type: RLPType, Value: rlpContractValue, Kind: common.DeclarationKindContract,