Skip to content

Commit 5f00be2

Browse files
authored
Merge pull request #9148 from ProofOfKeags/lnwire-dyncomms-update
DynComms [2/n]: lnwire: add authenticated wire messages for Dyn*
2 parents fb1fef9 + c64e3a6 commit 5f00be2

File tree

7 files changed

+393
-236
lines changed

7 files changed

+393
-236
lines changed

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -82,3 +82,6 @@ coverage.txt
8282
/lnd-*/
8383

8484
.aider*
85+
86+
# All test data generated from rapid.
87+
*/testdata

lnwire/dyn_ack.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,10 @@ type DynAck struct {
2424
// a dynamic commitment negotiation
2525
ChanID ChannelID
2626

27+
// Sig is a signature that acknowledges and approves the parameters
28+
// that were requested in the DynPropose
29+
Sig Sig
30+
2731
// LocalNonce is an optional field that is transmitted when accepting
2832
// a dynamic commitment upgrade to Taproot Channels. This nonce will be
2933
// used to verify the first commitment transaction signature. This will
@@ -54,6 +58,10 @@ func (da *DynAck) Encode(w *bytes.Buffer, _ uint32) error {
5458
return err
5559
}
5660

61+
if err := WriteSig(w, da.Sig); err != nil {
62+
return err
63+
}
64+
5765
var tlvRecords []tlv.Record
5866
da.LocalNonce.WhenSome(func(nonce Musig2Nonce) {
5967
tlvRecords = append(
@@ -88,7 +96,7 @@ func (da *DynAck) Encode(w *bytes.Buffer, _ uint32) error {
8896
// This is a part of the lnwire.Message interface.
8997
func (da *DynAck) Decode(r io.Reader, _ uint32) error {
9098
// Parse out main message.
91-
if err := ReadElements(r, &da.ChanID); err != nil {
99+
if err := ReadElements(r, &da.ChanID, &da.Sig); err != nil {
92100
return err
93101
}
94102

lnwire/dyn_commit.go

Lines changed: 146 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,146 @@
1+
package lnwire
2+
3+
import (
4+
"bytes"
5+
"io"
6+
7+
"github.com/btcsuite/btcd/btcutil"
8+
"github.com/lightningnetwork/lnd/tlv"
9+
)
10+
11+
// DynCommit is a composite message that is used to irrefutably execute a
12+
// dynamic commitment update.
13+
type DynCommit struct {
14+
// DynPropose is an embedded version of the original DynPropose message
15+
// that initiated this negotiation.
16+
DynPropose
17+
18+
// DynAck is an embedded version of the original DynAck message that
19+
// countersigned this negotiation.
20+
DynAck
21+
22+
// ExtraData is the set of data that was appended to this message to
23+
// fill out the full maximum transport message size. These fields can
24+
// be used to specify optional data such as custom TLV fields.
25+
ExtraData ExtraOpaqueData
26+
}
27+
28+
// A compile time check to ensure DynCommit implements the lnwire.Message
29+
// interface.
30+
var _ Message = (*DynCommit)(nil)
31+
32+
// A compile time check to ensure DynCommit implements the
33+
// lnwire.SizeableMessage interface.
34+
var _ SizeableMessage = (*DynCommit)(nil)
35+
36+
// Encode serializes the target DynAck into the passed io.Writer. Serialization
37+
// will observe the rules defined by the passed protocol version.
38+
//
39+
// This is a part of the lnwire.Message interface.
40+
func (dc *DynCommit) Encode(w *bytes.Buffer, _ uint32) error {
41+
if err := WriteChannelID(w, dc.DynPropose.ChanID); err != nil {
42+
return err
43+
}
44+
45+
if err := WriteSig(w, dc.Sig); err != nil {
46+
return err
47+
}
48+
49+
var extra ExtraOpaqueData
50+
err := extra.PackRecords(dynProposeRecords(&dc.DynPropose)...)
51+
if err != nil {
52+
return err
53+
}
54+
dc.ExtraData = extra
55+
56+
return WriteBytes(w, dc.ExtraData)
57+
}
58+
59+
// Decode deserializes the serialized DynCommit stored in the passed io.Reader
60+
// into the target DynAck using the deserialization rules defined by the passed
61+
// protocol version.
62+
//
63+
// This is a part of the lnwire.Message interface.
64+
func (dc *DynCommit) Decode(r io.Reader, _ uint32) error {
65+
// Parse out main message.
66+
if err := ReadElements(r, &dc.DynPropose.ChanID, &dc.Sig); err != nil {
67+
return err
68+
}
69+
dc.DynAck.ChanID = dc.DynPropose.ChanID
70+
71+
// Parse out TLV records.
72+
var tlvRecords ExtraOpaqueData
73+
if err := ReadElement(r, &tlvRecords); err != nil {
74+
return err
75+
}
76+
77+
// Prepare receiving buffers to be filled by TLV extraction.
78+
var dustLimit tlv.RecordT[tlv.TlvType0, uint64]
79+
var maxValue tlv.RecordT[tlv.TlvType2, uint64]
80+
var htlcMin tlv.RecordT[tlv.TlvType4, uint64]
81+
var reserve tlv.RecordT[tlv.TlvType6, uint64]
82+
csvDelay := dc.CsvDelay.Zero()
83+
maxHtlcs := dc.MaxAcceptedHTLCs.Zero()
84+
chanType := dc.ChannelType.Zero()
85+
86+
typeMap, err := tlvRecords.ExtractRecords(
87+
&dustLimit, &maxValue, &htlcMin, &reserve, &csvDelay, &maxHtlcs,
88+
&chanType,
89+
)
90+
if err != nil {
91+
return err
92+
}
93+
94+
// Check the results of the TLV Stream decoding and appropriately set
95+
// message fields.
96+
if val, ok := typeMap[dc.DustLimit.TlvType()]; ok && val == nil {
97+
var rec tlv.RecordT[tlv.TlvType0, btcutil.Amount]
98+
rec.Val = btcutil.Amount(dustLimit.Val)
99+
dc.DustLimit = tlv.SomeRecordT(rec)
100+
}
101+
if val, ok := typeMap[dc.MaxValueInFlight.TlvType()]; ok && val == nil {
102+
var rec tlv.RecordT[tlv.TlvType2, MilliSatoshi]
103+
rec.Val = MilliSatoshi(maxValue.Val)
104+
dc.MaxValueInFlight = tlv.SomeRecordT(rec)
105+
}
106+
if val, ok := typeMap[dc.HtlcMinimum.TlvType()]; ok && val == nil {
107+
var rec tlv.RecordT[tlv.TlvType4, MilliSatoshi]
108+
rec.Val = MilliSatoshi(htlcMin.Val)
109+
dc.HtlcMinimum = tlv.SomeRecordT(rec)
110+
}
111+
if val, ok := typeMap[dc.ChannelReserve.TlvType()]; ok && val == nil {
112+
var rec tlv.RecordT[tlv.TlvType6, btcutil.Amount]
113+
rec.Val = btcutil.Amount(reserve.Val)
114+
dc.ChannelReserve = tlv.SomeRecordT(rec)
115+
}
116+
if val, ok := typeMap[dc.CsvDelay.TlvType()]; ok && val == nil {
117+
dc.CsvDelay = tlv.SomeRecordT(csvDelay)
118+
}
119+
if val, ok := typeMap[dc.MaxAcceptedHTLCs.TlvType()]; ok && val == nil {
120+
dc.MaxAcceptedHTLCs = tlv.SomeRecordT(maxHtlcs)
121+
}
122+
if val, ok := typeMap[dc.ChannelType.TlvType()]; ok && val == nil {
123+
dc.ChannelType = tlv.SomeRecordT(chanType)
124+
}
125+
126+
if len(tlvRecords) != 0 {
127+
dc.ExtraData = tlvRecords
128+
}
129+
130+
return nil
131+
}
132+
133+
// MsgType returns the MessageType code which uniquely identifies this message
134+
// as a DynCommit on the wire.
135+
//
136+
// This is part of the lnwire.Message interface.
137+
func (dc *DynCommit) MsgType() MessageType {
138+
return MsgDynCommit
139+
}
140+
141+
// SerializedSize returns the serialized size of the message in bytes.
142+
//
143+
// This is part of the lnwire.SizeableMessage interface.
144+
func (dc *DynCommit) SerializedSize() (uint32, error) {
145+
return MessageSerializedSize(dc)
146+
}

0 commit comments

Comments
 (0)