Skip to content

Commit

Permalink
Remove cadence-type-id from function-value
Browse files Browse the repository at this point in the history
In JSON-CDC, sometimes cadence-type-id was encoded when it was just
a "stringification" of other encoded data and not necessary to encode.

In CCF, we don't need to keep this inefficiency for the sake of compatibility.

This commit removes cadence-type-id from function-value, which is also used by
function-type-value.

It also modifies FunctionType to generate ID if it is empty.  Generated ID is
stringification of its parameter types and return type.
  • Loading branch information
fxamacker committed Mar 24, 2023
1 parent 7a1b3f5 commit 54c6987
Show file tree
Hide file tree
Showing 5 changed files with 85 additions and 41 deletions.
25 changes: 8 additions & 17 deletions encoding/ccf/ccf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -7197,13 +7197,13 @@ func TestEncodeType(t *testing.T) {
{Label: "qux", Identifier: "baz", Type: cadence.StringType{}},
},
ReturnType: cadence.IntType{},
}).WithID("Foo"),
}).WithID("((String):Int)"),
},
[]byte{ // language=json, format=json-cdc
// {"type":"Type","value":{"staticType": { "kind" : "Function", "typeID":"Foo", "return" : {"kind" : "Int"}, "parameters" : [ {"label" : "qux", "id" : "baz", "type": {"kind" : "String"}} ]} } }
// {"type":"Type","value":{"staticType": { "kind" : "Function", "typeID":"((String):Int)", "return" : {"kind" : "Int"}, "parameters" : [ {"label" : "qux", "id" : "baz", "type": {"kind" : "String"}} ]} } }
//
// language=edn, format=ccf
// 130([137(41), 193(["Foo", [["qux", "baz", 185(1)]], 185(4)])])
// 130([137(41), 193([[["qux", "baz", 185(1)]], 185(4)])])
//
// language=cbor, format=ccf
// tag
Expand All @@ -7216,12 +7216,8 @@ func TestEncodeType(t *testing.T) {
0x18, 0x29,
// tag
0xd8, ccf.CBORTagFunctionTypeValue,
// array, 3 elements follow
0x83,
// string, 3 bytes follow
0x63,
// Foo
0x46, 0x6f, 0x6f,
// array, 2 elements follow
0x82,
// array, 1 elements follow
0x81,
// array, 3 elements follow
Expand Down Expand Up @@ -8821,7 +8817,7 @@ func TestExportFunctionValue(t *testing.T) {
// { "type": "Function", "value": { "functionType": { "kind": "Function", "typeID": "(():Void)", "parameters": [], "return": { "kind": "Void" } } } }
//
// language=edn, format=ccf
// 130([137(51), ["(():Void)", [], 185(50)]])
// 130([137(51), [[], 185(50)]])
//
// language=cbor, format=ccf
// tag
Expand All @@ -8832,13 +8828,8 @@ func TestExportFunctionValue(t *testing.T) {
0xd8, ccf.CBORTagSimpleType,
// Function type ID (51)
0x18, 0x33,
// array, 3 elements follow
0x83,
// element 0: cadence-type-id
// string, 9 bytes follow
0x69,
// (():Void)
0x28, 0x28, 0x29, 0x3a, 0x56, 0x6f, 0x69, 0x64, 0x29,
// array, 2 elements follow
0x82,
// element 1: parameters
// array, 0 element
0x80,
Expand Down
17 changes: 5 additions & 12 deletions encoding/ccf/decode.go
Original file line number Diff line number Diff line change
Expand Up @@ -1793,7 +1793,6 @@ func (d *Decoder) decodeParameterTypeValue(visited cadenceTypeByCCFTypeID) (cade
// language=CDDL
// function-value = [
//
// cadence-type-id: cadence-type-id,
// parameters: [
// * [
// label: tstr,
Expand All @@ -1805,25 +1804,19 @@ func (d *Decoder) decodeParameterTypeValue(visited cadenceTypeByCCFTypeID) (cade
//
// ]
func (d *Decoder) decodeFunctionTypeValue(visited cadenceTypeByCCFTypeID) (cadence.Type, error) {
// Decode array head of length 3
err := decodeCBORArrayWithKnownSize(d.dec, 3)
if err != nil {
return nil, err
}

// element 0: cadence-type-id
typeID, err := d.dec.DecodeString()
// Decode array head of length 2
err := decodeCBORArrayWithKnownSize(d.dec, 2)
if err != nil {
return nil, err
}

// element 1: parameters
// element 0: parameters
parameters, err := d.decodeParameterTypeValues(visited)
if err != nil {
return nil, err
}

// element 2: return-type
// element 1: return-type
returnType, err := d._decodeTypeValue(visited)
if err != nil {
return nil, err
Expand All @@ -1834,7 +1827,7 @@ func (d *Decoder) decodeFunctionTypeValue(visited cadenceTypeByCCFTypeID) (caden
"",
parameters,
returnType,
).WithID(typeID), nil
), nil
}

func decodeCBORArrayWithKnownSize(dec *cbor.StreamDecoder, n uint64) error {
Expand Down
17 changes: 5 additions & 12 deletions encoding/ccf/encode.go
Original file line number Diff line number Diff line change
Expand Up @@ -994,7 +994,6 @@ func (e *Encoder) encodeCapability(capability cadence.StorageCapability) error {
// language=CDDL
// function-value = [
//
// cadence-type-id: cadence-type-id,
// parameters: [
// * [
// label: tstr,
Expand All @@ -1006,28 +1005,22 @@ func (e *Encoder) encodeCapability(capability cadence.StorageCapability) error {
//
// ]
func (e *Encoder) encodeFunction(typ *cadence.FunctionType, visited ccfTypeIDByCadenceType) error {
// Encode array head of length 3.
// Encode array head of length 2.
err := e.enc.EncodeRawBytes([]byte{
// array, 3 items follow
0x83,
// array, 2 items follow
0x82,
})
if err != nil {
return err
}

// element 0: cadence-type-id as tstr.
err = e.encodeCadenceTypeID(typ.ID())
if err != nil {
return err
}

// element 1: parameters as array.
// element 0: parameters as array.
err = e.encodeParameterTypeValues(typ.Parameters, visited)
if err != nil {
return err
}

// element 2: return type as type-value.
// element 1: return type as type-value.
return e.encodeTypeValue(typ.ReturnType, visited)
}

Expand Down
20 changes: 20 additions & 0 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -1727,9 +1727,29 @@ func NewMeteredFunctionType(
func (*FunctionType) isType() {}

func (t *FunctionType) ID() string {
if t.typeID == "" {
t.typeID = t.id()
}
return t.typeID
}

func (t *FunctionType) id() string {
returnTypeID := t.ReturnType.ID()

switch len(t.Parameters) {
case 0:
return "(():" + returnTypeID + ")"
case 1:
return "((" + t.Parameters[0].Type.ID() + "):" + returnTypeID + ")"
default:
params := make([]string, len(t.Parameters))
for i, param := range t.Parameters {
params[i] = param.Type.ID()
}
return "((" + strings.Join(params, ", ") + "):" + returnTypeID + ")"
}
}

func (t *FunctionType) WithID(id string) *FunctionType {
t.typeID = id
return t
Expand Down
47 changes: 47 additions & 0 deletions types_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,6 +267,53 @@ func TestType_ID(t *testing.T) {
},
"S.test.ContractI",
},
{
&FunctionType{
UInt8Type{},
"Foo",
[]Parameter{
{
Type: StringType{},
},
},
},
"Foo",
},
{
&FunctionType{
UInt8Type{},
"",
[]Parameter{},
},
"(():UInt8)",
},
{
&FunctionType{
UInt8Type{},
"",
[]Parameter{
{
Type: StringType{},
},
},
},
"((String):UInt8)",
},
{
&FunctionType{
UInt8Type{},
"",
[]Parameter{
{
Type: StringType{},
},
{
Type: AddressType{},
},
},
},
"((String, Address):UInt8)",
},
}

test := func(ty Type, expected string) {
Expand Down

0 comments on commit 54c6987

Please sign in to comment.