Skip to content

Commit

Permalink
ccf encoding/decoding is backwards compatible
Browse files Browse the repository at this point in the history
  • Loading branch information
dsainati1 committed Jun 30, 2023
1 parent 0e14347 commit 3fcf2e9
Show file tree
Hide file tree
Showing 5 changed files with 172 additions and 10 deletions.
123 changes: 123 additions & 0 deletions encoding/ccf/ccf_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -6805,6 +6805,11 @@ func TestEncodeValueOfIntersectionType(t *testing.T) {
0xd8, ccf.CBORTagIntersectionType,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// array, 2 items follow
0x82,
// tag
0xd8, ccf.CBORTagTypeRef,
// bytes, 1 byte follows
Expand Down Expand Up @@ -7019,6 +7024,11 @@ func TestEncodeValueOfIntersectionType(t *testing.T) {
0xd8, ccf.CBORTagIntersectionType,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// array, 2 items follow
0x82,
// tag
0xd8, ccf.CBORTagTypeRef,
// bytes, 1 byte follows
Expand Down Expand Up @@ -9468,6 +9478,11 @@ func TestEncodeType(t *testing.T) {
0x18, 0x29,
// tag
0xd8, ccf.CBORTagIntersectionTypeValue,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// array, 0 element follows
0x80,
}
Expand Down Expand Up @@ -9499,6 +9514,11 @@ func TestEncodeType(t *testing.T) {
0x18, 0x29,
// tag
0xd8, ccf.CBORTagIntersectionTypeValue,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// array, 0 element follows
0x80,
}
Expand Down Expand Up @@ -9538,6 +9558,68 @@ func TestEncodeType(t *testing.T) {
0x18, 0x29,
// tag
0xd8, ccf.CBORTagIntersectionTypeValue,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// array, 1 element follows
0x81,
// tag
0xd8, ccf.CBORTagSimpleTypeValue,
// String type ID (1)
0x01,
},
// Expected decoded IntersectionType doesn't have type ID.
cadence.TypeValue{
StaticType: &cadence.IntersectionType{
Types: []cadence.Type{
cadence.StringType{},
},
},
},
)

})

