Skip to content

Commit

Permalink
lnwire: add HtlcMaximumMsat field to ChannelUpdate
Browse files Browse the repository at this point in the history
In this commit, we add a field to the ChannelUpdate
denoting the maximum HTLC we support sending over
this channel, a field which was recently added to the
spec.

This field serves multiple purposes. In the short
term, it enables nodes to signal the largest HTLC
they're willing to carry, allows light clients who
don't verify channel existence to have some guidance
when routing HTLCs, and finally may allow nodes to
preserve a portion of bandwidth at all times.

In the long term, this field can be used by
implementations of AMP to guide payment splitting,
as it becomes apparent to a node the largest possible
HTLC one can route over a particular channel.

This PR was made possible by the merge of lightningnetwork#1825,
which enables older nodes to properly retain and
verify signatures on updates that include new fields
(like this new max HTLC field) that they haven't yet
been updated to recognize.

In addition, the new ChannelUpdate fields are added to
the lnwire fuzzing tests.

Co-authored-by: Johan T. Halseth <johanth@gmail.com>
  • Loading branch information
valentinewallace and halseth committed Jan 12, 2019
1 parent 20d691e commit 61b0117
Show file tree
Hide file tree
Showing 2 changed files with 45 additions and 3 deletions.
47 changes: 44 additions & 3 deletions lnwire/channel_update.go
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,12 @@ import (
// present in the ChannelUpdate.
type ChanUpdateMsgFlags uint8

const (
// ChanUpdateOptionMaxHtlc is a bit that indicates whether the
// optional htlc_maximum_msat field is present in this ChannelUpdate.
ChanUpdateOptionMaxHtlc ChanUpdateMsgFlags = 1 << iota
)

// String returns the bitfield flags as a string.
func (c ChanUpdateMsgFlags) String() string {
return fmt.Sprintf("%08b", c)
Expand Down Expand Up @@ -95,6 +101,9 @@ type ChannelUpdate struct {
// satoshi.
FeeRate uint32

// HtlcMaximumMsat is the maximum HTLC value which will be accepted.
HtlcMaximumMsat MilliSatoshi

// ExtraOpaqueData is the set of data that was appended to this
// message, some of which we may not actually know how to iterate or
// parse. By holding onto this data, we ensure that we're able to
Expand Down Expand Up @@ -129,6 +138,13 @@ func (a *ChannelUpdate) Decode(r io.Reader, pver uint32) error {
return err
}

// Now check whether the max HTLC field is present and read it if so.
if a.MessageFlags&ChanUpdateOptionMaxHtlc != 0 {
if err := ReadElements(r, &a.HtlcMaximumMsat); err != nil {
return err
}
}

// Now that we've read out all the fields that we explicitly know of,
// we'll collect the remainder into the ExtraOpaqueData field. If there
// aren't any bytes, then we'll snip off the slice to avoid carrying
Expand All @@ -149,7 +165,7 @@ func (a *ChannelUpdate) Decode(r io.Reader, pver uint32) error {
//
// This is part of the lnwire.Message interface.
func (a *ChannelUpdate) Encode(w io.Writer, pver uint32) error {
return WriteElements(w,
err := WriteElements(w,
a.Signature,
a.ChainHash[:],
a.ShortChannelID,
Expand All @@ -160,8 +176,21 @@ func (a *ChannelUpdate) Encode(w io.Writer, pver uint32) error {
a.HtlcMinimumMsat,
a.BaseFee,
a.FeeRate,
a.ExtraOpaqueData,
)
if err != nil {
return err
}

// Now append optional fields if they are set. Currently, the only
// optional field is max HTLC.
if a.MessageFlags&ChanUpdateOptionMaxHtlc != 0 {
if err := WriteElements(w, a.HtlcMaximumMsat); err != nil {
return err
}
}

// Finally, append any extra opaque data.
return WriteElements(w, a.ExtraOpaqueData)
}

// MsgType returns the integer uniquely identifying this message type on the
Expand Down Expand Up @@ -196,11 +225,23 @@ func (a *ChannelUpdate) DataToSign() ([]byte, error) {
a.HtlcMinimumMsat,
a.BaseFee,
a.FeeRate,
a.ExtraOpaqueData,
)
if err != nil {
return nil, err
}

// Now append optional fields if they are set. Currently, the only
// optional field is max HTLC.
if a.MessageFlags&ChanUpdateOptionMaxHtlc != 0 {
if err := WriteElements(&w, a.HtlcMaximumMsat); err != nil {
return nil, err
}
}

// Finally, append any extra opaque data.
if err := WriteElements(&w, a.ExtraOpaqueData); err != nil {
return nil, err
}

return w.Bytes(), nil
}
1 change: 1 addition & 0 deletions lnwire/lnwire_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -656,6 +656,7 @@ func TestLightningWireProtocol(t *testing.T) {
ChannelFlags: ChanUpdateChanFlags(r.Int31()),
TimeLockDelta: uint16(r.Int31()),
HtlcMinimumMsat: MilliSatoshi(r.Int63()),
HtlcMaximumMsat: MilliSatoshi(r.Int63()),
BaseFee: uint32(r.Int31()),
FeeRate: uint32(r.Int31()),
}
Expand Down

0 comments on commit 61b0117

Please sign in to comment.