github.com/BlockABC/godash@v0.0.0-20191112120524-f4aa3a32c566/wire/msgversion.go (about)

     1  // Copyright (c) 2013-2016 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  	"net"
    13  	"strings"
    14  	"time"
    15  )
    16  
    17  // MaxUserAgentLen is the maximum allowed length for the user agent field in a
    18  // version message (MsgVersion).
    19  const MaxUserAgentLen = 2000
    20  
    21  // DefaultUserAgent for wire in the stack
    22  const DefaultUserAgent = "/btcwire:0.4.0/"
    23  
    24  // MsgVersion implements the Message interface and represents a bitcoin version
    25  // message.  It is used for a peer to advertise itself as soon as an outbound
    26  // connection is made.  The remote peer then uses this information along with
    27  // its own to negotiate.  The remote peer must then respond with a version
    28  // message of its own containing the negotiated values followed by a verack
    29  // message (MsgVerAck).  This exchange must take place before any further
    30  // communication is allowed to proceed.
    31  type MsgVersion struct {
    32  	// Version of the protocol the node is using.
    33  	ProtocolVersion int32
    34  
    35  	// Bitfield which identifies the enabled services.
    36  	Services ServiceFlag
    37  
    38  	// Time the message was generated.  This is encoded as an int64 on the wire.
    39  	Timestamp time.Time
    40  
    41  	// Address of the remote peer.
    42  	AddrYou NetAddress
    43  
    44  	// Address of the local peer.
    45  	AddrMe NetAddress
    46  
    47  	// Unique value associated with message that is used to detect self
    48  	// connections.
    49  	Nonce uint64
    50  
    51  	// The user agent that generated messsage.  This is a encoded as a varString
    52  	// on the wire.  This has a max length of MaxUserAgentLen.
    53  	UserAgent string
    54  
    55  	// Last block seen by the generator of the version message.
    56  	LastBlock int32
    57  
    58  	// Don't announce transactions to peer.
    59  	DisableRelayTx bool
    60  }
    61  
    62  // HasService returns whether the specified service is supported by the peer
    63  // that generated the message.
    64  func (msg *MsgVersion) HasService(service ServiceFlag) bool {
    65  	return msg.Services&service == service
    66  }
    67  
    68  // AddService adds service as a supported service by the peer generating the
    69  // message.
    70  func (msg *MsgVersion) AddService(service ServiceFlag) {
    71  	msg.Services |= service
    72  }
    73  
    74  // BtcDecode decodes r using the bitcoin protocol encoding into the receiver.
    75  // The version message is special in that the protocol version hasn't been
    76  // negotiated yet.  As a result, the pver field is ignored and any fields which
    77  // are added in new versions are optional.  This also mean that r must be a
    78  // *bytes.Buffer so the number of remaining bytes can be ascertained.
    79  //
    80  // This is part of the Message interface implementation.
    81  func (msg *MsgVersion) BtcDecode(r io.Reader, pver uint32) error {
    82  	buf, ok := r.(*bytes.Buffer)
    83  	if !ok {
    84  		return fmt.Errorf("MsgVersion.BtcDecode reader is not a " +
    85  			"*bytes.Buffer")
    86  	}
    87  
    88  	err := readElements(buf, &msg.ProtocolVersion, &msg.Services,
    89  		(*int64Time)(&msg.Timestamp))
    90  	if err != nil {
    91  		return err
    92  	}
    93  
    94  	err = readNetAddress(buf, pver, &msg.AddrYou, false)
    95  	if err != nil {
    96  		return err
    97  	}
    98  
    99  	// Protocol versions >= 106 added a from address, nonce, and user agent
   100  	// field and they are only considered present if there are bytes
   101  	// remaining in the message.
   102  	if buf.Len() > 0 {
   103  		err = readNetAddress(buf, pver, &msg.AddrMe, false)
   104  		if err != nil {
   105  			return err
   106  		}
   107  	}
   108  	if buf.Len() > 0 {
   109  		err = readElement(buf, &msg.Nonce)
   110  		if err != nil {
   111  			return err
   112  		}
   113  	}
   114  	if buf.Len() > 0 {
   115  		userAgent, err := ReadVarString(buf, pver)
   116  		if err != nil {
   117  			return err
   118  		}
   119  		err = validateUserAgent(userAgent)
   120  		if err != nil {
   121  			return err
   122  		}
   123  		msg.UserAgent = userAgent
   124  	}
   125  
   126  	// Protocol versions >= 209 added a last known block field.  It is only
   127  	// considered present if there are bytes remaining in the message.
   128  	if buf.Len() > 0 {
   129  		err = readElement(buf, &msg.LastBlock)
   130  		if err != nil {
   131  			return err
   132  		}
   133  	}
   134  
   135  	// There was no relay transactions field before BIP0037Version, but
   136  	// the default behavior prior to the addition of the field was to always
   137  	// relay transactions.
   138  	if buf.Len() > 0 {
   139  		// It's safe to ignore the error here since the buffer has at
   140  		// least one byte and that byte will result in a boolean value
   141  		// regardless of its value.  Also, the wire encoding for the
   142  		// field is true when transactions should be relayed, so reverse
   143  		// it for the DisableRelayTx field.
   144  		var relayTx bool
   145  		readElement(r, &relayTx)
   146  		msg.DisableRelayTx = !relayTx
   147  	}
   148  
   149  	return nil
   150  }
   151  
   152  // BtcEncode encodes the receiver to w using the bitcoin protocol encoding.
   153  // This is part of the Message interface implementation.
   154  func (msg *MsgVersion) BtcEncode(w io.Writer, pver uint32) error {
   155  	err := validateUserAgent(msg.UserAgent)
   156  	if err != nil {
   157  		return err
   158  	}
   159  
   160  	err = writeElements(w, msg.ProtocolVersion, msg.Services,
   161  		msg.Timestamp.Unix())
   162  	if err != nil {
   163  		return err
   164  	}
   165  
   166  	err = writeNetAddress(w, pver, &msg.AddrYou, false)
   167  	if err != nil {
   168  		return err
   169  	}
   170  
   171  	err = writeNetAddress(w, pver, &msg.AddrMe, false)
   172  	if err != nil {
   173  		return err
   174  	}
   175  
   176  	err = writeElement(w, msg.Nonce)
   177  	if err != nil {
   178  		return err
   179  	}
   180  
   181  	err = WriteVarString(w, pver, msg.UserAgent)
   182  	if err != nil {
   183  		return err
   184  	}
   185  
   186  	err = writeElement(w, msg.LastBlock)
   187  	if err != nil {
   188  		return err
   189  	}
   190  
   191  	// There was no relay transactions field before BIP0037Version.  Also,
   192  	// the wire encoding for the field is true when transactions should be
   193  	// relayed, so reverse it from the DisableRelayTx field.
   194  	if pver >= BIP0037Version {
   195  		err = writeElement(w, !msg.DisableRelayTx)
   196  		if err != nil {
   197  			return err
   198  		}
   199  	}
   200  	return nil
   201  }
   202  
   203  // Command returns the protocol command string for the message.  This is part
   204  // of the Message interface implementation.
   205  func (msg *MsgVersion) Command() string {
   206  	return CmdVersion
   207  }
   208  
   209  // MaxPayloadLength returns the maximum length the payload can be for the
   210  // receiver.  This is part of the Message interface implementation.
   211  func (msg *MsgVersion) MaxPayloadLength(pver uint32) uint32 {
   212  	// XXX: <= 106 different
   213  
   214  	// Protocol version 4 bytes + services 8 bytes + timestamp 8 bytes +
   215  	// remote and local net addresses + nonce 8 bytes + length of user
   216  	// agent (varInt) + max allowed useragent length + last block 4 bytes +
   217  	// relay transactions flag 1 byte.
   218  	return 33 + (maxNetAddressPayload(pver) * 2) + MaxVarIntPayload +
   219  		MaxUserAgentLen
   220  }
   221  
   222  // NewMsgVersion returns a new bitcoin version message that conforms to the
   223  // Message interface using the passed parameters and defaults for the remaining
   224  // fields.
   225  func NewMsgVersion(me *NetAddress, you *NetAddress, nonce uint64,
   226  	lastBlock int32) *MsgVersion {
   227  
   228  	// Limit the timestamp to one second precision since the protocol
   229  	// doesn't support better.
   230  	return &MsgVersion{
   231  		ProtocolVersion: int32(ProtocolVersion),
   232  		Services:        0,
   233  		Timestamp:       time.Unix(time.Now().Unix(), 0),
   234  		AddrYou:         *you,
   235  		AddrMe:          *me,
   236  		Nonce:           nonce,
   237  		UserAgent:       DefaultUserAgent,
   238  		LastBlock:       lastBlock,
   239  		DisableRelayTx:  false,
   240  	}
   241  }
   242  
   243  // NewMsgVersionFromConn is a convenience function that extracts the remote
   244  // and local address from conn and returns a new bitcoin version message that
   245  // conforms to the Message interface.  See NewMsgVersion.
   246  func NewMsgVersionFromConn(conn net.Conn, nonce uint64,
   247  	lastBlock int32) (*MsgVersion, error) {
   248  
   249  	// Don't assume any services until we know otherwise.
   250  	lna, err := NewNetAddress(conn.LocalAddr(), 0)
   251  	if err != nil {
   252  		return nil, err
   253  	}
   254  
   255  	// Don't assume any services until we know otherwise.
   256  	rna, err := NewNetAddress(conn.RemoteAddr(), 0)
   257  	if err != nil {
   258  		return nil, err
   259  	}
   260  
   261  	return NewMsgVersion(lna, rna, nonce, lastBlock), nil
   262  }
   263  
   264  // validateUserAgent checks userAgent length against MaxUserAgentLen
   265  func validateUserAgent(userAgent string) error {
   266  	if len(userAgent) > MaxUserAgentLen {
   267  		str := fmt.Sprintf("user agent too long [len %v, max %v]",
   268  			len(userAgent), MaxUserAgentLen)
   269  		return messageError("MsgVersion", str)
   270  	}
   271  	return nil
   272  }
   273  
   274  // AddUserAgent adds a user agent to the user agent string for the version
   275  // message.  The version string is not defined to any strict format, although
   276  // it is recommended to use the form "major.minor.revision" e.g. "2.6.41".
   277  func (msg *MsgVersion) AddUserAgent(name string, version string,
   278  	comments ...string) error {
   279  
   280  	newUserAgent := fmt.Sprintf("%s:%s", name, version)
   281  	if len(comments) != 0 {
   282  		newUserAgent = fmt.Sprintf("%s(%s)", newUserAgent,
   283  			strings.Join(comments, "; "))
   284  	}
   285  	newUserAgent = fmt.Sprintf("%s%s/", msg.UserAgent, newUserAgent)
   286  	err := validateUserAgent(newUserAgent)
   287  	if err != nil {
   288  		return err
   289  	}
   290  	msg.UserAgent = newUserAgent
   291  	return nil
   292  }