github.com/decred/dcrlnd@v0.7.6/lnwire/message.go (about)

     1  // Copyright (c) 2013-2017 The btcsuite developers
     2  // Copyright (c) 2015-2016 The Decred developers
     3  // code derived from https://github .com/btcsuite/btcd/blob/master/wire/message.go
     4  // Copyright (C) 2015-2017 The Lightning Network Developers
     5  
     6  package lnwire
     7  
     8  import (
     9  	"bytes"
    10  	"encoding/binary"
    11  	"fmt"
    12  	"io"
    13  )
    14  
    15  // MessageType is the unique 2 byte big-endian integer that indicates the type
    16  // of message on the wire. All messages have a very simple header which
    17  // consists simply of 2-byte message type. We omit a length field, and checksum
    18  // as the Lightning Protocol is intended to be encapsulated within a
    19  // confidential+authenticated cryptographic messaging protocol.
    20  type MessageType uint16
    21  
    22  // The currently defined message types within this current version of the
    23  // Lightning protocol.
    24  const (
    25  	MsgInit                    MessageType = 16
    26  	MsgError                               = 17
    27  	MsgPing                                = 18
    28  	MsgPong                                = 19
    29  	MsgOpenChannel                         = 32
    30  	MsgAcceptChannel                       = 33
    31  	MsgFundingCreated                      = 34
    32  	MsgFundingSigned                       = 35
    33  	MsgFundingLocked                       = 36
    34  	MsgShutdown                            = 38
    35  	MsgClosingSigned                       = 39
    36  	MsgUpdateAddHTLC                       = 128
    37  	MsgUpdateFulfillHTLC                   = 130
    38  	MsgUpdateFailHTLC                      = 131
    39  	MsgCommitSig                           = 132
    40  	MsgRevokeAndAck                        = 133
    41  	MsgUpdateFee                           = 134
    42  	MsgUpdateFailMalformedHTLC             = 135
    43  	MsgChannelReestablish                  = 136
    44  	MsgChannelAnnouncement                 = 256
    45  	MsgNodeAnnouncement                    = 257
    46  	MsgChannelUpdate                       = 258
    47  	MsgAnnounceSignatures                  = 259
    48  	MsgQueryShortChanIDs                   = 261
    49  	MsgReplyShortChanIDsEnd                = 262
    50  	MsgQueryChannelRange                   = 263
    51  	MsgReplyChannelRange                   = 264
    52  	MsgGossipTimestampRange                = 265
    53  )
    54  
    55  // ErrorEncodeMessage is used when failed to encode the message payload.
    56  func ErrorEncodeMessage(err error) error {
    57  	return fmt.Errorf("failed to encode message to buffer, got %w", err)
    58  }
    59  
    60  // ErrorWriteMessageType is used when failed to write the message type.
    61  func ErrorWriteMessageType(err error) error {
    62  	return fmt.Errorf("failed to write message type, got %w", err)
    63  }
    64  
    65  // ErrorPayloadTooLarge is used when the payload size exceeds the
    66  // MaxMsgBody.
    67  func ErrorPayloadTooLarge(size int) error {
    68  	return fmt.Errorf(
    69  		"message payload is too large - encoded %d bytes, "+
    70  			"but maximum message payload is %d bytes",
    71  		size, MaxMsgBody,
    72  	)
    73  
    74  }
    75  
    76  // String return the string representation of message type.
    77  func (t MessageType) String() string {
    78  	switch t {
    79  	case MsgInit:
    80  		return "Init"
    81  	case MsgOpenChannel:
    82  		return "MsgOpenChannel"
    83  	case MsgAcceptChannel:
    84  		return "MsgAcceptChannel"
    85  	case MsgFundingCreated:
    86  		return "MsgFundingCreated"
    87  	case MsgFundingSigned:
    88  		return "MsgFundingSigned"
    89  	case MsgFundingLocked:
    90  		return "FundingLocked"
    91  	case MsgShutdown:
    92  		return "Shutdown"
    93  	case MsgClosingSigned:
    94  		return "ClosingSigned"
    95  	case MsgUpdateAddHTLC:
    96  		return "UpdateAddHTLC"
    97  	case MsgUpdateFailHTLC:
    98  		return "UpdateFailHTLC"
    99  	case MsgUpdateFulfillHTLC:
   100  		return "UpdateFulfillHTLC"
   101  	case MsgCommitSig:
   102  		return "CommitSig"
   103  	case MsgRevokeAndAck:
   104  		return "RevokeAndAck"
   105  	case MsgUpdateFailMalformedHTLC:
   106  		return "UpdateFailMalformedHTLC"
   107  	case MsgChannelReestablish:
   108  		return "ChannelReestablish"
   109  	case MsgError:
   110  		return "Error"
   111  	case MsgChannelAnnouncement:
   112  		return "ChannelAnnouncement"
   113  	case MsgChannelUpdate:
   114  		return "ChannelUpdate"
   115  	case MsgNodeAnnouncement:
   116  		return "NodeAnnouncement"
   117  	case MsgPing:
   118  		return "Ping"
   119  	case MsgAnnounceSignatures:
   120  		return "AnnounceSignatures"
   121  	case MsgPong:
   122  		return "Pong"
   123  	case MsgUpdateFee:
   124  		return "UpdateFee"
   125  	case MsgQueryShortChanIDs:
   126  		return "QueryShortChanIDs"
   127  	case MsgReplyShortChanIDsEnd:
   128  		return "ReplyShortChanIDsEnd"
   129  	case MsgQueryChannelRange:
   130  		return "QueryChannelRange"
   131  	case MsgReplyChannelRange:
   132  		return "ReplyChannelRange"
   133  	case MsgGossipTimestampRange:
   134  		return "GossipTimestampRange"
   135  	default:
   136  		return "<unknown>"
   137  	}
   138  }
   139  
   140  // UnknownMessage is an implementation of the error interface that allows the
   141  // creation of an error in response to an unknown message.
   142  type UnknownMessage struct {
   143  	messageType MessageType
   144  }
   145  
   146  // Error returns a human readable string describing the error.
   147  //
   148  // This is part of the error interface.
   149  func (u *UnknownMessage) Error() string {
   150  	return fmt.Sprintf("unable to parse message of unknown type: %v",
   151  		u.messageType)
   152  }
   153  
   154  // Serializable is an interface which defines a lightning wire serializable
   155  // object.
   156  type Serializable interface {
   157  	// Decode reads the bytes stream and converts it to the object.
   158  	Decode(io.Reader, uint32) error
   159  
   160  	// Encode converts object to the bytes stream and write it into the
   161  	// write buffer.
   162  	Encode(*bytes.Buffer, uint32) error
   163  }
   164  
   165  // Message is an interface that defines a lightning wire protocol message. The
   166  // interface is general in order to allow implementing types full control over
   167  // the representation of its data.
   168  type Message interface {
   169  	Serializable
   170  	MsgType() MessageType
   171  }
   172  
   173  // makeEmptyMessage creates a new empty message of the proper concrete type
   174  // based on the passed message type.
   175  func makeEmptyMessage(msgType MessageType) (Message, error) {
   176  	var msg Message
   177  
   178  	switch msgType {
   179  	case MsgInit:
   180  		msg = &Init{}
   181  	case MsgOpenChannel:
   182  		msg = &OpenChannel{}
   183  	case MsgAcceptChannel:
   184  		msg = &AcceptChannel{}
   185  	case MsgFundingCreated:
   186  		msg = &FundingCreated{}
   187  	case MsgFundingSigned:
   188  		msg = &FundingSigned{}
   189  	case MsgFundingLocked:
   190  		msg = &FundingLocked{}
   191  	case MsgShutdown:
   192  		msg = &Shutdown{}
   193  	case MsgClosingSigned:
   194  		msg = &ClosingSigned{}
   195  	case MsgUpdateAddHTLC:
   196  		msg = &UpdateAddHTLC{}
   197  	case MsgUpdateFailHTLC:
   198  		msg = &UpdateFailHTLC{}
   199  	case MsgUpdateFulfillHTLC:
   200  		msg = &UpdateFulfillHTLC{}
   201  	case MsgCommitSig:
   202  		msg = &CommitSig{}
   203  	case MsgRevokeAndAck:
   204  		msg = &RevokeAndAck{}
   205  	case MsgUpdateFee:
   206  		msg = &UpdateFee{}
   207  	case MsgUpdateFailMalformedHTLC:
   208  		msg = &UpdateFailMalformedHTLC{}
   209  	case MsgChannelReestablish:
   210  		msg = &ChannelReestablish{}
   211  	case MsgError:
   212  		msg = &Error{}
   213  	case MsgChannelAnnouncement:
   214  		msg = &ChannelAnnouncement{}
   215  	case MsgChannelUpdate:
   216  		msg = &ChannelUpdate{}
   217  	case MsgNodeAnnouncement:
   218  		msg = &NodeAnnouncement{}
   219  	case MsgPing:
   220  		msg = &Ping{}
   221  	case MsgAnnounceSignatures:
   222  		msg = &AnnounceSignatures{}
   223  	case MsgPong:
   224  		msg = &Pong{}
   225  	case MsgQueryShortChanIDs:
   226  		msg = &QueryShortChanIDs{}
   227  	case MsgReplyShortChanIDsEnd:
   228  		msg = &ReplyShortChanIDsEnd{}
   229  	case MsgQueryChannelRange:
   230  		msg = &QueryChannelRange{}
   231  	case MsgReplyChannelRange:
   232  		msg = &ReplyChannelRange{}
   233  	case MsgGossipTimestampRange:
   234  		msg = &GossipTimestampRange{}
   235  	default:
   236  		if msgType < CustomTypeStart {
   237  			return nil, &UnknownMessage{msgType}
   238  		}
   239  		msg = &Custom{
   240  			Type: msgType,
   241  		}
   242  	}
   243  
   244  	return msg, nil
   245  }
   246  
   247  // WriteMessage writes a lightning Message to a buffer including the necessary
   248  // header information and returns the number of bytes written. If any error is
   249  // encountered, the buffer passed will be reset to its original state since we
   250  // don't want any broken bytes left. In other words, no bytes will be written
   251  // if there's an error. Either all or none of the message bytes will be written
   252  // to the buffer.
   253  //
   254  // NOTE: this method is not concurrent safe.
   255  func WriteMessage(buf *bytes.Buffer, msg Message, pver uint32) (int, error) {
   256  	// Record the size of the bytes already written in buffer.
   257  	oldByteSize := buf.Len()
   258  
   259  	// cleanBrokenBytes is a helper closure that helps reset the buffer to
   260  	// its original state. It truncates all the bytes written in current
   261  	// scope.
   262  	var cleanBrokenBytes = func(b *bytes.Buffer) int {
   263  		b.Truncate(oldByteSize)
   264  		return 0
   265  	}
   266  
   267  	// Write the message type.
   268  	var mType [2]byte
   269  	binary.BigEndian.PutUint16(mType[:], uint16(msg.MsgType()))
   270  	msgTypeBytes, err := buf.Write(mType[:])
   271  	if err != nil {
   272  		return cleanBrokenBytes(buf), ErrorWriteMessageType(err)
   273  	}
   274  
   275  	// Use the write buffer to encode our message.
   276  	if err := msg.Encode(buf, pver); err != nil {
   277  		return cleanBrokenBytes(buf), ErrorEncodeMessage(err)
   278  	}
   279  
   280  	// Enforce maximum overall message payload. The write buffer now has
   281  	// the size of len(originalBytes) + len(payload) + len(type). We want
   282  	// to enforce the payload here, so we subtract it by the length of the
   283  	// type and old bytes.
   284  	lenp := buf.Len() - oldByteSize - msgTypeBytes
   285  	if lenp > MaxMsgBody {
   286  		return cleanBrokenBytes(buf), ErrorPayloadTooLarge(lenp)
   287  	}
   288  
   289  	return buf.Len() - oldByteSize, nil
   290  }
   291  
   292  // ReadMessage reads, validates, and parses the next Lightning message from r
   293  // for the provided protocol version.
   294  func ReadMessage(r io.Reader, pver uint32) (Message, error) {
   295  	// First, we'll read out the first two bytes of the message so we can
   296  	// create the proper empty message.
   297  	var mType [2]byte
   298  	if _, err := io.ReadFull(r, mType[:]); err != nil {
   299  		return nil, err
   300  	}
   301  
   302  	msgType := MessageType(binary.BigEndian.Uint16(mType[:]))
   303  
   304  	// Now that we know the target message type, we can create the proper
   305  	// empty message type and decode the message into it.
   306  	msg, err := makeEmptyMessage(msgType)
   307  	if err != nil {
   308  		return nil, err
   309  	}
   310  	if err := msg.Decode(r, pver); err != nil {
   311  		return nil, err
   312  	}
   313  
   314  	return msg, nil
   315  }