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