github.com/decred/dcrlnd@v0.7.6/lnwire/writer.go (about) 1 package lnwire 2 3 import ( 4 "bytes" 5 "encoding/binary" 6 "errors" 7 "fmt" 8 "image/color" 9 "math" 10 "net" 11 12 "github.com/decred/dcrd/dcrec/secp256k1/v4" 13 "github.com/decred/dcrd/dcrutil/v4" 14 "github.com/decred/dcrd/wire" 15 "github.com/decred/dcrlnd/tor" 16 ) 17 18 var ( 19 // ErrNilFeatureVector is returned when the supplied feature is nil. 20 ErrNilFeatureVector = errors.New("cannot write nil feature vector") 21 22 // ErrPkScriptTooLong is returned when the length of the provided 23 // script exceeds 34. 24 ErrPkScriptTooLong = errors.New("'PkScript' too long") 25 26 // ErrNilTCPAddress is returned when the supplied address is nil. 27 ErrNilTCPAddress = errors.New("cannot write nil TCPAddr") 28 29 // ErrNilOnionAddress is returned when the supplied address is nil. 30 ErrNilOnionAddress = errors.New("cannot write nil onion address") 31 32 // ErrNilNetAddress is returned when a nil value is used in []net.Addr. 33 ErrNilNetAddress = errors.New("cannot write nil address") 34 35 // ErrNilPublicKey is returned when a nil pubkey is used. 36 ErrNilPublicKey = errors.New("cannot write nil pubkey") 37 38 // ErrUnknownServiceLength is returned when the onion service length is 39 // unknown. 40 ErrUnknownServiceLength = errors.New("unknown onion service length") 41 ) 42 43 // ErrOutpointIndexTooBig is used when the outpoint index exceeds the max value 44 // of uint16. 45 func ErrOutpointIndexTooBig(index uint32) error { 46 return fmt.Errorf( 47 "index for outpoint (%v) is greater than "+ 48 "max index of %v", index, math.MaxUint16, 49 ) 50 } 51 52 // WriteBytes appends the given bytes to the provided buffer. 53 // 54 // Note: We intentionally skip the interfacer linter check here because we want 55 // to have concrete type (bytes.Buffer) rather than interface type (io.Write) 56 // due to performance concern. 57 func WriteBytes(buf *bytes.Buffer, b []byte) error { // nolint: interfacer 58 _, err := buf.Write(b) 59 return err 60 } 61 62 // WriteUint8 appends the uint8 to the provided buffer. 63 // 64 // Note: We intentionally skip the interfacer linter check here because we want 65 // to have concrete type (bytes.Buffer) rather than interface type (io.Write) 66 // due to performance concern. 67 func WriteUint8(buf *bytes.Buffer, n uint8) error { // nolint: interfacer 68 _, err := buf.Write([]byte{n}) 69 return err 70 } 71 72 // WriteUint16 appends the uint16 to the provided buffer. It encodes the 73 // integer using big endian byte order. 74 // 75 // Note: We intentionally skip the interfacer linter check here because we want 76 // to have concrete type (bytes.Buffer) rather than interface type (io.Write) 77 // due to performance concern. 78 func WriteUint16(buf *bytes.Buffer, n uint16) error { // nolint: interfacer 79 var b [2]byte 80 binary.BigEndian.PutUint16(b[:], n) 81 _, err := buf.Write(b[:]) 82 return err 83 } 84 85 // WriteUint32 appends the uint32 to the provided buffer. It encodes the 86 // integer using big endian byte order. 87 func WriteUint32(buf *bytes.Buffer, n uint32) error { 88 var b [4]byte 89 binary.BigEndian.PutUint32(b[:], n) 90 _, err := buf.Write(b[:]) 91 return err 92 } 93 94 // WriteUint64 appends the uint64 to the provided buffer. It encodes the 95 // integer using big endian byte order. 96 // 97 // Note: We intentionally skip the interfacer linter check here because we want 98 // to have concrete type (bytes.Buffer) rather than interface type (io.Write) 99 // due to performance concern. 100 func WriteUint64(buf *bytes.Buffer, n uint64) error { // nolint: interfacer 101 var b [8]byte 102 binary.BigEndian.PutUint64(b[:], n) 103 _, err := buf.Write(b[:]) 104 return err 105 } 106 107 // WriteSatoshi appends the Satoshi value to the provided buffer. 108 func WriteSatoshi(buf *bytes.Buffer, amount dcrutil.Amount) error { 109 return WriteUint64(buf, uint64(amount)) 110 } 111 112 // WriteMilliAtom appends the MilliAtom value to the provided buffer. 113 func WriteMilliAtom(buf *bytes.Buffer, amount MilliAtom) error { 114 return WriteUint64(buf, uint64(amount)) 115 } 116 117 // WritePublicKey appends the compressed public key to the provided buffer. 118 func WritePublicKey(buf *bytes.Buffer, pub *secp256k1.PublicKey) error { 119 if pub == nil { 120 return ErrNilPublicKey 121 } 122 123 serializedPubkey := pub.SerializeCompressed() 124 return WriteBytes(buf, serializedPubkey) 125 126 } 127 128 // WriteChannelID appends the ChannelID to the provided buffer. 129 func WriteChannelID(buf *bytes.Buffer, channelID ChannelID) error { 130 return WriteBytes(buf, channelID[:]) 131 } 132 133 // WriteNodeAlias appends the alias to the provided buffer. 134 func WriteNodeAlias(buf *bytes.Buffer, alias NodeAlias) error { 135 return WriteBytes(buf, alias[:]) 136 } 137 138 // WriteShortChannelID appends the ShortChannelID to the provided buffer. It 139 // encodes the BlockHeight and TxIndex each using 3 bytes with big endian byte 140 // order, and encodes txPosition using 2 bytes with big endian byte order. 141 func WriteShortChannelID(buf *bytes.Buffer, shortChanID ShortChannelID) error { 142 // Check that field fit in 3 bytes and write the blockHeight 143 if shortChanID.BlockHeight > ((1 << 24) - 1) { 144 return errors.New("block height should fit in 3 bytes") 145 } 146 147 var blockHeight [4]byte 148 binary.BigEndian.PutUint32(blockHeight[:], shortChanID.BlockHeight) 149 150 if _, err := buf.Write(blockHeight[1:]); err != nil { 151 return err 152 } 153 154 // Check that field fit in 3 bytes and write the txIndex 155 if shortChanID.TxIndex > ((1 << 24) - 1) { 156 return errors.New("tx index should fit in 3 bytes") 157 } 158 159 var txIndex [4]byte 160 binary.BigEndian.PutUint32(txIndex[:], shortChanID.TxIndex) 161 if _, err := buf.Write(txIndex[1:]); err != nil { 162 return err 163 } 164 165 // Write the TxPosition 166 return WriteUint16(buf, shortChanID.TxPosition) 167 } 168 169 // WriteSig appends the signature to the provided buffer. 170 func WriteSig(buf *bytes.Buffer, sig Sig) error { 171 return WriteBytes(buf, sig[:]) 172 } 173 174 // WriteSigs appends the slice of signatures to the provided buffer with its 175 // length. 176 func WriteSigs(buf *bytes.Buffer, sigs []Sig) error { 177 // Write the length of the sigs. 178 if err := WriteUint16(buf, uint16(len(sigs))); err != nil { 179 return err 180 } 181 182 for _, sig := range sigs { 183 if err := WriteSig(buf, sig); err != nil { 184 return err 185 } 186 } 187 return nil 188 } 189 190 // WriteFailCode appends the FailCode to the provided buffer. 191 func WriteFailCode(buf *bytes.Buffer, e FailCode) error { 192 return WriteUint16(buf, uint16(e)) 193 } 194 195 // WriteRawFeatureVector encodes the feature using the feature's Encode method 196 // and appends the data to the provided buffer. An error will return if the 197 // passed feature is nil. 198 // 199 // Note: We intentionally skip the interfacer linter check here because we want 200 // to have concrete type (bytes.Buffer) rather than interface type (io.Write) 201 // due to performance concern. 202 func WriteRawFeatureVector(buf *bytes.Buffer, // nolint: interfacer 203 feature *RawFeatureVector) error { 204 205 if feature == nil { 206 return ErrNilFeatureVector 207 } 208 209 return feature.Encode(buf) 210 } 211 212 // WriteColorRGBA appends the RGBA color using three bytes. 213 func WriteColorRGBA(buf *bytes.Buffer, e color.RGBA) error { 214 // Write R 215 if err := WriteUint8(buf, e.R); err != nil { 216 return err 217 } 218 219 // Write G 220 if err := WriteUint8(buf, e.G); err != nil { 221 return err 222 } 223 224 // Write B 225 return WriteUint8(buf, e.B) 226 } 227 228 // WriteShortChanIDEncoding appends the ShortChanIDEncoding to the provided 229 // buffer. 230 func WriteShortChanIDEncoding(buf *bytes.Buffer, e ShortChanIDEncoding) error { 231 return WriteUint8(buf, uint8(e)) 232 } 233 234 // WriteFundingFlag appends the FundingFlag to the provided buffer. 235 func WriteFundingFlag(buf *bytes.Buffer, flag FundingFlag) error { 236 return WriteUint8(buf, uint8(flag)) 237 } 238 239 // WriteChanUpdateMsgFlags appends the update flag to the provided buffer. 240 func WriteChanUpdateMsgFlags(buf *bytes.Buffer, f ChanUpdateMsgFlags) error { 241 return WriteUint8(buf, uint8(f)) 242 } 243 244 // WriteChanUpdateChanFlags appends the update flag to the provided buffer. 245 func WriteChanUpdateChanFlags(buf *bytes.Buffer, f ChanUpdateChanFlags) error { 246 return WriteUint8(buf, uint8(f)) 247 } 248 249 // WriteDeliveryAddress appends the address to the provided buffer. 250 func WriteDeliveryAddress(buf *bytes.Buffer, addr DeliveryAddress) error { 251 return writeDataWithLength(buf, addr) 252 } 253 254 // WritePingPayload appends the payload to the provided buffer. 255 func WritePingPayload(buf *bytes.Buffer, payload PingPayload) error { 256 return writeDataWithLength(buf, payload) 257 } 258 259 // WritePongPayload appends the payload to the provided buffer. 260 func WritePongPayload(buf *bytes.Buffer, payload PongPayload) error { 261 return writeDataWithLength(buf, payload) 262 } 263 264 // WriteErrorData appends the data to the provided buffer. 265 func WriteErrorData(buf *bytes.Buffer, data ErrorData) error { 266 return writeDataWithLength(buf, data) 267 } 268 269 // WriteOpaqueReason appends the reason to the provided buffer. 270 func WriteOpaqueReason(buf *bytes.Buffer, reason OpaqueReason) error { 271 return writeDataWithLength(buf, reason) 272 } 273 274 // WriteBool appends the boolean to the provided buffer. 275 func WriteBool(buf *bytes.Buffer, b bool) error { 276 if b { 277 return WriteBytes(buf, []byte{1}) 278 } 279 return WriteBytes(buf, []byte{0}) 280 } 281 282 // WritePkScript appends the script to the provided buffer. Returns an error if 283 // the provided script exceeds 34 bytes. 284 // 285 // Note: We intentionally skip the interfacer linter check here because we want 286 // to have concrete type (bytes.Buffer) rather than interface type (io.Write) 287 // due to performance concern. 288 func WritePkScript(buf *bytes.Buffer, s PkScript) error { // nolint: interfacer 289 // The largest script we'll accept is a p2wsh which is exactly 290 // 34 bytes long. 291 scriptLength := len(s) 292 if scriptLength > 34 { 293 return ErrPkScriptTooLong 294 } 295 296 return wire.WriteVarBytes(buf, 0, s) 297 } 298 299 // WriteOutPoint appends the outpoint to the provided buffer. 300 func WriteOutPoint(buf *bytes.Buffer, p wire.OutPoint) error { 301 // Before we write anything to the buffer, check the Index is sane. 302 if p.Index > math.MaxUint16 { 303 return ErrOutpointIndexTooBig(p.Index) 304 } 305 306 var h [32]byte 307 copy(h[:], p.Hash[:]) 308 if _, err := buf.Write(h[:]); err != nil { 309 return err 310 } 311 312 // Write the index using two bytes. 313 return WriteUint16(buf, uint16(p.Index)) 314 } 315 316 // WriteTCPAddr appends the TCP address to the provided buffer, either a IPv4 317 // or a IPv6. 318 func WriteTCPAddr(buf *bytes.Buffer, addr *net.TCPAddr) error { 319 if addr == nil { 320 return ErrNilTCPAddress 321 } 322 323 // Make a slice of bytes to hold the data of descriptor and ip. At 324 // most, we need 17 bytes - 1 byte for the descriptor, 16 bytes for 325 // IPv6. 326 data := make([]byte, 0, 17) 327 328 if addr.IP.To4() != nil { 329 data = append(data, uint8(tcp4Addr)) 330 data = append(data, addr.IP.To4()...) 331 } else { 332 data = append(data, uint8(tcp6Addr)) 333 data = append(data, addr.IP.To16()...) 334 } 335 336 if _, err := buf.Write(data); err != nil { 337 return err 338 } 339 340 return WriteUint16(buf, uint16(addr.Port)) 341 } 342 343 // WriteOnionAddr appends the onion address to the provided buffer. 344 func WriteOnionAddr(buf *bytes.Buffer, addr *tor.OnionAddr) error { 345 if addr == nil { 346 return ErrNilOnionAddress 347 } 348 349 var ( 350 suffixIndex int 351 descriptor []byte 352 ) 353 354 // Decide the suffixIndex and descriptor. 355 switch len(addr.OnionService) { 356 case tor.V2Len: 357 descriptor = []byte{byte(v2OnionAddr)} 358 suffixIndex = tor.V2Len - tor.OnionSuffixLen 359 360 case tor.V3Len: 361 descriptor = []byte{byte(v3OnionAddr)} 362 suffixIndex = tor.V3Len - tor.OnionSuffixLen 363 364 default: 365 return ErrUnknownServiceLength 366 } 367 368 // Decode the address. 369 host, err := tor.Base32Encoding.DecodeString( 370 addr.OnionService[:suffixIndex], 371 ) 372 if err != nil { 373 return err 374 } 375 376 // Perform the actual write when the above checks passed. 377 if _, err := buf.Write(descriptor); err != nil { 378 return err 379 } 380 if _, err := buf.Write(host); err != nil { 381 return err 382 } 383 384 return WriteUint16(buf, uint16(addr.Port)) 385 } 386 387 // WriteNetAddrs appends a slice of addresses to the provided buffer with the 388 // length info. 389 func WriteNetAddrs(buf *bytes.Buffer, addresses []net.Addr) error { 390 // First, we'll encode all the addresses into an intermediate 391 // buffer. We need to do this in order to compute the total 392 // length of the addresses. 393 buffer := make([]byte, 0, MaxMsgBody) 394 addrBuf := bytes.NewBuffer(buffer) 395 396 for _, address := range addresses { 397 switch a := address.(type) { 398 case *net.TCPAddr: 399 if err := WriteTCPAddr(addrBuf, a); err != nil { 400 return err 401 } 402 case *tor.OnionAddr: 403 if err := WriteOnionAddr(addrBuf, a); err != nil { 404 return err 405 } 406 default: 407 return ErrNilNetAddress 408 } 409 } 410 411 // With the addresses fully encoded, we can now write out data. 412 return writeDataWithLength(buf, addrBuf.Bytes()) 413 } 414 415 // writeDataWithLength writes the data and its length to the buffer. 416 // 417 // Note: We intentionally skip the interfacer linter check here because we want 418 // to have concrete type (bytes.Buffer) rather than interface type (io.Write) 419 // due to performance concern. 420 func writeDataWithLength(buf *bytes.Buffer, // nolint: interfacer 421 data []byte) error { 422 423 var l [2]byte 424 binary.BigEndian.PutUint16(l[:], uint16(len(data))) 425 if _, err := buf.Write(l[:]); err != nil { 426 return err 427 } 428 429 _, err := buf.Write(data) 430 return err 431 }