From 2dbecfb8da786a8dfca2d9169772abf1cb35d027 Mon Sep 17 00:00:00 2001 From: Supun Setunga Date: Fri, 16 Aug 2024 10:51:59 -0700 Subject: [PATCH] Add support for exporting unmigrated path capabilities --- encoding/json/encode.go | 25 ++++++++------ encoding/json/encoding_test.go | 59 +++++++++++++++++++++++++++------- runtime/convertValues.go | 25 ++++++++++++++ runtime/convertValues_test.go | 16 +++++++++ 4 files changed, 105 insertions(+), 20 deletions(-) diff --git a/encoding/json/encode.go b/encoding/json/encode.go index f3512868c2..5edfeab676 100644 --- a/encoding/json/encode.go +++ b/encoding/json/encode.go @@ -214,9 +214,10 @@ type jsonTypeValue struct { } type jsonCapabilityValue struct { - BorrowType jsonValue `json:"borrowType"` - Address string `json:"address"` - ID string `json:"id"` + BorrowType jsonValue `json:"borrowType"` + Address string `json:"address"` + ID string `json:"id"` + DeprecatedPath jsonValue `json:"path,omitempty"` // Deprecated } type jsonFunctionValue struct { @@ -981,13 +982,19 @@ func prepareTypeValue(typeValue cadence.TypeValue) jsonValue { } func prepareCapability(capability cadence.Capability) jsonValue { + capabilityJson := jsonCapabilityValue{ + ID: encodeUInt(uint64(capability.ID)), + Address: encodeBytes(capability.Address.Bytes()), + BorrowType: PrepareType(capability.BorrowType, TypePreparationResults{}), + } + + if capability.DeprecatedPath != nil { + capabilityJson.DeprecatedPath = preparePath(*capability.DeprecatedPath) + } + return jsonValueObject{ - Type: capabilityTypeStr, - Value: jsonCapabilityValue{ - ID: encodeUInt(uint64(capability.ID)), - Address: encodeBytes(capability.Address.Bytes()), - BorrowType: PrepareType(capability.BorrowType, TypePreparationResults{}), - }, + Type: capabilityTypeStr, + Value: capabilityJson, } } diff --git a/encoding/json/encoding_test.go b/encoding/json/encoding_test.go index 9ba6776788..b22a24d98f 100644 --- a/encoding/json/encoding_test.go +++ b/encoding/json/encoding_test.go @@ -2781,15 +2781,18 @@ func TestEncodeCapability(t *testing.T) { t.Parallel() - testEncodeAndDecode( - t, - cadence.NewCapability( - 6, - cadence.BytesToAddress([]byte{1, 2, 3, 4, 5}), - cadence.IntType, - ), - // language=json - ` + t.Run("valid capability", func(t *testing.T) { + t.Parallel() + + testEncodeAndDecode( + t, + cadence.NewCapability( + 6, + cadence.BytesToAddress([]byte{1, 2, 3, 4, 5}), + cadence.IntType, + ), + // language=json + ` { "type": "Capability", "value": { @@ -2801,7 +2804,41 @@ func TestEncodeCapability(t *testing.T) { } } `, - ) + ) + }) + + t.Run("deprecated path capability", func(t *testing.T) { + t.Parallel() + + testEncode( + t, + cadence.NewDeprecatedPathCapability( //nolint:staticcheck + cadence.BytesToAddress([]byte{1, 2, 3, 4, 5}), + cadence.MustNewPath(common.PathDomainPublic, "foo"), + cadence.AnyResourceType, + ), + // language=json + ` + { + "type": "Capability", + "value": { + "path": { + "type": "Path", + "value": { + "domain": "public", + "identifier": "foo" + } + }, + "borrowType": { + "kind": "AnyResource" + }, + "address": "0x0000000102030405", + "id": "0" + } + } + `, + ) + }) } func TestDecodeCapability(t *testing.T) { @@ -2833,7 +2870,7 @@ func TestDecodeCapability(t *testing.T) { ) }) - t.Run("with backwards compatibility on a deprecated Path Capabliity", func(t *testing.T) { + t.Run("with backwards compatibility on a deprecated Path Capability", func(t *testing.T) { t.Parallel() testDecode( diff --git a/runtime/convertValues.go b/runtime/convertValues.go index ed21ad067a..2002839324 100644 --- a/runtime/convertValues.go +++ b/runtime/convertValues.go @@ -232,6 +232,8 @@ func exportValueWithInterpreter( return exportTypeValue(v, inter), nil case *interpreter.IDCapabilityValue: return exportCapabilityValue(v, inter) + case *interpreter.PathCapabilityValue: //nolint:staticcheck + return exportPathCapabilityValue(v, inter) case *interpreter.EphemeralReferenceValue: // Break recursion through references if _, ok := seenReferences[v]; ok { @@ -707,6 +709,29 @@ func exportCapabilityValue( ), nil } +func exportPathCapabilityValue( + v *interpreter.PathCapabilityValue, //nolint:staticcheck + inter *interpreter.Interpreter, +) (cadence.Capability, error) { + borrowType := inter.MustConvertStaticToSemaType(v.BorrowType) + exportedBorrowType := ExportMeteredType(inter, borrowType, map[sema.TypeID]cadence.Type{}) + + capability := cadence.NewMeteredCapability( + inter, + cadence.NewMeteredUInt64(inter, uint64(interpreter.InvalidCapabilityID)), + cadence.NewMeteredAddress(inter, v.Address), + exportedBorrowType, + ) + + path, err := exportPathValue(inter, v.Path) + if err != nil { + return cadence.Capability{}, err + } + capability.DeprecatedPath = &path + + return capability, nil +} + // exportEvent converts a runtime event to its native Go representation. func exportEvent( gauge common.MemoryGauge, diff --git a/runtime/convertValues_test.go b/runtime/convertValues_test.go index 56bd73e2d8..8ff803e884 100644 --- a/runtime/convertValues_test.go +++ b/runtime/convertValues_test.go @@ -566,6 +566,22 @@ func TestRuntimeExportValue(t *testing.T) { }, invalid: true, }, + { + label: "path capability", + value: &interpreter.PathCapabilityValue{ //nolint:staticcheck + BorrowType: interpreter.PrimitiveStaticTypeAnyResource, + Path: interpreter.PathValue{ + Domain: common.PathDomainStorage, + Identifier: "foo", + }, + Address: interpreter.AddressValue{0x1}, + }, + expected: cadence.NewDeprecatedPathCapability( //nolint:staticcheck + cadence.Address{0x1}, + cadence.MustNewPath(common.PathDomainStorage, "foo"), + cadence.AnyResourceType, + ), + }, } { test(tt) }