github.com/btcsuite/btcd@v0.24.0/wire/msgnotfound.go (about)

     1  // Copyright (c) 2013-2015 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  	"fmt"
     9  	"io"
    10  )
    11  
    12  // MsgNotFound defines a bitcoin notfound message which is sent in response to
    13  // a getdata message if any of the requested data in not available on the peer.
    14  // Each message is limited to a maximum number of inventory vectors, which is
    15  // currently 50,000.
    16  //
    17  // Use the AddInvVect function to build up the list of inventory vectors when
    18  // sending a notfound message to another peer.
    19  type MsgNotFound struct {
    20  	InvList []*InvVect
    21  }
    22  
    23  // AddInvVect adds an inventory vector to the message.
    24  func (msg *MsgNotFound) AddInvVect(iv *InvVect) error {
    25  	if len(msg.InvList)+1 > MaxInvPerMsg {
    26  		str := fmt.Sprintf("too many invvect in message [max %v]",
    27  			MaxInvPerMsg)
    28  		return messageError("MsgNotFound.AddInvVect", str)
    29  	}
    30  
    31  	msg.InvList = append(msg.InvList, iv)
    32  	return nil
    33  }
    34  
    35  // BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
    36  // This is part of the Message interface implementation.
    37  func (msg *MsgNotFound) BtcDecode(r io.Reader, pver uint32, enc MessageEncoding) error {
    38  	buf := binarySerializer.Borrow()
    39  	defer binarySerializer.Return(buf)
    40  
    41  	count, err := ReadVarIntBuf(r, pver, buf)
    42  	if err != nil {
    43  		return err
    44  	}
    45  
    46  	// Limit to max inventory vectors per message.
    47  	if count > MaxInvPerMsg {
    48  		str := fmt.Sprintf("too many invvect in message [%v]", count)
    49  		return messageError("MsgNotFound.BtcDecode", str)
    50  	}
    51  
    52  	// Create a contiguous slice of inventory vectors to deserialize into in
    53  	// order to reduce the number of allocations.
    54  	invList := make([]InvVect, count)
    55  	msg.InvList = make([]*InvVect, 0, count)
    56  	for i := uint64(0); i < count; i++ {
    57  		iv := &invList[i]
    58  		err := readInvVectBuf(r, pver, iv, buf)
    59  		if err != nil {
    60  			return err
    61  		}
    62  		msg.AddInvVect(iv)
    63  	}
    64  
    65  	return nil
    66  }
    67  
    68  // BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
    69  // This is part of the Message interface implementation.
    70  func (msg *MsgNotFound) BtcEncode(w io.Writer, pver uint32, enc MessageEncoding) error {
    71  	// Limit to max inventory vectors per message.
    72  	count := len(msg.InvList)
    73  	if count > MaxInvPerMsg {
    74  		str := fmt.Sprintf("too many invvect in message [%v]", count)
    75  		return messageError("MsgNotFound.BtcEncode", str)
    76  	}
    77  
    78  	buf := binarySerializer.Borrow()
    79  	defer binarySerializer.Return(buf)
    80  
    81  	err := WriteVarIntBuf(w, pver, uint64(count), buf)
    82  	if err != nil {
    83  		return err
    84  	}
    85  
    86  	for _, iv := range msg.InvList {
    87  		err := writeInvVectBuf(w, pver, iv, buf)
    88  		if err != nil {
    89  			return err
    90  		}
    91  	}
    92  
    93  	return nil
    94  }
    95  
    96  // Command returns the protocol command string for the message.  This is part
    97  // of the Message interface implementation.
    98  func (msg *MsgNotFound) Command() string {
    99  	return CmdNotFound
   100  }
   101  
   102  // MaxPayloadLength returns the maximum length the payload can be for the
   103  // receiver.  This is part of the Message interface implementation.
   104  func (msg *MsgNotFound) MaxPayloadLength(pver uint32) uint32 {
   105  	// Max var int 9 bytes + max InvVects at 36 bytes each.
   106  	// Num inventory vectors (varInt) + max allowed inventory vectors.
   107  	return MaxVarIntPayload + (MaxInvPerMsg * maxInvVectPayload)
   108  }
   109  
   110  // NewMsgNotFound returns a new bitcoin notfound message that conforms to the
   111  // Message interface.  See MsgNotFound for details.
   112  func NewMsgNotFound() *MsgNotFound {
   113  	return &MsgNotFound{
   114  		InvList: make([]*InvVect, 0, defaultInvListAlloc),
   115  	}
   116  }