Skip to content

Commit

Permalink
Merge pull request #340 from onflow/fxamacker/remove-empty-next-slab-…
Browse files Browse the repository at this point in the history
…id-in-encoded-map-data

Omit empty next slab ID in encoded map data slab
  • Loading branch information
fxamacker authored Sep 12, 2023
2 parents 2329549 + cbc8204 commit cf56a4c
Show file tree
Hide file tree
Showing 3 changed files with 22 additions and 40 deletions.
22 changes: 14 additions & 8 deletions map.go
Original file line number Diff line number Diff line change
Expand Up @@ -2200,20 +2200,21 @@ func newMapDataSlabFromDataV1(
var extraData *MapExtraData
var next SlabID

// Decode header
// Decode extra data
if h.isRoot() {
// Decode extra data
extraData, data, err = newMapExtraDataFromData(data, decMode, decodeTypeInfo)
if err != nil {
// Don't need to wrap error as external error because err is already categorized by newMapExtraDataFromData().
return nil, err
}
} else {
}

// Decode next slab ID
if h.hasNextSlabID() {
if len(data) < slabIDSize {
return nil, NewDecodingErrorf("data is too short for map data slab")
}

// Decode next slab ID
next, err = NewSlabIDFromRawBytes(data)
if err != nil {
// Don't need to wrap error as external error because err is already categorized by NewSlabIDFromRawBytes().
Expand Down Expand Up @@ -2291,6 +2292,10 @@ func (m *MapDataSlab) Encode(enc *Encoder) error {
h.setHasPointers()
}

if m.next != SlabIDUndefined {
h.setHasNextSlabID()
}

if m.anySize {
h.setNoSizeLimit()
}
Expand All @@ -2305,16 +2310,17 @@ func (m *MapDataSlab) Encode(enc *Encoder) error {
return NewEncodingError(err)
}

// Encode header
// Encode extra data
if m.extraData != nil {
// Encode extra data
err = m.extraData.Encode(enc)
if err != nil {
// Don't need to wrap error as external error because err is already categorized by MapExtraData.Encode().
return err
}
} else {
// Encode next slab ID to scratch
}

// Encode next slab ID
if m.next != SlabIDUndefined {
n, err := m.next.ToRawBytes(enc.Scratch[:])
if err != nil {
// Don't need to wrap error as external error because err is already categorized by SlabID.ToRawBytes().
Expand Down
29 changes: 5 additions & 24 deletions map_debug.go
Original file line number Diff line number Diff line change
Expand Up @@ -849,18 +849,16 @@ func validMapSlabSerialization(
}

// Extra check: encoded data size == header.size
encodedExtraDataSize, err := getEncodedMapExtraDataSize(slab.ExtraData(), cborEncMode)
encodedSlabSize, err := computeSlabSize(data)
if err != nil {
// Don't need to wrap error as external error because err is already categorized by getEncodedMapExtraDataSize().
// Don't need to wrap error as external error because err is already categorized by computeSlabSize().
return err
}

// Need to exclude extra data size from encoded data size.
encodedSlabSize := uint32(len(data) - encodedExtraDataSize)
if slab.Header().size != encodedSlabSize {
if slab.Header().size != uint32(encodedSlabSize) {
return NewFatalError(
fmt.Errorf("slab %d encoded size %d != header.size %d (encoded extra data size %d)",
id, encodedSlabSize, slab.Header().size, encodedExtraDataSize))
fmt.Errorf("slab %d encoded size %d != header.size %d",
id, encodedSlabSize, slab.Header().size))
}

// Compare encoded data of original slab with encoded data of decoded slab
Expand Down Expand Up @@ -1357,20 +1355,3 @@ func mapExtraDataEqual(expected, actual *MapExtraData) error {

return nil
}

func getEncodedMapExtraDataSize(extraData *MapExtraData, cborEncMode cbor.EncMode) (int, error) {
if extraData == nil {
return 0, nil
}

var buf bytes.Buffer
enc := NewEncoder(&buf, cborEncMode)

err := extraData.Encode(enc)
if err != nil {
// Don't need to wrap error as external error because err is already categorized by MapExtraData.Encode().
return 0, err
}

return len(buf.Bytes()), nil
}
11 changes: 3 additions & 8 deletions map_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -2737,7 +2737,7 @@ func TestMapEncodeDecode(t *testing.T) {
// data slab
id2: {
// version
0x10,
0x12,
// flag: map data
0x08,
// next slab id
Expand Down Expand Up @@ -2789,8 +2789,6 @@ func TestMapEncodeDecode(t *testing.T) {
0x10,
// flag: has pointer + map data
0x48,
// next slab id
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

// the following encoded data is valid CBOR

Expand Down Expand Up @@ -2864,7 +2862,8 @@ func TestMapEncodeDecode(t *testing.T) {
require.True(t, ok)
require.Equal(t, 2, len(meta.childrenHeaders))
require.Equal(t, uint32(len(stored[id2])), meta.childrenHeaders[0].size)
require.Equal(t, uint32(len(stored[id3])), meta.childrenHeaders[1].size)
// Need to add slabIDSize to encoded data slab here because empty slab ID is omitted during encoding.
require.Equal(t, uint32(len(stored[id3])+slabIDSize), meta.childrenHeaders[1].size)

// Decode data to new storage
storage2 := newTestPersistentStorageWithData(t, stored)
Expand Down Expand Up @@ -3392,8 +3391,6 @@ func TestMapEncodeDecode(t *testing.T) {
0x10,
// flag: any size + collision group
0x2b,
// next slab id
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

// the following encoded data is valid CBOR

Expand Down Expand Up @@ -3457,8 +3454,6 @@ func TestMapEncodeDecode(t *testing.T) {
0x10,
// flag: any size + collision group
0x2b,
// next slab id
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,

// the following encoded data is valid CBOR

Expand Down

0 comments on commit cf56a4c

Please sign in to comment.