t.Run("with legacy intersection type", func(t *testing.T) {
t.Parallel()

testEncodeAndDecodeEx(
t,
cadence.TypeValue{
StaticType: &cadence.IntersectionType{
Types: []cadence.Type{
cadence.StringType{},
},
LegacyRestrictedType: cadence.IntType{},
},
},
[]byte{
// language=json, format=json-cdc
// {"type":"Type","value":{"staticType": { "kind": "Intersection", "typeID":"Int{String}", "type" : {"kind" : "Int"}, "types" : [ {"kind" : "String"} ]} } }
//
// language=edn, format=ccf
// 130([137(41), 191([185(4), [185(1)]])])
//
// language=cbor, format=ccf
// tag
0xd8, ccf.CBORTagTypeAndValue,
// array, 2 elements follow
0x82,
// tag
0xd8, ccf.CBORTagSimpleType,
// Meta type ID (41)
0x18, 0x29,
// tag
0xd8, ccf.CBORTagIntersectionTypeValue,
// array, 2 items follow
0x82,
// type
// int type tag
0xd8,
// int type
0xb9, 0x04,
// array, 1 element follows
0x81,
// tag
Expand All @@ -9551,6 +9633,7 @@ func TestEncodeType(t *testing.T) {
Types: []cadence.Type{
cadence.StringType{},
},
LegacyRestrictedType: cadence.IntType{},
},
},
)
Expand Down Expand Up @@ -9588,6 +9671,11 @@ func TestEncodeType(t *testing.T) {
0x18, 0x29,
// tag
0xd8, ccf.CBORTagIntersectionTypeValue,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// array, 2 element follows
0x82,
// tag
Expand Down Expand Up @@ -9659,6 +9747,11 @@ func TestEncodeType(t *testing.T) {
0x18, 0x29,
// tag
0xd8, ccf.CBORTagIntersectionTypeValue,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// 3 sorted types
// array, 3 element follows
0x83,
Expand Down Expand Up @@ -14296,6 +14389,11 @@ func TestDecodeInvalidData(t *testing.T) {
0xd8, ccf.CBORTagIntersectionTypeValue,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// array, 2 items follow
0x82,
// tag
0xd8, ccf.CBORTagStructTypeValue,
// array, 5 items follow
Expand Down Expand Up @@ -14533,6 +14631,11 @@ func TestEncodeValueOfIntersectedInterface(t *testing.T) {
0x66, 0x69, 0x65, 0x6c, 0x64,
// tag
0xd8, ccf.CBORTagIntersectionType,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// array, 1 item follows
0x81,
// tag
Expand Down Expand Up @@ -14851,6 +14954,11 @@ func TestSortOptions(t *testing.T) {
0xd8, ccf.CBORTagIntersectionType,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// array, 2 items follow
0x82,
// tag
0xd8, ccf.CBORTagTypeRef,
// bytes, 1 byte follows
Expand Down Expand Up @@ -15040,6 +15148,11 @@ func TestSortOptions(t *testing.T) {
0xd8, ccf.CBORTagIntersectionType,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// array, 2 items follow
0x82,
// tag
0xd8, ccf.CBORTagTypeRef,
// bytes, 1 byte follows
Expand Down Expand Up @@ -15229,6 +15342,11 @@ func TestSortOptions(t *testing.T) {
0xd8, ccf.CBORTagIntersectionType,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// array, 2 items follow
0x82,
// tag
0xd8, ccf.CBORTagTypeRef,
// bytes, 1 byte follows
Expand Down Expand Up @@ -15418,6 +15536,11 @@ func TestSortOptions(t *testing.T) {
0xd8, ccf.CBORTagIntersectionType,
// array, 2 items follow
0x82,
// type
// null
0xf6,
// array, 2 items follow
0x82,
// tag
0xd8, ccf.CBORTagTypeRef,
// bytes, 1 byte follows
Expand Down
24 changes: 19 additions & 5 deletions encoding/ccf/decode_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -553,12 +553,24 @@ func (d *Decoder) decodeIntersectionType(
decodeTypeFn decodeTypeFn,
decodeIntersectionTypeFn decodeTypeFn,
) (cadence.Type, error) {
// types
// Decode array of length 2.
err := decodeCBORArrayWithKnownSize(d.dec, 2)
if err != nil {
return nil, err
}

// element 0: type
legacyRestrictedType, err := d.decodeNullableTypeValue(types)
if err != nil {
return nil, err
}

// element 1: types
typeCount, err := d.dec.DecodeArrayHead()
if err != nil {
return nil, err
}
if typeCount == 0 {
if typeCount == 0 && legacyRestrictedType == nil {
return nil, errors.New("unexpected empty intersection type")
}

Expand Down Expand Up @@ -602,14 +614,16 @@ func (d *Decoder) decodeIntersectionType(
intersectionTypes[i] = intersectedType
}

if len(intersectionTypes) == 0 {
if len(intersectionTypes) == 0 && legacyRestrictedType == nil {
return nil, errors.New("unexpected empty intersection type")
}

return cadence.NewMeteredIntersectionType(
intersectionType := cadence.NewMeteredIntersectionType(
d.gauge,
intersectionTypes,
), nil
)
intersectionType.LegacyRestrictedType = legacyRestrictedType
return intersectionType, nil
}

// decodeCCFTypeID decodes encoded id as
Expand Down
23 changes: 22 additions & 1 deletion encoding/ccf/encode_type.go
Original file line number Diff line number Diff line change
Expand Up @@ -390,7 +390,28 @@ func (e *Encoder) encodeIntersectionTypeWithRawTag(
return err
}

// types as array.
// Encode array head of length 2.
err = e.enc.EncodeArrayHead(2)
if err != nil {
return err
}

// if this is a type in the old format, encode it in the old format
if typ.LegacyRestrictedType != nil {
// element 0: type with given encodeTypeFn
err = encodeTypeFn(typ.LegacyRestrictedType, tids)
if err != nil {
return err
}
} else {
// element 0: otherwise encode nil
err = e.enc.EncodeNil()
if err != nil {
return err
}
}

// element 1: types as array.

// Encode array head with number of types.
intersectionTypes := typ.Types
Expand Down
3 changes: 3 additions & 0 deletions encoding/ccf/traverse_value.go
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,9 @@ func (ct *compositeTypes) traverseType(typ cadence.Type) (checkRuntimeType bool)

case *cadence.IntersectionType:
check := false
if typ.LegacyRestrictedType != nil {
check = ct.traverseType(typ.LegacyRestrictedType)
}
for _, typ := range typ.Types {
checkTyp := ct.traverseType(typ)
check = check || checkTyp
Expand Down
9 changes: 5 additions & 4 deletions types.go
Original file line number Diff line number Diff line change
Expand Up @@ -2272,10 +2272,11 @@ func (t *ReferenceType) Equal(other Type) bool {
type IntersectionSet = map[Type]struct{}

type IntersectionType struct {
typeID string
Types []Type
intersectionSet IntersectionSet
intersectionSetOnce sync.Once
typeID string
Types []Type
LegacyRestrictedType Type
intersectionSet IntersectionSet
intersectionSetOnce sync.Once
}

func NewIntersectionType(
Expand Down

0 comments on commit 3fcf2e9

Please sign in to comment.