github.com/onflow/flow-go@v0.35.7-crescendo-preview.23-atree-inlining/ledger/trie_encoder.go (about) 1 package ledger 2 3 import ( 4 "fmt" 5 6 "github.com/onflow/flow-go/ledger/common/bitutils" 7 "github.com/onflow/flow-go/ledger/common/hash" 8 "github.com/onflow/flow-go/ledger/common/utils" 9 ) 10 11 // Versions capture the maximum version of encoding this code supports. 12 // I.e. this code encodes data with the latest version and only decodes 13 // data with version smaller or equal to these versions. 14 // Bumping a version number prevents older versions of code from handling 15 // the newer version of data. New code handling new data version 16 // should be updated to also support backward compatibility if needed. 17 const ( 18 // CAUTION: if payload key encoding is changed, convertEncodedPayloadKey() 19 // must be modified to convert encoded payload key from one version to 20 // another version. 21 PayloadVersion = uint16(1) 22 TrieUpdateVersion = uint16(0) // Use payload version 0 encoding 23 TrieProofVersion = uint16(0) // Use payload version 0 encoding 24 TrieBatchProofVersion = uint16(0) // Use payload version 0 encoding 25 ) 26 27 // Type capture the type of encoded entity (e.g. State, Key, Value, Path) 28 type Type uint8 29 30 const ( 31 // TypeUnknown - unknown type 32 TypeUnknown = iota 33 // TypeState - type for State 34 TypeState 35 // TypeKeyPart - type for KeyParts (a subset of key) 36 TypeKeyPart 37 // TypeKey - type for Keys (unique identifier to reference a location in ledger) 38 TypeKey 39 // TypeValue - type for Ledger Values 40 TypeValue 41 // TypePath - type for Paths (trie storage location of a key value pair) 42 TypePath 43 // TypePayload - type for Payloads (stored at trie nodes including key value pair ) 44 TypePayload 45 // TypeProof type for Proofs 46 // (all data needed to verify a key value pair at specific state) 47 TypeProof 48 // TypeBatchProof - type for BatchProofs 49 TypeBatchProof 50 // TypeQuery - type for ledger query 51 TypeQuery 52 // TypeUpdate - type for ledger update 53 TypeUpdate 54 // TypeTrieUpdate - type for trie update 55 TypeTrieUpdate 56 // this is used to flag types from the future 57 typeUnsuported 58 ) 59 60 func (e Type) String() string { 61 return [...]string{"Unknown", "State", "KeyPart", "Key", "Value", "Path", "Payload", "Proof", "BatchProof", "Query", "Update", "Trie Update"}[e] 62 } 63 64 // CheckVersion extracts encoding bytes from a raw encoded message 65 // checks it against the supported versions and returns the rest of rawInput (excluding encDecVersion bytes) 66 func CheckVersion(rawInput []byte, maxVersion uint16) (rest []byte, version uint16, err error) { 67 version, rest, err = utils.ReadUint16(rawInput) 68 if err != nil { 69 return rest, version, fmt.Errorf("error checking the encoding decoding version: %w", err) 70 } 71 // error on versions coming from future till a time-machine is invented 72 if version > maxVersion { 73 return rest, version, fmt.Errorf("incompatible encoding decoding version (%d > %d): %w", version, maxVersion, err) 74 } 75 // return the rest of bytes 76 return rest, version, nil 77 } 78 79 // CheckType extracts encoding byte from a raw encoded message 80 // checks it against expected type and returns the rest of rawInput (excluding type byte) 81 func CheckType(rawInput []byte, expectedType uint8) (rest []byte, err error) { 82 t, r, err := utils.ReadUint8(rawInput) 83 if err != nil { 84 return r, fmt.Errorf("error checking type of the encoded entity: %w", err) 85 } 86 87 // error if type is known for this code 88 if t >= typeUnsuported { 89 return r, fmt.Errorf("unknown entity type in the encoded data (%d > %d)", t, typeUnsuported) 90 } 91 92 // error if type is known for this code 93 if t != expectedType { 94 return r, fmt.Errorf("unexpected entity type, got (%v) but (%v) was expected", Type(t), Type(expectedType)) 95 } 96 97 // return the rest of bytes 98 return r, nil 99 } 100 101 // EncodeKeyPart encodes a key part into a byte slice 102 func EncodeKeyPart(kp *KeyPart) []byte { 103 if kp == nil { 104 return []byte{} 105 } 106 // encode version 107 buffer := utils.AppendUint16([]byte{}, PayloadVersion) 108 109 // encode key part entity type 110 buffer = utils.AppendUint8(buffer, TypeKeyPart) 111 112 // encode the key part content 113 buffer = append(buffer, encodeKeyPart(kp, PayloadVersion)...) 114 return buffer 115 } 116 117 func encodeKeyPart(kp *KeyPart, version uint16) []byte { 118 buffer := make([]byte, 0, encodedKeyPartLength(kp, version)) 119 return encodeAndAppendKeyPart(buffer, kp, version) 120 } 121 122 func encodeAndAppendKeyPart(buffer []byte, kp *KeyPart, _ uint16) []byte { 123 // encode "Type" field of the key part 124 buffer = utils.AppendUint16(buffer, kp.Type) 125 126 // encode "Value" field of the key part 127 buffer = append(buffer, kp.Value...) 128 129 return buffer 130 } 131 132 func encodedKeyPartLength(kp *KeyPart, _ uint16) int { 133 // Key part is encoded as: type (2 bytes) + value 134 return 2 + len(kp.Value) 135 } 136 137 // DecodeKeyPart constructs a key part from an encoded key part 138 func DecodeKeyPart(encodedKeyPart []byte) (*KeyPart, error) { 139 rest, version, err := CheckVersion(encodedKeyPart, PayloadVersion) 140 if err != nil { 141 return nil, fmt.Errorf("error decoding key part: %w", err) 142 } 143 144 // check the type 145 rest, err = CheckType(rest, TypeKeyPart) 146 if err != nil { 147 return nil, fmt.Errorf("error decoding key part: %w", err) 148 } 149 150 // decode the key part content (zerocopy) 151 kpt, kpv, err := decodeKeyPart(rest, true, version) 152 if err != nil { 153 return nil, fmt.Errorf("error decoding key part: %w", err) 154 } 155 156 return &KeyPart{Type: kpt, Value: kpv}, nil 157 } 158 159 // decodeKeyPart decodes inp into KeyPart. If zeroCopy is true, KeyPart 160 // references data in inp. Otherwise, it is copied. 161 func decodeKeyPart(inp []byte, zeroCopy bool, _ uint16) (uint16, []byte, error) { 162 // read key part type and the rest is the key item part 163 kpt, kpv, err := utils.ReadUint16(inp) 164 if err != nil { 165 return 0, nil, fmt.Errorf("error decoding key part (content): %w", err) 166 } 167 if zeroCopy { 168 return kpt, kpv, nil 169 } 170 v := make([]byte, len(kpv)) 171 copy(v, kpv) 172 return kpt, v, nil 173 } 174 175 // EncodeKey encodes a key into a byte slice 176 func EncodeKey(k *Key) []byte { 177 if k == nil { 178 return []byte{} 179 } 180 // encode EncodingDecodingType 181 buffer := utils.AppendUint16([]byte{}, PayloadVersion) 182 // encode key entity type 183 buffer = utils.AppendUint8(buffer, TypeKey) 184 // encode key content 185 buffer = append(buffer, encodeKey(k, PayloadVersion)...) 186 187 return buffer 188 } 189 190 // encodeKey encodes a key into a byte slice 191 func encodeKey(k *Key, version uint16) []byte { 192 buffer := make([]byte, 0, encodedKeyLength(k, version)) 193 return encodeAndAppendKey(buffer, k, version) 194 } 195 196 func encodeAndAppendKey(buffer []byte, k *Key, version uint16) []byte { 197 // encode number of key parts 198 buffer = utils.AppendUint16(buffer, uint16(len(k.KeyParts))) 199 200 // iterate over key parts 201 for _, kp := range k.KeyParts { 202 // encode the len of the encoded key part 203 buffer = utils.AppendUint32(buffer, uint32(encodedKeyPartLength(&kp, version))) 204 205 // encode the key part 206 buffer = encodeAndAppendKeyPart(buffer, &kp, version) 207 } 208 209 return buffer 210 } 211 212 func encodedKeyLength(k *Key, version uint16) int { 213 // Key is encoded as: number of key parts (2 bytes) and for each key part, 214 // the key part size (4 bytes) + encoded key part (n bytes). 215 size := 2 + 4*len(k.KeyParts) 216 for _, kp := range k.KeyParts { 217 size += encodedKeyPartLength(&kp, version) 218 } 219 return size 220 } 221 222 // DecodeKey constructs a key from an encoded key part 223 func DecodeKey(encodedKey []byte) (*Key, error) { 224 // check the enc dec version 225 rest, version, err := CheckVersion(encodedKey, PayloadVersion) 226 if err != nil { 227 return nil, fmt.Errorf("error decoding key: %w", err) 228 } 229 // check the encoding type 230 rest, err = CheckType(rest, TypeKey) 231 if err != nil { 232 return nil, fmt.Errorf("error decoding key: %w", err) 233 } 234 235 // decode the key content (zerocopy) 236 key, err := decodeKey(rest, true, version) 237 if err != nil { 238 return nil, fmt.Errorf("error decoding key: %w", err) 239 } 240 return key, nil 241 } 242 243 func decodeKeyPartValueByType(inp []byte, typ uint16, zeroCopy bool, version uint16) ([]byte, bool, error) { 244 // Read number of key parts 245 numOfParts, rest, err := utils.ReadUint16(inp) 246 if err != nil { 247 return nil, false, fmt.Errorf("error decoding number of key parts: %w", err) 248 } 249 250 for i := 0; i < int(numOfParts); i++ { 251 var kpt uint16 252 var kpv []byte 253 254 kpt, kpv, rest, err = decodeKeyPartWithEncodedSizeInfo(rest, zeroCopy, version) 255 if err != nil { 256 return nil, false, err 257 } 258 if kpt == typ { 259 return kpv, true, nil 260 } 261 } 262 263 return nil, false, nil 264 } 265 266 func decodeKeyPartWithEncodedSizeInfo( 267 inp []byte, 268 zeroCopy bool, 269 version uint16, 270 ) ( 271 // kp KeyPart, 272 kpt uint16, 273 kpv []byte, 274 rest []byte, 275 err error, 276 ) { 277 278 // Read encoded key part size 279 kpEncSize, rest, err := utils.ReadUint32(inp) 280 if err != nil { 281 return 0, nil, nil, fmt.Errorf("error decoding key part: %w", err) 282 } 283 284 // Read encoded key part 285 var kpEnc []byte 286 kpEnc, rest, err = utils.ReadSlice(rest, int(kpEncSize)) 287 if err != nil { 288 return 0, nil, nil, fmt.Errorf("error decoding key part: %w", err) 289 } 290 291 // Decode encoded key part 292 kpType, kpValue, err := decodeKeyPart(kpEnc, zeroCopy, version) 293 if err != nil { 294 return 0, nil, nil, fmt.Errorf("error decoding key part: %w", err) 295 } 296 297 return kpType, kpValue, rest, nil 298 } 299 300 // decodeKey decodes inp into Key. If zeroCopy is true, returned key 301 // references data in inp. Otherwise, it is copied. 302 func decodeKey(inp []byte, zeroCopy bool, version uint16) (*Key, error) { 303 key := &Key{} 304 305 numOfParts, rest, err := utils.ReadUint16(inp) 306 if err != nil { 307 return nil, fmt.Errorf("error decoding key (content): %w", err) 308 } 309 310 if numOfParts == 0 { 311 return key, nil 312 } 313 314 key.KeyParts = make([]KeyPart, numOfParts) 315 316 for i := 0; i < int(numOfParts); i++ { 317 var kpt uint16 318 var kpv []byte 319 320 kpt, kpv, rest, err = decodeKeyPartWithEncodedSizeInfo(rest, zeroCopy, version) 321 if err != nil { 322 return nil, err 323 } 324 325 key.KeyParts[i] = KeyPart{kpt, kpv} 326 } 327 return key, nil 328 } 329 330 // EncodeValue encodes a value into a byte slice 331 func EncodeValue(v Value) []byte { 332 // encode EncodingDecodingType 333 buffer := utils.AppendUint16([]byte{}, PayloadVersion) 334 335 // encode key entity type 336 buffer = utils.AppendUint8(buffer, TypeValue) 337 338 // encode value 339 buffer = append(buffer, encodeValue(v, PayloadVersion)...) 340 341 return buffer 342 } 343 344 func encodeValue(v Value, _ uint16) []byte { 345 return v 346 } 347 348 func encodeAndAppendValue(buffer []byte, v Value, _ uint16) []byte { 349 return append(buffer, v...) 350 } 351 352 func encodedValueLength(v Value, _ uint16) int { 353 return len(v) 354 } 355 356 // DecodeValue constructs a ledger value using an encoded byte slice 357 func DecodeValue(encodedValue []byte) (Value, error) { 358 // check enc dec version 359 rest, _, err := CheckVersion(encodedValue, PayloadVersion) 360 if err != nil { 361 return nil, err 362 } 363 364 // check the encoding type 365 rest, err = CheckType(rest, TypeValue) 366 if err != nil { 367 return nil, err 368 } 369 370 return rest, nil 371 } 372 373 // EncodePayload encodes a ledger payload 374 func EncodePayload(p *Payload) []byte { 375 if p == nil { 376 return []byte{} 377 } 378 // encode EncodingDecodingType 379 buffer := utils.AppendUint16([]byte{}, PayloadVersion) 380 381 // encode key entity type 382 buffer = utils.AppendUint8(buffer, TypePayload) 383 384 // append encoded payload content 385 buffer = append(buffer, encodePayload(p, PayloadVersion)...) 386 return buffer 387 } 388 389 // EncodeAndAppendPayloadWithoutPrefix encodes a ledger payload 390 // without prefix (version and type) and appends to buffer. 391 // If payload is nil, unmodified buffer is returned. 392 func EncodeAndAppendPayloadWithoutPrefix(buffer []byte, p *Payload, version uint16) []byte { 393 if p == nil { 394 return buffer 395 } 396 return encodeAndAppendPayload(buffer, p, version) 397 } 398 399 func EncodedPayloadLengthWithoutPrefix(p *Payload, version uint16) int { 400 return encodedPayloadLength(p, version) 401 } 402 403 func encodePayload(p *Payload, version uint16) []byte { 404 buffer := make([]byte, 0, encodedPayloadLength(p, version)) 405 return encodeAndAppendPayload(buffer, p, version) 406 } 407 408 // convertEncodedPayloadKey returns encoded payload key in toVersion 409 // converted from encoded payload key in fromVersion. 410 func convertEncodedPayloadKey(key []byte, fromVersion uint16, toVersion uint16) []byte { 411 // No conversion is needed for now because 412 // payload key encoding version 0 is the same as version 1. 413 return key 414 } 415 416 func encodeAndAppendPayload(buffer []byte, p *Payload, version uint16) []byte { 417 418 // convert payload encoded key from PayloadVersion to version. 419 encKey := convertEncodedPayloadKey(p.encKey, PayloadVersion, version) 420 421 // encode encoded key size 422 buffer = utils.AppendUint32(buffer, uint32(len(encKey))) 423 424 // append encoded key 425 buffer = append(buffer, encKey...) 426 427 // encode encoded value size 428 encodedValueLen := encodedValueLength(p.Value(), version) 429 switch version { 430 case 0: 431 // In version 0, encoded value length is encoded as 8 bytes. 432 buffer = utils.AppendUint64(buffer, uint64(encodedValueLen)) 433 default: 434 // In version 1 and later, encoded value length is encoded as 4 bytes. 435 buffer = utils.AppendUint32(buffer, uint32(encodedValueLen)) 436 } 437 438 // encode value 439 buffer = encodeAndAppendValue(buffer, p.Value(), version) 440 441 return buffer 442 } 443 444 func encodedPayloadLength(p *Payload, version uint16) int { 445 if p == nil { 446 return 0 447 } 448 449 // Error isn't checked here because encoded key will be used directly 450 // in later commit and no error will be returned. 451 k, _ := p.Key() 452 453 switch version { 454 case 0: 455 // In version 0, payload is encoded as: 456 // encode key length (4 bytes) + encoded key + 457 // encoded value length (8 bytes) + encode value 458 return 4 + encodedKeyLength(&k, version) + 8 + encodedValueLength(p.Value(), version) 459 default: 460 // In version 1 and later, payload is encoded as: 461 // encode key length (4 bytes) + encoded key + 462 // encoded value length (4 bytes) + encode value 463 return 4 + encodedKeyLength(&k, version) + 4 + encodedValueLength(p.Value(), version) 464 } 465 } 466 467 // DecodePayload construct a payload from an encoded byte slice 468 func DecodePayload(encodedPayload []byte) (*Payload, error) { 469 // if empty don't decode 470 if len(encodedPayload) == 0 { 471 return nil, nil 472 } 473 // check the enc dec version 474 rest, version, err := CheckVersion(encodedPayload, PayloadVersion) 475 if err != nil { 476 return nil, fmt.Errorf("error decoding payload: %w", err) 477 } 478 // check the encoding type 479 rest, err = CheckType(rest, TypePayload) 480 if err != nil { 481 return nil, fmt.Errorf("error decoding payload: %w", err) 482 } 483 // decode payload (zerocopy) 484 return decodePayload(rest, true, version) 485 } 486 487 // DecodePayloadWithoutPrefix constructs a payload from encoded byte slice 488 // without prefix (version and type). If zeroCopy is true, returned payload 489 // references data in encodedPayload. Otherwise, it is copied. 490 func DecodePayloadWithoutPrefix(encodedPayload []byte, zeroCopy bool, version uint16) (*Payload, error) { 491 // if empty don't decode 492 if len(encodedPayload) == 0 { 493 return nil, nil 494 } 495 return decodePayload(encodedPayload, zeroCopy, version) 496 } 497 498 // decodePayload decodes inp into payload. If zeroCopy is true, 499 // returned payload references data in inp. Otherwise, it is copied. 500 func decodePayload(inp []byte, zeroCopy bool, version uint16) (*Payload, error) { 501 502 // read encoded key size 503 encKeySize, rest, err := utils.ReadUint32(inp) 504 if err != nil { 505 return nil, fmt.Errorf("error decoding payload: %w", err) 506 } 507 508 // read encoded key 509 ek, rest, err := utils.ReadSlice(rest, int(encKeySize)) 510 if err != nil { 511 return nil, fmt.Errorf("error decoding payload: %w", err) 512 } 513 514 // convert payload encoded key from version to PayloadVersion. 515 encKey := convertEncodedPayloadKey(ek, version, PayloadVersion) 516 517 // read encoded value size 518 var encValueSize int 519 switch version { 520 case 0: 521 var size uint64 522 size, rest, err = utils.ReadUint64(rest) 523 encValueSize = int(size) 524 default: 525 var size uint32 526 size, rest, err = utils.ReadUint32(rest) 527 encValueSize = int(size) 528 } 529 530 if err != nil { 531 return nil, fmt.Errorf("error decoding payload: %w", err) 532 } 533 534 // read encoded value 535 encValue, _, err := utils.ReadSlice(rest, encValueSize) 536 if err != nil { 537 return nil, fmt.Errorf("error decoding payload: %w", err) 538 } 539 540 if zeroCopy { 541 return &Payload{encKey, encValue}, nil 542 } 543 544 k := make([]byte, len(encKey)) 545 copy(k, encKey) 546 v := make([]byte, len(encValue)) 547 copy(v, encValue) 548 return &Payload{k, v}, nil 549 } 550 551 // EncodeTrieUpdate encodes a trie update struct 552 func EncodeTrieUpdate(t *TrieUpdate) []byte { 553 if t == nil { 554 return []byte{} 555 } 556 // encode EncodingDecodingType 557 buffer := utils.AppendUint16([]byte{}, TrieUpdateVersion) 558 559 // encode key entity type 560 buffer = utils.AppendUint8(buffer, TypeTrieUpdate) 561 562 // append encoded payload content 563 buffer = append(buffer, encodeTrieUpdate(t, TrieUpdateVersion)...) 564 565 return buffer 566 } 567 568 func encodeTrieUpdate(t *TrieUpdate, version uint16) []byte { 569 buffer := make([]byte, 0) 570 571 // encode root hash (size and data) 572 buffer = utils.AppendUint16(buffer, uint16(len(t.RootHash))) 573 buffer = append(buffer, t.RootHash[:]...) 574 575 // encode number of paths 576 buffer = utils.AppendUint32(buffer, uint32(t.Size())) 577 578 if t.Size() == 0 { 579 return buffer 580 } 581 582 // encode paths 583 // encode path size (assuming all paths are the same size) 584 buffer = utils.AppendUint16(buffer, uint16(PathLen)) 585 for _, path := range t.Paths { 586 buffer = append(buffer, path[:]...) 587 } 588 589 // we assume same number of payloads 590 // encode payloads 591 for _, pl := range t.Payloads { 592 encPl := encodePayload(pl, version) 593 buffer = utils.AppendUint32(buffer, uint32(len(encPl))) 594 buffer = append(buffer, encPl...) 595 } 596 597 return buffer 598 } 599 600 // DecodeTrieUpdate construct a trie update from an encoded byte slice 601 func DecodeTrieUpdate(encodedTrieUpdate []byte) (*TrieUpdate, error) { 602 // if empty don't decode 603 if len(encodedTrieUpdate) == 0 { 604 return nil, nil 605 } 606 // check the enc dec version 607 rest, version, err := CheckVersion(encodedTrieUpdate, TrieUpdateVersion) 608 if err != nil { 609 return nil, fmt.Errorf("error decoding trie update: %w", err) 610 } 611 // check the encoding type 612 rest, err = CheckType(rest, TypeTrieUpdate) 613 if err != nil { 614 return nil, fmt.Errorf("error decoding trie update: %w", err) 615 } 616 return decodeTrieUpdate(rest, version) 617 } 618 619 func decodeTrieUpdate(inp []byte, version uint16) (*TrieUpdate, error) { 620 621 // decode root hash 622 rhSize, rest, err := utils.ReadUint16(inp) 623 if err != nil { 624 return nil, fmt.Errorf("error decoding trie update: %w", err) 625 } 626 627 rhBytes, rest, err := utils.ReadSlice(rest, int(rhSize)) 628 if err != nil { 629 return nil, fmt.Errorf("error decoding trie update: %w", err) 630 } 631 rh, err := ToRootHash(rhBytes) 632 if err != nil { 633 return nil, fmt.Errorf("decode trie update failed: %w", err) 634 } 635 636 // decode number of paths 637 numOfPaths, rest, err := utils.ReadUint32(rest) 638 if err != nil { 639 return nil, fmt.Errorf("error decoding trie update: %w", err) 640 } 641 642 // decode path size 643 pathSize, rest, err := utils.ReadUint16(rest) 644 if err != nil { 645 return nil, fmt.Errorf("error decoding trie update: %w", err) 646 } 647 648 paths := make([]Path, numOfPaths) 649 payloads := make([]*Payload, numOfPaths) 650 651 var path Path 652 var encPath []byte 653 for i := 0; i < int(numOfPaths); i++ { 654 encPath, rest, err = utils.ReadSlice(rest, int(pathSize)) 655 if err != nil { 656 return nil, fmt.Errorf("error decoding trie update: %w", err) 657 } 658 path, err = ToPath(encPath) 659 if err != nil { 660 return nil, fmt.Errorf("error decoding trie update: %w", err) 661 } 662 paths[i] = path 663 } 664 665 var payloadSize uint32 666 var encPayload []byte 667 var payload *Payload 668 669 for i := 0; i < int(numOfPaths); i++ { 670 payloadSize, rest, err = utils.ReadUint32(rest) 671 if err != nil { 672 return nil, fmt.Errorf("error decoding trie update: %w", err) 673 } 674 encPayload, rest, err = utils.ReadSlice(rest, int(payloadSize)) 675 if err != nil { 676 return nil, fmt.Errorf("error decoding trie update: %w", err) 677 } 678 // Decode payload (zerocopy) 679 payload, err = decodePayload(encPayload, true, version) 680 if err != nil { 681 return nil, fmt.Errorf("error decoding trie update: %w", err) 682 } 683 payloads[i] = payload 684 } 685 return &TrieUpdate{RootHash: rh, Paths: paths, Payloads: payloads}, nil 686 } 687 688 // EncodeTrieProof encodes the content of a proof into a byte slice 689 func EncodeTrieProof(p *TrieProof) []byte { 690 if p == nil { 691 return []byte{} 692 } 693 // encode version 694 buffer := utils.AppendUint16([]byte{}, TrieProofVersion) 695 696 // encode proof entity type 697 buffer = utils.AppendUint8(buffer, TypeProof) 698 699 // append encoded proof content 700 proof := encodeTrieProof(p, TrieProofVersion) 701 buffer = append(buffer, proof...) 702 703 return buffer 704 } 705 706 func encodeTrieProof(p *TrieProof, version uint16) []byte { 707 // first byte is reserved for inclusion flag 708 buffer := make([]byte, 1) 709 if p.Inclusion { 710 // set the first bit to 1 if it is an inclusion proof 711 buffer[0] |= 1 << 7 712 } 713 714 // steps are encoded as a single byte 715 buffer = utils.AppendUint8(buffer, p.Steps) 716 717 // include flags size and content 718 buffer = utils.AppendUint8(buffer, uint8(len(p.Flags))) 719 buffer = append(buffer, p.Flags...) 720 721 // include path size and content 722 buffer = utils.AppendUint16(buffer, uint16(PathLen)) 723 buffer = append(buffer, p.Path[:]...) 724 725 // include encoded payload size and content 726 encPayload := encodePayload(p.Payload, version) 727 buffer = utils.AppendUint64(buffer, uint64(len(encPayload))) 728 buffer = append(buffer, encPayload...) 729 730 // and finally include all interims (hash values) 731 // number of interims 732 buffer = utils.AppendUint8(buffer, uint8(len(p.Interims))) 733 for _, inter := range p.Interims { 734 buffer = utils.AppendUint16(buffer, uint16(len(inter))) 735 buffer = append(buffer, inter[:]...) 736 } 737 738 return buffer 739 } 740 741 // DecodeTrieProof construct a proof from an encoded byte slice 742 func DecodeTrieProof(encodedProof []byte) (*TrieProof, error) { 743 // check the enc dec version 744 rest, version, err := CheckVersion(encodedProof, TrieProofVersion) 745 if err != nil { 746 return nil, fmt.Errorf("error decoding proof: %w", err) 747 } 748 // check the encoding type 749 rest, err = CheckType(rest, TypeProof) 750 if err != nil { 751 return nil, fmt.Errorf("error decoding proof: %w", err) 752 } 753 return decodeTrieProof(rest, version) 754 } 755 756 func decodeTrieProof(inp []byte, version uint16) (*TrieProof, error) { 757 pInst := NewTrieProof() 758 759 // Inclusion flag 760 byteInclusion, rest, err := utils.ReadSlice(inp, 1) 761 if err != nil { 762 return nil, fmt.Errorf("error decoding proof: %w", err) 763 } 764 pInst.Inclusion = bitutils.ReadBit(byteInclusion, 0) == 1 765 766 // read steps 767 steps, rest, err := utils.ReadUint8(rest) 768 if err != nil { 769 return nil, fmt.Errorf("error decoding proof: %w", err) 770 } 771 pInst.Steps = steps 772 773 // read flags 774 flagsSize, rest, err := utils.ReadUint8(rest) 775 if err != nil { 776 return nil, fmt.Errorf("error decoding proof: %w", err) 777 } 778 flags, rest, err := utils.ReadSlice(rest, int(flagsSize)) 779 if err != nil { 780 return nil, fmt.Errorf("error decoding proof: %w", err) 781 } 782 pInst.Flags = flags 783 784 // read path 785 pathSize, rest, err := utils.ReadUint16(rest) 786 if err != nil { 787 return nil, fmt.Errorf("error decoding proof: %w", err) 788 } 789 path, rest, err := utils.ReadSlice(rest, int(pathSize)) 790 if err != nil { 791 return nil, fmt.Errorf("error decoding proof: %w", err) 792 } 793 pInst.Path, err = ToPath(path) 794 if err != nil { 795 return nil, fmt.Errorf("error decoding proof: %w", err) 796 } 797 798 // read payload 799 encPayloadSize, rest, err := utils.ReadUint64(rest) 800 if err != nil { 801 return nil, fmt.Errorf("error decoding proof: %w", err) 802 } 803 encPayload, rest, err := utils.ReadSlice(rest, int(encPayloadSize)) 804 if err != nil { 805 return nil, fmt.Errorf("error decoding proof: %w", err) 806 } 807 // Decode payload (zerocopy) 808 payload, err := decodePayload(encPayload, true, version) 809 if err != nil { 810 return nil, fmt.Errorf("error decoding proof: %w", err) 811 } 812 pInst.Payload = payload 813 814 // read interims 815 interimsLen, rest, err := utils.ReadUint8(rest) 816 if err != nil { 817 return nil, fmt.Errorf("error decoding proof: %w", err) 818 } 819 820 interims := make([]hash.Hash, interimsLen) 821 822 var interimSize uint16 823 var interim hash.Hash 824 var interimBytes []byte 825 826 for i := 0; i < int(interimsLen); i++ { 827 interimSize, rest, err = utils.ReadUint16(rest) 828 if err != nil { 829 return nil, fmt.Errorf("error decoding proof: %w", err) 830 } 831 832 interimBytes, rest, err = utils.ReadSlice(rest, int(interimSize)) 833 if err != nil { 834 return nil, fmt.Errorf("error decoding proof: %w", err) 835 } 836 interim, err = hash.ToHash(interimBytes) 837 if err != nil { 838 return nil, fmt.Errorf("error decoding proof: %w", err) 839 } 840 841 interims[i] = interim 842 } 843 pInst.Interims = interims 844 845 return pInst, nil 846 } 847 848 // EncodeTrieBatchProof encodes a batch proof into a byte slice 849 func EncodeTrieBatchProof(bp *TrieBatchProof) []byte { 850 if bp == nil { 851 return []byte{} 852 } 853 // encode version 854 buffer := utils.AppendUint16([]byte{}, TrieBatchProofVersion) 855 856 // encode batch proof entity type 857 buffer = utils.AppendUint8(buffer, TypeBatchProof) 858 // encode batch proof content 859 buffer = append(buffer, encodeTrieBatchProof(bp, TrieBatchProofVersion)...) 860 861 return buffer 862 } 863 864 // encodeBatchProof encodes a batch proof into a byte slice 865 func encodeTrieBatchProof(bp *TrieBatchProof, version uint16) []byte { 866 buffer := make([]byte, 0) 867 // encode number of proofs 868 buffer = utils.AppendUint32(buffer, uint32(len(bp.Proofs))) 869 // iterate over proofs 870 for _, p := range bp.Proofs { 871 // encode the proof 872 encP := encodeTrieProof(p, version) 873 // encode the len of the encoded proof 874 buffer = utils.AppendUint64(buffer, uint64(len(encP))) 875 // append the encoded proof 876 buffer = append(buffer, encP...) 877 } 878 return buffer 879 } 880 881 // DecodeTrieBatchProof constructs a batch proof from an encoded byte slice 882 func DecodeTrieBatchProof(encodedBatchProof []byte) (*TrieBatchProof, error) { 883 // check the enc dec version 884 rest, version, err := CheckVersion(encodedBatchProof, TrieBatchProofVersion) 885 if err != nil { 886 return nil, fmt.Errorf("error decoding batch proof: %w", err) 887 } 888 // check the encoding type 889 rest, err = CheckType(rest, TypeBatchProof) 890 if err != nil { 891 return nil, fmt.Errorf("error decoding batch proof: %w", err) 892 } 893 894 // decode the batch proof content 895 bp, err := decodeTrieBatchProof(rest, version) 896 if err != nil { 897 return nil, fmt.Errorf("error decoding batch proof: %w", err) 898 } 899 return bp, nil 900 } 901 902 func decodeTrieBatchProof(inp []byte, version uint16) (*TrieBatchProof, error) { 903 bp := NewTrieBatchProof() 904 // number of proofs 905 numOfProofs, rest, err := utils.ReadUint32(inp) 906 if err != nil { 907 return nil, fmt.Errorf("error decoding batch proof (content): %w", err) 908 } 909 910 for i := 0; i < int(numOfProofs); i++ { 911 var encProofSize uint64 912 var encProof []byte 913 // read encoded proof size 914 encProofSize, rest, err = utils.ReadUint64(rest) 915 if err != nil { 916 return nil, fmt.Errorf("error decoding batch proof (content): %w", err) 917 } 918 919 // read encoded proof 920 encProof, rest, err = utils.ReadSlice(rest, int(encProofSize)) 921 if err != nil { 922 return nil, fmt.Errorf("error decoding batch proof (content): %w", err) 923 } 924 925 // decode encoded proof 926 proof, err := decodeTrieProof(encProof, version) 927 if err != nil { 928 return nil, fmt.Errorf("error decoding batch proof (content): %w", err) 929 } 930 bp.Proofs = append(bp.Proofs, proof) 931 } 932 return bp, nil 933 }