github.com/lbryio/lbcd@v0.22.119/wire/common.go (about) 1 // Copyright (c) 2013-2016 The btcsuite developers 2 // Use of this source code is governed by an ISC 3 // license that can be found in the LICENSE file. 4 5 package wire 6 7 import ( 8 "crypto/rand" 9 "encoding/binary" 10 "fmt" 11 "io" 12 "math" 13 "time" 14 15 "github.com/lbryio/lbcd/chaincfg/chainhash" 16 ) 17 18 const ( 19 // MaxVarIntPayload is the maximum payload size for a variable length integer. 20 MaxVarIntPayload = 9 21 ) 22 23 var ( 24 // littleEndian is a convenience variable since binary.LittleEndian is 25 // quite long. 26 littleEndian = binary.LittleEndian 27 28 // bigEndian is a convenience variable since binary.BigEndian is quite 29 // long. 30 bigEndian = binary.BigEndian 31 ) 32 33 // binaryFreeList defines a concurrent safe free list of byte slices (up to the 34 // maximum number defined by the binaryFreeListMaxItems constant) that have a 35 // cap of 8 (thus it supports up to a uint64). It is used to provide temporary 36 // buffers for serializing and deserializing primitive numbers to and from their 37 // binary encoding in order to greatly reduce the number of allocations 38 // required. 39 // 40 // For convenience, functions are provided for each of the primitive unsigned 41 // integers that automatically obtain a buffer from the free list, perform the 42 // necessary binary conversion, read from or write to the given io.Reader or 43 // io.Writer, and return the buffer to the free list. 44 type binaryFreeList chan []byte 45 46 // Uint8 reads a single byte from the provided reader using a buffer from the 47 // free list and returns it as a uint8. 48 func (l binaryFreeList) Uint8(r io.Reader) (uint8, error) { 49 buf := make([]byte, 1) // should be allocated on the stack 50 if _, err := io.ReadFull(r, buf); err != nil { 51 return 0, err 52 } 53 rv := buf[0] 54 return rv, nil 55 } 56 57 // Uint16 reads two bytes from the provided reader using a buffer from the 58 // free list, converts it to a number using the provided byte order, and returns 59 // the resulting uint16. 60 func (l binaryFreeList) Uint16(r io.Reader, byteOrder binary.ByteOrder) (uint16, error) { 61 buf := make([]byte, 2) // should be allocated on the stack 62 if _, err := io.ReadFull(r, buf); err != nil { 63 return 0, err 64 } 65 rv := byteOrder.Uint16(buf) 66 return rv, nil 67 } 68 69 // Uint32 reads four bytes from the provided reader using a buffer from the 70 // free list, converts it to a number using the provided byte order, and returns 71 // the resulting uint32. 72 func (l binaryFreeList) Uint32(r io.Reader, byteOrder binary.ByteOrder) (uint32, error) { 73 buf := make([]byte, 4) // should be allocated on the stack 74 if _, err := io.ReadFull(r, buf); err != nil { 75 return 0, err 76 } 77 rv := byteOrder.Uint32(buf) 78 return rv, nil 79 } 80 81 // Uint64 reads eight bytes from the provided reader using a buffer from the 82 // free list, converts it to a number using the provided byte order, and returns 83 // the resulting uint64. 84 func (l binaryFreeList) Uint64(r io.Reader, byteOrder binary.ByteOrder) (uint64, error) { 85 buf := make([]byte, 8) // should be allocated on the stack 86 if _, err := io.ReadFull(r, buf); err != nil { 87 return 0, err 88 } 89 rv := byteOrder.Uint64(buf) 90 return rv, nil 91 } 92 93 // PutUint8 copies the provided uint8 into a buffer from the free list and 94 // writes the resulting byte to the given writer. 95 func (l binaryFreeList) PutUint8(w io.Writer, val uint8) error { 96 buf := make([]byte, 1) // should be allocated on the stack 97 buf[0] = val 98 _, err := w.Write(buf) 99 return err 100 } 101 102 // PutUint16 serializes the provided uint16 using the given byte order into a 103 // buffer from the free list and writes the resulting two bytes to the given 104 // writer. 105 func (l binaryFreeList) PutUint16(w io.Writer, byteOrder binary.ByteOrder, val uint16) error { 106 buf := make([]byte, 2) // should be allocated on the stack 107 byteOrder.PutUint16(buf, val) 108 _, err := w.Write(buf) 109 return err 110 } 111 112 // PutUint32 serializes the provided uint32 using the given byte order into a 113 // buffer from the free list and writes the resulting four bytes to the given 114 // writer. 115 func (l binaryFreeList) PutUint32(w io.Writer, byteOrder binary.ByteOrder, val uint32) error { 116 buf := make([]byte, 4) // should be allocated on the stack 117 byteOrder.PutUint32(buf, val) 118 _, err := w.Write(buf) 119 return err 120 } 121 122 // PutUint64 serializes the provided uint64 using the given byte order into a 123 // buffer from the free list and writes the resulting eight bytes to the given 124 // writer. 125 func (l binaryFreeList) PutUint64(w io.Writer, byteOrder binary.ByteOrder, val uint64) error { 126 buf := make([]byte, 8) // should be allocated on the stack 127 byteOrder.PutUint64(buf, val) 128 _, err := w.Write(buf) 129 return err 130 } 131 132 // binarySerializer provides a free list of buffers to use for serializing and 133 // deserializing primitive integer values to and from io.Readers and io.Writers. 134 var binarySerializer binaryFreeList = make(chan []byte) 135 136 // errNonCanonicalVarInt is the common format string used for non-canonically 137 // encoded variable length integer errors. 138 var errNonCanonicalVarInt = "non-canonical varint %x - discriminant %x must " + 139 "encode a value greater than %x" 140 141 // uint32Time represents a unix timestamp encoded with a uint32. It is used as 142 // a way to signal the readElement function how to decode a timestamp into a Go 143 // time.Time since it is otherwise ambiguous. 144 type uint32Time time.Time 145 146 // int64Time represents a unix timestamp encoded with an int64. It is used as 147 // a way to signal the readElement function how to decode a timestamp into a Go 148 // time.Time since it is otherwise ambiguous. 149 type int64Time time.Time 150 151 // readElement reads the next sequence of bytes from r using little endian 152 // depending on the concrete type of element pointed to. 153 func readElement(r io.Reader, element interface{}) error { 154 // Attempt to read the element based on the concrete type via fast 155 // type assertions first. 156 switch e := element.(type) { 157 case *int32: 158 rv, err := binarySerializer.Uint32(r, littleEndian) 159 if err != nil { 160 return err 161 } 162 *e = int32(rv) 163 return nil 164 165 case *uint32: 166 rv, err := binarySerializer.Uint32(r, littleEndian) 167 if err != nil { 168 return err 169 } 170 *e = rv 171 return nil 172 173 case *int64: 174 rv, err := binarySerializer.Uint64(r, littleEndian) 175 if err != nil { 176 return err 177 } 178 *e = int64(rv) 179 return nil 180 181 case *uint64: 182 rv, err := binarySerializer.Uint64(r, littleEndian) 183 if err != nil { 184 return err 185 } 186 *e = rv 187 return nil 188 189 case *bool: 190 rv, err := binarySerializer.Uint8(r) 191 if err != nil { 192 return err 193 } 194 if rv == 0x00 { 195 *e = false 196 } else { 197 *e = true 198 } 199 return nil 200 201 // Unix timestamp encoded as a uint32. 202 case *uint32Time: 203 rv, err := binarySerializer.Uint32(r, binary.LittleEndian) 204 if err != nil { 205 return err 206 } 207 *e = uint32Time(time.Unix(int64(rv), 0)) 208 return nil 209 210 // Unix timestamp encoded as an int64. 211 case *int64Time: 212 rv, err := binarySerializer.Uint64(r, binary.LittleEndian) 213 if err != nil { 214 return err 215 } 216 *e = int64Time(time.Unix(int64(rv), 0)) 217 return nil 218 219 // Message header checksum. 220 case *[4]byte: 221 _, err := io.ReadFull(r, e[:]) 222 if err != nil { 223 return err 224 } 225 return nil 226 227 // Message header command. 228 case *[CommandSize]uint8: 229 _, err := io.ReadFull(r, e[:]) 230 if err != nil { 231 return err 232 } 233 return nil 234 235 // IP address. 236 case *[16]byte: 237 _, err := io.ReadFull(r, e[:]) 238 if err != nil { 239 return err 240 } 241 return nil 242 243 case *chainhash.Hash: 244 _, err := io.ReadFull(r, e[:]) 245 if err != nil { 246 return err 247 } 248 return nil 249 250 case *ServiceFlag: 251 rv, err := binarySerializer.Uint64(r, littleEndian) 252 if err != nil { 253 return err 254 } 255 *e = ServiceFlag(rv) 256 return nil 257 258 case *InvType: 259 rv, err := binarySerializer.Uint32(r, littleEndian) 260 if err != nil { 261 return err 262 } 263 *e = InvType(rv) 264 return nil 265 266 case *BitcoinNet: 267 rv, err := binarySerializer.Uint32(r, littleEndian) 268 if err != nil { 269 return err 270 } 271 *e = BitcoinNet(rv) 272 return nil 273 274 case *BloomUpdateType: 275 rv, err := binarySerializer.Uint8(r) 276 if err != nil { 277 return err 278 } 279 *e = BloomUpdateType(rv) 280 return nil 281 282 case *RejectCode: 283 rv, err := binarySerializer.Uint8(r) 284 if err != nil { 285 return err 286 } 287 *e = RejectCode(rv) 288 return nil 289 } 290 291 // Fall back to the slower binary.Read if a fast path was not available 292 // above. 293 return binary.Read(r, littleEndian, element) 294 } 295 296 // readElements reads multiple items from r. It is equivalent to multiple 297 // calls to readElement. 298 func readElements(r io.Reader, elements ...interface{}) error { 299 for _, element := range elements { 300 err := readElement(r, element) 301 if err != nil { 302 return err 303 } 304 } 305 return nil 306 } 307 308 // writeElement writes the little endian representation of element to w. 309 func writeElement(w io.Writer, element interface{}) error { 310 // Attempt to write the element based on the concrete type via fast 311 // type assertions first. 312 switch e := element.(type) { 313 case int32: 314 err := binarySerializer.PutUint32(w, littleEndian, uint32(e)) 315 if err != nil { 316 return err 317 } 318 return nil 319 320 case uint32: 321 err := binarySerializer.PutUint32(w, littleEndian, e) 322 if err != nil { 323 return err 324 } 325 return nil 326 327 case int64: 328 err := binarySerializer.PutUint64(w, littleEndian, uint64(e)) 329 if err != nil { 330 return err 331 } 332 return nil 333 334 case uint64: 335 err := binarySerializer.PutUint64(w, littleEndian, e) 336 if err != nil { 337 return err 338 } 339 return nil 340 341 case bool: 342 var err error 343 if e { 344 err = binarySerializer.PutUint8(w, 0x01) 345 } else { 346 err = binarySerializer.PutUint8(w, 0x00) 347 } 348 if err != nil { 349 return err 350 } 351 return nil 352 353 // Message header checksum. 354 case [4]byte: 355 _, err := w.Write(e[:]) 356 if err != nil { 357 return err 358 } 359 return nil 360 361 // Message header command. 362 case [CommandSize]uint8: 363 _, err := w.Write(e[:]) 364 if err != nil { 365 return err 366 } 367 return nil 368 369 // IP address. 370 case [16]byte: 371 _, err := w.Write(e[:]) 372 if err != nil { 373 return err 374 } 375 return nil 376 377 case *chainhash.Hash: 378 _, err := w.Write(e[:]) 379 if err != nil { 380 return err 381 } 382 return nil 383 384 case ServiceFlag: 385 err := binarySerializer.PutUint64(w, littleEndian, uint64(e)) 386 if err != nil { 387 return err 388 } 389 return nil 390 391 case InvType: 392 err := binarySerializer.PutUint32(w, littleEndian, uint32(e)) 393 if err != nil { 394 return err 395 } 396 return nil 397 398 case BitcoinNet: 399 err := binarySerializer.PutUint32(w, littleEndian, uint32(e)) 400 if err != nil { 401 return err 402 } 403 return nil 404 405 case BloomUpdateType: 406 err := binarySerializer.PutUint8(w, uint8(e)) 407 if err != nil { 408 return err 409 } 410 return nil 411 412 case RejectCode: 413 err := binarySerializer.PutUint8(w, uint8(e)) 414 if err != nil { 415 return err 416 } 417 return nil 418 } 419 420 // Fall back to the slower binary.Write if a fast path was not available 421 // above. 422 return binary.Write(w, littleEndian, element) 423 } 424 425 // writeElements writes multiple items to w. It is equivalent to multiple 426 // calls to writeElement. 427 func writeElements(w io.Writer, elements ...interface{}) error { 428 for _, element := range elements { 429 err := writeElement(w, element) 430 if err != nil { 431 return err 432 } 433 } 434 return nil 435 } 436 437 // ReadVarInt reads a variable length integer from r and returns it as a uint64. 438 func ReadVarInt(r io.Reader, pver uint32) (uint64, error) { 439 discriminant, err := binarySerializer.Uint8(r) 440 if err != nil { 441 return 0, err 442 } 443 444 var rv uint64 445 switch discriminant { 446 case 0xff: 447 sv, err := binarySerializer.Uint64(r, littleEndian) 448 if err != nil { 449 return 0, err 450 } 451 rv = sv 452 453 // The encoding is not canonical if the value could have been 454 // encoded using fewer bytes. 455 min := uint64(0x100000000) 456 if rv < min { 457 return 0, messageError("ReadVarInt", fmt.Sprintf( 458 errNonCanonicalVarInt, rv, discriminant, min)) 459 } 460 461 case 0xfe: 462 sv, err := binarySerializer.Uint32(r, littleEndian) 463 if err != nil { 464 return 0, err 465 } 466 rv = uint64(sv) 467 468 // The encoding is not canonical if the value could have been 469 // encoded using fewer bytes. 470 min := uint64(0x10000) 471 if rv < min { 472 return 0, messageError("ReadVarInt", fmt.Sprintf( 473 errNonCanonicalVarInt, rv, discriminant, min)) 474 } 475 476 case 0xfd: 477 sv, err := binarySerializer.Uint16(r, littleEndian) 478 if err != nil { 479 return 0, err 480 } 481 rv = uint64(sv) 482 483 // The encoding is not canonical if the value could have been 484 // encoded using fewer bytes. 485 min := uint64(0xfd) 486 if rv < min { 487 return 0, messageError("ReadVarInt", fmt.Sprintf( 488 errNonCanonicalVarInt, rv, discriminant, min)) 489 } 490 491 default: 492 rv = uint64(discriminant) 493 } 494 495 return rv, nil 496 } 497 498 // WriteVarInt serializes val to w using a variable number of bytes depending 499 // on its value. 500 func WriteVarInt(w io.Writer, pver uint32, val uint64) error { 501 if val < 0xfd { 502 return binarySerializer.PutUint8(w, uint8(val)) 503 } 504 505 if val <= math.MaxUint16 { 506 err := binarySerializer.PutUint8(w, 0xfd) 507 if err != nil { 508 return err 509 } 510 return binarySerializer.PutUint16(w, littleEndian, uint16(val)) 511 } 512 513 if val <= math.MaxUint32 { 514 err := binarySerializer.PutUint8(w, 0xfe) 515 if err != nil { 516 return err 517 } 518 return binarySerializer.PutUint32(w, littleEndian, uint32(val)) 519 } 520 521 err := binarySerializer.PutUint8(w, 0xff) 522 if err != nil { 523 return err 524 } 525 return binarySerializer.PutUint64(w, littleEndian, val) 526 } 527 528 // VarIntSerializeSize returns the number of bytes it would take to serialize 529 // val as a variable length integer. 530 func VarIntSerializeSize(val uint64) int { 531 // The value is small enough to be represented by itself, so it's 532 // just 1 byte. 533 if val < 0xfd { 534 return 1 535 } 536 537 // Discriminant 1 byte plus 2 bytes for the uint16. 538 if val <= math.MaxUint16 { 539 return 3 540 } 541 542 // Discriminant 1 byte plus 4 bytes for the uint32. 543 if val <= math.MaxUint32 { 544 return 5 545 } 546 547 // Discriminant 1 byte plus 8 bytes for the uint64. 548 return 9 549 } 550 551 // ReadVarString reads a variable length string from r and returns it as a Go 552 // string. A variable length string is encoded as a variable length integer 553 // containing the length of the string followed by the bytes that represent the 554 // string itself. An error is returned if the length is greater than the 555 // maximum block payload size since it helps protect against memory exhaustion 556 // attacks and forced panics through malformed messages. 557 func ReadVarString(r io.Reader, pver uint32) (string, error) { 558 count, err := ReadVarInt(r, pver) 559 if err != nil { 560 return "", err 561 } 562 563 // Prevent variable length strings that are larger than the maximum 564 // message size. It would be possible to cause memory exhaustion and 565 // panics without a sane upper bound on this count. 566 if count > MaxMessagePayload { 567 str := fmt.Sprintf("variable length string is too long "+ 568 "[count %d, max %d]", count, MaxMessagePayload) 569 return "", messageError("ReadVarString", str) 570 } 571 572 buf := make([]byte, count) 573 _, err = io.ReadFull(r, buf) 574 if err != nil { 575 return "", err 576 } 577 return string(buf), nil 578 } 579 580 // WriteVarString serializes str to w as a variable length integer containing 581 // the length of the string followed by the bytes that represent the string 582 // itself. 583 func WriteVarString(w io.Writer, pver uint32, str string) error { 584 err := WriteVarInt(w, pver, uint64(len(str))) 585 if err != nil { 586 return err 587 } 588 _, err = w.Write([]byte(str)) 589 return err 590 } 591 592 // ReadVarBytes reads a variable length byte array. A byte array is encoded 593 // as a varInt containing the length of the array followed by the bytes 594 // themselves. An error is returned if the length is greater than the 595 // passed maxAllowed parameter which helps protect against memory exhaustion 596 // attacks and forced panics through malformed messages. The fieldName 597 // parameter is only used for the error message so it provides more context in 598 // the error. 599 func ReadVarBytes(r io.Reader, pver uint32, maxAllowed uint32, 600 fieldName string) ([]byte, error) { 601 602 count, err := ReadVarInt(r, pver) 603 if err != nil { 604 return nil, err 605 } 606 607 // Prevent byte array larger than the max message size. It would 608 // be possible to cause memory exhaustion and panics without a sane 609 // upper bound on this count. 610 if count > uint64(maxAllowed) { 611 str := fmt.Sprintf("%s is larger than the max allowed size "+ 612 "[count %d, max %d]", fieldName, count, maxAllowed) 613 return nil, messageError("ReadVarBytes", str) 614 } 615 616 b := make([]byte, count) 617 _, err = io.ReadFull(r, b) 618 if err != nil { 619 return nil, err 620 } 621 return b, nil 622 } 623 624 // WriteVarBytes serializes a variable length byte array to w as a varInt 625 // containing the number of bytes, followed by the bytes themselves. 626 func WriteVarBytes(w io.Writer, pver uint32, bytes []byte) error { 627 slen := uint64(len(bytes)) 628 err := WriteVarInt(w, pver, slen) 629 if err != nil { 630 return err 631 } 632 633 _, err = w.Write(bytes) 634 return err 635 } 636 637 // randomUint64 returns a cryptographically random uint64 value. This 638 // unexported version takes a reader primarily to ensure the error paths 639 // can be properly tested by passing a fake reader in the tests. 640 func randomUint64(r io.Reader) (uint64, error) { 641 rv, err := binarySerializer.Uint64(r, bigEndian) 642 if err != nil { 643 return 0, err 644 } 645 return rv, nil 646 } 647 648 // RandomUint64 returns a cryptographically random uint64 value. 649 func RandomUint64() (uint64, error) { 650 return randomUint64(rand.Reader) 651 }