msgnotfound.go raw

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