diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 7d7f8c5a4b..8f15bbc71c 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -27,6 +27,6 @@ jobs: runs-on: ubuntu-latest steps: - uses: actions/checkout@v2 - - uses: golangci/golangci-lint-action@v1 + - uses: golangci/golangci-lint-action@v2 with: - version: v1.26 + version: v1.29 diff --git a/Makefile b/Makefile index 72b26f00ea..03e71718f1 100644 --- a/Makefile +++ b/Makefile @@ -39,7 +39,7 @@ build: .PHONY: install-tools install-tools: - curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b ${GOPATH}/bin v1.26.0 + curl -sSfL https://raw.githubusercontent.com/golangci/golangci-lint/master/install.sh | sh -s -- -b ${GOPATH}/bin v1.29.0 .PHONY: lint lint: diff --git a/languageserver/integration/resolving.go b/languageserver/integration/resolving.go index e4a0ed1d4b..90e18c68af 100644 --- a/languageserver/integration/resolving.go +++ b/languageserver/integration/resolving.go @@ -45,7 +45,7 @@ func resolveFileImport(mainPath string, location ast.StringLocation) (string, er } func (i *FlowIntegration) resolveAccountImport(location ast.AddressLocation) (string, error) { - accountAddr := location.ToAddress() + accountAddr := location.Address acct, err := i.flowClient.GetAccount(context.Background(), flow.BytesToAddress(accountAddr[:])) if err != nil { diff --git a/runtime/ast/import.go b/runtime/ast/import.go index a2c63ae9eb..f27aa95269 100644 --- a/runtime/ast/import.go +++ b/runtime/ast/import.go @@ -103,6 +103,10 @@ func (d *ImportDeclaration) MarshalJSON() ([]byte, error) { type Location interface { // ID returns the canonical ID for this import location. ID() LocationID + // TypeID returns a type ID for the given qualified identifier + TypeID(qualifiedIdentifier string) TypeID + // QualifiedIdentifier returns the qualified identifier for the given type ID + QualifiedIdentifier(typeID TypeID) string } func LocationsMatch(first, second Location) bool { @@ -137,17 +141,14 @@ func LocationFromTypeID(typeID string) Location { return nil } - return AddressLocation(address) - - case AddressContractLocationPrefix: - address, err := hex.DecodeString(pieces[1]) - if err != nil { - return nil + var name string + if len(pieces) > 2 { + name = pieces[2] } - return AddressContractLocation{ - AddressLocation: address, - Name: pieces[2], + return AddressLocation{ + Address: common.BytesToAddress(address), + Name: name, } } @@ -155,21 +156,50 @@ func LocationFromTypeID(typeID string) Location { } // LocationID - +// type LocationID string func NewLocationID(parts ...string) LocationID { return LocationID(strings.Join(parts, ".")) } -// IdentifierLocation +// TypeID +// +type TypeID string + +func NewTypeID(parts ...string) TypeID { + return TypeID(strings.Join(parts, ".")) +} +// IdentifierLocation +// const IdentifierLocationPrefix = "I" type IdentifierLocation string func (l IdentifierLocation) ID() LocationID { - return NewLocationID(IdentifierLocationPrefix, string(l)) + return NewLocationID( + IdentifierLocationPrefix, + string(l), + ) +} + +func (l IdentifierLocation) TypeID(qualifiedIdentifier string) TypeID { + return NewTypeID( + IdentifierLocationPrefix, + string(l), + qualifiedIdentifier, + ) +} + +func (l IdentifierLocation) QualifiedIdentifier(typeID TypeID) string { + pieces := strings.SplitN(string(typeID), ".", 3) + + if len(pieces) < 3 { + return "" + } + + return pieces[2] } func (l IdentifierLocation) MarshalJSON() ([]byte, error) { @@ -182,14 +212,35 @@ func (l IdentifierLocation) MarshalJSON() ([]byte, error) { }) } -// StringLocation - const StringLocationPrefix = "S" +// StringLocation +// type StringLocation string func (l StringLocation) ID() LocationID { - return NewLocationID(StringLocationPrefix, string(l)) + return NewLocationID( + StringLocationPrefix, + string(l), + ) +} + +func (l StringLocation) TypeID(qualifiedIdentifier string) TypeID { + return NewTypeID( + StringLocationPrefix, + string(l), + qualifiedIdentifier, + ) +} + +func (l StringLocation) QualifiedIdentifier(typeID TypeID) string { + pieces := strings.SplitN(string(typeID), ".", 3) + + if len(pieces) < 3 { + return "" + } + + return pieces[2] } func (l StringLocation) MarshalJSON() ([]byte, error) { @@ -202,66 +253,68 @@ func (l StringLocation) MarshalJSON() ([]byte, error) { }) } -// AddressLocation - const AddressLocationPrefix = "A" -type AddressLocation []byte +// AddressLocation is the location of a contract/contract interface at an address +// +type AddressLocation struct { + Address common.Address + Name string +} func (l AddressLocation) String() string { - return l.ToAddress().String() + if l.Name == "" { + return l.Address.String() + } + + return fmt.Sprintf( + "%s.%s", + l.Address.String(), + l.Name, + ) } func (l AddressLocation) ID() LocationID { - return NewLocationID(AddressLocationPrefix, l.ToAddress().Hex()) -} + if l.Name == "" { + return NewLocationID( + AddressLocationPrefix, + l.Address.Hex(), + ) + } -func (l AddressLocation) ToAddress() common.Address { - return common.BytesToAddress(l) + return NewLocationID( + AddressLocationPrefix, + l.Address.Hex(), + l.Name, + ) } -func (l AddressLocation) MarshalJSON() ([]byte, error) { - return json.Marshal(&struct { - Type string - Address string - }{ - Type: "AddressLocation", - Address: l.ToAddress().ShortHexWithPrefix(), - }) +func (l AddressLocation) TypeID(qualifiedIdentifier string) TypeID { + return NewTypeID( + AddressLocationPrefix, + l.Address.Hex(), + qualifiedIdentifier, + ) } -const AddressContractLocationPrefix = "AC" - -// AddressContractLocation is the location of a contract/contract interface at an address +func (l AddressLocation) QualifiedIdentifier(typeID TypeID) string { + pieces := strings.SplitN(string(typeID), ".", 3) -type AddressContractLocation struct { - AddressLocation AddressLocation - Name string -} - -func (l AddressContractLocation) String() string { - return fmt.Sprintf("%s.%s", - l.AddressLocation.String(), - l.Name, - ) -} + if len(pieces) < 3 { + return "" + } -func (l AddressContractLocation) ID() LocationID { - return NewLocationID( - AddressContractLocationPrefix, - l.AddressLocation.ToAddress().Hex(), - l.Name, - ) + return pieces[2] } -func (l AddressContractLocation) MarshalJSON() ([]byte, error) { +func (l AddressLocation) MarshalJSON() ([]byte, error) { return json.Marshal(&struct { Type string Address string Name string }{ - Type: "AddressContractLocation", - Address: l.AddressLocation.ToAddress().ShortHexWithPrefix(), + Type: "AddressLocation", + Address: l.Address.ShortHexWithPrefix(), Name: l.Name, }) } diff --git a/runtime/ast/import_test.go b/runtime/ast/import_test.go index 2b9087a381..2e726e6114 100644 --- a/runtime/ast/import_test.go +++ b/runtime/ast/import_test.go @@ -24,6 +24,8 @@ import ( "github.com/stretchr/testify/assert" "github.com/stretchr/testify/require" + + "github.com/onflow/cadence/runtime/common" ) func TestIdentifierLocation_MarshalJSON(t *testing.T) { @@ -70,7 +72,10 @@ func TestAddressLocation_MarshalJSON(t *testing.T) { t.Parallel() - loc := AddressLocation([]byte{1}) + loc := AddressLocation{ + Address: common.BytesToAddress([]byte{1}), + Name: "A", + } actual, err := json.Marshal(loc) require.NoError(t, err) @@ -79,7 +84,8 @@ func TestAddressLocation_MarshalJSON(t *testing.T) { ` { "Type": "AddressLocation", - "Address": "0x1" + "Address": "0x1", + "Name": "A" } `, string(actual), diff --git a/runtime/cmd/cmd.go b/runtime/cmd/cmd.go index c5d1f3c61e..c5cddb2125 100644 --- a/runtime/cmd/cmd.go +++ b/runtime/cmd/cmd.go @@ -58,7 +58,7 @@ func PrettyPrintError(writer io.Writer, err error, filename string, codes map[st case ast.StringLocation: filename = string(importLocation) case ast.AddressLocation: - filename = importLocation.ToAddress().ShortHexWithPrefix() + filename = importLocation.Address.ShortHexWithPrefix() case ast.IdentifierLocation: filename = string(importLocation) } diff --git a/runtime/contract_test.go b/runtime/contract_test.go index bf33ad23fc..ea637e4dda 100644 --- a/runtime/contract_test.go +++ b/runtime/contract_test.go @@ -499,13 +499,13 @@ func TestRuntimeImportMultipleContracts(t *testing.T) { }, resolveLocation: func(identifiers []ast.Identifier, location ast.Location) (result []sema.ResolvedLocation) { - // Resolve each identifier as an address contract location + // Resolve each identifier as an address location for _, identifier := range identifiers { result = append(result, sema.ResolvedLocation{ - Location: ast.AddressContractLocation{ - AddressLocation: location.(ast.AddressLocation), - Name: identifier.Identifier, + Location: ast.AddressLocation{ + Address: location.(ast.AddressLocation).Address, + Name: identifier.Identifier, }, Identifiers: []ast.Identifier{ identifier, diff --git a/runtime/interpreter/decode.go b/runtime/interpreter/decode.go index 7d9896014d..52b5e08633 100644 --- a/runtime/interpreter/decode.go +++ b/runtime/interpreter/decode.go @@ -25,6 +25,7 @@ import ( "math" "math/big" "strconv" + "strings" "github.com/fxamacker/cbor/v2" @@ -363,28 +364,11 @@ func (d *Decoder) decodeLocation(l interface{}) (ast.Location, error) { case cborTagIdentifierLocation: return d.decodeIdentifierLocation(content) - case cborTagAddressContractLocation: - return d.decodeAddressContractLocation(content) - default: return nil, fmt.Errorf("invalid location encoding tag: %d", tag.Number) } } -func (d *Decoder) decodeAddressLocation(v interface{}) (ast.Location, error) { - b, ok := v.([]byte) - if !ok { - return nil, fmt.Errorf("invalid address location encoding: %T", v) - } - - err := d.checkAddressLength(b) - if err != nil { - return nil, err - } - - return ast.AddressLocation(b), nil -} - func (d *Decoder) decodeStringLocation(v interface{}) (ast.Location, error) { s, ok := v.(string) if !ok { @@ -401,18 +385,37 @@ func (d *Decoder) decodeIdentifierLocation(v interface{}) (ast.Location, error) return ast.IdentifierLocation(s), nil } -func (d *Decoder) decodeAddressContractLocation(v interface{}) (ast.Location, error) { +func (d *Decoder) decodeAddressLocation(v interface{}) (ast.Location, error) { + + // If the encoded location is just a byte slice, + // it is the address and no name is provided + + encodedAddress, ok := v.([]byte) + if ok { + err := d.checkAddressLength(encodedAddress) + if err != nil { + return nil, err + } + + return ast.AddressLocation{ + Address: common.BytesToAddress(encodedAddress), + }, nil + } + + // Otherwise, the encoded location is expected to be a map, + // which includes both address and name + encoded, ok := v.(map[interface{}]interface{}) if !ok { - return nil, fmt.Errorf("invalid address contract location encoding: %T", v) + return nil, fmt.Errorf("invalid address location encoding: %T", v) } // Address - field1 := encoded[encodedAddressContractLocationAddressFieldKey] - encodedAddress, ok := field1.([]byte) + field1 := encoded[encodedAddressLocationAddressFieldKey] + encodedAddress, ok = field1.([]byte) if !ok { - return nil, fmt.Errorf("invalid address contract location address encoding: %T", field1) + return nil, fmt.Errorf("invalid address location address encoding: %T", field1) } err := d.checkAddressLength(encodedAddress) @@ -422,15 +425,15 @@ func (d *Decoder) decodeAddressContractLocation(v interface{}) (ast.Location, er // Name - field2 := encoded[encodedAddressContractLocationNameFieldKey] + field2 := encoded[encodedAddressLocationNameFieldKey] name, ok := field2.(string) if !ok { - return nil, fmt.Errorf("invalid address contract location name encoding: %T", field2) + return nil, fmt.Errorf("invalid address location name encoding: %T", field2) } - return ast.AddressContractLocation{ - AddressLocation: encodedAddress, - Name: name, + return ast.AddressLocation{ + Address: common.BytesToAddress(encodedAddress), + Name: name, }, nil } @@ -457,6 +460,10 @@ func (d *Decoder) decodeComposite(v interface{}, path []string) (*CompositeValue } typeID := sema.TypeID(encodedTypeID) + // Special case: The decoded location might be an address location which has no name + + location = d.inferAddressLocationName(location, typeID) + // Kind field3 := encoded[encodedCompositeValueKindFieldKey] @@ -1092,9 +1099,46 @@ func (d *Decoder) decodeLocationAndTypeID( } typeID := sema.TypeID(encodedTypeID) + // Special case: The decoded location might be an address location which has no name + + location = d.inferAddressLocationName(location, typeID) + return location, typeID, nil } +// inferAddressLocationName infers the name for an address location from a type ID. +// +// In the first version of the storage format, accounts could only store one contract +// instead of several contracts (separated by name), so composite's locations were +// address locations without a name, i.e. just the bare address. +// +// An update added support for multiple contracts per account, which added names to address locations: +// Each contract of an account is stored in a distinct location. +// +// So to keep backwards-compatibility: +// If the location is an address location without a name, +// then infer the name from the type ID. +// +func (d *Decoder) inferAddressLocationName(location ast.Location, typeID sema.TypeID) ast.Location { + + // Only consider address locations which have no name + + addressLocation, ok := location.(ast.AddressLocation) + if !ok || addressLocation.Name != "" { + return location + } + + // The first component of the type ID is the location name + + qualifiedIdentifier := location.QualifiedIdentifier(typeID) + parts := strings.SplitN(qualifiedIdentifier, ".", 2) + + return ast.AddressLocation{ + Address: addressLocation.Address, + Name: parts[0], + } +} + func (d *Decoder) decodeCompositeStaticType(v interface{}) (StaticType, error) { location, typeID, err := d.decodeLocationAndTypeID( v, diff --git a/runtime/interpreter/encode.go b/runtime/interpreter/encode.go index e206ebf673..a75a633253 100644 --- a/runtime/interpreter/encode.go +++ b/runtime/interpreter/encode.go @@ -143,7 +143,7 @@ const ( cborTagAddressLocation cborTagStringLocation cborTagIdentifierLocation - cborTagAddressContractLocation + _ _ _ _ @@ -844,17 +844,12 @@ func (e *Encoder) prepareCapabilityValue(v CapabilityValue) (interface{}, error) // NOTE: NEVER change, only add/increment; ensure uint64 const ( - encodedAddressContractLocationAddressFieldKey uint64 = 0 - encodedAddressContractLocationNameFieldKey uint64 = 1 + encodedAddressLocationAddressFieldKey uint64 = 0 + encodedAddressLocationNameFieldKey uint64 = 1 ) func (e *Encoder) prepareLocation(l ast.Location) (interface{}, error) { switch l := l.(type) { - case ast.AddressLocation: - return cbor.Tag{ - Number: cborTagAddressLocation, - Content: l.ToAddress().Bytes(), - }, nil case ast.StringLocation: return cbor.Tag{ @@ -868,13 +863,21 @@ func (e *Encoder) prepareLocation(l ast.Location) (interface{}, error) { Content: string(l), }, nil - case ast.AddressContractLocation: + case ast.AddressLocation: + var content interface{} + + if l.Name == "" { + content = l.Address.Bytes() + } else { + content = cborMap{ + encodedAddressLocationAddressFieldKey: l.Address.Bytes(), + encodedAddressLocationNameFieldKey: l.Name, + } + } + return cbor.Tag{ - Number: cborTagAddressContractLocation, - Content: cborMap{ - encodedAddressContractLocationAddressFieldKey: l.AddressLocation.ToAddress().Bytes(), - encodedAddressContractLocationNameFieldKey: l.Name, - }, + Number: cborTagAddressLocation, + Content: content, }, nil default: diff --git a/runtime/interpreter/encoding_test.go b/runtime/interpreter/encoding_test.go index 10191a0b4d..32d5958ed6 100644 --- a/runtime/interpreter/encoding_test.go +++ b/runtime/interpreter/encoding_test.go @@ -461,9 +461,14 @@ func TestEncodeDecodeComposite(t *testing.T) { }) t.Run("empty, address location", func(t *testing.T) { + expected := NewCompositeValue( - ast.AddressLocation{0x1}, - "A.0x1.TestStruct", + ast.AddressLocation{ + Address: common.BytesToAddress([]byte{0x1}), + // NOTE: not stored, inferred from type ID + Name: "TestContract", + }, + "A.0x1.TestContract.TestStruct", common.CompositeKindStructure, map[string]Value{}, nil, @@ -472,7 +477,7 @@ func TestEncodeDecodeComposite(t *testing.T) { testEncodeDecode(t, encodeDecodeTest{ - value: expected, + decodedValue: expected, encoded: []byte{ // tag 0xd8, cborTagCompositeValue, @@ -488,10 +493,12 @@ func TestEncodeDecodeComposite(t *testing.T) { 0x1, // key 1 0x1, - // UTF-8 string, length 16 - 0x70, - 0x41, 0x2e, 0x30, 0x78, 0x31, 0x2e, 0x54, 0x65, - 0x73, 0x74, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, + // UTF-8 string, length 29 + 0x78, 0x1D, + 0x41, + 0x2e, 0x30, 0x78, 0x31, + 0x2e, 0x54, 0x65, 0x73, 0x74, 0x43, 0x6F, 0x6E, 0x74, 0x72, 0x61, 0x63, 0x74, + 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, // key 2 0x2, // positive integer 1 @@ -501,6 +508,7 @@ func TestEncodeDecodeComposite(t *testing.T) { // map, 0 pairs of items follow 0xa0, }, + decodeOnly: true, }, ) }) @@ -545,11 +553,11 @@ func TestEncodeDecodeComposite(t *testing.T) { t.Run("empty, address location", func(t *testing.T) { expected := NewCompositeValue( - ast.AddressContractLocation{ - AddressLocation: ast.AddressLocation{0x1}, - Name: "TestStruct", + ast.AddressLocation{ + Address: common.BytesToAddress([]byte{0x1}), + Name: "TestStruct", }, - "AC.0x1.TestStruct", + "A.0x1.TestStruct", common.CompositeKindStructure, map[string]Value{}, nil, @@ -567,7 +575,7 @@ func TestEncodeDecodeComposite(t *testing.T) { // key 0 0x0, // tag - 0xd8, cborTagAddressContractLocation, + 0xd8, cborTagAddressLocation, // map, 4 pairs of items follow 0xa2, // key 0 @@ -585,8 +593,8 @@ func TestEncodeDecodeComposite(t *testing.T) { // key 1 0x1, // UTF-8 string, length 17 - 0x71, - 0x41, 0x43, 0x2e, 0x30, 0x78, 0x31, 0x2e, 0x54, + 0x70, + 0x41, 0x2e, 0x30, 0x78, 0x31, 0x2e, 0x54, 0x65, 0x73, 0x74, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, // key 2 0x2, @@ -601,7 +609,7 @@ func TestEncodeDecodeComposite(t *testing.T) { ) }) - t.Run("empty, address contract location, address too long", func(t *testing.T) { + t.Run("empty, address location, address too long", func(t *testing.T) { testEncodeDecode(t, encodeDecodeTest{ encoded: []byte{ @@ -612,7 +620,7 @@ func TestEncodeDecodeComposite(t *testing.T) { // key 0 0x0, // tag - 0xd8, cborTagAddressContractLocation, + 0xd8, cborTagAddressLocation, // map, 4 pairs of items follow 0xa2, // key 0 @@ -730,7 +738,7 @@ func TestEncodeDecodeIntValue(t *testing.T) { // byte string, length 1 0x41, // `-42` in decimal is is `0x2a` in hex. - // CBOR requires negative values to be encoded as `-1-n`, which is `-n - 1`, + // CBOR requires negative values to be encoded as `-1-n`, which is `-n - 1`, // which is `0x2a - 0x01`, which equals to `0x29`. 0x29, }, @@ -3278,7 +3286,8 @@ func TestEncodeDecodeLinkValue(t *testing.T) { TargetPath: publicPathValue, Type: ConvertSemaToPrimitiveStaticType(&sema.BoolType{}), }, - encoded: append(expectedLinkEncodingPrefix[:], + encoded: append( + expectedLinkEncodingPrefix[:], // tag 0xd8, cborTagPrimitiveStaticType, 0x6, @@ -3296,7 +3305,8 @@ func TestEncodeDecodeLinkValue(t *testing.T) { Type: PrimitiveStaticTypeBool, }, }, - encoded: append(expectedLinkEncodingPrefix[:], + encoded: append( + expectedLinkEncodingPrefix[:], // tag 0xd8, cborTagOptionalStaticType, // tag @@ -3317,7 +3327,8 @@ func TestEncodeDecodeLinkValue(t *testing.T) { Location: utils.TestLocation, }, }, - encoded: append(expectedLinkEncodingPrefix[:], + encoded: append( + expectedLinkEncodingPrefix[:], // tag 0xd8, cborTagCompositeStaticType, // map, 2 pairs of items follow @@ -3343,6 +3354,47 @@ func TestEncodeDecodeLinkValue(t *testing.T) { ) }) + t.Run("composite, struct, address location without name", func(t *testing.T) { + testEncodeDecode(t, + encodeDecodeTest{ + decodeOnly: true, + decodedValue: LinkValue{ + TargetPath: publicPathValue, + Type: CompositeStaticType{ + TypeID: "A.0x1.SimpleStruct", + Location: ast.AddressLocation{ + Address: common.BytesToAddress([]byte{0x1}), + Name: "SimpleStruct", + }, + }, + }, + encoded: append( + expectedLinkEncodingPrefix[:], + // tag + 0xd8, cborTagCompositeStaticType, + // map, 2 pairs of items follow + 0xa2, + // key 0 + 0x0, + // tag + 0xd8, cborTagAddressLocation, + // byte sequence, length 1 + 0x41, + // positive integer 1 + 0x1, + // key 1 + 0x1, + // UTF-8 string, length 18 + 0x72, + // A.0x1.SimpleStruct + 0x41, + 0x2E, 0x30, 0x78, 0x31, + 0x2E, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x53, 0x74, 0x72, 0x75, 0x63, 0x74, + ), + }, + ) + }) + t.Run("interface, struct", func(t *testing.T) { testEncodeDecode(t, encodeDecodeTest{ @@ -3353,7 +3405,8 @@ func TestEncodeDecodeLinkValue(t *testing.T) { Location: utils.TestLocation, }, }, - encoded: append(expectedLinkEncodingPrefix[:], + encoded: append( + expectedLinkEncodingPrefix[:], // tag 0xd8, cborTagInterfaceStaticType, // map, 2 pairs of items follow @@ -3379,6 +3432,47 @@ func TestEncodeDecodeLinkValue(t *testing.T) { ) }) + t.Run("interface, struct, address location without name", func(t *testing.T) { + testEncodeDecode(t, + encodeDecodeTest{ + decodeOnly: true, + decodedValue: LinkValue{ + TargetPath: publicPathValue, + Type: InterfaceStaticType{ + TypeID: "A.0x1.SimpleInterface", + Location: ast.AddressLocation{ + Address: common.BytesToAddress([]byte{0x1}), + Name: "SimpleInterface", + }, + }, + }, + encoded: append( + expectedLinkEncodingPrefix[:], + // tag + 0xd8, cborTagInterfaceStaticType, + // map, 2 pairs of items follow + 0xa2, + // key 0 + 0x0, + // tag + 0xd8, cborTagAddressLocation, + // byte sequence, length 1 + 0x41, + // positive integer 1 + 0x1, + // key 1 + 0x1, + // UTF-8 string, length 21 + 0x75, + // A.0x1.SimpleInterface + 0x41, + 0x2E, 0x30, 0x78, 0x31, + 0x2E, 0x53, 0x69, 0x6d, 0x70, 0x6c, 0x65, 0x49, 0x6e, 0x74, 0x65, 0x72, 0x66, 0x61, 0x63, 0x65, + ), + }, + ) + }) + t.Run("variable-sized, bool", func(t *testing.T) { testEncodeDecode(t, encodeDecodeTest{ @@ -3388,7 +3482,8 @@ func TestEncodeDecodeLinkValue(t *testing.T) { Type: PrimitiveStaticTypeBool, }, }, - encoded: append(expectedLinkEncodingPrefix[:], + encoded: append( + expectedLinkEncodingPrefix[:], // tag 0xd8, cborTagVariableSizedStaticType, // tag @@ -3409,7 +3504,8 @@ func TestEncodeDecodeLinkValue(t *testing.T) { Size: 42, }, }, - encoded: append(expectedLinkEncodingPrefix[:], + encoded: append( + expectedLinkEncodingPrefix[:], // tag 0xd8, cborTagConstantSizedStaticType, // map, 2 pairs of items follow @@ -3438,7 +3534,8 @@ func TestEncodeDecodeLinkValue(t *testing.T) { Type: PrimitiveStaticTypeBool, }, }, - encoded: append(expectedLinkEncodingPrefix[:], + encoded: append( + expectedLinkEncodingPrefix[:], // tag 0xd8, cborTagReferenceStaticType, // map, 2 pairs of items follow @@ -3467,7 +3564,8 @@ func TestEncodeDecodeLinkValue(t *testing.T) { Type: PrimitiveStaticTypeBool, }, }, - encoded: append(expectedLinkEncodingPrefix[:], + encoded: append( + expectedLinkEncodingPrefix[:], // tag 0xd8, cborTagReferenceStaticType, // map, 2 pairs of items follow @@ -3496,7 +3594,8 @@ func TestEncodeDecodeLinkValue(t *testing.T) { ValueType: PrimitiveStaticTypeString, }, }, - encoded: append(expectedLinkEncodingPrefix[:], + encoded: append( + expectedLinkEncodingPrefix[:], // tag 0xd8, cborTagDictionaryStaticType, // map, 2 pairs of items follow @@ -3538,7 +3637,8 @@ func TestEncodeDecodeLinkValue(t *testing.T) { }, }, }, - encoded: append(expectedLinkEncodingPrefix[:], + encoded: append( + expectedLinkEncodingPrefix[:], // tag 0xd8, cborTagRestrictedStaticType, // map, 2 pairs of items follow @@ -3615,7 +3715,8 @@ func TestEncodeDecodeLinkValue(t *testing.T) { TargetPath: publicPathValue, Type: CapabilityStaticType{}, }, - encoded: append(expectedLinkEncodingPrefix[:], + encoded: append( + expectedLinkEncodingPrefix[:], // tag 0xd8, cborTagCapabilityStaticType, // null @@ -3634,7 +3735,8 @@ func TestEncodeDecodeLinkValue(t *testing.T) { BorrowType: PrimitiveStaticTypeBool, }, }, - encoded: append(expectedLinkEncodingPrefix[:], + encoded: append( + expectedLinkEncodingPrefix[:], // tag 0xd8, cborTagCapabilityStaticType, // tag diff --git a/runtime/locations.go b/runtime/locations.go index 4569ca0cd0..d79e794a03 100644 --- a/runtime/locations.go +++ b/runtime/locations.go @@ -20,26 +20,26 @@ package runtime import ( "encoding/hex" + "strings" "github.com/onflow/cadence/runtime/ast" ) type ( - Location = ast.Location - LocationID = ast.LocationID - StringLocation = ast.StringLocation - AddressLocation = ast.AddressLocation - AddressContractLocation = ast.AddressContractLocation - Identifier = ast.Identifier + Location = ast.Location + LocationID = ast.LocationID + TypeID = ast.TypeID + StringLocation = ast.StringLocation + AddressLocation = ast.AddressLocation + Identifier = ast.Identifier ) const ( - IdentifierLocationPrefix = ast.IdentifierLocationPrefix - StringLocationPrefix = ast.StringLocationPrefix - AddressLocationPrefix = ast.AddressLocationPrefix - AddressContractLocationPrefix = ast.AddressContractLocationPrefix - TransactionLocationPrefix = "t" - ScriptLocationPrefix = "s" + IdentifierLocationPrefix = ast.IdentifierLocationPrefix + StringLocationPrefix = ast.StringLocationPrefix + AddressLocationPrefix = ast.AddressLocationPrefix + TransactionLocationPrefix = "t" + ScriptLocationPrefix = "s" ) // TransactionLocation @@ -47,7 +47,28 @@ const ( type TransactionLocation []byte func (l TransactionLocation) ID() ast.LocationID { - return ast.NewLocationID(TransactionLocationPrefix, l.String()) + return ast.NewLocationID( + TransactionLocationPrefix, + l.String(), + ) +} + +func (l TransactionLocation) TypeID(qualifiedIdentifier string) TypeID { + return ast.NewTypeID( + TransactionLocationPrefix, + l.String(), + qualifiedIdentifier, + ) +} + +func (l TransactionLocation) QualifiedIdentifier(typeID TypeID) string { + pieces := strings.SplitN(string(typeID), ".", 3) + + if len(pieces) < 3 { + return "" + } + + return pieces[2] } func (l TransactionLocation) String() string { @@ -59,7 +80,28 @@ func (l TransactionLocation) String() string { type ScriptLocation []byte func (l ScriptLocation) ID() ast.LocationID { - return ast.NewLocationID(ScriptLocationPrefix, l.String()) + return ast.NewLocationID( + ScriptLocationPrefix, + l.String(), + ) +} + +func (l ScriptLocation) TypeID(qualifiedIdentifier string) TypeID { + return ast.NewTypeID( + ScriptLocationPrefix, + l.String(), + qualifiedIdentifier, + ) +} + +func (l ScriptLocation) QualifiedIdentifier(typeID TypeID) string { + pieces := strings.SplitN(string(typeID), ".", 3) + + if len(pieces) < 3 { + return "" + } + + return pieces[2] } func (l ScriptLocation) String() string { @@ -74,6 +116,23 @@ func (l FileLocation) ID() ast.LocationID { return LocationID(l.String()) } +func (l FileLocation) TypeID(qualifiedIdentifier string) TypeID { + return ast.NewTypeID( + l.String(), + qualifiedIdentifier, + ) +} + +func (l FileLocation) QualifiedIdentifier(typeID TypeID) string { + pieces := strings.SplitN(string(typeID), ".", 2) + + if len(pieces) < 2 { + return "" + } + + return pieces[1] +} + func (l FileLocation) String() string { return string(l) } @@ -86,6 +145,23 @@ func (l REPLLocation) ID() LocationID { return LocationID(l.String()) } +func (l REPLLocation) TypeID(qualifiedIdentifier string) TypeID { + return ast.NewTypeID( + l.String(), + qualifiedIdentifier, + ) +} + +func (l REPLLocation) QualifiedIdentifier(typeID TypeID) string { + pieces := strings.SplitN(string(typeID), ".", 2) + + if len(pieces) < 2 { + return "" + } + + return pieces[1] +} + func (l REPLLocation) String() string { return "REPL" } diff --git a/runtime/parser2/declaration.go b/runtime/parser2/declaration.go index c95428515d..7fcb2d7935 100644 --- a/runtime/parser2/declaration.go +++ b/runtime/parser2/declaration.go @@ -578,7 +578,9 @@ func parseHexadecimalLocation(literal string) ast.AddressLocation { panic(err) } - return address + return ast.AddressLocation{ + Address: common.BytesToAddress(address), + } } // parseEventDeclaration parses an event declaration. diff --git a/runtime/parser2/declaration_test.go b/runtime/parser2/declaration_test.go index 6cef5d919a..c2a908ac2e 100644 --- a/runtime/parser2/declaration_test.go +++ b/runtime/parser2/declaration_test.go @@ -1225,7 +1225,9 @@ func TestParseImportDeclaration(t *testing.T) { []ast.Declaration{ &ast.ImportDeclaration{ Identifiers: nil, - Location: ast.AddressLocation{0x42}, + Location: ast.AddressLocation{ + Address: common.BytesToAddress([]byte{0x42}), + }, LocationPos: ast.Position{Line: 1, Column: 8, Offset: 8}, Range: ast.Range{ StartPos: ast.Position{Line: 1, Column: 1, Offset: 1}, @@ -1338,7 +1340,9 @@ func TestParseImportDeclaration(t *testing.T) { Pos: ast.Position{Line: 1, Column: 20, Offset: 20}, }, }, - Location: ast.AddressLocation{0x42}, + Location: ast.AddressLocation{ + Address: common.BytesToAddress([]byte{0x42}), + }, LocationPos: ast.Position{Line: 1, Column: 29, Offset: 29}, Range: ast.Range{ StartPos: ast.Position{Line: 1, Column: 1, Offset: 1}, @@ -2198,4 +2202,5 @@ func TestParseTransactionDeclaration(t *testing.T) { result, ) }) + } diff --git a/runtime/runtime.go b/runtime/runtime.go index e361c03897..ca88d6bec8 100644 --- a/runtime/runtime.go +++ b/runtime/runtime.go @@ -82,7 +82,7 @@ func validTopLevelDeclarations(location ast.Location) []common.DeclarationKind { switch location.(type) { case TransactionLocation: return validTopLevelDeclarationsInTransaction - case AddressLocation, AddressContractLocation: + case AddressLocation: return validTopLevelDeclarationsInAccountCode } @@ -107,8 +107,6 @@ func reportMetric( report(metrics, elapsed) } -const contractKey = "contract" - // interpreterRuntime is a interpreter-based version of the Flow runtime. type interpreterRuntime struct{} @@ -729,9 +727,7 @@ func (r *interpreterRuntime) injectedCompositeFieldsHandler( switch location := location.(type) { case AddressLocation: - address = location.ToAddress() - case AddressContractLocation: - address = location.AddressLocation.ToAddress() + address = location.Address default: panic(runtimeErrors.NewUnreachableError()) } @@ -845,11 +841,11 @@ func (r *interpreterRuntime) importResolver(runtimeInterface Interface) ImportRe } var code []byte - if addressContractLocation, ok := location.(AddressContractLocation); ok { + if addressLocation, ok := location.(AddressLocation); ok { wrapPanic(func() { code, err = runtimeInterface.GetAccountContractCode( - addressContractLocation.AddressLocation.ToAddress(), - addressContractLocation.Name, + addressLocation.Address, + addressLocation.Name, ) }) } else { @@ -1074,7 +1070,6 @@ func (r *interpreterRuntime) writeContract( name string, contractValue interpreter.OptionalValue, ) { - runtimeStorage.writeValue( addressValue.ToAddress(), formatContractKey(name), @@ -1083,12 +1078,9 @@ func (r *interpreterRuntime) writeContract( } func formatContractKey(name string) string { - if name == "" { - return contractKey - } + const contractKey = "contract" // \x1F = Information Separator One - return fmt.Sprintf("%s\x1F%s", contractKey, name) } @@ -1120,18 +1112,10 @@ func (r *interpreterRuntime) loadContract( var storedValue interpreter.OptionalValue = interpreter.NilValue{} switch location := compositeType.Location.(type) { - case AddressLocation: - address := location.ToAddress() - storedValue = runtimeStorage.readValue( - address, - contractKey, - false, - ) - case AddressContractLocation: - address := location.AddressLocation.ToAddress() + case AddressLocation: storedValue = runtimeStorage.readValue( - address, + location.Address, formatContractKey(location.Name), false, ) @@ -1421,9 +1405,9 @@ func (r *interpreterRuntime) newAuthAccountContractsChangeFunction( // Check the code - location := AddressContractLocation{ - AddressLocation: addressValue[:], - Name: nameArgument, + location := AddressLocation{ + Address: address, + Name: nameArgument, } // NOTE: do NOT use the cache! @@ -1550,7 +1534,7 @@ func (r *interpreterRuntime) updateAccountContractCode( name string, code []byte, addressValue interpreter.AddressValue, - location AddressContractLocation, + location AddressLocation, checker *sema.Checker, contractType *sema.CompositeType, constructorArguments []interpreter.Value, diff --git a/runtime/runtime_test.go b/runtime/runtime_test.go index e2a963e27c..776b7a52ec 100644 --- a/runtime/runtime_test.go +++ b/runtime/runtime_test.go @@ -2860,12 +2860,20 @@ func TestRuntimeFungibleTokenUpdateAccountCode(t *testing.T) { return []Address{signerAccount} }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, _ string) (code []byte, err error) { - key := string(AddressLocation(address[:]).ID()) + getAccountContractCode: func(address Address, name string) (code []byte, err error) { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) return accountCodes[key], nil }, updateAccountContractCode: func(address Address, name string, code []byte) (err error) { - key := string(AddressLocation(address[:]).ID()) + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) accountCodes[key] = code return nil }, @@ -2975,12 +2983,20 @@ func TestRuntimeFungibleTokenCreateAccount(t *testing.T) { return []Address{signerAccount} }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, _ string) (code []byte, err error) { - key := string(AddressLocation(address[:]).ID()) + getAccountContractCode: func(address Address, name string) (code []byte, err error) { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) return accountCodes[key], nil }, - updateAccountContractCode: func(address Address, _ string, code []byte) (err error) { - key := string(AddressLocation(address[:]).ID()) + updateAccountContractCode: func(address Address, name string, code []byte) (err error) { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) accountCodes[key] = code return nil }, @@ -3108,12 +3124,20 @@ func TestRuntimeInvokeStoredInterfaceFunction(t *testing.T) { return []Address{{0x1}} }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, _ string) (code []byte, err error) { - key := string(AddressLocation(address[:]).ID()) + getAccountContractCode: func(address Address, name string) (code []byte, err error) { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) return accountCodes[key], nil }, - updateAccountContractCode: func(address Address, _ string, code []byte) error { - key := string(AddressLocation(address[:]).ID()) + updateAccountContractCode: func(address Address, name string, code []byte) error { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) accountCodes[key] = code return nil }, @@ -3478,12 +3502,20 @@ func TestInterpretResourceOwnerFieldUseComposite(t *testing.T) { return []Address{address} }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, _ string) (code []byte, err error) { - key := string(AddressLocation(address[:]).ID()) + getAccountContractCode: func(address Address, name string) (code []byte, err error) { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) return accountCodes[key], nil }, - updateAccountContractCode: func(address Address, _ string, code []byte) error { - key := string(AddressLocation(address[:]).ID()) + updateAccountContractCode: func(address Address, name string, code []byte) error { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) accountCodes[key] = code return nil }, @@ -3624,13 +3656,21 @@ func TestInterpretResourceOwnerFieldUseArray(t *testing.T) { getSigningAccounts: func() []Address { return []Address{address} }, - getAccountContractCode: func(_ Address, _ string) (code []byte, err error) { - key := string(AddressLocation(address[:]).ID()) + getAccountContractCode: func(address Address, name string) (code []byte, err error) { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) return accountCodes[key], nil }, resolveLocation: singleIdentifierLocationResolver(t), - updateAccountContractCode: func(address Address, _ string, code []byte) error { - key := string(AddressLocation(address[:]).ID()) + updateAccountContractCode: func(address Address, name string, code []byte) error { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) accountCodes[key] = code return nil }, @@ -3777,12 +3817,20 @@ func TestInterpretResourceOwnerFieldUseDictionary(t *testing.T) { return []Address{address} }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, _ string) (code []byte, err error) { - key := string(AddressLocation(address[:]).ID()) + getAccountContractCode: func(address Address, name string) (code []byte, err error) { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) return accountCodes[key], nil }, updateAccountContractCode: func(address Address, name string, code []byte) error { - key := string(AddressLocation(address[:]).ID()) + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) accountCodes[key] = code return nil }, @@ -4431,12 +4479,20 @@ func TestRuntimeDeployCodeCaching(t *testing.T) { return signerAddresses }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, _ string) (code []byte, err error) { - key := string(AddressLocation(address[:]).ID()) + getAccountContractCode: func(address Address, name string) (code []byte, err error) { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) return accountCodes[key], nil }, - updateAccountContractCode: func(address Address, _ string, code []byte) error { - key := string(AddressLocation(address[:]).ID()) + updateAccountContractCode: func(address Address, name string, code []byte) error { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) accountCodes[key] = code return nil }, @@ -4545,12 +4601,20 @@ func TestRuntimeUpdateCodeCaching(t *testing.T) { return signerAddresses }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, _ string) (code []byte, err error) { - key := string(AddressLocation(address[:]).ID()) + getAccountContractCode: func(address Address, name string) (code []byte, err error) { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) return accountCodes[key], nil }, - updateAccountContractCode: func(address Address, _ string, code []byte) error { - key := string(AddressLocation(address[:]).ID()) + updateAccountContractCode: func(address Address, name string, code []byte) error { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) accountCodes[key] = code return nil }, @@ -4678,12 +4742,20 @@ func TestRuntimeNoCacheHitForToplevelPrograms(t *testing.T) { return signerAddresses }, resolveLocation: singleIdentifierLocationResolver(t), - getAccountContractCode: func(address Address, _ string) (code []byte, err error) { - key := string(AddressLocation(address[:]).ID()) + getAccountContractCode: func(address Address, name string) (code []byte, err error) { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) return accountCodes[key], nil }, - updateAccountContractCode: func(address Address, _ string, code []byte) error { - key := string(AddressLocation(address[:]).ID()) + updateAccountContractCode: func(address Address, name string, code []byte) error { + location := AddressLocation{ + Address: address, + Name: name, + } + key := string(location.ID()) accountCodes[key] = code return nil }, @@ -4720,7 +4792,7 @@ func TestRuntimeNoCacheHitForToplevelPrograms(t *testing.T) { require.Equal(t, []string{ - "AC.0100000000000000.HelloWorld", + "A.0100000000000000.HelloWorld", }, cacheHits, ) @@ -4823,9 +4895,9 @@ func TestRuntimeTransaction_ContractUpdate(t *testing.T) { return []ResolvedLocation{ { - Location: AddressContractLocation{ - AddressLocation: location.(AddressLocation), - Name: "Test", + Location: AddressLocation{ + Address: location.(AddressLocation).Address, + Name: "Test", }, Identifiers: []ast.Identifier{ { @@ -4971,9 +5043,9 @@ func singleIdentifierLocationResolver(t *testing.T) func(identifiers []Identifie return []ResolvedLocation{ { - Location: AddressContractLocation{ - AddressLocation: location.(AddressLocation), - Name: identifiers[0].Identifier, + Location: AddressLocation{ + Address: location.(AddressLocation).Address, + Name: identifiers[0].Identifier, }, Identifiers: identifiers, }, diff --git a/runtime/sema/check_import_declaration.go b/runtime/sema/check_import_declaration.go index 1f2b872489..f1f9934ef4 100644 --- a/runtime/sema/check_import_declaration.go +++ b/runtime/sema/check_import_declaration.go @@ -28,12 +28,12 @@ import ( // 1. Resolution of the import statement. // // The default case is that one location is resolved to one location (itself), -// though e.g. an address location may also be resolved into multiple "address contract" locations. +// though e.g. an address location may also be resolved into multiple address locations. // // For example, an import declaration `import a, b from 0x1` specifies the import of the declarations with // the identifiers `a` and `b` from the address location `0x1`. // This import declaration might be resolved into just the location itself, i.e. the address location `0x1`, -// but could also be resolved into multiple locations, e.g. the address contract locations `0x1.a` and `0x1.b`. +// but could also be resolved into multiple locations, e.g. the address locations `0x1.a` and `0x1.b`. // // 2. Acquiring the programs for the resolved imports. For each resolved import a separate program can be returned. // diff --git a/runtime/sema/errors.go b/runtime/sema/errors.go index cd54d47bc2..842eadc97d 100644 --- a/runtime/sema/errors.go +++ b/runtime/sema/errors.go @@ -615,7 +615,7 @@ type InvalidVariableKindError struct { func (e *InvalidVariableKindError) Error() string { if e.Kind == ast.VariableKindNotSpecified { - return fmt.Sprintf("missing variable kind") + return "missing variable kind" } return fmt.Sprintf("invalid variable kind: `%s`", e.Kind.Name()) } diff --git a/runtime/sema/type.go b/runtime/sema/type.go index 8866fdd1f1..948ffde14c 100644 --- a/runtime/sema/type.go +++ b/runtime/sema/type.go @@ -63,7 +63,7 @@ func qualifiedIdentifier(identifier string, containerType Type) string { return sb.String() } -type TypeID string +type TypeID = ast.TypeID type Type interface { IsType() @@ -4809,7 +4809,7 @@ func (t *CompositeType) QualifiedIdentifier() string { } func (t *CompositeType) ID() TypeID { - return TypeID(fmt.Sprintf("%s.%s", t.Location.ID(), t.QualifiedIdentifier())) + return t.Location.TypeID(t.QualifiedIdentifier()) } func (t *CompositeType) Equal(other Type) bool { @@ -5711,7 +5711,7 @@ func (t *InterfaceType) QualifiedIdentifier() string { } func (t *InterfaceType) ID() TypeID { - return TypeID(fmt.Sprintf("%s.%s", t.Location.ID(), t.QualifiedIdentifier())) + return t.Location.TypeID(t.QualifiedIdentifier()) } func (t *InterfaceType) Equal(other Type) bool { diff --git a/runtime/stdlib/flow.go b/runtime/stdlib/flow.go index dc05de10f0..5482c915f5 100644 --- a/runtime/stdlib/flow.go +++ b/runtime/stdlib/flow.go @@ -21,6 +21,7 @@ package stdlib import ( "fmt" "math/rand" + "strings" "github.com/onflow/cadence/runtime/ast" "github.com/onflow/cadence/runtime/common" @@ -183,6 +184,23 @@ func (l FlowLocation) ID() ast.LocationID { return ast.NewLocationID(flowLocationID) } +func (l FlowLocation) TypeID(qualifiedIdentifier string) ast.TypeID { + return ast.NewTypeID( + flowLocationID, + qualifiedIdentifier, + ) +} + +func (l FlowLocation) QualifiedIdentifier(typeID ast.TypeID) string { + pieces := strings.SplitN(string(typeID), ".", 2) + + if len(pieces) < 2 { + return "" + } + + return pieces[1] +} + // built-in event types func newFlowEventType(identifier string, parameters ...*sema.Parameter) *sema.CompositeType { diff --git a/runtime/storage_test.go b/runtime/storage_test.go index 172b582232..f3b5ba881b 100644 --- a/runtime/storage_test.go +++ b/runtime/storage_test.go @@ -136,7 +136,7 @@ func TestRuntimeHighLevelStorage(t *testing.T) { assert.NotNil(t, accountCode) rType := &cadence.ResourceType{ - TypeID: "AC.000000000000cade.Test.Test.R", + TypeID: "A.000000000000cade.Test.R", Identifier: "R", Fields: []cadence.Field{ { @@ -156,7 +156,7 @@ func TestRuntimeHighLevelStorage(t *testing.T) { address, "contract\x1fTest", cadence.NewContract([]cadence.Value{}).WithType(&cadence.ContractType{ - TypeID: "AC.000000000000cade.Test.Test", + TypeID: "A.000000000000cade.Test", Identifier: "Test", Fields: []cadence.Field{}, Initializers: nil, diff --git a/runtime/tests/checker/import_test.go b/runtime/tests/checker/import_test.go index ef3737c803..f0ca09ee8a 100644 --- a/runtime/tests/checker/import_test.go +++ b/runtime/tests/checker/import_test.go @@ -87,7 +87,7 @@ func TestCheckRepeatedImportResolution(t *testing.T) { t.Parallel() - importedAddressLocation := ast.AddressLocation{0x1} + importedAddress := common.BytesToAddress([]byte{0x1}) importedCheckerX, err := ParseAndCheckWithOptions(t, ` @@ -98,9 +98,9 @@ func TestCheckRepeatedImportResolution(t *testing.T) { pub let x = test() `, ParseAndCheckOptions{ - Location: ast.AddressContractLocation{ - AddressLocation: importedAddressLocation, - Name: "x", + Location: ast.AddressLocation{ + Address: importedAddress, + Name: "x", }, }, ) @@ -115,9 +115,9 @@ func TestCheckRepeatedImportResolution(t *testing.T) { pub let y = test() `, ParseAndCheckOptions{ - Location: ast.AddressContractLocation{ - AddressLocation: importedAddressLocation, - Name: "y", + Location: ast.AddressLocation{ + Address: importedAddress, + Name: "y", }, }, ) @@ -134,9 +134,9 @@ func TestCheckRepeatedImportResolution(t *testing.T) { func(identifiers []ast.Identifier, location ast.Location) (result []sema.ResolvedLocation) { for _, identifier := range identifiers { result = append(result, sema.ResolvedLocation{ - Location: ast.AddressContractLocation{ - AddressLocation: importedAddressLocation, - Name: identifier.Identifier, + Location: ast.AddressLocation{ + Address: importedAddress, + Name: identifier.Identifier, }, Identifiers: []ast.Identifier{ identifier, @@ -148,9 +148,9 @@ func TestCheckRepeatedImportResolution(t *testing.T) { ), sema.WithImportHandler( func(checker *sema.Checker, location ast.Location) (sema.Import, *sema.CheckerError) { - addressContractLocation := location.(ast.AddressContractLocation) + addressLocation := location.(ast.AddressLocation) var importedChecker *sema.Checker - switch addressContractLocation.Name { + switch addressLocation.Name { case "x": importedChecker = importedCheckerX case "y": @@ -210,7 +210,7 @@ func TestCheckImportResolutionSplit(t *testing.T) { t.Parallel() - importedAddressLocation := ast.AddressLocation{0x1} + importedAddress := common.BytesToAddress([]byte{0x1}) importedCheckerX, err := ParseAndCheckWithOptions(t, ` @@ -221,9 +221,9 @@ func TestCheckImportResolutionSplit(t *testing.T) { pub let x = test() `, ParseAndCheckOptions{ - Location: ast.AddressContractLocation{ - AddressLocation: importedAddressLocation, - Name: "x", + Location: ast.AddressLocation{ + Address: importedAddress, + Name: "x", }, }, ) @@ -238,9 +238,9 @@ func TestCheckImportResolutionSplit(t *testing.T) { pub let y = test() `, ParseAndCheckOptions{ - Location: ast.AddressContractLocation{ - AddressLocation: importedAddressLocation, - Name: "y", + Location: ast.AddressLocation{ + Address: importedAddress, + Name: "y", }, }, ) @@ -256,9 +256,9 @@ func TestCheckImportResolutionSplit(t *testing.T) { func(identifiers []ast.Identifier, location ast.Location) (result []sema.ResolvedLocation) { for _, identifier := range identifiers { result = append(result, sema.ResolvedLocation{ - Location: ast.AddressContractLocation{ - AddressLocation: importedAddressLocation, - Name: identifier.Identifier, + Location: ast.AddressLocation{ + Address: importedAddress, + Name: identifier.Identifier, }, Identifiers: []ast.Identifier{ identifier, @@ -270,9 +270,9 @@ func TestCheckImportResolutionSplit(t *testing.T) { ), sema.WithImportHandler( func(checker *sema.Checker, location ast.Location) (sema.Import, *sema.CheckerError) { - addressContractLocation := location.(ast.AddressContractLocation) + addressLocation := location.(ast.AddressLocation) var importedChecker *sema.Checker - switch addressContractLocation.Name { + switch addressLocation.Name { case "x": importedChecker = importedCheckerX case "y": diff --git a/runtime/tests/interpreter/import_test.go b/runtime/tests/interpreter/import_test.go index fa6b3fe2a2..167f8de3b8 100644 --- a/runtime/tests/interpreter/import_test.go +++ b/runtime/tests/interpreter/import_test.go @@ -121,15 +121,14 @@ func TestInterpretVirtualImport(t *testing.T) { // TestInterpretImportMultipleProgramsFromLocation demonstrates how two declarations (`a` and `b`) // can be imported from the same location (address location `0x1`). -// The single location (address location `0x1`) is resolved to two locations -// (address contract locations `0x1.a` and `0x1.b`). +// The single location (address location `0x1`) is resolved to two locations (address locations `0x1.a` and `0x1.b`). // Each requested declaration is so imported from a a separate program. // func TestInterpretImportMultipleProgramsFromLocation(t *testing.T) { t.Parallel() - addressLocation := ast.AddressLocation{0x1} + address := common.BytesToAddress([]byte{0x1}) importedCheckerA, err := checker.ParseAndCheckWithOptions(t, ` @@ -144,9 +143,9 @@ func TestInterpretImportMultipleProgramsFromLocation(t *testing.T) { } `, checker.ParseAndCheckOptions{ - Location: ast.AddressContractLocation{ - AddressLocation: addressLocation, - Name: "a", + Location: ast.AddressLocation{ + Address: address, + Name: "a", }, }, ) @@ -165,9 +164,9 @@ func TestInterpretImportMultipleProgramsFromLocation(t *testing.T) { } `, checker.ParseAndCheckOptions{ - Location: ast.AddressContractLocation{ - AddressLocation: addressLocation, - Name: "b", + Location: ast.AddressLocation{ + Address: address, + Name: "b", }, }, ) @@ -185,16 +184,20 @@ func TestInterpretImportMultipleProgramsFromLocation(t *testing.T) { Options: []sema.Option{ sema.WithLocationHandler( func(identifiers []ast.Identifier, location ast.Location) (result []sema.ResolvedLocation) { + require.Equal(t, - addressLocation, + ast.AddressLocation{ + Address: address, + Name: "", + }, location, ) for _, identifier := range identifiers { result = append(result, sema.ResolvedLocation{ - Location: ast.AddressContractLocation{ - AddressLocation: location.(ast.AddressLocation), - Name: identifier.Identifier, + Location: ast.AddressLocation{ + Address: location.(ast.AddressLocation).Address, + Name: identifier.Identifier, }, Identifiers: []ast.Identifier{ identifier, @@ -206,14 +209,14 @@ func TestInterpretImportMultipleProgramsFromLocation(t *testing.T) { ), sema.WithImportHandler( func(checker *sema.Checker, location ast.Location) (sema.Import, *sema.CheckerError) { - require.IsType(t, ast.AddressContractLocation{}, location) - addressContractLocation := location.(ast.AddressContractLocation) + require.IsType(t, ast.AddressLocation{}, location) + addressLocation := location.(ast.AddressLocation) - assert.Equal(t, addressLocation, addressContractLocation.AddressLocation) + assert.Equal(t, address, addressLocation.Address) var importedChecker *sema.Checker - switch addressContractLocation.Name { + switch addressLocation.Name { case "a": importedChecker = importedCheckerA case "b": @@ -234,14 +237,14 @@ func TestInterpretImportMultipleProgramsFromLocation(t *testing.T) { importingChecker, interpreter.WithImportLocationHandler( func(inter *interpreter.Interpreter, location ast.Location) interpreter.Import { - require.IsType(t, ast.AddressContractLocation{}, location) - addressContractLocation := location.(ast.AddressContractLocation) + require.IsType(t, ast.AddressLocation{}, location) + addressLocation := location.(ast.AddressLocation) - assert.Equal(t, addressLocation, addressContractLocation.AddressLocation) + assert.Equal(t, address, addressLocation.Address) var importedChecker *sema.Checker - switch addressContractLocation.Name { + switch addressLocation.Name { case "a": importedChecker = importedCheckerA case "b": diff --git a/runtime/tests/parser/parser_test.go b/runtime/tests/parser/parser_test.go index 743fce8d30..863228d1ee 100644 --- a/runtime/tests/parser/parser_test.go +++ b/runtime/tests/parser/parser_test.go @@ -4383,7 +4383,9 @@ func TestParseImportWithAddress(t *testing.T) { []Declaration{ &ImportDeclaration{ Identifiers: nil, - Location: AddressLocation{18, 52}, + Location: AddressLocation{ + Address: common.BytesToAddress([]byte{18, 52}), + }, Range: Range{ StartPos: Position{Offset: 9, Line: 2, Column: 8}, EndPos: Position{Offset: 21, Line: 2, Column: 20}, @@ -4418,7 +4420,9 @@ func TestParseImportWithIdentifiers(t *testing.T) { Pos: Position{Offset: 19, Line: 2, Column: 18}, }, }, - Location: AddressLocation{0}, + Location: AddressLocation{ + Address: common.BytesToAddress([]byte{0}), + }, Range: Range{ StartPos: Position{Offset: 9, Line: 2, Column: 8}, EndPos: Position{Offset: 28, Line: 2, Column: 27}, @@ -4515,7 +4519,9 @@ func TestParseImportWithFromIdentifier(t *testing.T) { Pos: Position{Offset: 16, Line: 2, Column: 15}, }, }, - Location: AddressLocation{0}, + Location: AddressLocation{ + Address: common.BytesToAddress([]byte{0}), + }, Range: Range{ StartPos: Position{Offset: 9, Line: 2, Column: 8}, EndPos: Position{Offset: 28, Line: 2, Column: 27},