github.com/onflow/atree@v0.6.0/array_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 "strings" 27 28 "github.com/fxamacker/cbor/v2" 29 ) 30 31 type ArrayStats struct { 32 Levels uint64 33 ElementCount uint64 34 MetaDataSlabCount uint64 35 DataSlabCount uint64 36 StorableSlabCount uint64 37 } 38 39 func (s *ArrayStats) SlabCount() uint64 { 40 return s.DataSlabCount + s.MetaDataSlabCount + s.StorableSlabCount 41 } 42 43 // GetArrayStats returns stats about array slabs. 44 func GetArrayStats(a *Array) (ArrayStats, error) { 45 level := uint64(0) 46 metaDataSlabCount := uint64(0) 47 dataSlabCount := uint64(0) 48 storableSlabCount := uint64(0) 49 50 nextLevelIDs := []StorageID{a.StorageID()} 51 52 for len(nextLevelIDs) > 0 { 53 54 ids := nextLevelIDs 55 56 nextLevelIDs = []StorageID(nil) 57 58 for _, id := range ids { 59 60 slab, err := getArraySlab(a.Storage, id) 61 if err != nil { 62 // Don't need to wrap error as external error because err is already categorized by getArraySlab(). 63 return ArrayStats{}, err 64 } 65 66 if slab.IsData() { 67 dataSlabCount++ 68 69 childStorables := slab.ChildStorables() 70 for _, s := range childStorables { 71 if _, ok := s.(StorageIDStorable); ok { 72 storableSlabCount++ 73 } 74 } 75 } else { 76 metaDataSlabCount++ 77 78 for _, storable := range slab.ChildStorables() { 79 id, ok := storable.(StorageIDStorable) 80 if !ok { 81 return ArrayStats{}, NewFatalError(fmt.Errorf("metadata slab's child storables are not of type StorageIDStorable")) 82 } 83 nextLevelIDs = append(nextLevelIDs, StorageID(id)) 84 } 85 } 86 } 87 88 level++ 89 90 } 91 92 return ArrayStats{ 93 Levels: level, 94 ElementCount: a.Count(), 95 MetaDataSlabCount: metaDataSlabCount, 96 DataSlabCount: dataSlabCount, 97 StorableSlabCount: storableSlabCount, 98 }, nil 99 } 100 101 // PrintArray prints array slab data to stdout. 102 func PrintArray(a *Array) { 103 dumps, err := DumpArraySlabs(a) 104 if err != nil { 105 fmt.Println(err) 106 return 107 } 108 fmt.Println(strings.Join(dumps, "\n")) 109 } 110 111 func DumpArraySlabs(a *Array) ([]string, error) { 112 var dumps []string 113 114 nextLevelIDs := []StorageID{a.StorageID()} 115 116 var overflowIDs []StorageID 117 118 level := 0 119 for len(nextLevelIDs) > 0 { 120 121 ids := nextLevelIDs 122 123 nextLevelIDs = []StorageID(nil) 124 125 for _, id := range ids { 126 127 slab, err := getArraySlab(a.Storage, id) 128 if err != nil { 129 // Don't need to wrap error as external error because err is already categorized by getArraySlab(). 130 return nil, err 131 } 132 133 if slab.IsData() { 134 dataSlab := slab.(*ArrayDataSlab) 135 dumps = append(dumps, fmt.Sprintf("level %d, %s", level+1, dataSlab)) 136 137 childStorables := dataSlab.ChildStorables() 138 for _, e := range childStorables { 139 if id, ok := e.(StorageIDStorable); ok { 140 overflowIDs = append(overflowIDs, StorageID(id)) 141 } 142 } 143 144 } else { 145 meta := slab.(*ArrayMetaDataSlab) 146 dumps = append(dumps, fmt.Sprintf("level %d, %s", level+1, meta)) 147 148 for _, storable := range slab.ChildStorables() { 149 id, ok := storable.(StorageIDStorable) 150 if !ok { 151 return nil, NewFatalError(errors.New("metadata slab's child storables are not of type StorageIDStorable")) 152 } 153 nextLevelIDs = append(nextLevelIDs, StorageID(id)) 154 } 155 } 156 } 157 158 level++ 159 } 160 161 for _, id := range overflowIDs { 162 slab, found, err := a.Storage.Retrieve(id) 163 if err != nil { 164 // Wrap err as external error (if needed) because err is returned by SlabStorage interface. 165 return nil, wrapErrorfAsExternalErrorIfNeeded(err, fmt.Sprintf("failed to retrieve slab %s", id)) 166 } 167 if !found { 168 return nil, NewSlabNotFoundErrorf(id, "slab not found during array slab dump") 169 } 170 dumps = append(dumps, fmt.Sprintf("overflow: %s", slab)) 171 } 172 173 return dumps, nil 174 } 175 176 type TypeInfoComparator func(TypeInfo, TypeInfo) bool 177 178 func ValidArray(a *Array, typeInfo TypeInfo, tic TypeInfoComparator, hip HashInputProvider) error { 179 180 extraData := a.root.ExtraData() 181 if extraData == nil { 182 return NewFatalError(fmt.Errorf("root slab %d doesn't have extra data", a.root.ID())) 183 } 184 185 // Verify that extra data has correct type information 186 if typeInfo != nil && !tic(extraData.TypeInfo, typeInfo) { 187 return NewFatalError(fmt.Errorf( 188 "root slab %d type information %v is wrong, want %v", 189 a.root.ID(), 190 extraData.TypeInfo, 191 typeInfo, 192 )) 193 } 194 195 computedCount, dataSlabIDs, nextDataSlabIDs, err := 196 validArraySlab(tic, hip, a.Storage, a.root.Header().id, 0, nil, []StorageID{}, []StorageID{}) 197 if err != nil { 198 // Don't need to wrap error as external error because err is already categorized by validArraySlab(). 199 return err 200 } 201 202 // Verify array count 203 if computedCount != uint32(a.Count()) { 204 return NewFatalError(fmt.Errorf("root slab %d count %d is wrong, want %d", a.root.ID(), a.Count(), computedCount)) 205 } 206 207 // Verify next data slab ids 208 if !reflect.DeepEqual(dataSlabIDs[1:], nextDataSlabIDs) { 209 return NewFatalError(fmt.Errorf("chained next data slab ids %v are wrong, want %v", 210 nextDataSlabIDs, dataSlabIDs[1:])) 211 } 212 213 return nil 214 } 215 216 func validArraySlab( 217 tic TypeInfoComparator, 218 hip HashInputProvider, 219 storage SlabStorage, 220 id StorageID, 221 level int, 222 headerFromParentSlab *ArraySlabHeader, 223 dataSlabIDs []StorageID, 224 nextDataSlabIDs []StorageID, 225 ) ( 226 elementCount uint32, 227 _dataSlabIDs []StorageID, 228 _nextDataSlabIDs []StorageID, 229 err error, 230 ) { 231 232 slab, err := getArraySlab(storage, id) 233 if err != nil { 234 // Don't need to wrap error as external error because err is already categorized by getArraySlab(). 235 return 0, nil, nil, err 236 } 237 238 if level > 0 { 239 // Verify that non-root slab doesn't have extra data 240 if slab.ExtraData() != nil { 241 return 0, nil, nil, NewFatalError(fmt.Errorf("non-root slab %d has extra data", id)) 242 } 243 244 // Verify that non-root slab doesn't underflow 245 if underflowSize, underflow := slab.IsUnderflow(); underflow { 246 return 0, nil, nil, NewFatalError(fmt.Errorf("slab %d underflows by %d bytes", id, underflowSize)) 247 } 248 249 } 250 251 // Verify that slab doesn't overflow 252 if slab.IsFull() { 253 return 0, nil, nil, NewFatalError(fmt.Errorf("slab %d overflows", id)) 254 } 255 256 // Verify that header is in sync with header from parent slab 257 if headerFromParentSlab != nil { 258 if !reflect.DeepEqual(*headerFromParentSlab, slab.Header()) { 259 return 0, nil, nil, NewFatalError(fmt.Errorf("slab %d header %+v is different from header %+v from parent slab", 260 id, slab.Header(), headerFromParentSlab)) 261 } 262 } 263 264 if slab.IsData() { 265 dataSlab, ok := slab.(*ArrayDataSlab) 266 if !ok { 267 return 0, nil, nil, NewFatalError(fmt.Errorf("slab %d is not ArrayDataSlab", id)) 268 } 269 270 // Verify that element count is the same as header.count 271 if uint32(len(dataSlab.elements)) != dataSlab.header.count { 272 return 0, nil, nil, NewFatalError(fmt.Errorf("data slab %d header count %d is wrong, want %d", 273 id, dataSlab.header.count, len(dataSlab.elements))) 274 } 275 276 // Verify that aggregated element size + slab prefix is the same as header.size 277 computedSize := uint32(arrayDataSlabPrefixSize) 278 if level == 0 { 279 computedSize = uint32(arrayRootDataSlabPrefixSize) 280 } 281 for _, e := range dataSlab.elements { 282 283 // Verify element size is <= inline size 284 if e.ByteSize() > uint32(MaxInlineArrayElementSize) { 285 return 0, nil, nil, NewFatalError(fmt.Errorf("data slab %d element %s size %d is too large, want < %d", 286 id, e, e.ByteSize(), MaxInlineArrayElementSize)) 287 } 288 289 computedSize += e.ByteSize() 290 } 291 292 if computedSize != dataSlab.header.size { 293 return 0, nil, nil, NewFatalError(fmt.Errorf("data slab %d header size %d is wrong, want %d", 294 id, dataSlab.header.size, computedSize)) 295 } 296 297 dataSlabIDs = append(dataSlabIDs, id) 298 299 if dataSlab.next != StorageIDUndefined { 300 nextDataSlabIDs = append(nextDataSlabIDs, dataSlab.next) 301 } 302 303 // Verify element 304 for _, e := range dataSlab.elements { 305 v, err := e.StoredValue(storage) 306 if err != nil { 307 // Wrap err as external error (if needed) because err is returned by Storable interface. 308 return 0, nil, nil, wrapErrorfAsExternalErrorIfNeeded(err, 309 fmt.Sprintf( 310 "data slab %s element %s can't be converted to value", 311 id, e, 312 )) 313 } 314 err = ValidValue(v, nil, tic, hip) 315 if err != nil { 316 // Don't need to wrap error as external error because err is already categorized by ValidValue(). 317 return 0, nil, nil, fmt.Errorf( 318 "data slab %d element %s isn't valid: %w", 319 id, e, err, 320 ) 321 } 322 } 323 324 return dataSlab.header.count, dataSlabIDs, nextDataSlabIDs, nil 325 } 326 327 meta, ok := slab.(*ArrayMetaDataSlab) 328 if !ok { 329 return 0, nil, nil, NewFatalError(fmt.Errorf("slab %d is not ArrayMetaDataSlab", id)) 330 } 331 332 if level == 0 { 333 // Verify that root slab has more than one child slabs 334 if len(meta.childrenHeaders) < 2 { 335 return 0, nil, nil, NewFatalError(fmt.Errorf("root metadata slab %d has %d children, want at least 2 children ", 336 id, len(meta.childrenHeaders))) 337 } 338 } 339 340 // Verify childrenCountSum 341 if len(meta.childrenCountSum) != len(meta.childrenHeaders) { 342 return 0, nil, nil, NewFatalError(fmt.Errorf("metadata slab %d has %d childrenCountSum, want %d", 343 id, len(meta.childrenCountSum), len(meta.childrenHeaders))) 344 } 345 346 computedCount := uint32(0) 347 for i, h := range meta.childrenHeaders { 348 // Verify child slabs 349 var count uint32 350 count, dataSlabIDs, nextDataSlabIDs, err = 351 validArraySlab(tic, hip, storage, h.id, level+1, &h, dataSlabIDs, nextDataSlabIDs) 352 if err != nil { 353 // Don't need to wrap error as external error because err is already categorized by validArraySlab(). 354 return 0, nil, nil, err 355 } 356 357 computedCount += count 358 359 // Verify childrenCountSum 360 if meta.childrenCountSum[i] != computedCount { 361 return 0, nil, nil, NewFatalError(fmt.Errorf("metadata slab %d childrenCountSum[%d] is %d, want %d", 362 id, i, meta.childrenCountSum[i], computedCount)) 363 } 364 } 365 366 // Verify that aggregated element count is the same as header.count 367 if computedCount != meta.header.count { 368 return 0, nil, nil, NewFatalError(fmt.Errorf("metadata slab %d header count %d is wrong, want %d", 369 id, meta.header.count, computedCount)) 370 } 371 372 // Verify that aggregated header size + slab prefix is the same as header.size 373 computedSize := uint32(len(meta.childrenHeaders)*arraySlabHeaderSize) + arrayMetaDataSlabPrefixSize 374 if computedSize != meta.header.size { 375 return 0, nil, nil, NewFatalError(fmt.Errorf("metadata slab %d header size %d is wrong, want %d", 376 id, meta.header.size, computedSize)) 377 } 378 379 return meta.header.count, dataSlabIDs, nextDataSlabIDs, nil 380 } 381 382 // ValidArraySerialization traverses array tree and verifies serialization 383 // by encoding, decoding, and re-encoding slabs. 384 // It compares in-memory objects of original slab with decoded slab. 385 // It also compares encoded data of original slab with encoded data of decoded slab. 386 func ValidArraySerialization( 387 a *Array, 388 cborDecMode cbor.DecMode, 389 cborEncMode cbor.EncMode, 390 decodeStorable StorableDecoder, 391 decodeTypeInfo TypeInfoDecoder, 392 compare StorableComparator, 393 ) error { 394 return validArraySlabSerialization( 395 a.Storage, 396 a.root.ID(), 397 cborDecMode, 398 cborEncMode, 399 decodeStorable, 400 decodeTypeInfo, 401 compare, 402 ) 403 } 404 405 func validArraySlabSerialization( 406 storage SlabStorage, 407 id StorageID, 408 cborDecMode cbor.DecMode, 409 cborEncMode cbor.EncMode, 410 decodeStorable StorableDecoder, 411 decodeTypeInfo TypeInfoDecoder, 412 compare StorableComparator, 413 ) error { 414 415 slab, err := getArraySlab(storage, id) 416 if err != nil { 417 // Don't need to wrap error as external error because err is already categorized by getArraySlab(). 418 return err 419 } 420 421 // Encode slab 422 data, err := Encode(slab, cborEncMode) 423 if err != nil { 424 // Don't need to wrap error as external error because err is already categorized by Encode(). 425 return err 426 } 427 428 // Decode encoded slab 429 decodedSlab, err := DecodeSlab(id, data, cborDecMode, decodeStorable, decodeTypeInfo) 430 if err != nil { 431 // Don't need to wrap error as external error because err is already categorized by DecodeSlab(). 432 return err 433 } 434 435 // Re-encode decoded slab 436 dataFromDecodedSlab, err := Encode(decodedSlab, cborEncMode) 437 if err != nil { 438 // Don't need to wrap error as external error because err is already categorized by Encode(). 439 return err 440 } 441 442 // Extra check: encoded data size == header.size 443 encodedExtraDataSize, err := getEncodedArrayExtraDataSize(slab.ExtraData(), cborEncMode) 444 if err != nil { 445 // Don't need to wrap error as external error because err is already categorized by getEncodedArrayExtraDataSize(). 446 return err 447 } 448 449 // Need to exclude extra data size from encoded data size. 450 encodedSlabSize := uint32(len(data) - encodedExtraDataSize) 451 if slab.Header().size != encodedSlabSize { 452 return NewFatalError(fmt.Errorf("slab %d encoded size %d != header.size %d (encoded extra data size %d)", 453 id, encodedSlabSize, slab.Header().size, encodedExtraDataSize)) 454 } 455 456 // Compare encoded data of original slab with encoded data of decoded slab 457 if !bytes.Equal(data, dataFromDecodedSlab) { 458 return NewFatalError(fmt.Errorf("slab %d encoded data is different from decoded slab's encoded data, got %v, want %v", 459 id, dataFromDecodedSlab, data)) 460 } 461 462 if slab.IsData() { 463 dataSlab, ok := slab.(*ArrayDataSlab) 464 if !ok { 465 return NewFatalError(fmt.Errorf("slab %d is not ArrayDataSlab", id)) 466 } 467 468 decodedDataSlab, ok := decodedSlab.(*ArrayDataSlab) 469 if !ok { 470 return NewFatalError(fmt.Errorf("decoded slab %d is not ArrayDataSlab", id)) 471 } 472 473 // Compare slabs 474 err = arrayDataSlabEqual( 475 dataSlab, 476 decodedDataSlab, 477 storage, 478 cborDecMode, 479 cborEncMode, 480 decodeStorable, 481 decodeTypeInfo, 482 compare, 483 ) 484 if err != nil { 485 // Don't need to wrap error as external error because err is already categorized by arrayDataSlabEqual(). 486 return fmt.Errorf("data slab %d round-trip serialization failed: %w", id, err) 487 } 488 489 return nil 490 } 491 492 metaSlab, ok := slab.(*ArrayMetaDataSlab) 493 if !ok { 494 return NewFatalError(fmt.Errorf("slab %d is not ArrayMetaDataSlab", id)) 495 } 496 497 decodedMetaSlab, ok := decodedSlab.(*ArrayMetaDataSlab) 498 if !ok { 499 return NewFatalError(fmt.Errorf("decoded slab %d is not ArrayMetaDataSlab", id)) 500 } 501 502 // Compare slabs 503 err = arrayMetaDataSlabEqual(metaSlab, decodedMetaSlab) 504 if err != nil { 505 // Don't need to wrap error as external error because err is already categorized by arrayMetaDataSlabEqual(). 506 return fmt.Errorf("metadata slab %d round-trip serialization failed: %w", id, err) 507 } 508 509 for _, h := range metaSlab.childrenHeaders { 510 // Verify child slabs 511 err = validArraySlabSerialization( 512 storage, 513 h.id, 514 cborDecMode, 515 cborEncMode, 516 decodeStorable, 517 decodeTypeInfo, 518 compare, 519 ) 520 if err != nil { 521 // Don't need to wrap error as external error because err is already categorized by validArraySlabSerialization(). 522 return err 523 } 524 } 525 526 return nil 527 } 528 529 func arrayDataSlabEqual( 530 expected *ArrayDataSlab, 531 actual *ArrayDataSlab, 532 storage SlabStorage, 533 cborDecMode cbor.DecMode, 534 cborEncMode cbor.EncMode, 535 decodeStorable StorableDecoder, 536 decodeTypeInfo TypeInfoDecoder, 537 compare StorableComparator, 538 ) error { 539 540 // Compare extra data 541 err := arrayExtraDataEqual(expected.extraData, actual.extraData) 542 if err != nil { 543 // Don't need to wrap error as external error because err is already categorized by arrayExtraDataEqual(). 544 return err 545 } 546 547 // Compare next 548 if expected.next != actual.next { 549 return NewFatalError(fmt.Errorf("next %d is wrong, want %d", actual.next, expected.next)) 550 } 551 552 // Compare header 553 if !reflect.DeepEqual(expected.header, actual.header) { 554 return NewFatalError(fmt.Errorf("header %+v is wrong, want %+v", actual.header, expected.header)) 555 } 556 557 // Compare elements length 558 if len(expected.elements) != len(actual.elements) { 559 return NewFatalError(fmt.Errorf("elements len %d is wrong, want %d", len(actual.elements), len(expected.elements))) 560 } 561 562 // Compare element 563 for i := 0; i < len(expected.elements); i++ { 564 ee := expected.elements[i] 565 ae := actual.elements[i] 566 if !compare(ee, ae) { 567 return NewFatalError(fmt.Errorf("element %d %+v is wrong, want %+v", i, ae, ee)) 568 } 569 570 // Compare nested element 571 if idStorable, ok := ee.(StorageIDStorable); ok { 572 573 ev, err := idStorable.StoredValue(storage) 574 if err != nil { 575 // Don't need to wrap error as external error because err is already categorized by StorageIDStorable.StoredValue(). 576 return err 577 } 578 579 return ValidValueSerialization( 580 ev, 581 cborDecMode, 582 cborEncMode, 583 decodeStorable, 584 decodeTypeInfo, 585 compare, 586 ) 587 } 588 } 589 590 return nil 591 } 592 593 func arrayMetaDataSlabEqual(expected, actual *ArrayMetaDataSlab) error { 594 595 // Compare extra data 596 err := arrayExtraDataEqual(expected.extraData, actual.extraData) 597 if err != nil { 598 // Don't need to wrap error as external error because err is already categorized by arrayExtraDataEqual(). 599 return err 600 } 601 602 // Compare header 603 if !reflect.DeepEqual(expected.header, actual.header) { 604 return NewFatalError(fmt.Errorf("header %+v is wrong, want %+v", actual.header, expected.header)) 605 } 606 607 // Compare childrenHeaders 608 if !reflect.DeepEqual(expected.childrenHeaders, actual.childrenHeaders) { 609 return NewFatalError(fmt.Errorf("childrenHeaders %+v is wrong, want %+v", actual.childrenHeaders, expected.childrenHeaders)) 610 } 611 612 // Compare childrenCountSum 613 if !reflect.DeepEqual(expected.childrenCountSum, actual.childrenCountSum) { 614 return NewFatalError(fmt.Errorf("childrenCountSum %+v is wrong, want %+v", actual.childrenCountSum, expected.childrenCountSum)) 615 } 616 617 return nil 618 } 619 620 func arrayExtraDataEqual(expected, actual *ArrayExtraData) error { 621 622 if (expected == nil) && (actual == nil) { 623 return nil 624 } 625 626 if (expected == nil) != (actual == nil) { 627 return NewFatalError(fmt.Errorf("has extra data is %t, want %t", actual == nil, expected == nil)) 628 } 629 630 if !reflect.DeepEqual(*expected, *actual) { 631 return NewFatalError(fmt.Errorf("extra data %+v is wrong, want %+v", *actual, *expected)) 632 } 633 634 return nil 635 } 636 637 func getEncodedArrayExtraDataSize(extraData *ArrayExtraData, cborEncMode cbor.EncMode) (int, error) { 638 if extraData == nil { 639 return 0, nil 640 } 641 642 var buf bytes.Buffer 643 enc := NewEncoder(&buf, cborEncMode) 644 645 // Normally the flag shouldn't be 0. But in this case we just need the encoded data size 646 // so the content of the flag doesn't matter. 647 err := extraData.Encode(enc, byte(0)) 648 if err != nil { 649 // Don't need to wrap error as external error because err is already categorized by ArrayExtraData.Encode(). 650 return 0, err 651 } 652 653 return len(buf.Bytes()), nil 654 } 655 656 func ValidValueSerialization( 657 value Value, 658 cborDecMode cbor.DecMode, 659 cborEncMode cbor.EncMode, 660 decodeStorable StorableDecoder, 661 decodeTypeInfo TypeInfoDecoder, 662 compare StorableComparator, 663 ) error { 664 665 switch v := value.(type) { 666 case *Array: 667 return ValidArraySerialization( 668 v, 669 cborDecMode, 670 cborEncMode, 671 decodeStorable, 672 decodeTypeInfo, 673 compare, 674 ) 675 case *OrderedMap: 676 return ValidMapSerialization( 677 v, 678 cborDecMode, 679 cborEncMode, 680 decodeStorable, 681 decodeTypeInfo, 682 compare, 683 ) 684 } 685 return nil 686 }