github.com/onflow/atree@v0.6.0/map_debug.go (about)

     1  /*
     2   * Atree - Scalable Arrays and Ordered Maps
     3   *
     4   * Copyright 2021 Dapper Labs, Inc.
     5   *
     6   * Licensed under the Apache License, Version 2.0 (the "License");
     7   * you may not use this file except in compliance with the License.
     8   * You may obtain a copy of the License at
     9   *
    10   *   http://www.apache.org/licenses/LICENSE-2.0
    11   *
    12   * Unless required by applicable law or agreed to in writing, software
    13   * distributed under the License is distributed on an "AS IS" BASIS,
    14   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    15   * See the License for the specific language governing permissions and
    16   * limitations under the License.
    17   */
    18  
    19  package atree
    20  
    21  import (
    22  	"bytes"
    23  	"errors"
    24  	"fmt"
    25  	"reflect"
    26  	"sort"
    27  	"strings"
    28  
    29  	"github.com/fxamacker/cbor/v2"
    30  )
    31  
    32  type MapStats struct {
    33  	Levels                 uint64
    34  	ElementCount           uint64
    35  	MetaDataSlabCount      uint64
    36  	DataSlabCount          uint64
    37  	CollisionDataSlabCount uint64
    38  	StorableSlabCount      uint64
    39  }
    40  
    41  func (s *MapStats) SlabCount() uint64 {
    42  	return s.DataSlabCount + s.MetaDataSlabCount + s.CollisionDataSlabCount + s.StorableSlabCount
    43  }
    44  
    45  // GetMapStats returns stats about the map slabs.
    46  func GetMapStats(m *OrderedMap) (MapStats, error) {
    47  	level := uint64(0)
    48  	metaDataSlabCount := uint64(0)
    49  	dataSlabCount := uint64(0)
    50  	collisionDataSlabCount := uint64(0)
    51  	storableDataSlabCount := uint64(0)
    52  
    53  	nextLevelIDs := []StorageID{m.StorageID()}
    54  
    55  	for len(nextLevelIDs) > 0 {
    56  
    57  		ids := nextLevelIDs
    58  
    59  		nextLevelIDs = []StorageID(nil)
    60  
    61  		for _, id := range ids {
    62  
    63  			slab, err := getMapSlab(m.Storage, id)
    64  			if err != nil {
    65  				// Don't need to wrap error as external error because err is already categorized by getMapSlab().
    66  				return MapStats{}, err
    67  			}
    68  
    69  			if slab.IsData() {
    70  				dataSlabCount++
    71  
    72  				leaf := slab.(*MapDataSlab)
    73  				elementGroups := []elements{leaf.elements}
    74  
    75  				for len(elementGroups) > 0 {
    76  
    77  					var nestedElementGroups []elements
    78  
    79  					for i := 0; i < len(elementGroups); i++ {
    80  
    81  						elems := elementGroups[i]
    82  
    83  						for j := 0; j < int(elems.Count()); j++ {
    84  							elem, err := elems.Element(j)
    85  							if err != nil {
    86  								// Don't need to wrap error as external error because err is already categorized by elements.Element().
    87  								return MapStats{}, err
    88  							}
    89  
    90  							if group, ok := elem.(elementGroup); ok {
    91  								if !group.Inline() {
    92  									collisionDataSlabCount++
    93  								}
    94  
    95  								nested, err := group.Elements(m.Storage)
    96  								if err != nil {
    97  									// Don't need to wrap error as external error because err is already categorized by elementGroup.Elements().
    98  									return MapStats{}, err
    99  								}
   100  								nestedElementGroups = append(nestedElementGroups, nested)
   101  
   102  							} else {
   103  								e := elem.(*singleElement)
   104  								if _, ok := e.key.(StorageIDStorable); ok {
   105  									storableDataSlabCount++
   106  								}
   107  								if _, ok := e.value.(StorageIDStorable); ok {
   108  									storableDataSlabCount++
   109  								}
   110  							}
   111  						}
   112  					}
   113  					elementGroups = nestedElementGroups
   114  				}
   115  			} else {
   116  				metaDataSlabCount++
   117  
   118  				for _, storable := range slab.ChildStorables() {
   119  					id, ok := storable.(StorageIDStorable)
   120  					if !ok {
   121  						return MapStats{}, NewFatalError(fmt.Errorf("metadata slab's child storables are not of type StorageIDStorable"))
   122  					}
   123  					nextLevelIDs = append(nextLevelIDs, StorageID(id))
   124  				}
   125  			}
   126  		}
   127  
   128  		level++
   129  	}
   130  
   131  	return MapStats{
   132  		Levels:                 level,
   133  		ElementCount:           m.Count(),
   134  		MetaDataSlabCount:      metaDataSlabCount,
   135  		DataSlabCount:          dataSlabCount,
   136  		CollisionDataSlabCount: collisionDataSlabCount,
   137  		StorableSlabCount:      storableDataSlabCount,
   138  	}, nil
   139  }
   140  
   141  func PrintMap(m *OrderedMap) {
   142  	dumps, err := DumpMapSlabs(m)
   143  	if err != nil {
   144  		fmt.Println(err)
   145  		return
   146  	}
   147  	fmt.Println(strings.Join(dumps, "\n"))
   148  }
   149  
   150  func DumpMapSlabs(m *OrderedMap) ([]string, error) {
   151  	var dumps []string
   152  
   153  	nextLevelIDs := []StorageID{m.StorageID()}
   154  
   155  	var overflowIDs []StorageID
   156  	var collisionSlabIDs []StorageID
   157  
   158  	level := 0
   159  	for len(nextLevelIDs) > 0 {
   160  
   161  		ids := nextLevelIDs
   162  
   163  		nextLevelIDs = []StorageID(nil)
   164  
   165  		for _, id := range ids {
   166  
   167  			slab, err := getMapSlab(m.Storage, id)
   168  			if err != nil {
   169  				// Don't need to wrap error as external error because err is already categorized by getMapSlab().
   170  				return nil, err
   171  			}
   172  
   173  			if slab.IsData() {
   174  				dataSlab := slab.(*MapDataSlab)
   175  				dumps = append(dumps, fmt.Sprintf("level %d, %s", level+1, dataSlab))
   176  
   177  				for i := 0; i < int(dataSlab.elements.Count()); i++ {
   178  					elem, err := dataSlab.elements.Element(i)
   179  					if err != nil {
   180  						// Don't need to wrap error as external error because err is already categorized by elements.Element().
   181  						return nil, err
   182  					}
   183  					if group, ok := elem.(elementGroup); ok {
   184  						if !group.Inline() {
   185  							extSlab := group.(*externalCollisionGroup)
   186  							collisionSlabIDs = append(collisionSlabIDs, extSlab.id)
   187  						}
   188  					}
   189  				}
   190  
   191  				childStorables := dataSlab.ChildStorables()
   192  				for _, e := range childStorables {
   193  					if id, ok := e.(StorageIDStorable); ok {
   194  						overflowIDs = append(overflowIDs, StorageID(id))
   195  					}
   196  				}
   197  
   198  			} else {
   199  				meta := slab.(*MapMetaDataSlab)
   200  				dumps = append(dumps, fmt.Sprintf("level %d, %s", level+1, meta))
   201  
   202  				for _, storable := range slab.ChildStorables() {
   203  					id, ok := storable.(StorageIDStorable)
   204  					if !ok {
   205  						return nil, NewFatalError(errors.New("metadata slab's child storables are not of type StorageIDStorable"))
   206  					}
   207  					nextLevelIDs = append(nextLevelIDs, StorageID(id))
   208  				}
   209  			}
   210  		}
   211  
   212  		level++
   213  	}
   214  
   215  	for _, id := range collisionSlabIDs {
   216  		slab, err := getMapSlab(m.Storage, id)
   217  		if err != nil {
   218  			// Don't need to wrap error as external error because err is already categorized by getMapSlab().
   219  			return nil, err
   220  		}
   221  		dumps = append(dumps, fmt.Sprintf("collision: %s", slab.String()))
   222  	}
   223  
   224  	// overflowIDs include collisionSlabIDs
   225  	for _, id := range overflowIDs {
   226  		found := false
   227  		for _, cid := range collisionSlabIDs {
   228  			if id == cid {
   229  				found = true
   230  				break
   231  			}
   232  		}
   233  		if found {
   234  			continue
   235  		}
   236  		slab, found, err := m.Storage.Retrieve(id)
   237  		if err != nil {
   238  			// Wrap err as external error (if needed) because err is returned by SlabStorage interface.
   239  			return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to retrieve slab %s", id))
   240  		}
   241  		if !found {
   242  			return nil, NewSlabNotFoundErrorf(id, "slab not found during map slab dump")
   243  		}
   244  		dumps = append(dumps, fmt.Sprintf("overflow: %s", slab))
   245  	}
   246  
   247  	return dumps, nil
   248  }
   249  
   250  func ValidMap(m *OrderedMap, typeInfo TypeInfo, tic TypeInfoComparator, hip HashInputProvider) error {
   251  
   252  	extraData := m.root.ExtraData()
   253  	if extraData == nil {
   254  		return NewFatalError(fmt.Errorf("root slab %d doesn't have extra data", m.root.ID()))
   255  	}
   256  
   257  	// Verify that extra data has correct type information
   258  	if typeInfo != nil && !tic(extraData.TypeInfo, typeInfo) {
   259  		return NewFatalError(
   260  			fmt.Errorf(
   261  				"root slab %d type information %v, want %v",
   262  				m.root.ID(),
   263  				extraData.TypeInfo,
   264  				typeInfo,
   265  			))
   266  	}
   267  
   268  	// Verify that extra data has seed
   269  	if extraData.Seed == 0 {
   270  		return NewFatalError(fmt.Errorf("root slab %d seed is uninitialized", m.root.ID()))
   271  	}
   272  
   273  	computedCount, dataSlabIDs, nextDataSlabIDs, firstKeys, err := validMapSlab(
   274  		m.Storage, m.digesterBuilder, tic, hip, m.root.ID(), 0, nil, []StorageID{}, []StorageID{}, []Digest{})
   275  	if err != nil {
   276  		// Don't need to wrap error as external error because err is already categorized by validMapSlab().
   277  		return err
   278  	}
   279  
   280  	// Verify that extra data has correct count
   281  	if computedCount != extraData.Count {
   282  		return NewFatalError(
   283  			fmt.Errorf(
   284  				"root slab %d count %d is wrong, want %d",
   285  				m.root.ID(),
   286  				extraData.Count,
   287  				computedCount,
   288  			))
   289  	}
   290  
   291  	// Verify next data slab ids
   292  	if !reflect.DeepEqual(dataSlabIDs[1:], nextDataSlabIDs) {
   293  		return NewFatalError(fmt.Errorf("chained next data slab ids %v are wrong, want %v",
   294  			nextDataSlabIDs, dataSlabIDs[1:]))
   295  	}
   296  
   297  	// Verify data slabs' first keys are sorted
   298  	if !sort.SliceIsSorted(firstKeys, func(i, j int) bool {
   299  		return firstKeys[i] < firstKeys[j]
   300  	}) {
   301  		return NewFatalError(fmt.Errorf("chained first keys %v are not sorted", firstKeys))
   302  	}
   303  
   304  	// Verify data slabs' first keys are unique
   305  	if len(firstKeys) > 1 {
   306  		prev := firstKeys[0]
   307  		for _, d := range firstKeys[1:] {
   308  			if prev == d {
   309  				return NewFatalError(fmt.Errorf("chained first keys %v are not unique", firstKeys))
   310  			}
   311  			prev = d
   312  		}
   313  	}
   314  
   315  	return nil
   316  }
   317  
   318  func validMapSlab(
   319  	storage SlabStorage,
   320  	digesterBuilder DigesterBuilder,
   321  	tic TypeInfoComparator,
   322  	hip HashInputProvider,
   323  	id StorageID,
   324  	level int,
   325  	headerFromParentSlab *MapSlabHeader,
   326  	dataSlabIDs []StorageID,
   327  	nextDataSlabIDs []StorageID,
   328  	firstKeys []Digest,
   329  ) (
   330  	elementCount uint64,
   331  	_dataSlabIDs []StorageID,
   332  	_nextDataSlabIDs []StorageID,
   333  	_firstKeys []Digest,
   334  	err error,
   335  ) {
   336  
   337  	slab, err := getMapSlab(storage, id)
   338  	if err != nil {
   339  		// Don't need to wrap error as external error because err is already categorized by getMapSlab().
   340  		return 0, nil, nil, nil, err
   341  	}
   342  
   343  	if level > 0 {
   344  		// Verify that non-root slab doesn't have extra data.
   345  		if slab.ExtraData() != nil {
   346  			return 0, nil, nil, nil, NewFatalError(fmt.Errorf("non-root slab %d has extra data", id))
   347  		}
   348  
   349  		// Verify that non-root slab doesn't underflow
   350  		if underflowSize, underflow := slab.IsUnderflow(); underflow {
   351  			return 0, nil, nil, nil, NewFatalError(fmt.Errorf("slab %d underflows by %d bytes", id, underflowSize))
   352  		}
   353  
   354  	}
   355  
   356  	// Verify that slab doesn't overflow
   357  	if slab.IsFull() {
   358  		return 0, nil, nil, nil, NewFatalError(fmt.Errorf("slab %d overflows", id))
   359  	}
   360  
   361  	// Verify that header is in sync with header from parent slab
   362  	if headerFromParentSlab != nil {
   363  		if !reflect.DeepEqual(*headerFromParentSlab, slab.Header()) {
   364  			return 0, nil, nil, nil, NewFatalError(
   365  				fmt.Errorf("slab %d header %+v is different from header %+v from parent slab",
   366  					id, slab.Header(), headerFromParentSlab))
   367  		}
   368  	}
   369  
   370  	if slab.IsData() {
   371  
   372  		dataSlab, ok := slab.(*MapDataSlab)
   373  		if !ok {
   374  			return 0, nil, nil, nil, NewFatalError(fmt.Errorf("slab %d is not MapDataSlab", id))
   375  		}
   376  
   377  		// Verify data slab's elements
   378  		elementCount, elementSize, err := validMapElements(storage, digesterBuilder, tic, hip, id, dataSlab.elements, 0, nil)
   379  		if err != nil {
   380  			// Don't need to wrap error as external error because err is already categorized by validMapElements().
   381  			return 0, nil, nil, nil, err
   382  		}
   383  
   384  		// Verify slab's first key
   385  		if dataSlab.elements.firstKey() != dataSlab.header.firstKey {
   386  			return 0, nil, nil, nil, NewFatalError(
   387  				fmt.Errorf("data slab %d header first key %d is wrong, want %d",
   388  					id, dataSlab.header.firstKey, dataSlab.elements.firstKey()))
   389  		}
   390  
   391  		// Verify that aggregated element size + slab prefix is the same as header.size
   392  		computedSize := uint32(mapDataSlabPrefixSize)
   393  		if level == 0 {
   394  			computedSize = uint32(mapRootDataSlabPrefixSize)
   395  		}
   396  		computedSize += elementSize
   397  
   398  		if computedSize != dataSlab.header.size {
   399  			return 0, nil, nil, nil, NewFatalError(
   400  				fmt.Errorf("data slab %d header size %d is wrong, want %d",
   401  					id, dataSlab.header.size, computedSize))
   402  		}
   403  
   404  		// Verify any size flag
   405  		if dataSlab.anySize {
   406  			return 0, nil, nil, nil, NewFatalError(
   407  				fmt.Errorf("data slab %d anySize %t is wrong, want false",
   408  					id, dataSlab.anySize))
   409  		}
   410  
   411  		// Verify collision group flag
   412  		if dataSlab.collisionGroup {
   413  			return 0, nil, nil, nil, NewFatalError(
   414  				fmt.Errorf("data slab %d collisionGroup %t is wrong, want false",
   415  					id, dataSlab.collisionGroup))
   416  		}
   417  
   418  		dataSlabIDs = append(dataSlabIDs, id)
   419  
   420  		if dataSlab.next != StorageIDUndefined {
   421  			nextDataSlabIDs = append(nextDataSlabIDs, dataSlab.next)
   422  		}
   423  
   424  		firstKeys = append(firstKeys, dataSlab.header.firstKey)
   425  
   426  		return elementCount, dataSlabIDs, nextDataSlabIDs, firstKeys, nil
   427  	}
   428  
   429  	meta, ok := slab.(*MapMetaDataSlab)
   430  	if !ok {
   431  		return 0, nil, nil, nil, NewFatalError(fmt.Errorf("slab %d is not MapMetaDataSlab", id))
   432  	}
   433  
   434  	if level == 0 {
   435  		// Verify that root slab has more than one child slabs
   436  		if len(meta.childrenHeaders) < 2 {
   437  			return 0, nil, nil, nil, NewFatalError(
   438  				fmt.Errorf("root metadata slab %d has %d children, want at least 2 children ",
   439  					id, len(meta.childrenHeaders)))
   440  		}
   441  	}
   442  
   443  	elementCount = 0
   444  	for _, h := range meta.childrenHeaders {
   445  		// Verify child slabs
   446  		count := uint64(0)
   447  		count, dataSlabIDs, nextDataSlabIDs, firstKeys, err =
   448  			validMapSlab(storage, digesterBuilder, tic, hip, h.id, level+1, &h, dataSlabIDs, nextDataSlabIDs, firstKeys)
   449  		if err != nil {
   450  			// Don't need to wrap error as external error because err is already categorized by validMapSlab().
   451  			return 0, nil, nil, nil, err
   452  		}
   453  
   454  		elementCount += count
   455  	}
   456  
   457  	// Verify slab header first key
   458  	if meta.childrenHeaders[0].firstKey != meta.header.firstKey {
   459  		return 0, nil, nil, nil, NewFatalError(
   460  			fmt.Errorf("metadata slab %d header first key %d is wrong, want %d",
   461  				id, meta.header.firstKey, meta.childrenHeaders[0].firstKey))
   462  	}
   463  
   464  	// Verify that child slab's first keys are sorted.
   465  	sortedHKey := sort.SliceIsSorted(meta.childrenHeaders, func(i, j int) bool {
   466  		return meta.childrenHeaders[i].firstKey < meta.childrenHeaders[j].firstKey
   467  	})
   468  	if !sortedHKey {
   469  		return 0, nil, nil, nil, NewFatalError(fmt.Errorf("metadata slab %d child slab's first key isn't sorted %+v", id, meta.childrenHeaders))
   470  	}
   471  
   472  	// Verify that child slab's first keys are unique.
   473  	if len(meta.childrenHeaders) > 1 {
   474  		prev := meta.childrenHeaders[0].firstKey
   475  		for _, h := range meta.childrenHeaders[1:] {
   476  			if prev == h.firstKey {
   477  				return 0, nil, nil, nil, NewFatalError(
   478  					fmt.Errorf("metadata slab %d child header first key isn't unique %v",
   479  						id, meta.childrenHeaders))
   480  			}
   481  			prev = h.firstKey
   482  		}
   483  	}
   484  
   485  	// Verify slab header's size
   486  	computedSize := uint32(len(meta.childrenHeaders)*mapSlabHeaderSize) + mapMetaDataSlabPrefixSize
   487  	if computedSize != meta.header.size {
   488  		return 0, nil, nil, nil, NewFatalError(
   489  			fmt.Errorf("metadata slab %d header size %d is wrong, want %d",
   490  				id, meta.header.size, computedSize))
   491  	}
   492  
   493  	return elementCount, dataSlabIDs, nextDataSlabIDs, firstKeys, nil
   494  }
   495  
   496  func validMapElements(
   497  	storage SlabStorage,
   498  	db DigesterBuilder,
   499  	tic TypeInfoComparator,
   500  	hip HashInputProvider,
   501  	id StorageID,
   502  	elements elements,
   503  	digestLevel uint,
   504  	hkeyPrefixes []Digest,
   505  ) (
   506  	elementCount uint64,
   507  	elementSize uint32,
   508  	err error,
   509  ) {
   510  
   511  	switch elems := elements.(type) {
   512  	case *hkeyElements:
   513  		return validMapHkeyElements(storage, db, tic, hip, id, elems, digestLevel, hkeyPrefixes)
   514  	case *singleElements:
   515  		return validMapSingleElements(storage, db, tic, hip, id, elems, digestLevel, hkeyPrefixes)
   516  	default:
   517  		return 0, 0, NewFatalError(fmt.Errorf("slab %d has unknown elements type %T at digest level %d", id, elements, digestLevel))
   518  	}
   519  }
   520  
   521  func validMapHkeyElements(
   522  	storage SlabStorage,
   523  	db DigesterBuilder,
   524  	tic TypeInfoComparator,
   525  	hip HashInputProvider,
   526  	id StorageID,
   527  	elements *hkeyElements,
   528  	digestLevel uint,
   529  	hkeyPrefixes []Digest,
   530  ) (
   531  	elementCount uint64,
   532  	elementSize uint32,
   533  	err error,
   534  ) {
   535  
   536  	// Verify element's level
   537  	if digestLevel != elements.level {
   538  		return 0, 0, NewFatalError(
   539  			fmt.Errorf("data slab %d elements digest level %d is wrong, want %d",
   540  				id, elements.level, digestLevel))
   541  	}
   542  
   543  	// Verify number of hkeys is the same as number of elements
   544  	if len(elements.hkeys) != len(elements.elems) {
   545  		return 0, 0, NewFatalError(
   546  			fmt.Errorf("data slab %d hkeys count %d is wrong, want %d",
   547  				id, len(elements.hkeys), len(elements.elems)))
   548  	}
   549  
   550  	// Verify hkeys are sorted
   551  	if !sort.SliceIsSorted(elements.hkeys, func(i, j int) bool {
   552  		return elements.hkeys[i] < elements.hkeys[j]
   553  	}) {
   554  		return 0, 0, NewFatalError(fmt.Errorf("data slab %d hkeys is not sorted %v", id, elements.hkeys))
   555  	}
   556  
   557  	// Verify hkeys are unique
   558  	if len(elements.hkeys) > 1 {
   559  		prev := elements.hkeys[0]
   560  		for _, d := range elements.hkeys[1:] {
   561  			if prev == d {
   562  				return 0, 0, NewFatalError(fmt.Errorf("data slab %d hkeys is not unique %v", id, elements.hkeys))
   563  			}
   564  			prev = d
   565  		}
   566  	}
   567  
   568  	elementSize = uint32(hkeyElementsPrefixSize)
   569  
   570  	for i := 0; i < len(elements.elems); i++ {
   571  		e := elements.elems[i]
   572  
   573  		elementSize += digestSize
   574  
   575  		// Verify element size is <= inline size
   576  		if digestLevel == 0 {
   577  			if e.Size() > uint32(maxInlineMapElementSize) {
   578  				return 0, 0, NewFatalError(
   579  					fmt.Errorf("data slab %d element %s size %d is too large, want < %d",
   580  						id, e, e.Size(), maxInlineMapElementSize))
   581  			}
   582  		}
   583  
   584  		if group, ok := e.(elementGroup); ok {
   585  
   586  			ge, err := group.Elements(storage)
   587  			if err != nil {
   588  				// Don't need to wrap error as external error because err is already categorized by elementGroup.Elements().
   589  				return 0, 0, err
   590  			}
   591  
   592  			hkeys := make([]Digest, len(hkeyPrefixes)+1)
   593  			copy(hkeys, hkeyPrefixes)
   594  			hkeys[len(hkeys)-1] = elements.hkeys[i]
   595  
   596  			count, size, err := validMapElements(storage, db, tic, hip, id, ge, digestLevel+1, hkeys)
   597  			if err != nil {
   598  				// Don't need to wrap error as external error because err is already categorized by validMapElement().
   599  				return 0, 0, err
   600  			}
   601  
   602  			if _, ok := e.(*inlineCollisionGroup); ok {
   603  				size += inlineCollisionGroupPrefixSize
   604  			} else {
   605  				size = externalCollisionGroupPrefixSize + 2 + 1 + 16
   606  			}
   607  
   608  			// Verify element group size
   609  			if size != e.Size() {
   610  				return 0, 0, NewFatalError(fmt.Errorf("data slab %d element %s size %d is wrong, want %d", id, e, e.Size(), size))
   611  			}
   612  
   613  			elementSize += e.Size()
   614  
   615  			elementCount += count
   616  
   617  		} else {
   618  
   619  			se, ok := e.(*singleElement)
   620  			if !ok {
   621  				return 0, 0, NewFatalError(fmt.Errorf("data slab %d element type %T is wrong, want *singleElement", id, e))
   622  			}
   623  
   624  			hkeys := make([]Digest, len(hkeyPrefixes)+1)
   625  			copy(hkeys, hkeyPrefixes)
   626  			hkeys[len(hkeys)-1] = elements.hkeys[i]
   627  
   628  			// Verify element
   629  			computedSize, maxDigestLevel, err := validSingleElement(storage, db, tic, hip, se, hkeys)
   630  			if err != nil {
   631  				// Don't need to wrap error as external error because err is already categorized by validSingleElement().
   632  				return 0, 0, fmt.Errorf("data slab %d: %w", id, err)
   633  			}
   634  
   635  			// Verify digest level
   636  			if digestLevel >= maxDigestLevel {
   637  				return 0, 0, NewFatalError(
   638  					fmt.Errorf("data slab %d, hkey elements %s: digest level %d is wrong, want < %d",
   639  						id, elements, digestLevel, maxDigestLevel))
   640  			}
   641  
   642  			elementSize += computedSize
   643  
   644  			elementCount++
   645  		}
   646  	}
   647  
   648  	// Verify elements size
   649  	if elementSize != elements.Size() {
   650  		return 0, 0, NewFatalError(fmt.Errorf("data slab %d elements size %d is wrong, want %d", id, elements.Size(), elementSize))
   651  	}
   652  
   653  	return elementCount, elementSize, nil
   654  }
   655  
   656  func validMapSingleElements(
   657  	storage SlabStorage,
   658  	db DigesterBuilder,
   659  	tic TypeInfoComparator,
   660  	hip HashInputProvider,
   661  	id StorageID,
   662  	elements *singleElements,
   663  	digestLevel uint,
   664  	hkeyPrefixes []Digest,
   665  ) (
   666  	elementCount uint64,
   667  	elementSize uint32,
   668  	err error,
   669  ) {
   670  
   671  	// Verify elements' level
   672  	if digestLevel != elements.level {
   673  		return 0, 0, NewFatalError(
   674  			fmt.Errorf("data slab %d elements level %d is wrong, want %d",
   675  				id, elements.level, digestLevel))
   676  	}
   677  
   678  	elementSize = singleElementsPrefixSize
   679  
   680  	for _, e := range elements.elems {
   681  
   682  		// Verify element
   683  		computedSize, maxDigestLevel, err := validSingleElement(storage, db, tic, hip, e, hkeyPrefixes)
   684  		if err != nil {
   685  			// Don't need to wrap error as external error because err is already categorized by validSingleElement().
   686  			return 0, 0, fmt.Errorf("data slab %d: %w", id, err)
   687  		}
   688  
   689  		// Verify element size is <= inline size
   690  		if e.Size() > uint32(maxInlineMapElementSize) {
   691  			return 0, 0, NewFatalError(
   692  				fmt.Errorf("data slab %d element %s size %d is too large, want < %d",
   693  					id, e, e.Size(), maxInlineMapElementSize))
   694  		}
   695  
   696  		// Verify digest level
   697  		if digestLevel != maxDigestLevel {
   698  			return 0, 0, NewFatalError(
   699  				fmt.Errorf("data slab %d single elements %s digest level %d is wrong, want %d",
   700  					id, elements, digestLevel, maxDigestLevel))
   701  		}
   702  
   703  		elementSize += computedSize
   704  	}
   705  
   706  	// Verify elements size
   707  	if elementSize != elements.Size() {
   708  		return 0, 0, NewFatalError(fmt.Errorf("slab %d elements size %d is wrong, want %d", id, elements.Size(), elementSize))
   709  	}
   710  
   711  	return uint64(len(elements.elems)), elementSize, nil
   712  }
   713  
   714  func validSingleElement(
   715  	storage SlabStorage,
   716  	db DigesterBuilder,
   717  	tic TypeInfoComparator,
   718  	hip HashInputProvider,
   719  	e *singleElement,
   720  	digests []Digest,
   721  ) (
   722  	size uint32,
   723  	digestMaxLevel uint,
   724  	err error,
   725  ) {
   726  
   727  	// Verify key pointer
   728  	if _, keyPointer := e.key.(StorageIDStorable); e.keyPointer != keyPointer {
   729  		return 0, 0, NewFatalError(fmt.Errorf("element %s keyPointer %t is wrong, want %t", e, e.keyPointer, keyPointer))
   730  	}
   731  
   732  	// Verify key
   733  	kv, err := e.key.StoredValue(storage)
   734  	if err != nil {
   735  		// Wrap err as external error (if needed) because err is returned by Stroable interface.
   736  		return 0, 0, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("element %s key can't be converted to value", e))
   737  	}
   738  
   739  	err = ValidValue(kv, nil, tic, hip)
   740  	if err != nil {
   741  		// Don't need to wrap error as external error because err is already categorized by ValidValue().
   742  		return 0, 0, fmt.Errorf("element %s key isn't valid: %w", e, err)
   743  	}
   744  
   745  	// Verify value pointer
   746  	if _, valuePointer := e.value.(StorageIDStorable); e.valuePointer != valuePointer {
   747  		return 0, 0, NewFatalError(fmt.Errorf("element %s valuePointer %t is wrong, want %t", e, e.valuePointer, valuePointer))
   748  	}
   749  
   750  	// Verify value
   751  	vv, err := e.value.StoredValue(storage)
   752  	if err != nil {
   753  		// Wrap err as external error (if needed) because err is returned by Stroable interface.
   754  		return 0, 0, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("element %s value can't be converted to value", e))
   755  	}
   756  
   757  	err = ValidValue(vv, nil, tic, hip)
   758  	if err != nil {
   759  		// Don't need to wrap error as external error because err is already categorized by ValidValue().
   760  		return 0, 0, fmt.Errorf("element %s value isn't valid: %w", e, err)
   761  	}
   762  
   763  	// Verify size
   764  	computedSize := singleElementPrefixSize + e.key.ByteSize() + e.value.ByteSize()
   765  	if computedSize != e.Size() {
   766  		return 0, 0, NewFatalError(fmt.Errorf("element %s size %d is wrong, want %d", e, e.Size(), computedSize))
   767  	}
   768  
   769  	// Verify digest
   770  	digest, err := db.Digest(hip, kv)
   771  	if err != nil {
   772  		// Wrap err as external error (if needed) because err is returned by DigesterBuilder interface.
   773  		return 0, 0, wrapErrorfAsExternalErrorIfNeeded(err, "failed to create digester")
   774  	}
   775  
   776  	computedDigests, err := digest.DigestPrefix(digest.Levels())
   777  	if err != nil {
   778  		// Wrap err as external error (if needed) because err is returned by Digester interface.
   779  		return 0, 0, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to generate digest prefix up to level %d", digest.Levels()))
   780  	}
   781  
   782  	if !reflect.DeepEqual(digests, computedDigests[:len(digests)]) {
   783  		return 0, 0, NewFatalError(fmt.Errorf("element %s digest %v is wrong, want %v", e, digests, computedDigests))
   784  	}
   785  
   786  	return computedSize, digest.Levels(), nil
   787  }
   788  
   789  func ValidValue(value Value, typeInfo TypeInfo, tic TypeInfoComparator, hip HashInputProvider) error {
   790  	switch v := value.(type) {
   791  	case *Array:
   792  		return ValidArray(v, typeInfo, tic, hip)
   793  	case *OrderedMap:
   794  		return ValidMap(v, typeInfo, tic, hip)
   795  	}
   796  	return nil
   797  }
   798  
   799  // ValidMapSerialization traverses ordered map tree and verifies serialization
   800  // by encoding, decoding, and re-encoding slabs.
   801  // It compares in-memory objects of original slab with decoded slab.
   802  // It also compares encoded data of original slab with encoded data of decoded slab.
   803  func ValidMapSerialization(
   804  	m *OrderedMap,
   805  	cborDecMode cbor.DecMode,
   806  	cborEncMode cbor.EncMode,
   807  	decodeStorable StorableDecoder,
   808  	decodeTypeInfo TypeInfoDecoder,
   809  	compare StorableComparator,
   810  ) error {
   811  	return validMapSlabSerialization(
   812  		m.Storage,
   813  		m.root.ID(),
   814  		cborDecMode,
   815  		cborEncMode,
   816  		decodeStorable,
   817  		decodeTypeInfo,
   818  		compare,
   819  	)
   820  }
   821  
   822  func validMapSlabSerialization(
   823  	storage SlabStorage,
   824  	id StorageID,
   825  	cborDecMode cbor.DecMode,
   826  	cborEncMode cbor.EncMode,
   827  	decodeStorable StorableDecoder,
   828  	decodeTypeInfo TypeInfoDecoder,
   829  	compare StorableComparator,
   830  ) error {
   831  
   832  	slab, err := getMapSlab(storage, id)
   833  	if err != nil {
   834  		// Don't need to wrap error as external error because err is already categorized by getMapSlab().
   835  		return err
   836  	}
   837  
   838  	// Encode slab
   839  	data, err := Encode(slab, cborEncMode)
   840  	if err != nil {
   841  		// Don't need to wrap error as external error because err is already categorized by Encode().
   842  		return err
   843  	}
   844  
   845  	// Decode encoded slab
   846  	decodedSlab, err := DecodeSlab(id, data, cborDecMode, decodeStorable, decodeTypeInfo)
   847  	if err != nil {
   848  		// Don't need to wrap error as external error because err is already categorized by DecodeSlab().
   849  		return err
   850  	}
   851  
   852  	// Re-encode decoded slab
   853  	dataFromDecodedSlab, err := Encode(decodedSlab, cborEncMode)
   854  	if err != nil {
   855  		// Don't need to wrap error as external error because err is already categorized by Encode().
   856  		return err
   857  	}
   858  
   859  	// Extra check: encoded data size == header.size
   860  	encodedExtraDataSize, err := getEncodedMapExtraDataSize(slab.ExtraData(), cborEncMode)
   861  	if err != nil {
   862  		// Don't need to wrap error as external error because err is already categorized by getEncodedMapExtraDataSize().
   863  		return err
   864  	}
   865  
   866  	// Need to exclude extra data size from encoded data size.
   867  	encodedSlabSize := uint32(len(data) - encodedExtraDataSize)
   868  	if slab.Header().size != encodedSlabSize {
   869  		return NewFatalError(
   870  			fmt.Errorf("slab %d encoded size %d != header.size %d (encoded extra data size %d)",
   871  				id, encodedSlabSize, slab.Header().size, encodedExtraDataSize))
   872  	}
   873  
   874  	// Compare encoded data of original slab with encoded data of decoded slab
   875  	if !bytes.Equal(data, dataFromDecodedSlab) {
   876  		return NewFatalError(
   877  			fmt.Errorf("slab %d encoded data is different from decoded slab's encoded data, got %v, want %v",
   878  				id, dataFromDecodedSlab, data))
   879  	}
   880  
   881  	if slab.IsData() {
   882  		dataSlab, ok := slab.(*MapDataSlab)
   883  		if !ok {
   884  			return NewFatalError(fmt.Errorf("slab %d is not MapDataSlab", id))
   885  		}
   886  
   887  		decodedDataSlab, ok := decodedSlab.(*MapDataSlab)
   888  		if !ok {
   889  			return NewFatalError(fmt.Errorf("decoded slab %d is not MapDataSlab", id))
   890  		}
   891  
   892  		// Compare slabs
   893  		err = mapDataSlabEqual(
   894  			dataSlab,
   895  			decodedDataSlab,
   896  			storage,
   897  			cborDecMode,
   898  			cborEncMode,
   899  			decodeStorable,
   900  			decodeTypeInfo,
   901  			compare,
   902  		)
   903  		if err != nil {
   904  			// Don't need to wrap error as external error because err is already categorized by mapDataSlabEqual().
   905  			return fmt.Errorf("data slab %d round-trip serialization failed: %w", id, err)
   906  		}
   907  
   908  		return nil
   909  	}
   910  
   911  	metaSlab, ok := slab.(*MapMetaDataSlab)
   912  	if !ok {
   913  		return NewFatalError(fmt.Errorf("slab %d is not MapMetaDataSlab", id))
   914  	}
   915  
   916  	decodedMetaSlab, ok := decodedSlab.(*MapMetaDataSlab)
   917  	if !ok {
   918  		return NewFatalError(fmt.Errorf("decoded slab %d is not MapMetaDataSlab", id))
   919  	}
   920  
   921  	// Compare slabs
   922  	err = mapMetaDataSlabEqual(metaSlab, decodedMetaSlab)
   923  	if err != nil {
   924  		// Don't need to wrap error as external error because err is already categorized by mapMetaDataSlabEqual().
   925  		return fmt.Errorf("metadata slab %d round-trip serialization failed: %w", id, err)
   926  	}
   927  
   928  	for _, h := range metaSlab.childrenHeaders {
   929  		// Verify child slabs
   930  		err = validMapSlabSerialization(
   931  			storage,
   932  			h.id,
   933  			cborDecMode,
   934  			cborEncMode,
   935  			decodeStorable,
   936  			decodeTypeInfo,
   937  			compare,
   938  		)
   939  		if err != nil {
   940  			// Don't need to wrap error as external error because err is already categorized by validMapSlabSerialization().
   941  			return err
   942  		}
   943  	}
   944  
   945  	return nil
   946  }
   947  
   948  func mapDataSlabEqual(
   949  	expected *MapDataSlab,
   950  	actual *MapDataSlab,
   951  	storage SlabStorage,
   952  	cborDecMode cbor.DecMode,
   953  	cborEncMode cbor.EncMode,
   954  	decodeStorable StorableDecoder,
   955  	decodeTypeInfo TypeInfoDecoder,
   956  	compare StorableComparator,
   957  ) error {
   958  
   959  	// Compare extra data
   960  	err := mapExtraDataEqual(expected.extraData, actual.extraData)
   961  	if err != nil {
   962  		// Don't need to wrap error as external error because err is already categorized by mapExtraDataEqual().
   963  		return err
   964  	}
   965  
   966  	// Compare next
   967  	if expected.next != actual.next {
   968  		return NewFatalError(fmt.Errorf("next %d is wrong, want %d", actual.next, expected.next))
   969  	}
   970  
   971  	// Compare anySize flag
   972  	if expected.anySize != actual.anySize {
   973  		return NewFatalError(fmt.Errorf("anySize %t is wrong, want %t", actual.anySize, expected.anySize))
   974  	}
   975  
   976  	// Compare collisionGroup flag
   977  	if expected.collisionGroup != actual.collisionGroup {
   978  		return NewFatalError(fmt.Errorf("collisionGroup %t is wrong, want %t", actual.collisionGroup, expected.collisionGroup))
   979  	}
   980  
   981  	// Compare header
   982  	if !reflect.DeepEqual(expected.header, actual.header) {
   983  		return NewFatalError(fmt.Errorf("header %+v is wrong, want %+v", actual.header, expected.header))
   984  	}
   985  
   986  	// Compare elements
   987  	err = mapElementsEqual(
   988  		expected.elements,
   989  		actual.elements,
   990  		storage,
   991  		cborDecMode,
   992  		cborEncMode,
   993  		decodeStorable,
   994  		decodeTypeInfo,
   995  		compare,
   996  	)
   997  	if err != nil {
   998  		// Don't need to wrap error as external error because err is already categorized by mapElementsEqual().
   999  		return err
  1000  	}
  1001  
  1002  	return nil
  1003  }
  1004  
  1005  func mapElementsEqual(
  1006  	expected elements,
  1007  	actual elements,
  1008  	storage SlabStorage,
  1009  	cborDecMode cbor.DecMode,
  1010  	cborEncMode cbor.EncMode,
  1011  	decodeStorable StorableDecoder,
  1012  	decodeTypeInfo TypeInfoDecoder,
  1013  	compare StorableComparator,
  1014  ) error {
  1015  	switch expectedElems := expected.(type) {
  1016  
  1017  	case *hkeyElements:
  1018  		actualElems, ok := actual.(*hkeyElements)
  1019  		if !ok {
  1020  			return NewFatalError(fmt.Errorf("elements type %T is wrong, want %T", actual, expected))
  1021  		}
  1022  		return mapHkeyElementsEqual(
  1023  			expectedElems,
  1024  			actualElems,
  1025  			storage,
  1026  			cborDecMode,
  1027  			cborEncMode,
  1028  			decodeStorable,
  1029  			decodeTypeInfo,
  1030  			compare,
  1031  		)
  1032  
  1033  	case *singleElements:
  1034  		actualElems, ok := actual.(*singleElements)
  1035  		if !ok {
  1036  			return NewFatalError(fmt.Errorf("elements type %T is wrong, want %T", actual, expected))
  1037  		}
  1038  		return mapSingleElementsEqual(
  1039  			expectedElems,
  1040  			actualElems,
  1041  			storage,
  1042  			cborDecMode,
  1043  			cborEncMode,
  1044  			decodeStorable,
  1045  			decodeTypeInfo,
  1046  			compare,
  1047  		)
  1048  
  1049  	}
  1050  
  1051  	return nil
  1052  }
  1053  
  1054  func mapHkeyElementsEqual(
  1055  	expected *hkeyElements,
  1056  	actual *hkeyElements,
  1057  	storage SlabStorage,
  1058  	cborDecMode cbor.DecMode,
  1059  	cborEncMode cbor.EncMode,
  1060  	decodeStorable StorableDecoder,
  1061  	decodeTypeInfo TypeInfoDecoder,
  1062  	compare StorableComparator,
  1063  ) error {
  1064  
  1065  	if expected.level != actual.level {
  1066  		return NewFatalError(fmt.Errorf("hkeyElements level %d is wrong, want %d", actual.level, expected.level))
  1067  	}
  1068  
  1069  	if expected.size != actual.size {
  1070  		return NewFatalError(fmt.Errorf("hkeyElements size %d is wrong, want %d", actual.size, expected.size))
  1071  	}
  1072  
  1073  	if len(expected.hkeys) == 0 {
  1074  		if len(actual.hkeys) != 0 {
  1075  			return NewFatalError(fmt.Errorf("hkeyElements hkeys %v is wrong, want %v", actual.hkeys, expected.hkeys))
  1076  		}
  1077  	} else {
  1078  		if !reflect.DeepEqual(expected.hkeys, actual.hkeys) {
  1079  			return NewFatalError(fmt.Errorf("hkeyElements hkeys %v is wrong, want %v", actual.hkeys, expected.hkeys))
  1080  		}
  1081  	}
  1082  
  1083  	if len(expected.elems) != len(actual.elems) {
  1084  		return NewFatalError(fmt.Errorf("hkeyElements elems len %d is wrong, want %d", len(actual.elems), len(expected.elems)))
  1085  	}
  1086  
  1087  	for i := 0; i < len(expected.elems); i++ {
  1088  		expectedEle := expected.elems[i]
  1089  		actualEle := actual.elems[i]
  1090  
  1091  		err := mapElementEqual(
  1092  			expectedEle,
  1093  			actualEle,
  1094  			storage,
  1095  			cborDecMode,
  1096  			cborEncMode,
  1097  			decodeStorable,
  1098  			decodeTypeInfo,
  1099  			compare,
  1100  		)
  1101  		if err != nil {
  1102  			// Don't need to wrap error as external error because err is already categorized by mapElementEqual().
  1103  			return err
  1104  		}
  1105  	}
  1106  
  1107  	return nil
  1108  }
  1109  
  1110  func mapSingleElementsEqual(
  1111  	expected *singleElements,
  1112  	actual *singleElements,
  1113  	storage SlabStorage,
  1114  	cborDecMode cbor.DecMode,
  1115  	cborEncMode cbor.EncMode,
  1116  	decodeStorable StorableDecoder,
  1117  	decodeTypeInfo TypeInfoDecoder,
  1118  	compare StorableComparator,
  1119  ) error {
  1120  
  1121  	if expected.level != actual.level {
  1122  		return NewFatalError(fmt.Errorf("singleElements level %d is wrong, want %d", actual.level, expected.level))
  1123  	}
  1124  
  1125  	if expected.size != actual.size {
  1126  		return NewFatalError(fmt.Errorf("singleElements size %d is wrong, want %d", actual.size, expected.size))
  1127  	}
  1128  
  1129  	if len(expected.elems) != len(actual.elems) {
  1130  		return NewFatalError(fmt.Errorf("singleElements elems len %d is wrong, want %d", len(actual.elems), len(expected.elems)))
  1131  	}
  1132  
  1133  	for i := 0; i < len(expected.elems); i++ {
  1134  		expectedElem := expected.elems[i]
  1135  		actualElem := actual.elems[i]
  1136  
  1137  		err := mapSingleElementEqual(
  1138  			expectedElem,
  1139  			actualElem,
  1140  			storage,
  1141  			cborDecMode,
  1142  			cborEncMode,
  1143  			decodeStorable,
  1144  			decodeTypeInfo,
  1145  			compare,
  1146  		)
  1147  		if err != nil {
  1148  			// Don't need to wrap error as external error because err is already categorized by mapSingleElementEqual().
  1149  			return err
  1150  		}
  1151  	}
  1152  
  1153  	return nil
  1154  }
  1155  
  1156  func mapElementEqual(
  1157  	expected element,
  1158  	actual element,
  1159  	storage SlabStorage,
  1160  	cborDecMode cbor.DecMode,
  1161  	cborEncMode cbor.EncMode,
  1162  	decodeStorable StorableDecoder,
  1163  	decodeTypeInfo TypeInfoDecoder,
  1164  	compare StorableComparator,
  1165  ) error {
  1166  	switch expectedElem := expected.(type) {
  1167  
  1168  	case *singleElement:
  1169  		actualElem, ok := actual.(*singleElement)
  1170  		if !ok {
  1171  			return NewFatalError(fmt.Errorf("elements type %T is wrong, want %T", actual, expected))
  1172  		}
  1173  		return mapSingleElementEqual(
  1174  			expectedElem,
  1175  			actualElem,
  1176  			storage,
  1177  			cborDecMode,
  1178  			cborEncMode,
  1179  			decodeStorable,
  1180  			decodeTypeInfo,
  1181  			compare,
  1182  		)
  1183  
  1184  	case *inlineCollisionGroup:
  1185  		actualElem, ok := actual.(*inlineCollisionGroup)
  1186  		if !ok {
  1187  			return NewFatalError(fmt.Errorf("elements type %T is wrong, want %T", actual, expected))
  1188  		}
  1189  		return mapElementsEqual(
  1190  			expectedElem.elements,
  1191  			actualElem.elements,
  1192  			storage,
  1193  			cborDecMode,
  1194  			cborEncMode,
  1195  			decodeStorable,
  1196  			decodeTypeInfo,
  1197  			compare,
  1198  		)
  1199  
  1200  	case *externalCollisionGroup:
  1201  		actualElem, ok := actual.(*externalCollisionGroup)
  1202  		if !ok {
  1203  			return NewFatalError(fmt.Errorf("elements type %T is wrong, want %T", actual, expected))
  1204  		}
  1205  		return mapExternalCollisionElementsEqual(
  1206  			expectedElem,
  1207  			actualElem,
  1208  			storage,
  1209  			cborDecMode,
  1210  			cborEncMode,
  1211  			decodeStorable,
  1212  			decodeTypeInfo,
  1213  			compare,
  1214  		)
  1215  
  1216  	}
  1217  
  1218  	return nil
  1219  }
  1220  
  1221  func mapExternalCollisionElementsEqual(
  1222  	expected *externalCollisionGroup,
  1223  	actual *externalCollisionGroup,
  1224  	storage SlabStorage,
  1225  	cborDecMode cbor.DecMode,
  1226  	cborEncMode cbor.EncMode,
  1227  	decodeStorable StorableDecoder,
  1228  	decodeTypeInfo TypeInfoDecoder,
  1229  	compare StorableComparator,
  1230  ) error {
  1231  
  1232  	if expected.size != actual.size {
  1233  		return NewFatalError(fmt.Errorf("externalCollisionGroup size %d is wrong, want %d", actual.size, expected.size))
  1234  	}
  1235  
  1236  	if expected.id != actual.id {
  1237  		return NewFatalError(fmt.Errorf("externalCollisionGroup id %d is wrong, want %d", actual.id, expected.id))
  1238  	}
  1239  
  1240  	// Compare external collision slab
  1241  	err := validMapSlabSerialization(
  1242  		storage,
  1243  		expected.id,
  1244  		cborDecMode,
  1245  		cborEncMode,
  1246  		decodeStorable,
  1247  		decodeTypeInfo,
  1248  		compare,
  1249  	)
  1250  	if err != nil {
  1251  		// Don't need to wrap error as external error because err is already categorized by validMapSlabSerialization().
  1252  		return err
  1253  	}
  1254  
  1255  	return nil
  1256  }
  1257  
  1258  func mapSingleElementEqual(
  1259  	expected *singleElement,
  1260  	actual *singleElement,
  1261  	storage SlabStorage,
  1262  	cborDecMode cbor.DecMode,
  1263  	cborEncMode cbor.EncMode,
  1264  	decodeStorable StorableDecoder,
  1265  	decodeTypeInfo TypeInfoDecoder,
  1266  	compare StorableComparator,
  1267  ) error {
  1268  
  1269  	if expected.size != actual.size {
  1270  		return NewFatalError(fmt.Errorf("singleElement size %d is wrong, want %d", actual.size, expected.size))
  1271  	}
  1272  
  1273  	if expected.keyPointer != actual.keyPointer {
  1274  		return NewFatalError(fmt.Errorf("singleElement keyPointer %t is wrong, want %t", actual.keyPointer, expected.keyPointer))
  1275  	}
  1276  
  1277  	if expected.valuePointer != actual.valuePointer {
  1278  		return NewFatalError(fmt.Errorf("singleElement valuePointer %t is wrong, want %t", actual.valuePointer, expected.valuePointer))
  1279  	}
  1280  
  1281  	if !compare(expected.key, actual.key) {
  1282  		return NewFatalError(fmt.Errorf("singleElement key %v is wrong, want %v", actual.key, expected.key))
  1283  	}
  1284  
  1285  	// Compare key stored in a separate slab
  1286  	if idStorable, ok := expected.key.(StorageIDStorable); ok {
  1287  
  1288  		v, err := idStorable.StoredValue(storage)
  1289  		if err != nil {
  1290  			// Don't need to wrap error as external error because err is already categorized by StorageIDStorable.StoredValue().
  1291  			return err
  1292  		}
  1293  
  1294  		err = ValidValueSerialization(
  1295  			v,
  1296  			cborDecMode,
  1297  			cborEncMode,
  1298  			decodeStorable,
  1299  			decodeTypeInfo,
  1300  			compare,
  1301  		)
  1302  		if err != nil {
  1303  			// Don't need to wrap error as external error because err is already categorized by ValidValueSerialization().
  1304  			return err
  1305  		}
  1306  	}
  1307  
  1308  	if !compare(expected.value, actual.value) {
  1309  		return NewFatalError(fmt.Errorf("singleElement value %v is wrong, want %v", actual.value, expected.value))
  1310  	}
  1311  
  1312  	// Compare value stored in a separate slab
  1313  	if idStorable, ok := expected.value.(StorageIDStorable); ok {
  1314  
  1315  		v, err := idStorable.StoredValue(storage)
  1316  		if err != nil {
  1317  			// Don't need to wrap error as external error because err is already categorized by StorageIDStorable.StoredValue().
  1318  			return err
  1319  		}
  1320  
  1321  		err = ValidValueSerialization(
  1322  			v,
  1323  			cborDecMode,
  1324  			cborEncMode,
  1325  			decodeStorable,
  1326  			decodeTypeInfo,
  1327  			compare,
  1328  		)
  1329  		if err != nil {
  1330  			// Don't need to wrap error as external error because err is already categorized by ValidValueSerialization().
  1331  			return err
  1332  		}
  1333  	}
  1334  
  1335  	return nil
  1336  }
  1337  
  1338  func mapMetaDataSlabEqual(expected, actual *MapMetaDataSlab) error {
  1339  
  1340  	// Compare extra data
  1341  	err := mapExtraDataEqual(expected.extraData, actual.extraData)
  1342  	if err != nil {
  1343  		// Don't need to wrap error as external error because err is already categorized by mapExtraDataEqual().
  1344  		return err
  1345  	}
  1346  
  1347  	// Compare header
  1348  	if !reflect.DeepEqual(expected.header, actual.header) {
  1349  		return NewFatalError(fmt.Errorf("header %+v is wrong, want %+v", actual.header, expected.header))
  1350  	}
  1351  
  1352  	// Compare childrenHeaders
  1353  	if !reflect.DeepEqual(expected.childrenHeaders, actual.childrenHeaders) {
  1354  		return NewFatalError(fmt.Errorf("childrenHeaders %+v is wrong, want %+v", actual.childrenHeaders, expected.childrenHeaders))
  1355  	}
  1356  
  1357  	return nil
  1358  }
  1359  
  1360  func mapExtraDataEqual(expected, actual *MapExtraData) error {
  1361  
  1362  	if (expected == nil) && (actual == nil) {
  1363  		return nil
  1364  	}
  1365  
  1366  	if (expected == nil) != (actual == nil) {
  1367  		return NewFatalError(fmt.Errorf("has extra data is %t, want %t", actual == nil, expected == nil))
  1368  	}
  1369  
  1370  	if !reflect.DeepEqual(*expected, *actual) {
  1371  		return NewFatalError(fmt.Errorf("extra data %+v is wrong, want %+v", *actual, *expected))
  1372  	}
  1373  
  1374  	return nil
  1375  }
  1376  
  1377  func getEncodedMapExtraDataSize(extraData *MapExtraData, cborEncMode cbor.EncMode) (int, error) {
  1378  	if extraData == nil {
  1379  		return 0, nil
  1380  	}
  1381  
  1382  	var buf bytes.Buffer
  1383  	enc := NewEncoder(&buf, cborEncMode)
  1384  
  1385  	err := extraData.Encode(enc, byte(0), byte(0))
  1386  	if err != nil {
  1387  		// Don't need to wrap error as external error because err is already categorized by MapExtraData.Encode().
  1388  		return 0, err
  1389  	}
  1390  
  1391  	return len(buf.Bytes()), nil
  1392  }