Merge pull request #4884 from yyforyongyu/3004-buffer-pool
lnwire: fix heap escapes to reduce gc pressure
This commit is contained in:
44 files changed
+2936
-391
No files matched your search
+1
-1
@@ -7,7 +7,7 @@ import (
|
||||
// ReadSize represents the size of the maximum message that can be read off the
|
||||
// wire by brontide. The buffer is used to hold the ciphertext while the
|
||||
// brontide state machine decrypts the message.
|
||||
const ReadSize = lnwire.MaxMessagePayload + 16
|
||||
const ReadSize = lnwire.MaxSliceLength + 16
|
||||
|
||||
// Read is a static byte array sized to the maximum-allowed Lightning message
|
||||
// size, plus 16 bytes for the MAC.
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ import (
|
||||
// WriteSize represents the size of the maximum plaintext message than can be
|
||||
// sent using brontide. The buffer does not include extra space for the MAC, as
|
||||
// that is applied by the Noise protocol after encrypting the plaintext.
|
||||
const WriteSize = lnwire.MaxMessagePayload
|
||||
const WriteSize = lnwire.MaxSliceLength
|
||||
|
||||
// Write is static byte array occupying to maximum-allowed plaintext-message
|
||||
// size.
|
||||
|
||||
@@ -265,8 +265,15 @@ func (s *Single) Serialize(w io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
// TODO(yy): remove the type assertion when we finished refactoring db
|
||||
// into using write buffer.
|
||||
buf, ok := w.(*bytes.Buffer)
|
||||
if !ok {
|
||||
return fmt.Errorf("expect io.Writer to be *bytes.Buffer")
|
||||
}
|
||||
|
||||
return lnwire.WriteElements(
|
||||
w,
|
||||
buf,
|
||||
byte(s.Version),
|
||||
uint16(len(singleBytes.Bytes())),
|
||||
singleBytes.Bytes(),
|
||||
|
||||
@@ -2,6 +2,7 @@ package channeldb
|
||||
|
||||
import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"sync"
|
||||
|
||||
"io"
|
||||
@@ -232,7 +233,14 @@ func (p *WaitingProof) Encode(w io.Writer) error {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := p.AnnounceSignatures.Encode(w, 0); err != nil {
|
||||
// TODO(yy): remove the type assertion when we finished refactoring db
|
||||
// into using write buffer.
|
||||
buf, ok := w.(*bytes.Buffer)
|
||||
if !ok {
|
||||
return fmt.Errorf("expect io.Writer to be *bytes.Buffer")
|
||||
}
|
||||
|
||||
if err := p.AnnounceSignatures.Encode(buf, 0); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -121,6 +121,10 @@ you.
|
||||
* [Update MC store in blocks](https://github.com/lightningnetwork/lnd/pull/5515)
|
||||
to make payment throughput better when using etcd.
|
||||
|
||||
* [The `lnwire` package now uses a write buffer pool](https://github.com/lightningnetwork/lnd/pull/4884)
|
||||
when encoding/decoding messages. Such that most of the heap escapes are fixed,
|
||||
resulting in less memory being used when running `lnd`.
|
||||
|
||||
## Bug Fixes
|
||||
|
||||
A bug has been fixed that would cause `lnd` to [try to bootstrap using the
|
||||
|
||||
+59
-18
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
@@ -115,7 +116,7 @@ var _ Message = (*AcceptChannel)(nil)
|
||||
// protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *AcceptChannel) Encode(w io.Writer, pver uint32) error {
|
||||
func (a *AcceptChannel) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
// Since the upfront script is encoded as a TLV record, concatenate it
|
||||
// with the ExtraData, and write them as one.
|
||||
tlvRecords, err := packShutdownScript(
|
||||
@@ -125,23 +126,63 @@ func (a *AcceptChannel) Encode(w io.Writer, pver uint32) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteElements(w,
|
||||
a.PendingChannelID[:],
|
||||
a.DustLimit,
|
||||
a.MaxValueInFlight,
|
||||
a.ChannelReserve,
|
||||
a.HtlcMinimum,
|
||||
a.MinAcceptDepth,
|
||||
a.CsvDelay,
|
||||
a.MaxAcceptedHTLCs,
|
||||
a.FundingKey,
|
||||
a.RevocationPoint,
|
||||
a.PaymentPoint,
|
||||
a.DelayedPaymentPoint,
|
||||
a.HtlcPoint,
|
||||
a.FirstCommitmentPoint,
|
||||
tlvRecords,
|
||||
)
|
||||
if err := WriteBytes(w, a.PendingChannelID[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSatoshi(w, a.DustLimit); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteMilliSatoshi(w, a.MaxValueInFlight); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSatoshi(w, a.ChannelReserve); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteMilliSatoshi(w, a.HtlcMinimum); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, a.MinAcceptDepth); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint16(w, a.CsvDelay); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint16(w, a.MaxAcceptedHTLCs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, a.FundingKey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, a.RevocationPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, a.PaymentPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, a.DelayedPaymentPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, a.HtlcPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, a.FirstCommitmentPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, tlvRecords)
|
||||
}
|
||||
|
||||
// Decode deserializes the serialized AcceptChannel stored in the passed
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
@@ -64,14 +65,24 @@ func (a *AnnounceSignatures) Decode(r io.Reader, pver uint32) error {
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *AnnounceSignatures) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
a.ChannelID,
|
||||
a.ShortChannelID,
|
||||
a.NodeSignature,
|
||||
a.BitcoinSignature,
|
||||
a.ExtraOpaqueData,
|
||||
)
|
||||
func (a *AnnounceSignatures) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteChannelID(w, a.ChannelID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteShortChannelID(w, a.ShortChannelID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSig(w, a.NodeSignature); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSig(w, a.BitcoinSignature); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, a.ExtraOpaqueData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
@@ -87,21 +87,52 @@ func (a *ChannelAnnouncement) Decode(r io.Reader, pver uint32) error {
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelAnnouncement) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
a.NodeSig1,
|
||||
a.NodeSig2,
|
||||
a.BitcoinSig1,
|
||||
a.BitcoinSig2,
|
||||
a.Features,
|
||||
a.ChainHash[:],
|
||||
a.ShortChannelID,
|
||||
a.NodeID1,
|
||||
a.NodeID2,
|
||||
a.BitcoinKey1,
|
||||
a.BitcoinKey2,
|
||||
a.ExtraOpaqueData,
|
||||
)
|
||||
func (a *ChannelAnnouncement) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteSig(w, a.NodeSig1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSig(w, a.NodeSig2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSig(w, a.BitcoinSig1); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSig(w, a.BitcoinSig2); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteRawFeatureVector(w, a.Features); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, a.ChainHash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteShortChannelID(w, a.ShortChannelID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, a.NodeID1[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, a.NodeID2[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, a.BitcoinKey1[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, a.BitcoinKey2[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, a.ExtraOpaqueData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
@@ -116,20 +147,40 @@ func (a *ChannelAnnouncement) MsgType() MessageType {
|
||||
// be signed.
|
||||
func (a *ChannelAnnouncement) DataToSign() ([]byte, error) {
|
||||
// We should not include the signatures itself.
|
||||
var w bytes.Buffer
|
||||
err := WriteElements(&w,
|
||||
a.Features,
|
||||
a.ChainHash[:],
|
||||
a.ShortChannelID,
|
||||
a.NodeID1,
|
||||
a.NodeID2,
|
||||
a.BitcoinKey1,
|
||||
a.BitcoinKey2,
|
||||
a.ExtraOpaqueData,
|
||||
)
|
||||
if err != nil {
|
||||
b := make([]byte, 0, MaxMsgBody)
|
||||
buf := bytes.NewBuffer(b)
|
||||
|
||||
if err := WriteRawFeatureVector(buf, a.Features); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return w.Bytes(), nil
|
||||
if err := WriteBytes(buf, a.ChainHash[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteShortChannelID(buf, a.ShortChannelID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteBytes(buf, a.NodeID1[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteBytes(buf, a.NodeID2[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteBytes(buf, a.BitcoinKey1[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteBytes(buf, a.BitcoinKey2[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteBytes(buf, a.ExtraOpaqueData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
@@ -75,13 +76,16 @@ var _ Message = (*ChannelReestablish)(nil)
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelReestablish) Encode(w io.Writer, pver uint32) error {
|
||||
err := WriteElements(w,
|
||||
a.ChanID,
|
||||
a.NextLocalCommitHeight,
|
||||
a.RemoteCommitTailHeight,
|
||||
)
|
||||
if err != nil {
|
||||
func (a *ChannelReestablish) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteChannelID(w, a.ChanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint64(w, a.NextLocalCommitHeight); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint64(w, a.RemoteCommitTailHeight); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -93,15 +97,18 @@ func (a *ChannelReestablish) Encode(w io.Writer, pver uint32) error {
|
||||
//
|
||||
// NOTE: This is here primarily for the quickcheck tests, in
|
||||
// practice, we'll always populate this field.
|
||||
return WriteElements(w, a.ExtraData)
|
||||
return WriteBytes(w, a.ExtraData)
|
||||
}
|
||||
|
||||
// Otherwise, we'll write out the remaining elements.
|
||||
return WriteElements(w,
|
||||
a.LastRemoteCommitSecret[:],
|
||||
a.LocalUnrevokedCommitPoint,
|
||||
a.ExtraData,
|
||||
)
|
||||
if err := WriteBytes(w, a.LastRemoteCommitSecret[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, a.LocalUnrevokedCommitPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
return WriteBytes(w, a.ExtraData)
|
||||
}
|
||||
|
||||
// Decode deserializes a serialized ChannelReestablish stored in the passed
|
||||
|
||||
+80
-33
@@ -159,33 +159,58 @@ func (a *ChannelUpdate) Decode(r io.Reader, pver uint32) error {
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *ChannelUpdate) Encode(w io.Writer, pver uint32) error {
|
||||
err := WriteElements(w,
|
||||
a.Signature,
|
||||
a.ChainHash[:],
|
||||
a.ShortChannelID,
|
||||
a.Timestamp,
|
||||
a.MessageFlags,
|
||||
a.ChannelFlags,
|
||||
a.TimeLockDelta,
|
||||
a.HtlcMinimumMsat,
|
||||
a.BaseFee,
|
||||
a.FeeRate,
|
||||
)
|
||||
if err != nil {
|
||||
func (a *ChannelUpdate) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteSig(w, a.Signature); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, a.ChainHash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteShortChannelID(w, a.ShortChannelID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, a.Timestamp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteChanUpdateMsgFlags(w, a.MessageFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteChanUpdateChanFlags(w, a.ChannelFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint16(w, a.TimeLockDelta); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteMilliSatoshi(w, a.HtlcMinimumMsat); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, a.BaseFee); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, a.FeeRate); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now append optional fields if they are set. Currently, the only
|
||||
// optional field is max HTLC.
|
||||
if a.MessageFlags.HasMaxHtlc() {
|
||||
if err := WriteElements(w, a.HtlcMaximumMsat); err != nil {
|
||||
err := WriteMilliSatoshi(w, a.HtlcMaximumMsat)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, append any extra opaque data.
|
||||
return a.ExtraOpaqueData.Encode(w)
|
||||
return WriteBytes(w, a.ExtraOpaqueData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
@@ -199,36 +224,58 @@ func (a *ChannelUpdate) MsgType() MessageType {
|
||||
// DataToSign is used to retrieve part of the announcement message which should
|
||||
// be signed.
|
||||
func (a *ChannelUpdate) DataToSign() ([]byte, error) {
|
||||
|
||||
// We should not include the signatures itself.
|
||||
var w bytes.Buffer
|
||||
err := WriteElements(&w,
|
||||
a.ChainHash[:],
|
||||
a.ShortChannelID,
|
||||
a.Timestamp,
|
||||
a.MessageFlags,
|
||||
a.ChannelFlags,
|
||||
a.TimeLockDelta,
|
||||
a.HtlcMinimumMsat,
|
||||
a.BaseFee,
|
||||
a.FeeRate,
|
||||
)
|
||||
if err != nil {
|
||||
b := make([]byte, 0, MaxMsgBody)
|
||||
buf := bytes.NewBuffer(b)
|
||||
if err := WriteBytes(buf, a.ChainHash[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteShortChannelID(buf, a.ShortChannelID); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteUint32(buf, a.Timestamp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteChanUpdateMsgFlags(buf, a.MessageFlags); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteChanUpdateChanFlags(buf, a.ChannelFlags); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteUint16(buf, a.TimeLockDelta); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteMilliSatoshi(buf, a.HtlcMinimumMsat); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteUint32(buf, a.BaseFee); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteUint32(buf, a.FeeRate); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// Now append optional fields if they are set. Currently, the only
|
||||
// optional field is max HTLC.
|
||||
if a.MessageFlags.HasMaxHtlc() {
|
||||
if err := WriteElements(&w, a.HtlcMaximumMsat); err != nil {
|
||||
err := WriteMilliSatoshi(buf, a.HtlcMaximumMsat)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
// Finally, append any extra opaque data.
|
||||
if err := a.ExtraOpaqueData.Encode(&w); err != nil {
|
||||
if err := WriteBytes(buf, a.ExtraOpaqueData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return w.Bytes(), nil
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcutil"
|
||||
@@ -63,10 +64,20 @@ func (c *ClosingSigned) Decode(r io.Reader, pver uint32) error {
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ClosingSigned) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(
|
||||
w, c.ChannelID, c.FeeSatoshis, c.Signature, c.ExtraData,
|
||||
)
|
||||
func (c *ClosingSigned) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteChannelID(w, c.ChannelID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSatoshi(w, c.FeeSatoshis); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSig(w, c.Signature); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
+15
-7
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
@@ -69,13 +70,20 @@ func (c *CommitSig) Decode(r io.Reader, pver uint32) error {
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *CommitSig) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.CommitSig,
|
||||
c.HtlcSigs,
|
||||
c.ExtraData,
|
||||
)
|
||||
func (c *CommitSig) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteChannelID(w, c.ChanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSig(w, c.CommitSig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSigs(w, c.HtlcSigs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
+7
-5
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"io"
|
||||
)
|
||||
@@ -103,11 +104,12 @@ func (c *Error) Decode(r io.Reader, pver uint32) error {
|
||||
// protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *Error) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.Data,
|
||||
)
|
||||
func (c *Error) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteBytes(w, c.ChanID[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteErrorData(w, c.Data)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying an Error message on the
|
||||
|
||||
@@ -16,9 +16,9 @@ import (
|
||||
type ExtraOpaqueData []byte
|
||||
|
||||
// Encode attempts to encode the raw extra bytes into the passed io.Writer.
|
||||
func (e *ExtraOpaqueData) Encode(w io.Writer) error {
|
||||
func (e *ExtraOpaqueData) Encode(w *bytes.Buffer) error {
|
||||
eBytes := []byte((*e)[:])
|
||||
if err := WriteElements(w, eBytes); err != nil {
|
||||
if err := WriteBytes(w, eBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
+2
-2
@@ -91,7 +91,7 @@ const (
|
||||
// attacks on the receiver of a payment.
|
||||
PaymentAddrOptional FeatureBit = 15
|
||||
|
||||
// MPPOptional is a required feature bit that signals that the receiver
|
||||
// MPPRequired is a required feature bit that signals that the receiver
|
||||
// of a payment requires settlement of an invoice with more than one
|
||||
// HTLC.
|
||||
MPPRequired FeatureBit = 16
|
||||
@@ -124,7 +124,7 @@ const (
|
||||
// transactions, which also imply anchor commitments.
|
||||
AnchorsZeroFeeHtlcTxRequired FeatureBit = 22
|
||||
|
||||
// AnchorsZeroFeeHtlcTxRequired is an optional feature bit that signals
|
||||
// AnchorsZeroFeeHtlcTxOptional is an optional feature bit that signals
|
||||
// that the node supports channels having zero-fee second-level HTLC
|
||||
// transactions, which also imply anchor commitments.
|
||||
AnchorsZeroFeeHtlcTxOptional FeatureBit = 23
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
@@ -40,11 +41,20 @@ var _ Message = (*FundingCreated)(nil)
|
||||
// protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (f *FundingCreated) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(
|
||||
w, f.PendingChannelID[:], f.FundingPoint, f.CommitSig,
|
||||
f.ExtraData,
|
||||
)
|
||||
func (f *FundingCreated) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteBytes(w, f.PendingChannelID[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteOutPoint(w, f.FundingPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSig(w, f.CommitSig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, f.ExtraData)
|
||||
}
|
||||
|
||||
// Decode deserializes the serialized FundingCreated stored in the passed
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
@@ -58,12 +59,16 @@ func (c *FundingLocked) Decode(r io.Reader, pver uint32) error {
|
||||
// protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *FundingLocked) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.NextPerCommitmentPoint,
|
||||
c.ExtraData,
|
||||
)
|
||||
func (c *FundingLocked) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteChannelID(w, c.ChanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, c.NextPerCommitmentPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the uint32 code which uniquely identifies this message as a
|
||||
|
||||
@@ -1,6 +1,9 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
// FundingSigned is sent from Bob (the responder) to Alice (the initiator)
|
||||
// after receiving the funding outpoint and her signature for Bob's version of
|
||||
@@ -29,8 +32,16 @@ var _ Message = (*FundingSigned)(nil)
|
||||
// protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (f *FundingSigned) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w, f.ChanID, f.CommitSig, f.ExtraData)
|
||||
func (f *FundingSigned) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteChannelID(w, f.ChanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSig(w, f.CommitSig); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, f.ExtraData)
|
||||
}
|
||||
|
||||
// Decode deserializes the serialized FundingSigned stored in the passed
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
@@ -57,13 +58,20 @@ func (g *GossipTimestampRange) Decode(r io.Reader, pver uint32) error {
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (g *GossipTimestampRange) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
g.ChainHash[:],
|
||||
g.FirstTimestamp,
|
||||
g.TimestampRange,
|
||||
g.ExtraData,
|
||||
)
|
||||
func (g *GossipTimestampRange) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteBytes(w, g.ChainHash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, g.FirstTimestamp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, g.TimestampRange); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, g.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
+14
-7
@@ -1,6 +1,9 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
// Init is the first message reveals the features supported or required by this
|
||||
// node. Nodes wait for receipt of the other's features to simplify error
|
||||
@@ -56,12 +59,16 @@ func (msg *Init) Decode(r io.Reader, pver uint32) error {
|
||||
// the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (msg *Init) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
msg.GlobalFeatures,
|
||||
msg.Features,
|
||||
msg.ExtraData,
|
||||
)
|
||||
func (msg *Init) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteRawFeatureVector(w, msg.GlobalFeatures); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteRawFeatureVector(w, msg.Features); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, msg.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
+14
-10
@@ -75,13 +75,11 @@ func (a addressType) AddrLen() uint16 {
|
||||
}
|
||||
|
||||
// WriteElement is a one-stop shop to write the big endian representation of
|
||||
// any element which is to be serialized for the wire protocol. The passed
|
||||
// io.Writer should be backed by an appropriately sized byte slice, or be able
|
||||
// to dynamically expand to accommodate additional data.
|
||||
// any element which is to be serialized for the wire protocol.
|
||||
//
|
||||
// TODO(roasbeef): this should eventually draw from a buffer pool for
|
||||
// serialization.
|
||||
func WriteElement(w io.Writer, element interface{}) error {
|
||||
// TODO(yy): rm this method once we finish dereferencing it from other
|
||||
// packages.
|
||||
func WriteElement(w *bytes.Buffer, element interface{}) error {
|
||||
switch e := element.(type) {
|
||||
case NodeAlias:
|
||||
if _, err := w.Write(e[:]); err != nil {
|
||||
@@ -437,10 +435,13 @@ func WriteElement(w io.Writer, element interface{}) error {
|
||||
}
|
||||
|
||||
// WriteElements is writes each element in the elements slice to the passed
|
||||
// io.Writer using WriteElement.
|
||||
func WriteElements(w io.Writer, elements ...interface{}) error {
|
||||
// buffer using WriteElement.
|
||||
//
|
||||
// TODO(yy): rm this method once we finish dereferencing it from other
|
||||
// packages.
|
||||
func WriteElements(buf *bytes.Buffer, elements ...interface{}) error {
|
||||
for _, element := range elements {
|
||||
err := WriteElement(w, element)
|
||||
err := WriteElement(buf, element)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -828,8 +829,11 @@ func ReadElement(r io.Reader, element interface{}) error {
|
||||
length := binary.BigEndian.Uint16(addrLen[:])
|
||||
|
||||
var addrBytes [deliveryAddressMaxSize]byte
|
||||
|
||||
if length > deliveryAddressMaxSize {
|
||||
return fmt.Errorf("cannot read %d bytes into addrBytes", length)
|
||||
return fmt.Errorf(
|
||||
"cannot read %d bytes into addrBytes", length,
|
||||
)
|
||||
}
|
||||
if _, err = io.ReadFull(r, addrBytes[:length]); err != nil {
|
||||
return err
|
||||
|
||||
@@ -232,7 +232,7 @@ func TestMaxOutPointIndex(t *testing.T) {
|
||||
}
|
||||
|
||||
var b bytes.Buffer
|
||||
if err := WriteElement(&b, op); err == nil {
|
||||
if err := WriteOutPoint(&b, op); err == nil {
|
||||
t.Fatalf("write of outPoint should fail, index exceeds 16-bits")
|
||||
}
|
||||
}
|
||||
|
||||
+57
-35
@@ -12,10 +12,6 @@ import (
|
||||
"io"
|
||||
)
|
||||
|
||||
// MaxMessagePayload is the maximum bytes a message can be regardless of other
|
||||
// individual limits imposed by messages themselves.
|
||||
const MaxMessagePayload = 65535 // 65KB
|
||||
|
||||
// MessageType is the unique 2 byte big-endian integer that indicates the type
|
||||
// of message on the wire. All messages have a very simple header which
|
||||
// consists simply of 2-byte message type. We omit a length field, and checksum
|
||||
@@ -56,6 +52,27 @@ const (
|
||||
MsgGossipTimestampRange = 265
|
||||
)
|
||||
|
||||
// ErrorEncodeMessage is used when failed to encode the message payload.
|
||||
func ErrorEncodeMessage(err error) error {
|
||||
return fmt.Errorf("failed to encode message to buffer, got %w", err)
|
||||
}
|
||||
|
||||
// ErrorWriteMessageType is used when failed to write the message type.
|
||||
func ErrorWriteMessageType(err error) error {
|
||||
return fmt.Errorf("failed to write message type, got %w", err)
|
||||
}
|
||||
|
||||
// ErrorPayloadTooLarge is used when the payload size exceeds the
|
||||
// MaxMsgBody.
|
||||
func ErrorPayloadTooLarge(size int) error {
|
||||
return fmt.Errorf(
|
||||
"message payload is too large - encoded %d bytes, "+
|
||||
"but maximum message payload is %d bytes",
|
||||
size, MaxMsgBody,
|
||||
)
|
||||
|
||||
}
|
||||
|
||||
// String return the string representation of message type.
|
||||
func (t MessageType) String() string {
|
||||
switch t {
|
||||
@@ -141,8 +158,8 @@ type Serializable interface {
|
||||
Decode(io.Reader, uint32) error
|
||||
|
||||
// Encode converts object to the bytes stream and write it into the
|
||||
// writer.
|
||||
Encode(io.Writer, uint32) error
|
||||
// write buffer.
|
||||
Encode(*bytes.Buffer, uint32) error
|
||||
}
|
||||
|
||||
// Message is an interface that defines a lightning wire protocol message. The
|
||||
@@ -222,44 +239,49 @@ func makeEmptyMessage(msgType MessageType) (Message, error) {
|
||||
return msg, nil
|
||||
}
|
||||
|
||||
// WriteMessage writes a lightning Message to w including the necessary header
|
||||
// information and returns the number of bytes written.
|
||||
func WriteMessage(w io.Writer, msg Message, pver uint32) (int, error) {
|
||||
totalBytes := 0
|
||||
// WriteMessage writes a lightning Message to a buffer including the necessary
|
||||
// header information and returns the number of bytes written. If any error is
|
||||
// encountered, the buffer passed will be reset to its original state since we
|
||||
// don't want any broken bytes left. In other words, no bytes will be written
|
||||
// if there's an error. Either all or none of the message bytes will be written
|
||||
// to the buffer.
|
||||
//
|
||||
// NOTE: this method is not concurrent safe.
|
||||
func WriteMessage(buf *bytes.Buffer, msg Message, pver uint32) (int, error) {
|
||||
// Record the size of the bytes already written in buffer.
|
||||
oldByteSize := buf.Len()
|
||||
|
||||
// Encode the message payload itself into a temporary buffer.
|
||||
// TODO(roasbeef): create buffer pool
|
||||
var bw bytes.Buffer
|
||||
if err := msg.Encode(&bw, pver); err != nil {
|
||||
return totalBytes, err
|
||||
}
|
||||
payload := bw.Bytes()
|
||||
lenp := len(payload)
|
||||
|
||||
// Enforce maximum message payload, which means the body cannot be
|
||||
// greater than MaxMsgBody.
|
||||
if lenp > MaxMsgBody {
|
||||
return totalBytes, fmt.Errorf("message payload is too large - "+
|
||||
"encoded %d bytes, but maximum message body is %d bytes",
|
||||
lenp, MaxMsgBody)
|
||||
// cleanBrokenBytes is a helper closure that helps reset the buffer to
|
||||
// its original state. It truncates all the bytes written in current
|
||||
// scope.
|
||||
var cleanBrokenBytes = func(b *bytes.Buffer) int {
|
||||
b.Truncate(oldByteSize)
|
||||
return 0
|
||||
}
|
||||
|
||||
// With the initial sanity checks complete, we'll now write out the
|
||||
// message type itself.
|
||||
// Write the message type.
|
||||
var mType [2]byte
|
||||
binary.BigEndian.PutUint16(mType[:], uint16(msg.MsgType()))
|
||||
n, err := w.Write(mType[:])
|
||||
totalBytes += n
|
||||
msgTypeBytes, err := buf.Write(mType[:])
|
||||
if err != nil {
|
||||
return totalBytes, err
|
||||
return cleanBrokenBytes(buf), ErrorWriteMessageType(err)
|
||||
}
|
||||
|
||||
// With the message type written, we'll now write out the raw payload
|
||||
// itself.
|
||||
n, err = w.Write(payload)
|
||||
totalBytes += n
|
||||
// Use the write buffer to encode our message.
|
||||
if err := msg.Encode(buf, pver); err != nil {
|
||||
return cleanBrokenBytes(buf), ErrorEncodeMessage(err)
|
||||
}
|
||||
|
||||
return totalBytes, err
|
||||
// Enforce maximum overall message payload. The write buffer now has
|
||||
// the size of len(originalBytes) + len(payload) + len(type). We want
|
||||
// to enforce the payload here, so we subtract it by the length of the
|
||||
// type and old bytes.
|
||||
lenp := buf.Len() - oldByteSize - msgTypeBytes
|
||||
if lenp > MaxMsgBody {
|
||||
return cleanBrokenBytes(buf), ErrorPayloadTooLarge(lenp)
|
||||
}
|
||||
|
||||
return buf.Len() - oldByteSize, nil
|
||||
}
|
||||
|
||||
// ReadMessage reads, validates, and parses the next Lightning message from r
|
||||
|
||||
File diff suppressed because it is too large.
Load diff
+60
-23
@@ -124,17 +124,37 @@ func (a *NodeAnnouncement) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode serializes the target NodeAnnouncement into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
func (a *NodeAnnouncement) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
a.Signature,
|
||||
a.Features,
|
||||
a.Timestamp,
|
||||
a.NodeID,
|
||||
a.RGBColor,
|
||||
a.Alias,
|
||||
a.Addresses,
|
||||
a.ExtraOpaqueData,
|
||||
)
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (a *NodeAnnouncement) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteSig(w, a.Signature); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteRawFeatureVector(w, a.Features); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, a.Timestamp); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, a.NodeID[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteColorRGBA(w, a.RGBColor); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteNodeAlias(w, a.Alias); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteNetAddrs(w, a.Addresses); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, a.ExtraOpaqueData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
@@ -149,19 +169,36 @@ func (a *NodeAnnouncement) MsgType() MessageType {
|
||||
func (a *NodeAnnouncement) DataToSign() ([]byte, error) {
|
||||
|
||||
// We should not include the signatures itself.
|
||||
var w bytes.Buffer
|
||||
err := WriteElements(&w,
|
||||
a.Features,
|
||||
a.Timestamp,
|
||||
a.NodeID,
|
||||
a.RGBColor,
|
||||
a.Alias[:],
|
||||
a.Addresses,
|
||||
a.ExtraOpaqueData,
|
||||
)
|
||||
if err != nil {
|
||||
buffer := make([]byte, 0, MaxMsgBody)
|
||||
buf := bytes.NewBuffer(buffer)
|
||||
|
||||
if err := WriteRawFeatureVector(buf, a.Features); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return w.Bytes(), nil
|
||||
if err := WriteUint32(buf, a.Timestamp); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteBytes(buf, a.NodeID[:]); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteColorRGBA(buf, a.RGBColor); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteNodeAlias(buf, a.Alias); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteNetAddrs(buf, a.Addresses); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := WriteBytes(buf, a.ExtraOpaqueData); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return buf.Bytes(), nil
|
||||
}
|
||||
+53
-35
@@ -419,8 +419,12 @@ func (f *FailIncorrectDetails) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailIncorrectDetails) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w, f.amount, f.height)
|
||||
func (f *FailIncorrectDetails) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteMilliSatoshi(w, f.amount); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteUint32(w, f.height)
|
||||
}
|
||||
|
||||
// FailFinalExpiryTooSoon is returned if the cltv_expiry is too low, the final
|
||||
@@ -485,8 +489,8 @@ func (f *FailInvalidOnionVersion) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailInvalidOnionVersion) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElement(w, f.OnionSHA256[:])
|
||||
func (f *FailInvalidOnionVersion) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
return WriteBytes(w, f.OnionSHA256[:])
|
||||
}
|
||||
|
||||
// FailInvalidOnionHmac is return if the onion HMAC is incorrect.
|
||||
@@ -519,8 +523,8 @@ func (f *FailInvalidOnionHmac) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailInvalidOnionHmac) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElement(w, f.OnionSHA256[:])
|
||||
func (f *FailInvalidOnionHmac) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
return WriteBytes(w, f.OnionSHA256[:])
|
||||
}
|
||||
|
||||
// Returns a human readable string describing the target FailureMessage.
|
||||
@@ -561,8 +565,8 @@ func (f *FailInvalidOnionKey) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailInvalidOnionKey) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElement(w, f.OnionSHA256[:])
|
||||
func (f *FailInvalidOnionKey) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
return WriteBytes(w, f.OnionSHA256[:])
|
||||
}
|
||||
|
||||
// Returns a human readable string describing the target FailureMessage.
|
||||
@@ -670,7 +674,9 @@ func (f *FailTemporaryChannelFailure) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailTemporaryChannelFailure) Encode(w io.Writer, pver uint32) error {
|
||||
func (f *FailTemporaryChannelFailure) Encode(w *bytes.Buffer,
|
||||
pver uint32) error {
|
||||
|
||||
var payload []byte
|
||||
if f.Update != nil {
|
||||
var bw bytes.Buffer
|
||||
@@ -680,7 +686,7 @@ func (f *FailTemporaryChannelFailure) Encode(w io.Writer, pver uint32) error {
|
||||
payload = bw.Bytes()
|
||||
}
|
||||
|
||||
if err := WriteElement(w, uint16(len(payload))); err != nil {
|
||||
if err := WriteUint16(w, uint16(len(payload))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -749,8 +755,8 @@ func (f *FailAmountBelowMinimum) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailAmountBelowMinimum) Encode(w io.Writer, pver uint32) error {
|
||||
if err := WriteElement(w, f.HtlcMsat); err != nil {
|
||||
func (f *FailAmountBelowMinimum) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteMilliSatoshi(w, f.HtlcMsat); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -817,8 +823,8 @@ func (f *FailFeeInsufficient) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailFeeInsufficient) Encode(w io.Writer, pver uint32) error {
|
||||
if err := WriteElement(w, f.HtlcMsat); err != nil {
|
||||
func (f *FailFeeInsufficient) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteMilliSatoshi(w, f.HtlcMsat); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -885,8 +891,8 @@ func (f *FailIncorrectCltvExpiry) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailIncorrectCltvExpiry) Encode(w io.Writer, pver uint32) error {
|
||||
if err := WriteElement(w, f.CltvExpiry); err != nil {
|
||||
func (f *FailIncorrectCltvExpiry) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteUint32(w, f.CltvExpiry); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -942,7 +948,7 @@ func (f *FailExpiryTooSoon) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailExpiryTooSoon) Encode(w io.Writer, pver uint32) error {
|
||||
func (f *FailExpiryTooSoon) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
return writeOnionErrorChanUpdate(w, &f.Update, pver)
|
||||
}
|
||||
|
||||
@@ -1006,8 +1012,8 @@ func (f *FailChannelDisabled) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailChannelDisabled) Encode(w io.Writer, pver uint32) error {
|
||||
if err := WriteElement(w, f.Flags); err != nil {
|
||||
func (f *FailChannelDisabled) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteUint16(w, f.Flags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
@@ -1056,8 +1062,10 @@ func (f *FailFinalIncorrectCltvExpiry) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailFinalIncorrectCltvExpiry) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElement(w, f.CltvExpiry)
|
||||
func (f *FailFinalIncorrectCltvExpiry) Encode(w *bytes.Buffer,
|
||||
pver uint32) error {
|
||||
|
||||
return WriteUint32(w, f.CltvExpiry)
|
||||
}
|
||||
|
||||
// FailFinalIncorrectHtlcAmount is returned if the amt_to_forward is higher
|
||||
@@ -1102,8 +1110,10 @@ func (f *FailFinalIncorrectHtlcAmount) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *FailFinalIncorrectHtlcAmount) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElement(w, f.IncomingHTLCAmount)
|
||||
func (f *FailFinalIncorrectHtlcAmount) Encode(w *bytes.Buffer,
|
||||
pver uint32) error {
|
||||
|
||||
return WriteMilliSatoshi(w, f.IncomingHTLCAmount)
|
||||
}
|
||||
|
||||
// FailExpiryTooFar is returned if the CLTV expiry in the HTLC is too far in the
|
||||
@@ -1177,13 +1187,13 @@ func (f *InvalidOnionPayload) Decode(r io.Reader, pver uint32) error {
|
||||
// Encode writes the failure in bytes stream.
|
||||
//
|
||||
// NOTE: Part of the Serializable interface.
|
||||
func (f *InvalidOnionPayload) Encode(w io.Writer, pver uint32) error {
|
||||
func (f *InvalidOnionPayload) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
var buf [8]byte
|
||||
if err := tlv.WriteVarInt(w, f.Type, &buf); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteElements(w, f.Offset)
|
||||
return WriteUint16(w, f.Offset)
|
||||
}
|
||||
|
||||
// FailMPPTimeout is returned if the complete amount for a multi part payment
|
||||
@@ -1263,7 +1273,7 @@ func DecodeFailureMessage(r io.Reader, pver uint32) (FailureMessage, error) {
|
||||
|
||||
// EncodeFailure encodes, including the necessary onion failure header
|
||||
// information.
|
||||
func EncodeFailure(w io.Writer, failure FailureMessage, pver uint32) error {
|
||||
func EncodeFailure(w *bytes.Buffer, failure FailureMessage, pver uint32) error {
|
||||
var failureMessageBuffer bytes.Buffer
|
||||
|
||||
err := EncodeFailureMessage(&failureMessageBuffer, failure, pver)
|
||||
@@ -1283,17 +1293,25 @@ func EncodeFailure(w io.Writer, failure FailureMessage, pver uint32) error {
|
||||
// messages are fixed size.
|
||||
pad := make([]byte, FailureMessageLength-len(failureMessage))
|
||||
|
||||
return WriteElements(w,
|
||||
uint16(len(failureMessage)),
|
||||
failureMessage,
|
||||
uint16(len(pad)),
|
||||
pad,
|
||||
)
|
||||
if err := WriteUint16(w, uint16(len(failureMessage))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, failureMessage); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := WriteUint16(w, uint16(len(pad))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, pad)
|
||||
}
|
||||
|
||||
// EncodeFailureMessage encodes just the failure message without adding a length
|
||||
// and padding the message for the onion protocol.
|
||||
func EncodeFailureMessage(w io.Writer, failure FailureMessage, pver uint32) error {
|
||||
func EncodeFailureMessage(w *bytes.Buffer,
|
||||
failure FailureMessage, pver uint32) error {
|
||||
|
||||
// First, we'll write out the error code itself into the failure
|
||||
// buffer.
|
||||
var codeBytes [2]byte
|
||||
@@ -1401,7 +1419,7 @@ func makeEmptyOnionError(code FailCode) (FailureMessage, error) {
|
||||
// writeOnionErrorChanUpdate writes out a ChannelUpdate using the onion error
|
||||
// format. The format is that we first write out the true serialized length of
|
||||
// the channel update, followed by the serialized channel update itself.
|
||||
func writeOnionErrorChanUpdate(w io.Writer, chanUpdate *ChannelUpdate,
|
||||
func writeOnionErrorChanUpdate(w *bytes.Buffer, chanUpdate *ChannelUpdate,
|
||||
pver uint32) error {
|
||||
|
||||
// First, we encode the channel update in a temporary buffer in order
|
||||
@@ -1414,7 +1432,7 @@ func writeOnionErrorChanUpdate(w io.Writer, chanUpdate *ChannelUpdate,
|
||||
// Now that we know the size, we can write the length out in the main
|
||||
// writer.
|
||||
updateLen := b.Len()
|
||||
if err := WriteElement(w, uint16(updateLen)); err != nil {
|
||||
if err := WriteUint16(w, uint16(updateLen)); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
|
||||
@@ -275,6 +275,8 @@ func (f *mockFailIncorrectDetailsNoHeight) Decode(r io.Reader, pver uint32) erro
|
||||
return nil
|
||||
}
|
||||
|
||||
func (f *mockFailIncorrectDetailsNoHeight) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElement(w, f.amount)
|
||||
func (f *mockFailIncorrectDetailsNoHeight) Encode(w *bytes.Buffer,
|
||||
pver uint32) error {
|
||||
|
||||
return WriteUint64(w, f.amount)
|
||||
}
|
||||
+76
-22
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
@@ -150,7 +151,7 @@ var _ Message = (*OpenChannel)(nil)
|
||||
// protocol version.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (o *OpenChannel) Encode(w io.Writer, pver uint32) error {
|
||||
func (o *OpenChannel) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
// Since the upfront script is encoded as a TLV record, concatenate it
|
||||
// with the ExtraData, and write them as one.
|
||||
tlvRecords, err := packShutdownScript(
|
||||
@@ -160,27 +161,80 @@ func (o *OpenChannel) Encode(w io.Writer, pver uint32) error {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteElements(w,
|
||||
o.ChainHash[:],
|
||||
o.PendingChannelID[:],
|
||||
o.FundingAmount,
|
||||
o.PushAmount,
|
||||
o.DustLimit,
|
||||
o.MaxValueInFlight,
|
||||
o.ChannelReserve,
|
||||
o.HtlcMinimum,
|
||||
o.FeePerKiloWeight,
|
||||
o.CsvDelay,
|
||||
o.MaxAcceptedHTLCs,
|
||||
o.FundingKey,
|
||||
o.RevocationPoint,
|
||||
o.PaymentPoint,
|
||||
o.DelayedPaymentPoint,
|
||||
o.HtlcPoint,
|
||||
o.FirstCommitmentPoint,
|
||||
o.ChannelFlags,
|
||||
tlvRecords,
|
||||
)
|
||||
if err := WriteBytes(w, o.ChainHash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, o.PendingChannelID[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSatoshi(w, o.FundingAmount); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteMilliSatoshi(w, o.PushAmount); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSatoshi(w, o.DustLimit); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteMilliSatoshi(w, o.MaxValueInFlight); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteSatoshi(w, o.ChannelReserve); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteMilliSatoshi(w, o.HtlcMinimum); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, o.FeePerKiloWeight); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint16(w, o.CsvDelay); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint16(w, o.MaxAcceptedHTLCs); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, o.FundingKey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, o.RevocationPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, o.PaymentPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, o.DelayedPaymentPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, o.HtlcPoint); err != nil {
|
||||
return err
|
||||
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, o.FirstCommitmentPoint); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteFundingFlag(w, o.ChannelFlags); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, tlvRecords)
|
||||
}
|
||||
|
||||
// Decode deserializes the serialized OpenChannel stored in the passed
|
||||
|
||||
+10
-5
@@ -1,6 +1,9 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
// PingPayload is a set of opaque bytes used to pad out a ping message.
|
||||
type PingPayload []byte
|
||||
@@ -44,10 +47,12 @@ func (p *Ping) Decode(r io.Reader, pver uint32) error {
|
||||
// protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (p *Ping) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
p.NumPongBytes,
|
||||
p.PaddingBytes)
|
||||
func (p *Ping) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteUint16(w, p.NumPongBytes); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WritePingPayload(w, p.PaddingBytes)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
+6
-5
@@ -1,6 +1,9 @@
|
||||
package lnwire
|
||||
|
||||
import "io"
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
// PongPayload is a set of opaque bytes sent in response to a ping message.
|
||||
type PongPayload []byte
|
||||
@@ -40,10 +43,8 @@ func (p *Pong) Decode(r io.Reader, pver uint32) error {
|
||||
// protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (p *Pong) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
p.PongBytes,
|
||||
)
|
||||
func (p *Pong) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
return WritePongPayload(w, p.PongBytes)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"math"
|
||||
|
||||
@@ -58,13 +59,20 @@ func (q *QueryChannelRange) Decode(r io.Reader, pver uint32) error {
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (q *QueryChannelRange) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
q.ChainHash[:],
|
||||
q.FirstBlockHeight,
|
||||
q.NumBlocks,
|
||||
q.ExtraData,
|
||||
)
|
||||
func (q *QueryChannelRange) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteBytes(w, q.ChainHash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, q.FirstBlockHeight); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, q.NumBlocks); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, q.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
@@ -291,26 +291,25 @@ func decodeShortChanIDs(r io.Reader) (ShortChanIDEncoding, []ShortChannelID, err
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (q *QueryShortChanIDs) Encode(w io.Writer, pver uint32) error {
|
||||
func (q *QueryShortChanIDs) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
// First, we'll write out the chain hash.
|
||||
err := WriteElements(w, q.ChainHash[:])
|
||||
if err != nil {
|
||||
if err := WriteBytes(w, q.ChainHash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Base on our encoding type, we'll write out the set of short channel
|
||||
// ID's.
|
||||
err = encodeShortChanIDs(w, q.EncodingType, q.ShortChanIDs, q.noSort)
|
||||
err := encodeShortChanIDs(w, q.EncodingType, q.ShortChanIDs, q.noSort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return q.ExtraData.Encode(w)
|
||||
return WriteBytes(w, q.ExtraData)
|
||||
}
|
||||
|
||||
// encodeShortChanIDs encodes the passed short channel ID's into the passed
|
||||
// io.Writer, respecting the specified encoding type.
|
||||
func encodeShortChanIDs(w io.Writer, encodingType ShortChanIDEncoding,
|
||||
func encodeShortChanIDs(w *bytes.Buffer, encodingType ShortChanIDEncoding,
|
||||
shortChanIDs []ShortChannelID, noSort bool) error {
|
||||
|
||||
// For both of the current encoding types, the channel ID's are to be
|
||||
@@ -332,20 +331,21 @@ func encodeShortChanIDs(w io.Writer, encodingType ShortChanIDEncoding,
|
||||
// body. We add 1 as the response will have the encoding type
|
||||
// prepended to it.
|
||||
numBytesBody := uint16(len(shortChanIDs)*8) + 1
|
||||
if err := WriteElements(w, numBytesBody); err != nil {
|
||||
if err := WriteUint16(w, numBytesBody); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// We'll then write out the encoding that that follows the
|
||||
// actual encoded short channel ID's.
|
||||
if err := WriteElements(w, encodingType); err != nil {
|
||||
err := WriteShortChanIDEncoding(w, encodingType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Now that we know they're sorted, we can write out each short
|
||||
// channel ID to the buffer.
|
||||
for _, chanID := range shortChanIDs {
|
||||
if err := WriteElements(w, chanID); err != nil {
|
||||
if err := WriteShortChannelID(w, chanID); err != nil {
|
||||
return fmt.Errorf("unable to write short chan "+
|
||||
"ID: %v", err)
|
||||
}
|
||||
@@ -360,29 +360,40 @@ func encodeShortChanIDs(w io.Writer, encodingType ShortChanIDEncoding,
|
||||
// TODO(roasbeef): assumes the caller knows the proper chunk size to
|
||||
// pass to avoid bin-packing here
|
||||
case EncodingSortedZlib:
|
||||
// We'll make a new buffer, then wrap that with a zlib writer
|
||||
// so we can write directly to the buffer and encode in a
|
||||
// streaming manner.
|
||||
var buf bytes.Buffer
|
||||
zlibWriter := zlib.NewWriter(&buf)
|
||||
|
||||
// If we don't have anything at all to write, then we'll write
|
||||
// an empty payload so we don't include things like the zlib
|
||||
// header when the remote party is expecting no actual short
|
||||
// channel IDs.
|
||||
var compressedPayload []byte
|
||||
if len(shortChanIDs) > 0 {
|
||||
// We'll make a new write buffer to hold the bytes of
|
||||
// shortChanIDs.
|
||||
var wb bytes.Buffer
|
||||
|
||||
// Next, we'll write out all the channel ID's directly
|
||||
// into the zlib writer, which will do compressing on
|
||||
// the fly.
|
||||
for _, chanID := range shortChanIDs {
|
||||
err := WriteElements(zlibWriter, chanID)
|
||||
err := WriteShortChannelID(&wb, chanID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("unable to write short chan "+
|
||||
"ID: %v", err)
|
||||
return fmt.Errorf(
|
||||
"unable to write short chan "+
|
||||
"ID: %v", err,
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
// With shortChanIDs written into wb, we'll create a
|
||||
// zlib writer and write all the compressed bytes.
|
||||
var zlibBuffer bytes.Buffer
|
||||
zlibWriter := zlib.NewWriter(&zlibBuffer)
|
||||
|
||||
if _, err := zlibWriter.Write(wb.Bytes()); err != nil {
|
||||
return fmt.Errorf(
|
||||
"unable to write compressed short chan"+
|
||||
"ID: %w", err)
|
||||
}
|
||||
|
||||
// Now that we've written all the elements, we'll
|
||||
// ensure the compressed stream is written to the
|
||||
// underlying buffer.
|
||||
@@ -391,7 +402,7 @@ func encodeShortChanIDs(w io.Writer, encodingType ShortChanIDEncoding,
|
||||
"compression: %v", err)
|
||||
}
|
||||
|
||||
compressedPayload = buf.Bytes()
|
||||
compressedPayload = zlibBuffer.Bytes()
|
||||
}
|
||||
|
||||
// Now that we have all the items compressed, we can compute
|
||||
@@ -407,15 +418,15 @@ func encodeShortChanIDs(w io.Writer, encodingType ShortChanIDEncoding,
|
||||
|
||||
// Finally, we can write out the number of bytes, the
|
||||
// compression type, and finally the buffer itself.
|
||||
if err := WriteElements(w, uint16(numBytesBody)); err != nil {
|
||||
if err := WriteUint16(w, uint16(numBytesBody)); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := WriteElements(w, encodingType); err != nil {
|
||||
err := WriteShortChanIDEncoding(w, encodingType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := w.Write(compressedPayload)
|
||||
return err
|
||||
return WriteBytes(w, compressedPayload)
|
||||
|
||||
default:
|
||||
// If we're trying to encode with an encoding type that we
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
"math"
|
||||
|
||||
@@ -85,23 +86,29 @@ func (c *ReplyChannelRange) Decode(r io.Reader, pver uint32) error {
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ReplyChannelRange) Encode(w io.Writer, pver uint32) error {
|
||||
err := WriteElements(w,
|
||||
c.ChainHash[:],
|
||||
c.FirstBlockHeight,
|
||||
c.NumBlocks,
|
||||
c.Complete,
|
||||
)
|
||||
func (c *ReplyChannelRange) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteBytes(w, c.ChainHash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, c.FirstBlockHeight); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, c.NumBlocks); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint8(w, c.Complete); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err := encodeShortChanIDs(w, c.EncodingType, c.ShortChanIDs, c.noSort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
err = encodeShortChanIDs(w, c.EncodingType, c.ShortChanIDs, c.noSort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return c.ExtraData.Encode(w)
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
@@ -54,12 +55,16 @@ func (c *ReplyShortChanIDsEnd) Decode(r io.Reader, pver uint32) error {
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *ReplyShortChanIDsEnd) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChainHash[:],
|
||||
c.Complete,
|
||||
c.ExtraData,
|
||||
)
|
||||
func (c *ReplyShortChanIDsEnd) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteBytes(w, c.ChainHash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint8(w, c.Complete); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
@@ -65,13 +66,20 @@ func (c *RevokeAndAck) Decode(r io.Reader, pver uint32) error {
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *RevokeAndAck) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.Revocation[:],
|
||||
c.NextRevocationKey,
|
||||
c.ExtraData,
|
||||
)
|
||||
func (c *RevokeAndAck) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteChannelID(w, c.ChanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, c.Revocation[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WritePublicKey(w, c.NextRevocationKey); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
+11
-2
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
@@ -46,8 +47,16 @@ func (s *Shutdown) Decode(r io.Reader, pver uint32) error {
|
||||
// the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (s *Shutdown) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w, s.ChannelID, s.Address, s.ExtraData)
|
||||
func (s *Shutdown) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteChannelID(w, s.ChannelID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteDeliveryAddress(w, s.Address); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, s.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
+29
-12
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
@@ -84,20 +85,36 @@ func (c *UpdateAddHTLC) Decode(r io.Reader, pver uint32) error {
|
||||
)
|
||||
}
|
||||
|
||||
// Encode serializes the target UpdateAddHTLC into the passed io.Writer observing
|
||||
// the protocol version specified.
|
||||
// Encode serializes the target UpdateAddHTLC into the passed io.Writer
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateAddHTLC) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.ID,
|
||||
c.Amount,
|
||||
c.PaymentHash[:],
|
||||
c.Expiry,
|
||||
c.OnionBlob[:],
|
||||
c.ExtraData,
|
||||
)
|
||||
func (c *UpdateAddHTLC) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteChannelID(w, c.ChanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint64(w, c.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteMilliSatoshi(w, c.Amount); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, c.PaymentHash[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, c.Expiry); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, c.OnionBlob[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
@@ -54,13 +55,20 @@ func (c *UpdateFailHTLC) Decode(r io.Reader, pver uint32) error {
|
||||
// the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFailHTLC) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.ID,
|
||||
c.Reason,
|
||||
c.ExtraData,
|
||||
)
|
||||
func (c *UpdateFailHTLC) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteChannelID(w, c.ChanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint64(w, c.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteOpaqueReason(w, c.Reason); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/sha256"
|
||||
"io"
|
||||
)
|
||||
@@ -53,14 +54,26 @@ func (c *UpdateFailMalformedHTLC) Decode(r io.Reader, pver uint32) error {
|
||||
// io.Writer observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFailMalformedHTLC) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.ID,
|
||||
c.ShaOnionBlob[:],
|
||||
c.FailureCode,
|
||||
c.ExtraData,
|
||||
)
|
||||
func (c *UpdateFailMalformedHTLC) Encode(w *bytes.Buffer,
|
||||
pver uint32) error {
|
||||
|
||||
if err := WriteChannelID(w, c.ChanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint64(w, c.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, c.ShaOnionBlob[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteFailCode(w, c.FailureCode); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
+11
-6
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
@@ -51,12 +52,16 @@ func (c *UpdateFee) Decode(r io.Reader, pver uint32) error {
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFee) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.FeePerKw,
|
||||
c.ExtraData,
|
||||
)
|
||||
func (c *UpdateFee) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteChannelID(w, c.ChanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint32(w, c.FeePerKw); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"io"
|
||||
)
|
||||
|
||||
@@ -60,13 +61,20 @@ func (c *UpdateFulfillHTLC) Decode(r io.Reader, pver uint32) error {
|
||||
// observing the protocol version specified.
|
||||
//
|
||||
// This is part of the lnwire.Message interface.
|
||||
func (c *UpdateFulfillHTLC) Encode(w io.Writer, pver uint32) error {
|
||||
return WriteElements(w,
|
||||
c.ChanID,
|
||||
c.ID,
|
||||
c.PaymentPreimage[:],
|
||||
c.ExtraData,
|
||||
)
|
||||
func (c *UpdateFulfillHTLC) Encode(w *bytes.Buffer, pver uint32) error {
|
||||
if err := WriteChannelID(w, c.ChanID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteUint64(w, c.ID); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if err := WriteBytes(w, c.PaymentPreimage[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteBytes(w, c.ExtraData)
|
||||
}
|
||||
|
||||
// MsgType returns the integer uniquely identifying this message type on the
|
||||
|
||||
@@ -0,0 +1,431 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/binary"
|
||||
"errors"
|
||||
"fmt"
|
||||
"image/color"
|
||||
"math"
|
||||
"net"
|
||||
|
||||
"github.com/btcsuite/btcd/btcec"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightningnetwork/lnd/tor"
|
||||
)
|
||||
|
||||
var (
|
||||
// ErrNilFeatureVector is returned when the supplied feature is nil.
|
||||
ErrNilFeatureVector = errors.New("cannot write nil feature vector")
|
||||
|
||||
// ErrPkScriptTooLong is returned when the length of the provided
|
||||
// script exceeds 34.
|
||||
ErrPkScriptTooLong = errors.New("'PkScript' too long")
|
||||
|
||||
// ErrNilTCPAddress is returned when the supplied address is nil.
|
||||
ErrNilTCPAddress = errors.New("cannot write nil TCPAddr")
|
||||
|
||||
// ErrNilOnionAddress is returned when the supplied address is nil.
|
||||
ErrNilOnionAddress = errors.New("cannot write nil onion address")
|
||||
|
||||
// ErrNilNetAddress is returned when a nil value is used in []net.Addr.
|
||||
ErrNilNetAddress = errors.New("cannot write nil address")
|
||||
|
||||
// ErrNilPublicKey is returned when a nil pubkey is used.
|
||||
ErrNilPublicKey = errors.New("cannot write nil pubkey")
|
||||
|
||||
// ErrUnknownServiceLength is returned when the onion service length is
|
||||
// unknown.
|
||||
ErrUnknownServiceLength = errors.New("unknown onion service length")
|
||||
)
|
||||
|
||||
// ErrOutpointIndexTooBig is used when the outpoint index exceeds the max value
|
||||
// of uint16.
|
||||
func ErrOutpointIndexTooBig(index uint32) error {
|
||||
return fmt.Errorf(
|
||||
"index for outpoint (%v) is greater than "+
|
||||
"max index of %v", index, math.MaxUint16,
|
||||
)
|
||||
}
|
||||
|
||||
// WriteBytes appends the given bytes to the provided buffer.
|
||||
//
|
||||
// Note: We intentionally skip the interfacer linter check here because we want
|
||||
// to have concrete type (bytes.Buffer) rather than interface type (io.Write)
|
||||
// due to performance concern.
|
||||
func WriteBytes(buf *bytes.Buffer, b []byte) error { // nolint: interfacer
|
||||
_, err := buf.Write(b)
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteUint8 appends the uint8 to the provided buffer.
|
||||
//
|
||||
// Note: We intentionally skip the interfacer linter check here because we want
|
||||
// to have concrete type (bytes.Buffer) rather than interface type (io.Write)
|
||||
// due to performance concern.
|
||||
func WriteUint8(buf *bytes.Buffer, n uint8) error { // nolint: interfacer
|
||||
_, err := buf.Write([]byte{n})
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteUint16 appends the uint16 to the provided buffer. It encodes the
|
||||
// integer using big endian byte order.
|
||||
//
|
||||
// Note: We intentionally skip the interfacer linter check here because we want
|
||||
// to have concrete type (bytes.Buffer) rather than interface type (io.Write)
|
||||
// due to performance concern.
|
||||
func WriteUint16(buf *bytes.Buffer, n uint16) error { // nolint: interfacer
|
||||
var b [2]byte
|
||||
binary.BigEndian.PutUint16(b[:], n)
|
||||
_, err := buf.Write(b[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteUint32 appends the uint32 to the provided buffer. It encodes the
|
||||
// integer using big endian byte order.
|
||||
func WriteUint32(buf *bytes.Buffer, n uint32) error {
|
||||
var b [4]byte
|
||||
binary.BigEndian.PutUint32(b[:], n)
|
||||
_, err := buf.Write(b[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteUint64 appends the uint64 to the provided buffer. It encodes the
|
||||
// integer using big endian byte order.
|
||||
//
|
||||
// Note: We intentionally skip the interfacer linter check here because we want
|
||||
// to have concrete type (bytes.Buffer) rather than interface type (io.Write)
|
||||
// due to performance concern.
|
||||
func WriteUint64(buf *bytes.Buffer, n uint64) error { // nolint: interfacer
|
||||
var b [8]byte
|
||||
binary.BigEndian.PutUint64(b[:], n)
|
||||
_, err := buf.Write(b[:])
|
||||
return err
|
||||
}
|
||||
|
||||
// WriteSatoshi appends the Satoshi value to the provided buffer.
|
||||
func WriteSatoshi(buf *bytes.Buffer, amount btcutil.Amount) error {
|
||||
return WriteUint64(buf, uint64(amount))
|
||||
}
|
||||
|
||||
// WriteMilliSatoshi appends the MilliSatoshi value to the provided buffer.
|
||||
func WriteMilliSatoshi(buf *bytes.Buffer, amount MilliSatoshi) error {
|
||||
return WriteUint64(buf, uint64(amount))
|
||||
}
|
||||
|
||||
// WritePublicKey appends the compressed public key to the provided buffer.
|
||||
func WritePublicKey(buf *bytes.Buffer, pub *btcec.PublicKey) error {
|
||||
if pub == nil {
|
||||
return ErrNilPublicKey
|
||||
}
|
||||
|
||||
serializedPubkey := pub.SerializeCompressed()
|
||||
return WriteBytes(buf, serializedPubkey)
|
||||
|
||||
}
|
||||
|
||||
// WriteChannelID appends the ChannelID to the provided buffer.
|
||||
func WriteChannelID(buf *bytes.Buffer, channelID ChannelID) error {
|
||||
return WriteBytes(buf, channelID[:])
|
||||
}
|
||||
|
||||
// WriteNodeAlias appends the alias to the provided buffer.
|
||||
func WriteNodeAlias(buf *bytes.Buffer, alias NodeAlias) error {
|
||||
return WriteBytes(buf, alias[:])
|
||||
}
|
||||
|
||||
// WriteShortChannelID appends the ShortChannelID to the provided buffer. It
|
||||
// encodes the BlockHeight and TxIndex each using 3 bytes with big endian byte
|
||||
// order, and encodes txPosition using 2 bytes with big endian byte order.
|
||||
func WriteShortChannelID(buf *bytes.Buffer, shortChanID ShortChannelID) error {
|
||||
// Check that field fit in 3 bytes and write the blockHeight
|
||||
if shortChanID.BlockHeight > ((1 << 24) - 1) {
|
||||
return errors.New("block height should fit in 3 bytes")
|
||||
}
|
||||
|
||||
var blockHeight [4]byte
|
||||
binary.BigEndian.PutUint32(blockHeight[:], shortChanID.BlockHeight)
|
||||
|
||||
if _, err := buf.Write(blockHeight[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Check that field fit in 3 bytes and write the txIndex
|
||||
if shortChanID.TxIndex > ((1 << 24) - 1) {
|
||||
return errors.New("tx index should fit in 3 bytes")
|
||||
}
|
||||
|
||||
var txIndex [4]byte
|
||||
binary.BigEndian.PutUint32(txIndex[:], shortChanID.TxIndex)
|
||||
if _, err := buf.Write(txIndex[1:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write the TxPosition
|
||||
return WriteUint16(buf, shortChanID.TxPosition)
|
||||
}
|
||||
|
||||
// WriteSig appends the signature to the provided buffer.
|
||||
func WriteSig(buf *bytes.Buffer, sig Sig) error {
|
||||
return WriteBytes(buf, sig[:])
|
||||
}
|
||||
|
||||
// WriteSigs appends the slice of signatures to the provided buffer with its
|
||||
// length.
|
||||
func WriteSigs(buf *bytes.Buffer, sigs []Sig) error {
|
||||
// Write the length of the sigs.
|
||||
if err := WriteUint16(buf, uint16(len(sigs))); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
for _, sig := range sigs {
|
||||
if err := WriteSig(buf, sig); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// WriteFailCode appends the FailCode to the provided buffer.
|
||||
func WriteFailCode(buf *bytes.Buffer, e FailCode) error {
|
||||
return WriteUint16(buf, uint16(e))
|
||||
}
|
||||
|
||||
// WriteRawFeatureVector encodes the feature using the feature's Encode method
|
||||
// and appends the data to the provided buffer. An error will return if the
|
||||
// passed feature is nil.
|
||||
//
|
||||
// Note: We intentionally skip the interfacer linter check here because we want
|
||||
// to have concrete type (bytes.Buffer) rather than interface type (io.Write)
|
||||
// due to performance concern.
|
||||
func WriteRawFeatureVector(buf *bytes.Buffer, // nolint: interfacer
|
||||
feature *RawFeatureVector) error {
|
||||
|
||||
if feature == nil {
|
||||
return ErrNilFeatureVector
|
||||
}
|
||||
|
||||
return feature.Encode(buf)
|
||||
}
|
||||
|
||||
// WriteColorRGBA appends the RGBA color using three bytes.
|
||||
func WriteColorRGBA(buf *bytes.Buffer, e color.RGBA) error {
|
||||
// Write R
|
||||
if err := WriteUint8(buf, e.R); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write G
|
||||
if err := WriteUint8(buf, e.G); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write B
|
||||
return WriteUint8(buf, e.B)
|
||||
}
|
||||
|
||||
// WriteShortChanIDEncoding appends the ShortChanIDEncoding to the provided
|
||||
// buffer.
|
||||
func WriteShortChanIDEncoding(buf *bytes.Buffer, e ShortChanIDEncoding) error {
|
||||
return WriteUint8(buf, uint8(e))
|
||||
}
|
||||
|
||||
// WriteFundingFlag appends the FundingFlag to the provided buffer.
|
||||
func WriteFundingFlag(buf *bytes.Buffer, flag FundingFlag) error {
|
||||
return WriteUint8(buf, uint8(flag))
|
||||
}
|
||||
|
||||
// WriteChanUpdateMsgFlags appends the update flag to the provided buffer.
|
||||
func WriteChanUpdateMsgFlags(buf *bytes.Buffer, f ChanUpdateMsgFlags) error {
|
||||
return WriteUint8(buf, uint8(f))
|
||||
}
|
||||
|
||||
// WriteChanUpdateChanFlags appends the update flag to the provided buffer.
|
||||
func WriteChanUpdateChanFlags(buf *bytes.Buffer, f ChanUpdateChanFlags) error {
|
||||
return WriteUint8(buf, uint8(f))
|
||||
}
|
||||
|
||||
// WriteDeliveryAddress appends the address to the provided buffer.
|
||||
func WriteDeliveryAddress(buf *bytes.Buffer, addr DeliveryAddress) error {
|
||||
return writeDataWithLength(buf, addr)
|
||||
}
|
||||
|
||||
// WritePingPayload appends the payload to the provided buffer.
|
||||
func WritePingPayload(buf *bytes.Buffer, payload PingPayload) error {
|
||||
return writeDataWithLength(buf, payload)
|
||||
}
|
||||
|
||||
// WritePongPayload appends the payload to the provided buffer.
|
||||
func WritePongPayload(buf *bytes.Buffer, payload PongPayload) error {
|
||||
return writeDataWithLength(buf, payload)
|
||||
}
|
||||
|
||||
// WriteErrorData appends the data to the provided buffer.
|
||||
func WriteErrorData(buf *bytes.Buffer, data ErrorData) error {
|
||||
return writeDataWithLength(buf, data)
|
||||
}
|
||||
|
||||
// WriteOpaqueReason appends the reason to the provided buffer.
|
||||
func WriteOpaqueReason(buf *bytes.Buffer, reason OpaqueReason) error {
|
||||
return writeDataWithLength(buf, reason)
|
||||
}
|
||||
|
||||
// WriteBool appends the boolean to the provided buffer.
|
||||
func WriteBool(buf *bytes.Buffer, b bool) error {
|
||||
if b {
|
||||
return WriteBytes(buf, []byte{1})
|
||||
}
|
||||
return WriteBytes(buf, []byte{0})
|
||||
}
|
||||
|
||||
// WritePkScript appends the script to the provided buffer. Returns an error if
|
||||
// the provided script exceeds 34 bytes.
|
||||
//
|
||||
// Note: We intentionally skip the interfacer linter check here because we want
|
||||
// to have concrete type (bytes.Buffer) rather than interface type (io.Write)
|
||||
// due to performance concern.
|
||||
func WritePkScript(buf *bytes.Buffer, s PkScript) error { // nolint: interfacer
|
||||
// The largest script we'll accept is a p2wsh which is exactly
|
||||
// 34 bytes long.
|
||||
scriptLength := len(s)
|
||||
if scriptLength > 34 {
|
||||
return ErrPkScriptTooLong
|
||||
}
|
||||
|
||||
return wire.WriteVarBytes(buf, 0, s)
|
||||
}
|
||||
|
||||
// WriteOutPoint appends the outpoint to the provided buffer.
|
||||
func WriteOutPoint(buf *bytes.Buffer, p wire.OutPoint) error {
|
||||
// Before we write anything to the buffer, check the Index is sane.
|
||||
if p.Index > math.MaxUint16 {
|
||||
return ErrOutpointIndexTooBig(p.Index)
|
||||
}
|
||||
|
||||
var h [32]byte
|
||||
copy(h[:], p.Hash[:])
|
||||
if _, err := buf.Write(h[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Write the index using two bytes.
|
||||
return WriteUint16(buf, uint16(p.Index))
|
||||
}
|
||||
|
||||
// WriteTCPAddr appends the TCP address to the provided buffer, either a IPv4
|
||||
// or a IPv6.
|
||||
func WriteTCPAddr(buf *bytes.Buffer, addr *net.TCPAddr) error {
|
||||
if addr == nil {
|
||||
return ErrNilTCPAddress
|
||||
}
|
||||
|
||||
// Make a slice of bytes to hold the data of descriptor and ip. At
|
||||
// most, we need 17 bytes - 1 byte for the descriptor, 16 bytes for
|
||||
// IPv6.
|
||||
data := make([]byte, 0, 17)
|
||||
|
||||
if addr.IP.To4() != nil {
|
||||
data = append(data, uint8(tcp4Addr))
|
||||
data = append(data, addr.IP.To4()...)
|
||||
} else {
|
||||
data = append(data, uint8(tcp6Addr))
|
||||
data = append(data, addr.IP.To16()...)
|
||||
}
|
||||
|
||||
if _, err := buf.Write(data); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteUint16(buf, uint16(addr.Port))
|
||||
}
|
||||
|
||||
// WriteOnionAddr appends the onion address to the provided buffer.
|
||||
func WriteOnionAddr(buf *bytes.Buffer, addr *tor.OnionAddr) error {
|
||||
if addr == nil {
|
||||
return ErrNilOnionAddress
|
||||
}
|
||||
|
||||
var (
|
||||
suffixIndex int
|
||||
descriptor []byte
|
||||
)
|
||||
|
||||
// Decide the suffixIndex and descriptor.
|
||||
switch len(addr.OnionService) {
|
||||
case tor.V2Len:
|
||||
descriptor = []byte{byte(v2OnionAddr)}
|
||||
suffixIndex = tor.V2Len - tor.OnionSuffixLen
|
||||
|
||||
case tor.V3Len:
|
||||
descriptor = []byte{byte(v3OnionAddr)}
|
||||
suffixIndex = tor.V3Len - tor.OnionSuffixLen
|
||||
|
||||
default:
|
||||
return ErrUnknownServiceLength
|
||||
}
|
||||
|
||||
// Decode the address.
|
||||
host, err := tor.Base32Encoding.DecodeString(
|
||||
addr.OnionService[:suffixIndex],
|
||||
)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
// Perform the actual write when the above checks passed.
|
||||
if _, err := buf.Write(descriptor); err != nil {
|
||||
return err
|
||||
}
|
||||
if _, err := buf.Write(host); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
return WriteUint16(buf, uint16(addr.Port))
|
||||
}
|
||||
|
||||
// WriteNetAddrs appends a slice of addresses to the provided buffer with the
|
||||
// length info.
|
||||
func WriteNetAddrs(buf *bytes.Buffer, addresses []net.Addr) error {
|
||||
// First, we'll encode all the addresses into an intermediate
|
||||
// buffer. We need to do this in order to compute the total
|
||||
// length of the addresses.
|
||||
buffer := make([]byte, 0, MaxMsgBody)
|
||||
addrBuf := bytes.NewBuffer(buffer)
|
||||
|
||||
for _, address := range addresses {
|
||||
switch a := address.(type) {
|
||||
case *net.TCPAddr:
|
||||
if err := WriteTCPAddr(addrBuf, a); err != nil {
|
||||
return err
|
||||
}
|
||||
case *tor.OnionAddr:
|
||||
if err := WriteOnionAddr(addrBuf, a); err != nil {
|
||||
return err
|
||||
}
|
||||
default:
|
||||
return ErrNilNetAddress
|
||||
}
|
||||
}
|
||||
|
||||
// With the addresses fully encoded, we can now write out data.
|
||||
return writeDataWithLength(buf, addrBuf.Bytes())
|
||||
}
|
||||
|
||||
// writeDataWithLength writes the data and its length to the buffer.
|
||||
//
|
||||
// Note: We intentionally skip the interfacer linter check here because we want
|
||||
// to have concrete type (bytes.Buffer) rather than interface type (io.Write)
|
||||
// due to performance concern.
|
||||
func writeDataWithLength(buf *bytes.Buffer, // nolint: interfacer
|
||||
data []byte) error {
|
||||
|
||||
var l [2]byte
|
||||
binary.BigEndian.PutUint16(l[:], uint16(len(data)))
|
||||
if _, err := buf.Write(l[:]); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
_, err := buf.Write(data)
|
||||
return err
|
||||
}
|
||||
@@ -0,0 +1,618 @@
|
||||
package lnwire
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/base32"
|
||||
"image/color"
|
||||
"math"
|
||||
"net"
|
||||
"testing"
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/lightningnetwork/lnd/tor"
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestWriteBytes(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := []byte{1, 2, 3}
|
||||
|
||||
err := WriteBytes(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, data, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteUint8(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := uint8(1)
|
||||
expectedBytes := []byte{1}
|
||||
|
||||
err := WriteUint8(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteUint16(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := uint16(1)
|
||||
expectedBytes := []byte{0, 1}
|
||||
|
||||
err := WriteUint16(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteUint32(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := uint32(1)
|
||||
expectedBytes := []byte{0, 0, 0, 1}
|
||||
|
||||
err := WriteUint32(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteUint64(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := uint64(1)
|
||||
expectedBytes := []byte{0, 0, 0, 0, 0, 0, 0, 1}
|
||||
|
||||
err := WriteUint64(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteSatoshi(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := btcutil.Amount(1)
|
||||
expectedBytes := []byte{0, 0, 0, 0, 0, 0, 0, 1}
|
||||
|
||||
err := WriteSatoshi(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteMilliSatoshi(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := MilliSatoshi(1)
|
||||
expectedBytes := []byte{0, 0, 0, 0, 0, 0, 0, 1}
|
||||
|
||||
err := WriteMilliSatoshi(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWritePublicKey(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// Check that when nil pubkey is used, an error will return.
|
||||
err := WritePublicKey(buf, nil)
|
||||
require.Equal(t, ErrNilPublicKey, err)
|
||||
|
||||
pub, err := randPubKey()
|
||||
require.NoError(t, err)
|
||||
expectedBytes := pub.SerializeCompressed()
|
||||
|
||||
err = WritePublicKey(buf, pub)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteChannelID(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := ChannelID{1}
|
||||
expectedBytes := [32]byte{1}
|
||||
|
||||
err := WriteChannelID(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes[:], buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteNodeAlias(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := NodeAlias{1}
|
||||
expectedBytes := [32]byte{1}
|
||||
|
||||
err := WriteNodeAlias(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes[:], buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteShortChannelID(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := ShortChannelID{BlockHeight: 1, TxIndex: 2, TxPosition: 3}
|
||||
expectedBytes := []byte{
|
||||
0, 0, 1, // First three bytes encodes BlockHeight.
|
||||
0, 0, 2, // Second three bytes encodes TxIndex.
|
||||
0, 3, // Final two bytes encodes TxPosition.
|
||||
}
|
||||
|
||||
err := WriteShortChannelID(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteSig(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := Sig{1, 2, 3}
|
||||
expectedBytes := [64]byte{1, 2, 3}
|
||||
|
||||
err := WriteSig(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes[:], buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteSigs(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
sig1, sig2, sig3 := Sig{1}, Sig{2}, Sig{3}
|
||||
data := []Sig{sig1, sig2, sig3}
|
||||
|
||||
// First two bytes encode the length of the slice.
|
||||
expectedBytes := []byte{0, 3}
|
||||
expectedBytes = append(expectedBytes, sig1[:]...)
|
||||
expectedBytes = append(expectedBytes, sig2[:]...)
|
||||
expectedBytes = append(expectedBytes, sig3[:]...)
|
||||
|
||||
err := WriteSigs(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteFailCode(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := FailCode(1)
|
||||
expectedBytes := []byte{0, 1}
|
||||
|
||||
err := WriteFailCode(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
// TODO(yy): expand the test to cover more encoding scenarios.
|
||||
func TestWriteRawFeatureVector(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// Check that when nil feature is used, an error will return.
|
||||
err := WriteRawFeatureVector(buf, nil)
|
||||
require.Equal(t, ErrNilFeatureVector, err)
|
||||
|
||||
// Create a raw feature vector.
|
||||
feature := &RawFeatureVector{features: map[FeatureBit]bool{
|
||||
InitialRoutingSync: true, // FeatureBit 3.
|
||||
}}
|
||||
expectedBytes := []byte{
|
||||
0, 1, // First two bytes encode the length.
|
||||
8, // Last byte encodes the feature bit (1 << 3).
|
||||
}
|
||||
|
||||
err = WriteRawFeatureVector(buf, feature)
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteColorRGBA(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := color.RGBA{R: 1, G: 2, B: 3}
|
||||
expectedBytes := []byte{1, 2, 3}
|
||||
|
||||
err := WriteColorRGBA(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteShortChanIDEncoding(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := ShortChanIDEncoding(1)
|
||||
expectedBytes := []byte{1}
|
||||
|
||||
err := WriteShortChanIDEncoding(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteFundingFlag(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := FundingFlag(1)
|
||||
expectedBytes := []byte{1}
|
||||
|
||||
err := WriteFundingFlag(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteChanUpdateMsgFlags(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := ChanUpdateMsgFlags(1)
|
||||
expectedBytes := []byte{1}
|
||||
|
||||
err := WriteChanUpdateMsgFlags(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteChanUpdateChanFlags(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := ChanUpdateChanFlags(1)
|
||||
expectedBytes := []byte{1}
|
||||
|
||||
err := WriteChanUpdateChanFlags(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteDeliveryAddress(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := DeliveryAddress{1, 1, 1}
|
||||
expectedBytes := []byte{
|
||||
0, 3, // First two bytes encode the length.
|
||||
1, 1, 1, // The actual data.
|
||||
}
|
||||
|
||||
err := WriteDeliveryAddress(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWritePingPayload(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := PingPayload{1, 1, 1}
|
||||
expectedBytes := []byte{
|
||||
0, 3, // First two bytes encode the length.
|
||||
1, 1, 1, // The actual data.
|
||||
}
|
||||
|
||||
err := WritePingPayload(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWritePongPayload(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := PongPayload{1, 1, 1}
|
||||
expectedBytes := []byte{
|
||||
0, 3, // First two bytes encode the length.
|
||||
1, 1, 1, // The actual data.
|
||||
}
|
||||
|
||||
err := WritePongPayload(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteErrorData(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := ErrorData{1, 1, 1}
|
||||
expectedBytes := []byte{
|
||||
0, 3, // First two bytes encode the length.
|
||||
1, 1, 1, // The actual data.
|
||||
}
|
||||
|
||||
err := WriteErrorData(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteOpaqueReason(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
data := OpaqueReason{1, 1, 1}
|
||||
expectedBytes := []byte{
|
||||
0, 3, // First two bytes encode the length.
|
||||
1, 1, 1, // The actual data.
|
||||
}
|
||||
|
||||
err := WriteOpaqueReason(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteBool(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// Test write true.
|
||||
data := true
|
||||
expectedBytes := []byte{1}
|
||||
|
||||
err := WriteBool(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
|
||||
// Test write false.
|
||||
data = false
|
||||
expectedBytes = append(expectedBytes, 0)
|
||||
|
||||
err = WriteBool(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWritePkScript(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// Write a very long script to check the error is returned as expected.
|
||||
script := PkScript{}
|
||||
zeros := [35]byte{}
|
||||
script = append(script, zeros[:]...)
|
||||
err := WritePkScript(buf, script)
|
||||
require.Equal(t, ErrPkScriptTooLong, err)
|
||||
|
||||
data := PkScript{1, 1, 1}
|
||||
expectedBytes := []byte{
|
||||
3, // First byte encodes the length.
|
||||
1, 1, 1, // The actual data.
|
||||
}
|
||||
|
||||
err = WritePkScript(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteOutPoint(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
// Create an outpoint with very large index to check the error is
|
||||
// returned as expected.
|
||||
outpointWrong := wire.OutPoint{Index: math.MaxUint16 + 1}
|
||||
err := WriteOutPoint(buf, outpointWrong)
|
||||
require.Equal(t, ErrOutpointIndexTooBig(outpointWrong.Index), err)
|
||||
|
||||
// Now check the normal write succeeds.
|
||||
hash := chainhash.Hash{1}
|
||||
data := wire.OutPoint{Index: 2, Hash: hash}
|
||||
expectedBytes := []byte{}
|
||||
expectedBytes = append(expectedBytes, hash[:]...)
|
||||
expectedBytes = append(expectedBytes, []byte{0, 2}...)
|
||||
|
||||
err = WriteOutPoint(buf, data)
|
||||
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, expectedBytes, buf.Bytes())
|
||||
}
|
||||
|
||||
func TestWriteTCPAddr(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
addr *net.TCPAddr
|
||||
|
||||
expectedErr error
|
||||
expectedBytes []byte
|
||||
}{
|
||||
{
|
||||
// Check that the error is returned when nil address is
|
||||
// used.
|
||||
name: "nil address err",
|
||||
addr: nil,
|
||||
expectedErr: ErrNilTCPAddress,
|
||||
expectedBytes: nil,
|
||||
},
|
||||
{
|
||||
// Check write IPv4.
|
||||
name: "write ipv4",
|
||||
addr: &net.TCPAddr{
|
||||
IP: net.IP{127, 0, 0, 1},
|
||||
Port: 8080,
|
||||
},
|
||||
expectedErr: nil,
|
||||
expectedBytes: []byte{
|
||||
0x1, // The addressType.
|
||||
0x7f, 0x0, 0x0, 0x1, // The IP.
|
||||
0x1f, 0x90, // The port (31 * 256 + 144).
|
||||
},
|
||||
},
|
||||
{
|
||||
// Check write IPv6.
|
||||
name: "write ipv6",
|
||||
addr: &net.TCPAddr{
|
||||
IP: net.IP{
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
1, 1, 1, 1, 1, 1, 1, 1,
|
||||
},
|
||||
Port: 8080,
|
||||
},
|
||||
expectedErr: nil,
|
||||
expectedBytes: []byte{
|
||||
0x2, // The addressType.
|
||||
// The IP.
|
||||
0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
|
||||
0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1, 0x1,
|
||||
0x1f, 0x90, // The port (31 * 256 + 144).
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
oldLen := buf.Len()
|
||||
|
||||
err := WriteTCPAddr(buf, tc.addr)
|
||||
require.Equal(t, tc.expectedErr, err)
|
||||
|
||||
bytesWritten := buf.Bytes()[oldLen:buf.Len()]
|
||||
require.Equal(t, tc.expectedBytes, bytesWritten)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteOnionAddr(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
addr *tor.OnionAddr
|
||||
|
||||
expectedErr error
|
||||
expectedBytes []byte
|
||||
}{
|
||||
{
|
||||
// Check that the error is returned when nil address is
|
||||
// used.
|
||||
name: "nil address err",
|
||||
addr: nil,
|
||||
expectedErr: ErrNilOnionAddress,
|
||||
expectedBytes: nil,
|
||||
},
|
||||
{
|
||||
// Check the error is returned when an invalid onion
|
||||
// address is used.
|
||||
name: "wrong onion service length",
|
||||
addr: &tor.OnionAddr{OnionService: "wrong"},
|
||||
expectedErr: ErrUnknownServiceLength,
|
||||
expectedBytes: nil,
|
||||
},
|
||||
{
|
||||
// Check when the address has invalid base32 encoding,
|
||||
// the error is returned.
|
||||
name: "invalid base32 encoding",
|
||||
addr: &tor.OnionAddr{
|
||||
OnionService: "1234567890123456.onion",
|
||||
},
|
||||
expectedErr: base32.CorruptInputError(0),
|
||||
expectedBytes: nil,
|
||||
},
|
||||
{
|
||||
// Check write onion v2.
|
||||
name: "onion address v2",
|
||||
addr: &tor.OnionAddr{
|
||||
OnionService: "abcdefghijklmnop.onion",
|
||||
Port: 9065,
|
||||
},
|
||||
expectedErr: nil,
|
||||
expectedBytes: []byte{
|
||||
0x3, // The descriptor.
|
||||
0x0, 0x44, 0x32, 0x14, 0xc7, // The host.
|
||||
0x42, 0x54, 0xb6, 0x35, 0xcf,
|
||||
0x23, 0x69, // The port.
|
||||
},
|
||||
},
|
||||
{
|
||||
// Check write onion v3.
|
||||
name: "onion address v3",
|
||||
addr: &tor.OnionAddr{
|
||||
OnionService: "abcdefghij" +
|
||||
"abcdefghijabcdefghij" +
|
||||
"abcdefghijabcdefghij" +
|
||||
"234567.onion",
|
||||
Port: 9065,
|
||||
},
|
||||
expectedErr: nil,
|
||||
expectedBytes: []byte{
|
||||
0x4, // The descriptor.
|
||||
0x0, 0x44, 0x32, 0x14, 0xc7, 0x42, 0x40,
|
||||
0x11, 0xc, 0x85, 0x31, 0xd0, 0x90, 0x4,
|
||||
0x43, 0x21, 0x4c, 0x74, 0x24, 0x1, 0x10,
|
||||
0xc8, 0x53, 0x1d, 0x9, 0x0, 0x44, 0x32,
|
||||
0x14, 0xc7, 0x42, 0x75, 0xbe, 0x77, 0xdf,
|
||||
0x23, 0x69, // The port.
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
oldLen := buf.Len()
|
||||
|
||||
err := WriteOnionAddr(buf, tc.addr)
|
||||
require.Equal(t, tc.expectedErr, err)
|
||||
|
||||
bytesWritten := buf.Bytes()[oldLen:buf.Len()]
|
||||
require.Equal(t, tc.expectedBytes, bytesWritten)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestWriteNetAddrs(t *testing.T) {
|
||||
buf := new(bytes.Buffer)
|
||||
tcpAddr := &net.TCPAddr{
|
||||
IP: net.IP{127, 0, 0, 1},
|
||||
Port: 8080,
|
||||
}
|
||||
onionAddr := &tor.OnionAddr{
|
||||
OnionService: "abcdefghijklmnop.onion",
|
||||
Port: 9065,
|
||||
}
|
||||
|
||||
testCases := []struct {
|
||||
name string
|
||||
addr []net.Addr
|
||||
|
||||
expectedErr error
|
||||
expectedBytes []byte
|
||||
}{
|
||||
{
|
||||
// Check that the error is returned when nil address is
|
||||
// used.
|
||||
name: "nil address err",
|
||||
addr: []net.Addr{nil, tcpAddr, onionAddr},
|
||||
expectedErr: ErrNilNetAddress,
|
||||
expectedBytes: nil,
|
||||
},
|
||||
{
|
||||
// Check empty address slice.
|
||||
name: "empty address slice",
|
||||
addr: []net.Addr{},
|
||||
expectedErr: nil,
|
||||
// Use two bytes to encode the address size.
|
||||
expectedBytes: []byte{0, 0},
|
||||
},
|
||||
{
|
||||
// Check a successful writes of a slice of addresses.
|
||||
name: "two addresses",
|
||||
addr: []net.Addr{tcpAddr, onionAddr},
|
||||
expectedErr: nil,
|
||||
expectedBytes: []byte{
|
||||
// 7 bytes for TCP and 13 bytes for onion.
|
||||
0x0, 0x14,
|
||||
// TCP address.
|
||||
0x1, 0x7f, 0x0, 0x0, 0x1, 0x1f, 0x90,
|
||||
// Onion address.
|
||||
0x3, 0x0, 0x44, 0x32, 0x14, 0xc7, 0x42,
|
||||
0x54, 0xb6, 0x35, 0xcf, 0x23, 0x69,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
for _, tc := range testCases {
|
||||
tc := tc
|
||||
t.Run(tc.name, func(t *testing.T) {
|
||||
oldLen := buf.Len()
|
||||
|
||||
err := WriteNetAddrs(buf, tc.addr)
|
||||
require.Equal(t, tc.expectedErr, err)
|
||||
|
||||
bytesWritten := buf.Bytes()[oldLen:buf.Len()]
|
||||
require.Equal(t, tc.expectedBytes, bytesWritten)
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -5,8 +5,6 @@ import (
|
||||
"encoding/binary"
|
||||
"fmt"
|
||||
"io"
|
||||
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
)
|
||||
|
||||
// MaxMessagePayload is the maximum bytes a message can be regardless of other
|
||||
@@ -75,7 +73,14 @@ func (m MessageType) String() string {
|
||||
|
||||
// Serializable is an interface which defines a lightning wire serializable
|
||||
// object.
|
||||
type Serializable = lnwire.Serializable
|
||||
type Serializable interface {
|
||||
// Decode reads the bytes stream and converts it to the object.
|
||||
Decode(io.Reader, uint32) error
|
||||
|
||||
// Encode converts object to the bytes stream and write it into the
|
||||
// write buffer.
|
||||
Encode(io.Writer, uint32) error
|
||||
}
|
||||
|
||||
// Message is an interface that defines a lightning wire protocol message. The
|
||||
// interface is general in order to allow implementing types full control over
|
||||
|
||||
Reference in new issue
Block a user