github.com/dashpay/godash@v0.0.0-20160726055534-e038a21e0e3d/wire/msgtx.go (about) 1 // Copyright (c) 2013-2015 The btcsuite developers 2 // Copyright (c) 2016 The Dash developers 3 // Use of this source code is governed by an ISC 4 // license that can be found in the LICENSE file. 5 6 package wire 7 8 import ( 9 "bytes" 10 "fmt" 11 "io" 12 "strconv" 13 ) 14 15 const ( 16 // TxVersion is the current latest supported transaction version. 17 TxVersion = 1 18 19 // MaxTxInSequenceNum is the maximum sequence number the sequence field 20 // of a transaction input can be. 21 MaxTxInSequenceNum uint32 = 0xffffffff 22 23 // MaxPrevOutIndex is the maximum index the index field of a previous 24 // outpoint can be. 25 MaxPrevOutIndex uint32 = 0xffffffff 26 ) 27 28 const ( 29 // defaultTxInOutAlloc is the default size used for the backing array 30 // for transaction inputs and outputs. The array will dynamically grow 31 // as needed, but this figure is intended to provide enough space for 32 // the number of inputs and outputs in a typical transaction without 33 // needing to grow the backing array multiple times. 34 defaultTxInOutAlloc = 15 35 36 // minTxInPayload is the minimum payload size for a transaction input. 37 // PreviousOutPoint.Hash + PreviousOutPoint.Index 4 bytes + Varint for 38 // SignatureScript length 1 byte + Sequence 4 bytes. 39 minTxInPayload = 9 + HashSize 40 41 // maxTxInPerMessage is the maximum number of transactions inputs that 42 // a transaction which fits into a message could possibly have. 43 maxTxInPerMessage = (MaxMessagePayload / minTxInPayload) + 1 44 45 // minTxOutPayload is the minimum payload size for a transaction output. 46 // Value 8 bytes + Varint for PkScript length 1 byte. 47 minTxOutPayload = 9 48 49 // maxTxOutPerMessage is the maximum number of transactions outputs that 50 // a transaction which fits into a message could possibly have. 51 maxTxOutPerMessage = (MaxMessagePayload / minTxOutPayload) + 1 52 53 // minTxPayload is the minimum payload size for a transaction. Note 54 // that any realistically usable transaction must have at least one 55 // input or output, but that is a rule enforced at a higher layer, so 56 // it is intentionally not included here. 57 // Version 4 bytes + Varint number of transaction inputs 1 byte + Varint 58 // number of transaction outputs 1 byte + LockTime 4 bytes + min input 59 // payload + min output payload. 60 minTxPayload = 10 61 62 // freeListMaxScriptSize is the size of each buffer in the free list 63 // that is used for deserializing scripts from the wire before they are 64 // concatenated into a single contiguous buffers. This value was chosen 65 // because it is slightly more than twice the size of the vast majority 66 // of all "standard" scripts. Larger scripts are still deserialized 67 // properly as the free list will simply be bypassed for them. 68 freeListMaxScriptSize = 512 69 70 // freeListMaxItems is the number of buffers to keep in the free list 71 // to use for script deserialization. This value allows up to 100 72 // scripts per transaction being simultaneously deserialized by 125 73 // peers. Thus, the peak usage of the free list is 12,500 * 512 = 74 // 6,400,000 bytes. 75 freeListMaxItems = 12500 76 ) 77 78 // scriptFreeList defines a free list of byte slices (up to the maximum number 79 // defined by the freeListMaxItems constant) that have a cap according to the 80 // freeListMaxScriptSize constant. It is used to provide temporary buffers for 81 // deserializing scripts in order to greatly reduce the number of allocations 82 // required. 83 // 84 // The caller can obtain a buffer from the free list by calling the Borrow 85 // function and should return it via the Return function when done using it. 86 type scriptFreeList chan []byte 87 88 // Borrow returns a byte slice from the free list with a length according the 89 // provided size. A new buffer is allocated if there are any items available. 90 // 91 // When the size is larger than the max size allowed for items on the free list 92 // a new buffer of the appropriate size is allocated and returned. It is safe 93 // to attempt to return said buffer via the Return function as it will be 94 // ignored and allowed to go the garbage collector. 95 func (c scriptFreeList) Borrow(size uint64) []byte { 96 if size > freeListMaxScriptSize { 97 return make([]byte, size, size) 98 } 99 100 var buf []byte 101 select { 102 case buf = <-c: 103 default: 104 buf = make([]byte, freeListMaxScriptSize) 105 } 106 return buf[:size] 107 } 108 109 // Return puts the provided byte slice back on the free list when it has a cap 110 // of the expected length. The buffer is expected to have been obtained via 111 // the Borrow function. Any slices that are not of the appropriate size, such 112 // as those whose size is greater than the largest allowed free list item size 113 // are simply ignored so they can go to the garbage collector. 114 func (c scriptFreeList) Return(buf []byte) { 115 // Ignore any buffers returned that aren't the expected size for the 116 // free list. 117 if cap(buf) != freeListMaxScriptSize { 118 return 119 } 120 121 // Return the buffer to the free list when it's not full. Otherwise let 122 // it be garbage collected. 123 select { 124 case c <- buf: 125 default: 126 // Let it go to the garbage collector. 127 } 128 } 129 130 // Create the concurrent safe free list to use for script deserialization. As 131 // previously described, this free list is maintained to significantly reduce 132 // the number of allocations. 133 var scriptPool scriptFreeList = make(chan []byte, freeListMaxItems) 134 135 // OutPoint defines a bitcoin data type that is used to track previous 136 // transaction outputs. 137 type OutPoint struct { 138 Hash ShaHash 139 Index uint32 140 } 141 142 // NewOutPoint returns a new bitcoin transaction outpoint point with the 143 // provided hash and index. 144 func NewOutPoint(hash *ShaHash, index uint32) *OutPoint { 145 return &OutPoint{ 146 Hash: *hash, 147 Index: index, 148 } 149 } 150 151 // String returns the OutPoint in the human-readable form "hash:index". 152 func (o OutPoint) String() string { 153 // Allocate enough for hash string, colon, and 10 digits. Although 154 // at the time of writing, the number of digits can be no greater than 155 // the length of the decimal representation of maxTxOutPerMessage, the 156 // maximum message payload may increase in the future and this 157 // optimization may go unnoticed, so allocate space for 10 decimal 158 // digits, which will fit any uint32. 159 buf := make([]byte, 2*HashSize+1, 2*HashSize+1+10) 160 copy(buf, o.Hash.String()) 161 buf[2*HashSize] = ':' 162 buf = strconv.AppendUint(buf, uint64(o.Index), 10) 163 return string(buf) 164 } 165 166 // TxIn defines a bitcoin transaction input. 167 type TxIn struct { 168 PreviousOutPoint OutPoint 169 SignatureScript []byte 170 Sequence uint32 171 } 172 173 // SerializeSize returns the number of bytes it would take to serialize the 174 // the transaction input. 175 func (t *TxIn) SerializeSize() int { 176 // Outpoint Hash 32 bytes + Outpoint Index 4 bytes + Sequence 4 bytes + 177 // serialized varint size for the length of SignatureScript + 178 // SignatureScript bytes. 179 return 40 + VarIntSerializeSize(uint64(len(t.SignatureScript))) + 180 len(t.SignatureScript) 181 } 182 183 // NewTxIn returns a new bitcoin transaction input with the provided 184 // previous outpoint point and signature script with a default sequence of 185 // MaxTxInSequenceNum. 186 func NewTxIn(prevOut *OutPoint, signatureScript []byte) *TxIn { 187 return &TxIn{ 188 PreviousOutPoint: *prevOut, 189 SignatureScript: signatureScript, 190 Sequence: MaxTxInSequenceNum, 191 } 192 } 193 194 // TxOut defines a bitcoin transaction output. 195 type TxOut struct { 196 Value int64 197 PkScript []byte 198 } 199 200 // SerializeSize returns the number of bytes it would take to serialize the 201 // the transaction output. 202 func (t *TxOut) SerializeSize() int { 203 // Value 8 bytes + serialized varint size for the length of PkScript + 204 // PkScript bytes. 205 return 8 + VarIntSerializeSize(uint64(len(t.PkScript))) + len(t.PkScript) 206 } 207 208 // NewTxOut returns a new bitcoin transaction output with the provided 209 // transaction value and public key script. 210 func NewTxOut(value int64, pkScript []byte) *TxOut { 211 return &TxOut{ 212 Value: value, 213 PkScript: pkScript, 214 } 215 } 216 217 // MsgTx implements the Message interface and represents a bitcoin tx message. 218 // It is used to deliver transaction information in response to a getdata 219 // message (MsgGetData) for a given transaction. 220 // 221 // Use the AddTxIn and AddTxOut functions to build up the list of transaction 222 // inputs and outputs. 223 type MsgTx struct { 224 Version int32 225 TxIn []*TxIn 226 TxOut []*TxOut 227 LockTime uint32 228 } 229 230 // AddTxIn adds a transaction input to the message. 231 func (msg *MsgTx) AddTxIn(ti *TxIn) { 232 msg.TxIn = append(msg.TxIn, ti) 233 } 234 235 // AddTxOut adds a transaction output to the message. 236 func (msg *MsgTx) AddTxOut(to *TxOut) { 237 msg.TxOut = append(msg.TxOut, to) 238 } 239 240 // TxSha generates the ShaHash name for the transaction. 241 func (msg *MsgTx) TxSha() ShaHash { 242 // Encode the transaction and calculate double sha256 on the result. 243 // Ignore the error returns since the only way the encode could fail 244 // is being out of memory or due to nil pointers, both of which would 245 // cause a run-time panic. 246 buf := bytes.NewBuffer(make([]byte, 0, msg.SerializeSize())) 247 _ = msg.Serialize(buf) 248 return DoubleSha256SH(buf.Bytes()) 249 } 250 251 // Copy creates a deep copy of a transaction so that the original does not get 252 // modified when the copy is manipulated. 253 func (msg *MsgTx) Copy() *MsgTx { 254 // Create new tx and start by copying primitive values and making space 255 // for the transaction inputs and outputs. 256 newTx := MsgTx{ 257 Version: msg.Version, 258 TxIn: make([]*TxIn, 0, len(msg.TxIn)), 259 TxOut: make([]*TxOut, 0, len(msg.TxOut)), 260 LockTime: msg.LockTime, 261 } 262 263 // Deep copy the old TxIn data. 264 for _, oldTxIn := range msg.TxIn { 265 // Deep copy the old previous outpoint. 266 oldOutPoint := oldTxIn.PreviousOutPoint 267 newOutPoint := OutPoint{} 268 newOutPoint.Hash.SetBytes(oldOutPoint.Hash[:]) 269 newOutPoint.Index = oldOutPoint.Index 270 271 // Deep copy the old signature script. 272 var newScript []byte 273 oldScript := oldTxIn.SignatureScript 274 oldScriptLen := len(oldScript) 275 if oldScriptLen > 0 { 276 newScript = make([]byte, oldScriptLen, oldScriptLen) 277 copy(newScript, oldScript[:oldScriptLen]) 278 } 279 280 // Create new txIn with the deep copied data and append it to 281 // new Tx. 282 newTxIn := TxIn{ 283 PreviousOutPoint: newOutPoint, 284 SignatureScript: newScript, 285 Sequence: oldTxIn.Sequence, 286 } 287 newTx.TxIn = append(newTx.TxIn, &newTxIn) 288 } 289 290 // Deep copy the old TxOut data. 291 for _, oldTxOut := range msg.TxOut { 292 // Deep copy the old PkScript 293 var newScript []byte 294 oldScript := oldTxOut.PkScript 295 oldScriptLen := len(oldScript) 296 if oldScriptLen > 0 { 297 newScript = make([]byte, oldScriptLen, oldScriptLen) 298 copy(newScript, oldScript[:oldScriptLen]) 299 } 300 301 // Create new txOut with the deep copied data and append it to 302 // new Tx. 303 newTxOut := TxOut{ 304 Value: oldTxOut.Value, 305 PkScript: newScript, 306 } 307 newTx.TxOut = append(newTx.TxOut, &newTxOut) 308 } 309 310 return &newTx 311 } 312 313 // BtcDecode decodes r using the bitcoin protocol encoding into the receiver. 314 // This is part of the Message interface implementation. 315 // See Deserialize for decoding transactions stored to disk, such as in a 316 // database, as opposed to decoding transactions from the wire. 317 func (msg *MsgTx) BtcDecode(r io.Reader, pver uint32) error { 318 version, err := binarySerializer.Uint32(r, littleEndian) 319 if err != nil { 320 return err 321 } 322 msg.Version = int32(version) 323 324 count, err := ReadVarInt(r, pver) 325 if err != nil { 326 return err 327 } 328 329 // Prevent more input transactions than could possibly fit into a 330 // message. It would be possible to cause memory exhaustion and panics 331 // without a sane upper bound on this count. 332 if count > uint64(maxTxInPerMessage) { 333 str := fmt.Sprintf("too many input transactions to fit into "+ 334 "max message size [count %d, max %d]", count, 335 maxTxInPerMessage) 336 return messageError("MsgTx.BtcDecode", str) 337 } 338 339 // returnScriptBuffers is a closure that returns any script buffers that 340 // were borrowed from the pool when there are any deserialization 341 // errors. This is only valid to call before the final step which 342 // replaces the scripts with the location in a contiguous buffer and 343 // returns them. 344 returnScriptBuffers := func() { 345 for _, txIn := range msg.TxIn { 346 if txIn == nil || txIn.SignatureScript == nil { 347 continue 348 } 349 scriptPool.Return(txIn.SignatureScript) 350 } 351 for _, txOut := range msg.TxOut { 352 if txOut == nil || txOut.PkScript == nil { 353 continue 354 } 355 scriptPool.Return(txOut.PkScript) 356 } 357 } 358 359 // Deserialize the inputs. 360 var totalScriptSize uint64 361 txIns := make([]TxIn, count) 362 msg.TxIn = make([]*TxIn, count) 363 for i := uint64(0); i < count; i++ { 364 // The pointer is set now in case a script buffer is borrowed 365 // and needs to be returned to the pool on error. 366 ti := &txIns[i] 367 msg.TxIn[i] = ti 368 err = readTxIn(r, pver, msg.Version, ti) 369 if err != nil { 370 returnScriptBuffers() 371 return err 372 } 373 totalScriptSize += uint64(len(ti.SignatureScript)) 374 } 375 376 count, err = ReadVarInt(r, pver) 377 if err != nil { 378 returnScriptBuffers() 379 return err 380 } 381 382 // Prevent more output transactions than could possibly fit into a 383 // message. It would be possible to cause memory exhaustion and panics 384 // without a sane upper bound on this count. 385 if count > uint64(maxTxOutPerMessage) { 386 returnScriptBuffers() 387 str := fmt.Sprintf("too many output transactions to fit into "+ 388 "max message size [count %d, max %d]", count, 389 maxTxOutPerMessage) 390 return messageError("MsgTx.BtcDecode", str) 391 } 392 393 // Deserialize the outputs. 394 txOuts := make([]TxOut, count) 395 msg.TxOut = make([]*TxOut, count) 396 for i := uint64(0); i < count; i++ { 397 // The pointer is set now in case a script buffer is borrowed 398 // and needs to be returned to the pool on error. 399 to := &txOuts[i] 400 msg.TxOut[i] = to 401 err = readTxOut(r, pver, msg.Version, to) 402 if err != nil { 403 returnScriptBuffers() 404 return err 405 } 406 totalScriptSize += uint64(len(to.PkScript)) 407 } 408 409 msg.LockTime, err = binarySerializer.Uint32(r, littleEndian) 410 if err != nil { 411 returnScriptBuffers() 412 return err 413 } 414 415 // Create a single allocation to house all of the scripts and set each 416 // input signature script and output public key script to the 417 // appropriate subslice of the overall contiguous buffer. Then, return 418 // each individual script buffer back to the pool so they can be reused 419 // for future deserializations. This is done because it significantly 420 // reduces the number of allocations the garbage collector needs to 421 // track, which in turn improves performance and drastically reduces the 422 // amount of runtime overhead that would otherwise be needed to keep 423 // track of millions of small allocations. 424 // 425 // NOTE: It is no longer valid to call the returnScriptBuffers closure 426 // after these blocks of code run because it is already done and the 427 // scripts in the transaction inputs and outputs no longer point to the 428 // buffers. 429 var offset uint64 430 scripts := make([]byte, totalScriptSize) 431 for i := 0; i < len(msg.TxIn); i++ { 432 // Copy the signature script into the contiguous buffer at the 433 // appropriate offset. 434 signatureScript := msg.TxIn[i].SignatureScript 435 copy(scripts[offset:], signatureScript) 436 437 // Reset the signature script of the transaction input to the 438 // slice of the contiguous buffer where the script lives. 439 scriptSize := uint64(len(signatureScript)) 440 end := offset + scriptSize 441 msg.TxIn[i].SignatureScript = scripts[offset:end:end] 442 offset += scriptSize 443 444 // Return the temporary script buffer to the pool. 445 scriptPool.Return(signatureScript) 446 } 447 for i := 0; i < len(msg.TxOut); i++ { 448 // Copy the public key script into the contiguous buffer at the 449 // appropriate offset. 450 pkScript := msg.TxOut[i].PkScript 451 copy(scripts[offset:], pkScript) 452 453 // Reset the public key script of the transaction output to the 454 // slice of the contiguous buffer where the script lives. 455 scriptSize := uint64(len(pkScript)) 456 end := offset + scriptSize 457 msg.TxOut[i].PkScript = scripts[offset:end:end] 458 offset += scriptSize 459 460 // Return the temporary script buffer to the pool. 461 scriptPool.Return(pkScript) 462 } 463 464 return nil 465 } 466 467 // Deserialize decodes a transaction from r into the receiver using a format 468 // that is suitable for long-term storage such as a database while respecting 469 // the Version field in the transaction. This function differs from BtcDecode 470 // in that BtcDecode decodes from the bitcoin wire protocol as it was sent 471 // across the network. The wire encoding can technically differ depending on 472 // the protocol version and doesn't even really need to match the format of a 473 // stored transaction at all. As of the time this comment was written, the 474 // encoded transaction is the same in both instances, but there is a distinct 475 // difference and separating the two allows the API to be flexible enough to 476 // deal with changes. 477 func (msg *MsgTx) Deserialize(r io.Reader) error { 478 // At the current time, there is no difference between the wire encoding 479 // at protocol version 0 and the stable long-term storage format. As 480 // a result, make use of BtcDecode. 481 return msg.BtcDecode(r, 0) 482 } 483 484 // BtcEncode encodes the receiver to w using the bitcoin protocol encoding. 485 // This is part of the Message interface implementation. 486 // See Serialize for encoding transactions to be stored to disk, such as in a 487 // database, as opposed to encoding transactions for the wire. 488 func (msg *MsgTx) BtcEncode(w io.Writer, pver uint32) error { 489 err := binarySerializer.PutUint32(w, littleEndian, uint32(msg.Version)) 490 if err != nil { 491 return err 492 } 493 494 count := uint64(len(msg.TxIn)) 495 err = WriteVarInt(w, pver, count) 496 if err != nil { 497 return err 498 } 499 500 for _, ti := range msg.TxIn { 501 err = writeTxIn(w, pver, msg.Version, ti) 502 if err != nil { 503 return err 504 } 505 } 506 507 count = uint64(len(msg.TxOut)) 508 err = WriteVarInt(w, pver, count) 509 if err != nil { 510 return err 511 } 512 513 for _, to := range msg.TxOut { 514 err = writeTxOut(w, pver, msg.Version, to) 515 if err != nil { 516 return err 517 } 518 } 519 520 err = binarySerializer.PutUint32(w, littleEndian, msg.LockTime) 521 if err != nil { 522 return err 523 } 524 525 return nil 526 } 527 528 // Serialize encodes the transaction to w using a format that suitable for 529 // long-term storage such as a database while respecting the Version field in 530 // the transaction. This function differs from BtcEncode in that BtcEncode 531 // encodes the transaction to the bitcoin wire protocol in order to be sent 532 // across the network. The wire encoding can technically differ depending on 533 // the protocol version and doesn't even really need to match the format of a 534 // stored transaction at all. As of the time this comment was written, the 535 // encoded transaction is the same in both instances, but there is a distinct 536 // difference and separating the two allows the API to be flexible enough to 537 // deal with changes. 538 func (msg *MsgTx) Serialize(w io.Writer) error { 539 // At the current time, there is no difference between the wire encoding 540 // at protocol version 0 and the stable long-term storage format. As 541 // a result, make use of BtcEncode. 542 return msg.BtcEncode(w, 0) 543 544 } 545 546 // SerializeSize returns the number of bytes it would take to serialize the 547 // the transaction. 548 func (msg *MsgTx) SerializeSize() int { 549 // Version 4 bytes + LockTime 4 bytes + Serialized varint size for the 550 // number of transaction inputs and outputs. 551 n := 8 + VarIntSerializeSize(uint64(len(msg.TxIn))) + 552 VarIntSerializeSize(uint64(len(msg.TxOut))) 553 554 for _, txIn := range msg.TxIn { 555 n += txIn.SerializeSize() 556 } 557 558 for _, txOut := range msg.TxOut { 559 n += txOut.SerializeSize() 560 } 561 562 return n 563 } 564 565 // Command returns the protocol command string for the message. This is part 566 // of the Message interface implementation. 567 func (msg *MsgTx) Command() string { 568 return CmdTx 569 } 570 571 // MaxPayloadLength returns the maximum length the payload can be for the 572 // receiver. This is part of the Message interface implementation. 573 func (msg *MsgTx) MaxPayloadLength(pver uint32) uint32 { 574 return MaxBlockPayload 575 } 576 577 // PkScriptLocs returns a slice containing the start of each public key script 578 // within the raw serialized transaction. The caller can easily obtain the 579 // length of each script by using len on the script available via the 580 // appropriate transaction output entry. 581 func (msg *MsgTx) PkScriptLocs() []int { 582 numTxOut := len(msg.TxOut) 583 if numTxOut == 0 { 584 return nil 585 } 586 587 // The starting offset in the serialized transaction of the first 588 // transaction output is: 589 // 590 // Version 4 bytes + serialized varint size for the number of 591 // transaction inputs and outputs + serialized size of each transaction 592 // input. 593 n := 4 + VarIntSerializeSize(uint64(len(msg.TxIn))) + 594 VarIntSerializeSize(uint64(numTxOut)) 595 for _, txIn := range msg.TxIn { 596 n += txIn.SerializeSize() 597 } 598 599 // Calculate and set the appropriate offset for each public key script. 600 pkScriptLocs := make([]int, numTxOut) 601 for i, txOut := range msg.TxOut { 602 // The offset of the script in the transaction output is: 603 // 604 // Value 8 bytes + serialized varint size for the length of 605 // PkScript. 606 n += 8 + VarIntSerializeSize(uint64(len(txOut.PkScript))) 607 pkScriptLocs[i] = n 608 n += len(txOut.PkScript) 609 } 610 611 return pkScriptLocs 612 } 613 614 // NewMsgTx returns a new bitcoin tx message that conforms to the Message 615 // interface. The return instance has a default version of TxVersion and there 616 // are no transaction inputs or outputs. Also, the lock time is set to zero 617 // to indicate the transaction is valid immediately as opposed to some time in 618 // future. 619 func NewMsgTx() *MsgTx { 620 return &MsgTx{ 621 Version: TxVersion, 622 TxIn: make([]*TxIn, 0, defaultTxInOutAlloc), 623 TxOut: make([]*TxOut, 0, defaultTxInOutAlloc), 624 } 625 } 626 627 // readOutPoint reads the next sequence of bytes from r as an OutPoint. 628 func readOutPoint(r io.Reader, pver uint32, version int32, op *OutPoint) error { 629 _, err := io.ReadFull(r, op.Hash[:]) 630 if err != nil { 631 return err 632 } 633 634 op.Index, err = binarySerializer.Uint32(r, littleEndian) 635 if err != nil { 636 return err 637 } 638 639 return nil 640 } 641 642 // writeOutPoint encodes op to the bitcoin protocol encoding for an OutPoint 643 // to w. 644 func writeOutPoint(w io.Writer, pver uint32, version int32, op *OutPoint) error { 645 _, err := w.Write(op.Hash[:]) 646 if err != nil { 647 return err 648 } 649 650 err = binarySerializer.PutUint32(w, littleEndian, op.Index) 651 if err != nil { 652 return err 653 } 654 return nil 655 } 656 657 // readScript reads a variable length byte array that represents a transaction 658 // script. It is encoded as a varInt containing the length of the array 659 // followed by the bytes themselves. An error is returned if the length is 660 // greater than the passed maxAllowed parameter which helps protect against 661 // memory exhuastion attacks and forced panics thorugh malformed messages. The 662 // fieldName parameter is only used for the error message so it provides more 663 // context in the error. 664 func readScript(r io.Reader, pver uint32, maxAllowed uint32, fieldName string) ([]byte, error) { 665 count, err := ReadVarInt(r, pver) 666 if err != nil { 667 return nil, err 668 } 669 670 // Prevent byte array larger than the max message size. It would 671 // be possible to cause memory exhaustion and panics without a sane 672 // upper bound on this count. 673 if count > uint64(maxAllowed) { 674 str := fmt.Sprintf("%s is larger than the max allowed size "+ 675 "[count %d, max %d]", fieldName, count, maxAllowed) 676 return nil, messageError("readScript", str) 677 } 678 679 b := scriptPool.Borrow(count) 680 _, err = io.ReadFull(r, b) 681 if err != nil { 682 scriptPool.Return(b) 683 return nil, err 684 } 685 return b, nil 686 } 687 688 // readTxIn reads the next sequence of bytes from r as a transaction input 689 // (TxIn). 690 func readTxIn(r io.Reader, pver uint32, version int32, ti *TxIn) error { 691 err := readOutPoint(r, pver, version, &ti.PreviousOutPoint) 692 if err != nil { 693 return err 694 } 695 696 ti.SignatureScript, err = readScript(r, pver, MaxMessagePayload, 697 "transaction input signature script") 698 if err != nil { 699 return err 700 } 701 702 err = readElement(r, &ti.Sequence) 703 if err != nil { 704 return err 705 } 706 707 return nil 708 } 709 710 // writeTxIn encodes ti to the bitcoin protocol encoding for a transaction 711 // input (TxIn) to w. 712 func writeTxIn(w io.Writer, pver uint32, version int32, ti *TxIn) error { 713 err := writeOutPoint(w, pver, version, &ti.PreviousOutPoint) 714 if err != nil { 715 return err 716 } 717 718 err = WriteVarBytes(w, pver, ti.SignatureScript) 719 if err != nil { 720 return err 721 } 722 723 err = binarySerializer.PutUint32(w, littleEndian, ti.Sequence) 724 if err != nil { 725 return err 726 } 727 728 return nil 729 } 730 731 // readTxOut reads the next sequence of bytes from r as a transaction output 732 // (TxOut). 733 func readTxOut(r io.Reader, pver uint32, version int32, to *TxOut) error { 734 err := readElement(r, &to.Value) 735 if err != nil { 736 return err 737 } 738 739 to.PkScript, err = readScript(r, pver, MaxMessagePayload, 740 "transaction output public key script") 741 if err != nil { 742 return err 743 } 744 745 return nil 746 } 747 748 // writeTxOut encodes to into the bitcoin protocol encoding for a transaction 749 // output (TxOut) to w. 750 func writeTxOut(w io.Writer, pver uint32, version int32, to *TxOut) error { 751 err := binarySerializer.PutUint64(w, littleEndian, uint64(to.Value)) 752 if err != nil { 753 return err 754 } 755 756 err = WriteVarBytes(w, pver, to.PkScript) 757 if err != nil { 758 return err 759 } 760 return nil 761 }