github.com/decred/dcrlnd@v0.7.6/lnwire/lnwire.go (about) 1 package lnwire 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "fmt" 7 "image/color" 8 "io" 9 "math" 10 11 "net" 12 13 "github.com/decred/dcrd/chaincfg/chainhash" 14 "github.com/decred/dcrd/dcrec/secp256k1/v4" 15 "github.com/decred/dcrd/dcrutil/v4" 16 "github.com/decred/dcrd/wire" 17 "github.com/decred/dcrlnd/tor" 18 "github.com/go-errors/errors" 19 ) 20 21 const ( 22 // MaxSliceLength is the maximum allowed length for any opaque byte 23 // slices in the wire protocol. 24 MaxSliceLength = 65535 25 26 // MaxMsgBody is the largest payload any message is allowed to provide. 27 // This is two less than the MaxSliceLength as each message has a 2 28 // byte type that precedes the message body. 29 MaxMsgBody = 65533 30 ) 31 32 // PkScript is simple type definition which represents a raw serialized public 33 // key script. 34 type PkScript []byte 35 36 // addressType specifies the network protocol and version that should be used 37 // when connecting to a node at a particular address. 38 type addressType uint8 39 40 const ( 41 // noAddr denotes a blank address. An address of this type indicates 42 // that a node doesn't have any advertised addresses. 43 noAddr addressType = 0 44 45 // tcp4Addr denotes an IPv4 TCP address. 46 tcp4Addr addressType = 1 47 48 // tcp6Addr denotes an IPv6 TCP address. 49 tcp6Addr addressType = 2 50 51 // v2OnionAddr denotes a version 2 Tor onion service address. 52 v2OnionAddr addressType = 3 53 54 // v3OnionAddr denotes a version 3 Tor (prop224) onion service address. 55 v3OnionAddr addressType = 4 56 ) 57 58 // AddrLen returns the number of bytes that it takes to encode the target 59 // address. 60 func (a addressType) AddrLen() uint16 { 61 switch a { 62 case noAddr: 63 return 0 64 case tcp4Addr: 65 return 6 66 case tcp6Addr: 67 return 18 68 case v2OnionAddr: 69 return 12 70 case v3OnionAddr: 71 return 37 72 default: 73 return 0 74 } 75 } 76 77 // WriteElement is a one-stop shop to write the big endian representation of 78 // any element which is to be serialized for the wire protocol. 79 // 80 // TODO(yy): rm this method once we finish dereferencing it from other 81 // packages. 82 func WriteElement(w *bytes.Buffer, element interface{}) error { 83 switch e := element.(type) { 84 case NodeAlias: 85 if _, err := w.Write(e[:]); err != nil { 86 return err 87 } 88 89 case ShortChanIDEncoding: 90 var b [1]byte 91 b[0] = uint8(e) 92 if _, err := w.Write(b[:]); err != nil { 93 return err 94 } 95 case uint8: 96 var b [1]byte 97 b[0] = e 98 if _, err := w.Write(b[:]); err != nil { 99 return err 100 } 101 case FundingFlag: 102 var b [1]byte 103 b[0] = uint8(e) 104 if _, err := w.Write(b[:]); err != nil { 105 return err 106 } 107 case uint16: 108 var b [2]byte 109 binary.BigEndian.PutUint16(b[:], e) 110 if _, err := w.Write(b[:]); err != nil { 111 return err 112 } 113 case ChanUpdateMsgFlags: 114 var b [1]byte 115 b[0] = uint8(e) 116 if _, err := w.Write(b[:]); err != nil { 117 return err 118 } 119 case ChanUpdateChanFlags: 120 var b [1]byte 121 b[0] = uint8(e) 122 if _, err := w.Write(b[:]); err != nil { 123 return err 124 } 125 case MilliAtom: 126 var b [8]byte 127 binary.BigEndian.PutUint64(b[:], uint64(e)) 128 if _, err := w.Write(b[:]); err != nil { 129 return err 130 } 131 case dcrutil.Amount: 132 var b [8]byte 133 binary.BigEndian.PutUint64(b[:], uint64(e)) 134 if _, err := w.Write(b[:]); err != nil { 135 return err 136 } 137 case uint32: 138 var b [4]byte 139 binary.BigEndian.PutUint32(b[:], e) 140 if _, err := w.Write(b[:]); err != nil { 141 return err 142 } 143 case uint64: 144 var b [8]byte 145 binary.BigEndian.PutUint64(b[:], e) 146 if _, err := w.Write(b[:]); err != nil { 147 return err 148 } 149 case *secp256k1.PublicKey: 150 if e == nil { 151 return fmt.Errorf("cannot write nil pubkey") 152 } 153 154 var b [33]byte 155 serializedPubkey := e.SerializeCompressed() 156 copy(b[:], serializedPubkey) 157 if _, err := w.Write(b[:]); err != nil { 158 return err 159 } 160 case []Sig: 161 var b [2]byte 162 numSigs := uint16(len(e)) 163 binary.BigEndian.PutUint16(b[:], numSigs) 164 if _, err := w.Write(b[:]); err != nil { 165 return err 166 } 167 168 for _, sig := range e { 169 if err := WriteElement(w, sig); err != nil { 170 return err 171 } 172 } 173 case Sig: 174 // Write buffer 175 if _, err := w.Write(e[:]); err != nil { 176 return err 177 } 178 case PingPayload: 179 var l [2]byte 180 binary.BigEndian.PutUint16(l[:], uint16(len(e))) 181 if _, err := w.Write(l[:]); err != nil { 182 return err 183 } 184 185 if _, err := w.Write(e[:]); err != nil { 186 return err 187 } 188 case PongPayload: 189 var l [2]byte 190 binary.BigEndian.PutUint16(l[:], uint16(len(e))) 191 if _, err := w.Write(l[:]); err != nil { 192 return err 193 } 194 195 if _, err := w.Write(e[:]); err != nil { 196 return err 197 } 198 case ErrorData: 199 var l [2]byte 200 binary.BigEndian.PutUint16(l[:], uint16(len(e))) 201 if _, err := w.Write(l[:]); err != nil { 202 return err 203 } 204 205 if _, err := w.Write(e[:]); err != nil { 206 return err 207 } 208 case OpaqueReason: 209 var l [2]byte 210 binary.BigEndian.PutUint16(l[:], uint16(len(e))) 211 if _, err := w.Write(l[:]); err != nil { 212 return err 213 } 214 215 if _, err := w.Write(e[:]); err != nil { 216 return err 217 } 218 case [33]byte: 219 if _, err := w.Write(e[:]); err != nil { 220 return err 221 } 222 case []byte: 223 if _, err := w.Write(e); err != nil { 224 return err 225 } 226 case PkScript: 227 // The largest script we'll accept is a p2wsh which is exactly 228 // 34 bytes long. 229 scriptLength := len(e) 230 if scriptLength > 34 { 231 return fmt.Errorf("'PkScript' too long") 232 } 233 234 if err := wire.WriteVarBytes(w, 0, e); err != nil { 235 return err 236 } 237 case *RawFeatureVector: 238 if e == nil { 239 return fmt.Errorf("cannot write nil feature vector") 240 } 241 242 if err := e.Encode(w); err != nil { 243 return err 244 } 245 246 case wire.OutPoint: 247 var h [32]byte 248 copy(h[:], e.Hash[:]) 249 if _, err := w.Write(h[:]); err != nil { 250 return err 251 } 252 253 if e.Index > math.MaxUint16 { 254 return fmt.Errorf("index for outpoint (%v) is "+ 255 "greater than max index of %v", e.Index, 256 math.MaxUint16) 257 } 258 259 var idx [2]byte 260 binary.BigEndian.PutUint16(idx[:], uint16(e.Index)) 261 if _, err := w.Write(idx[:]); err != nil { 262 return err 263 } 264 265 case ChannelID: 266 if _, err := w.Write(e[:]); err != nil { 267 return err 268 } 269 case FailCode: 270 if err := WriteElement(w, uint16(e)); err != nil { 271 return err 272 } 273 case ShortChannelID: 274 // Check that field fit in 3 bytes and write the blockHeight 275 if e.BlockHeight > ((1 << 24) - 1) { 276 return errors.New("block height should fit in 3 bytes") 277 } 278 279 var blockHeight [4]byte 280 binary.BigEndian.PutUint32(blockHeight[:], e.BlockHeight) 281 282 if _, err := w.Write(blockHeight[1:]); err != nil { 283 return err 284 } 285 286 // Check that field fit in 3 bytes and write the txIndex 287 if e.TxIndex > ((1 << 24) - 1) { 288 return errors.New("tx index should fit in 3 bytes") 289 } 290 291 var txIndex [4]byte 292 binary.BigEndian.PutUint32(txIndex[:], e.TxIndex) 293 if _, err := w.Write(txIndex[1:]); err != nil { 294 return err 295 } 296 297 // Write the txPosition 298 var txPosition [2]byte 299 binary.BigEndian.PutUint16(txPosition[:], e.TxPosition) 300 if _, err := w.Write(txPosition[:]); err != nil { 301 return err 302 } 303 304 case *net.TCPAddr: 305 if e == nil { 306 return fmt.Errorf("cannot write nil TCPAddr") 307 } 308 309 if e.IP.To4() != nil { 310 var descriptor [1]byte 311 descriptor[0] = uint8(tcp4Addr) 312 if _, err := w.Write(descriptor[:]); err != nil { 313 return err 314 } 315 316 var ip [4]byte 317 copy(ip[:], e.IP.To4()) 318 if _, err := w.Write(ip[:]); err != nil { 319 return err 320 } 321 } else { 322 var descriptor [1]byte 323 descriptor[0] = uint8(tcp6Addr) 324 if _, err := w.Write(descriptor[:]); err != nil { 325 return err 326 } 327 var ip [16]byte 328 copy(ip[:], e.IP.To16()) 329 if _, err := w.Write(ip[:]); err != nil { 330 return err 331 } 332 } 333 var port [2]byte 334 binary.BigEndian.PutUint16(port[:], uint16(e.Port)) 335 if _, err := w.Write(port[:]); err != nil { 336 return err 337 } 338 339 case *tor.OnionAddr: 340 if e == nil { 341 return errors.New("cannot write nil onion address") 342 } 343 344 var suffixIndex int 345 switch len(e.OnionService) { 346 case tor.V2Len: 347 descriptor := []byte{byte(v2OnionAddr)} 348 if _, err := w.Write(descriptor); err != nil { 349 return err 350 } 351 suffixIndex = tor.V2Len - tor.OnionSuffixLen 352 case tor.V3Len: 353 descriptor := []byte{byte(v3OnionAddr)} 354 if _, err := w.Write(descriptor); err != nil { 355 return err 356 } 357 suffixIndex = tor.V3Len - tor.OnionSuffixLen 358 default: 359 return errors.New("unknown onion service length") 360 } 361 362 host, err := tor.Base32Encoding.DecodeString( 363 e.OnionService[:suffixIndex], 364 ) 365 if err != nil { 366 return err 367 } 368 if _, err := w.Write(host); err != nil { 369 return err 370 } 371 372 var port [2]byte 373 binary.BigEndian.PutUint16(port[:], uint16(e.Port)) 374 if _, err := w.Write(port[:]); err != nil { 375 return err 376 } 377 378 case []net.Addr: 379 // First, we'll encode all the addresses into an intermediate 380 // buffer. We need to do this in order to compute the total 381 // length of the addresses. 382 var addrBuf bytes.Buffer 383 for _, address := range e { 384 if err := WriteElement(&addrBuf, address); err != nil { 385 return err 386 } 387 } 388 389 // With the addresses fully encoded, we can now write out the 390 // number of bytes needed to encode them. 391 addrLen := addrBuf.Len() 392 if err := WriteElement(w, uint16(addrLen)); err != nil { 393 return err 394 } 395 396 // Finally, we'll write out the raw addresses themselves, but 397 // only if we have any bytes to write. 398 if addrLen > 0 { 399 if _, err := w.Write(addrBuf.Bytes()); err != nil { 400 return err 401 } 402 } 403 case color.RGBA: 404 if err := WriteElements(w, e.R, e.G, e.B); err != nil { 405 return err 406 } 407 408 case DeliveryAddress: 409 var length [2]byte 410 binary.BigEndian.PutUint16(length[:], uint16(len(e))) 411 if _, err := w.Write(length[:]); err != nil { 412 return err 413 } 414 if _, err := w.Write(e[:]); err != nil { 415 return err 416 } 417 418 case bool: 419 var b [1]byte 420 if e { 421 b[0] = 1 422 } 423 if _, err := w.Write(b[:]); err != nil { 424 return err 425 } 426 427 case ExtraOpaqueData: 428 return e.Encode(w) 429 430 default: 431 return fmt.Errorf("unknown type in WriteElement: %T", e) 432 } 433 434 return nil 435 } 436 437 // WriteElements is writes each element in the elements slice to the passed 438 // buffer using WriteElement. 439 // 440 // TODO(yy): rm this method once we finish dereferencing it from other 441 // packages. 442 func WriteElements(buf *bytes.Buffer, elements ...interface{}) error { 443 for _, element := range elements { 444 err := WriteElement(buf, element) 445 if err != nil { 446 return err 447 } 448 } 449 return nil 450 } 451 452 // ReadElement is a one-stop utility function to deserialize any datastructure 453 // encoded using the serialization format of lnwire. 454 func ReadElement(r io.Reader, element interface{}) error { 455 var err error 456 switch e := element.(type) { 457 case *bool: 458 var b [1]byte 459 if _, err := io.ReadFull(r, b[:]); err != nil { 460 return err 461 } 462 463 if b[0] == 1 { 464 *e = true 465 } 466 467 case *NodeAlias: 468 var a [32]byte 469 if _, err := io.ReadFull(r, a[:]); err != nil { 470 return err 471 } 472 473 alias, err := NewNodeAlias(string(a[:])) 474 if err != nil { 475 return err 476 } 477 478 *e = alias 479 case *ShortChanIDEncoding: 480 var b [1]uint8 481 if _, err := r.Read(b[:]); err != nil { 482 return err 483 } 484 *e = ShortChanIDEncoding(b[0]) 485 case *uint8: 486 var b [1]uint8 487 if _, err := r.Read(b[:]); err != nil { 488 return err 489 } 490 *e = b[0] 491 case *FundingFlag: 492 var b [1]uint8 493 if _, err := r.Read(b[:]); err != nil { 494 return err 495 } 496 *e = FundingFlag(b[0]) 497 case *uint16: 498 var b [2]byte 499 if _, err := io.ReadFull(r, b[:]); err != nil { 500 return err 501 } 502 *e = binary.BigEndian.Uint16(b[:]) 503 case *ChanUpdateMsgFlags: 504 var b [1]uint8 505 if _, err := r.Read(b[:]); err != nil { 506 return err 507 } 508 *e = ChanUpdateMsgFlags(b[0]) 509 case *ChanUpdateChanFlags: 510 var b [1]uint8 511 if _, err := r.Read(b[:]); err != nil { 512 return err 513 } 514 *e = ChanUpdateChanFlags(b[0]) 515 case *uint32: 516 var b [4]byte 517 if _, err := io.ReadFull(r, b[:]); err != nil { 518 return err 519 } 520 *e = binary.BigEndian.Uint32(b[:]) 521 case *uint64: 522 var b [8]byte 523 if _, err := io.ReadFull(r, b[:]); err != nil { 524 return err 525 } 526 *e = binary.BigEndian.Uint64(b[:]) 527 case *MilliAtom: 528 var b [8]byte 529 if _, err := io.ReadFull(r, b[:]); err != nil { 530 return err 531 } 532 *e = MilliAtom(int64(binary.BigEndian.Uint64(b[:]))) 533 case *dcrutil.Amount: 534 var b [8]byte 535 if _, err := io.ReadFull(r, b[:]); err != nil { 536 return err 537 } 538 *e = dcrutil.Amount(int64(binary.BigEndian.Uint64(b[:]))) 539 case **secp256k1.PublicKey: 540 var b [secp256k1.PubKeyBytesLenCompressed]byte 541 if _, err = io.ReadFull(r, b[:]); err != nil { 542 return err 543 } 544 545 pubKey, err := secp256k1.ParsePubKey(b[:]) 546 if err != nil { 547 return err 548 } 549 *e = pubKey 550 case **RawFeatureVector: 551 f := NewRawFeatureVector() 552 err = f.Decode(r) 553 if err != nil { 554 return err 555 } 556 557 *e = f 558 559 case *[]Sig: 560 var l [2]byte 561 if _, err := io.ReadFull(r, l[:]); err != nil { 562 return err 563 } 564 numSigs := binary.BigEndian.Uint16(l[:]) 565 566 var sigs []Sig 567 if numSigs > 0 { 568 sigs = make([]Sig, numSigs) 569 for i := 0; i < int(numSigs); i++ { 570 if err := ReadElement(r, &sigs[i]); err != nil { 571 return err 572 } 573 } 574 } 575 576 *e = sigs 577 578 case *Sig: 579 if _, err := io.ReadFull(r, e[:]); err != nil { 580 return err 581 } 582 case *OpaqueReason: 583 var l [2]byte 584 if _, err := io.ReadFull(r, l[:]); err != nil { 585 return err 586 } 587 reasonLen := binary.BigEndian.Uint16(l[:]) 588 589 *e = OpaqueReason(make([]byte, reasonLen)) 590 if _, err := io.ReadFull(r, *e); err != nil { 591 return err 592 } 593 case *ErrorData: 594 var l [2]byte 595 if _, err := io.ReadFull(r, l[:]); err != nil { 596 return err 597 } 598 errorLen := binary.BigEndian.Uint16(l[:]) 599 600 *e = ErrorData(make([]byte, errorLen)) 601 if _, err := io.ReadFull(r, *e); err != nil { 602 return err 603 } 604 case *PingPayload: 605 var l [2]byte 606 if _, err := io.ReadFull(r, l[:]); err != nil { 607 return err 608 } 609 pingLen := binary.BigEndian.Uint16(l[:]) 610 611 *e = PingPayload(make([]byte, pingLen)) 612 if _, err := io.ReadFull(r, *e); err != nil { 613 return err 614 } 615 case *PongPayload: 616 var l [2]byte 617 if _, err := io.ReadFull(r, l[:]); err != nil { 618 return err 619 } 620 pongLen := binary.BigEndian.Uint16(l[:]) 621 622 *e = PongPayload(make([]byte, pongLen)) 623 if _, err := io.ReadFull(r, *e); err != nil { 624 return err 625 } 626 case *[33]byte: 627 if _, err := io.ReadFull(r, e[:]); err != nil { 628 return err 629 } 630 case []byte: 631 if _, err := io.ReadFull(r, e); err != nil { 632 return err 633 } 634 case *PkScript: 635 pkScript, err := wire.ReadVarBytes(r, 0, 34, "pkscript") 636 if err != nil { 637 return err 638 } 639 *e = pkScript 640 case *wire.OutPoint: 641 var h [32]byte 642 if _, err = io.ReadFull(r, h[:]); err != nil { 643 return err 644 } 645 hash, err := chainhash.NewHash(h[:]) 646 if err != nil { 647 return err 648 } 649 650 var idxBytes [2]byte 651 _, err = io.ReadFull(r, idxBytes[:]) 652 if err != nil { 653 return err 654 } 655 index := binary.BigEndian.Uint16(idxBytes[:]) 656 657 *e = wire.OutPoint{ 658 Hash: *hash, 659 Index: uint32(index), 660 } 661 case *FailCode: 662 if err := ReadElement(r, (*uint16)(e)); err != nil { 663 return err 664 } 665 case *ChannelID: 666 if _, err := io.ReadFull(r, e[:]); err != nil { 667 return err 668 } 669 670 case *ShortChannelID: 671 var blockHeight [4]byte 672 if _, err = io.ReadFull(r, blockHeight[1:]); err != nil { 673 return err 674 } 675 676 var txIndex [4]byte 677 if _, err = io.ReadFull(r, txIndex[1:]); err != nil { 678 return err 679 } 680 681 var txPosition [2]byte 682 if _, err = io.ReadFull(r, txPosition[:]); err != nil { 683 return err 684 } 685 686 *e = ShortChannelID{ 687 BlockHeight: binary.BigEndian.Uint32(blockHeight[:]), 688 TxIndex: binary.BigEndian.Uint32(txIndex[:]), 689 TxPosition: binary.BigEndian.Uint16(txPosition[:]), 690 } 691 692 case *[]net.Addr: 693 // First, we'll read the number of total bytes that have been 694 // used to encode the set of addresses. 695 var numAddrsBytes [2]byte 696 if _, err = io.ReadFull(r, numAddrsBytes[:]); err != nil { 697 return err 698 } 699 addrsLen := binary.BigEndian.Uint16(numAddrsBytes[:]) 700 701 // With the number of addresses, read, we'll now pull in the 702 // buffer of the encoded addresses into memory. 703 addrs := make([]byte, addrsLen) 704 if _, err := io.ReadFull(r, addrs); err != nil { 705 return err 706 } 707 addrBuf := bytes.NewReader(addrs) 708 709 // Finally, we'll parse the remaining address payload in 710 // series, using the first byte to denote how to decode the 711 // address itself. 712 var ( 713 addresses []net.Addr 714 addrBytesRead uint16 715 ) 716 717 for addrBytesRead < addrsLen { 718 var descriptor [1]byte 719 if _, err = io.ReadFull(addrBuf, descriptor[:]); err != nil { 720 return err 721 } 722 723 addrBytesRead++ 724 725 var address net.Addr 726 switch aType := addressType(descriptor[0]); aType { 727 case noAddr: 728 addrBytesRead += aType.AddrLen() 729 continue 730 731 case tcp4Addr: 732 var ip [4]byte 733 if _, err := io.ReadFull(addrBuf, ip[:]); err != nil { 734 return err 735 } 736 737 var port [2]byte 738 if _, err := io.ReadFull(addrBuf, port[:]); err != nil { 739 return err 740 } 741 742 address = &net.TCPAddr{ 743 IP: net.IP(ip[:]), 744 Port: int(binary.BigEndian.Uint16(port[:])), 745 } 746 addrBytesRead += aType.AddrLen() 747 748 case tcp6Addr: 749 var ip [16]byte 750 if _, err := io.ReadFull(addrBuf, ip[:]); err != nil { 751 return err 752 } 753 754 var port [2]byte 755 if _, err := io.ReadFull(addrBuf, port[:]); err != nil { 756 return err 757 } 758 759 address = &net.TCPAddr{ 760 IP: net.IP(ip[:]), 761 Port: int(binary.BigEndian.Uint16(port[:])), 762 } 763 addrBytesRead += aType.AddrLen() 764 765 case v2OnionAddr: 766 var h [tor.V2DecodedLen]byte 767 if _, err := io.ReadFull(addrBuf, h[:]); err != nil { 768 return err 769 } 770 771 var p [2]byte 772 if _, err := io.ReadFull(addrBuf, p[:]); err != nil { 773 return err 774 } 775 776 onionService := tor.Base32Encoding.EncodeToString(h[:]) 777 onionService += tor.OnionSuffix 778 port := int(binary.BigEndian.Uint16(p[:])) 779 780 address = &tor.OnionAddr{ 781 OnionService: onionService, 782 Port: port, 783 } 784 addrBytesRead += aType.AddrLen() 785 786 case v3OnionAddr: 787 var h [tor.V3DecodedLen]byte 788 if _, err := io.ReadFull(addrBuf, h[:]); err != nil { 789 return err 790 } 791 792 var p [2]byte 793 if _, err := io.ReadFull(addrBuf, p[:]); err != nil { 794 return err 795 } 796 797 onionService := tor.Base32Encoding.EncodeToString(h[:]) 798 onionService += tor.OnionSuffix 799 port := int(binary.BigEndian.Uint16(p[:])) 800 801 address = &tor.OnionAddr{ 802 OnionService: onionService, 803 Port: port, 804 } 805 addrBytesRead += aType.AddrLen() 806 807 default: 808 return &ErrUnknownAddrType{aType} 809 } 810 811 addresses = append(addresses, address) 812 } 813 814 *e = addresses 815 case *color.RGBA: 816 err := ReadElements(r, 817 &e.R, 818 &e.G, 819 &e.B, 820 ) 821 if err != nil { 822 return err 823 } 824 case *DeliveryAddress: 825 var addrLen [2]byte 826 if _, err = io.ReadFull(r, addrLen[:]); err != nil { 827 return err 828 } 829 length := binary.BigEndian.Uint16(addrLen[:]) 830 831 var addrBytes [deliveryAddressMaxSize]byte 832 833 if length > deliveryAddressMaxSize { 834 return fmt.Errorf( 835 "cannot read %d bytes into addrBytes", length, 836 ) 837 } 838 if _, err = io.ReadFull(r, addrBytes[:length]); err != nil { 839 return err 840 } 841 *e = addrBytes[:length] 842 843 case *ExtraOpaqueData: 844 return e.Decode(r) 845 846 default: 847 return fmt.Errorf("unknown type in ReadElement: %T", e) 848 } 849 850 return nil 851 } 852 853 // ReadElements deserializes a variable number of elements into the passed 854 // io.Reader, with each element being deserialized according to the ReadElement 855 // function. 856 func ReadElements(r io.Reader, elements ...interface{}) error { 857 for _, element := range elements { 858 err := ReadElement(r, element) 859 if err != nil { 860 return err 861 } 862 } 863 return nil 864 }