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 }