• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

lightningnetwork / lnd / 13211764208

08 Feb 2025 03:08AM UTC coverage: 49.288% (-9.5%) from 58.815%
13211764208

Pull #9489

github

calvinrzachman
itest: verify switchrpc server enforces send then track

We prevent the rpc server from allowing onion dispatches for
attempt IDs which have already been tracked by rpc clients.

This helps protect the client from leaking a duplicate onion
attempt. NOTE: This is not the only method for solving this
issue! The issue could be addressed via careful client side
programming which accounts for the uncertainty and async
nature of dispatching onions to a remote process via RPC.
This would require some lnd ChannelRouter changes for how
we intend to use these RPCs though.
Pull Request #9489: multi: add BuildOnion, SendOnion, and TrackOnion RPCs

474 of 990 new or added lines in 11 files covered. (47.88%)

27321 existing lines in 435 files now uncovered.

101192 of 205306 relevant lines covered (49.29%)

1.54 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

0.0
/lnwire/dyn_ack.go
1
package lnwire
2

3
import (
4
        "bytes"
5
        "io"
6

7
        "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
8
        "github.com/lightningnetwork/lnd/fn/v2"
9
        "github.com/lightningnetwork/lnd/tlv"
10
)
11

12
const (
13
        // DALocalMusig2Pubnonce is the TLV type number that identifies the
14
        // musig2 public nonce that we need to verify the commitment transaction
15
        // signature.
16
        DALocalMusig2Pubnonce tlv.Type = 0
17
)
18

19
// DynAck is the message used to accept the parameters of a dynamic commitment
20
// negotiation. Additional optional parameters will need to be present depending
21
// on the details of the dynamic commitment upgrade.
22
type DynAck struct {
23
        // ChanID is the ChannelID of the channel that is currently undergoing
24
        // a dynamic commitment negotiation
25
        ChanID ChannelID
26

27
        // LocalNonce is an optional field that is transmitted when accepting
28
        // a dynamic commitment upgrade to Taproot Channels. This nonce will be
29
        // used to verify the first commitment transaction signature. This will
30
        // only be populated if the DynPropose we are responding to specifies
31
        // taproot channels in the ChannelType field.
32
        LocalNonce fn.Option[Musig2Nonce]
33

34
        // ExtraData is the set of data that was appended to this message to
35
        // fill out the full maximum transport message size. These fields can
36
        // be used to specify optional data such as custom TLV fields.
37
        ExtraData ExtraOpaqueData
38
}
39

40
// A compile time check to ensure DynAck implements the lnwire.Message
41
// interface.
42
var _ Message = (*DynAck)(nil)
43

44
// Encode serializes the target DynAck into the passed io.Writer. Serialization
45
// will observe the rules defined by the passed protocol version.
46
//
47
// This is a part of the lnwire.Message interface.
UNCOV
48
func (da *DynAck) Encode(w *bytes.Buffer, _ uint32) error {
×
UNCOV
49
        if err := WriteChannelID(w, da.ChanID); err != nil {
×
50
                return err
×
51
        }
×
52

UNCOV
53
        var tlvRecords []tlv.Record
×
UNCOV
54
        da.LocalNonce.WhenSome(func(nonce Musig2Nonce) {
×
UNCOV
55
                tlvRecords = append(
×
UNCOV
56
                        tlvRecords, tlv.MakeStaticRecord(
×
UNCOV
57
                                DALocalMusig2Pubnonce, &nonce,
×
UNCOV
58
                                musig2.PubNonceSize, nonceTypeEncoder,
×
UNCOV
59
                                nonceTypeDecoder,
×
UNCOV
60
                        ),
×
UNCOV
61
                )
×
UNCOV
62
        })
×
UNCOV
63
        tlv.SortRecords(tlvRecords)
×
UNCOV
64

×
UNCOV
65
        tlvStream, err := tlv.NewStream(tlvRecords...)
×
UNCOV
66
        if err != nil {
×
67
                return err
×
68
        }
×
69

UNCOV
70
        var extraBytesWriter bytes.Buffer
×
UNCOV
71
        if err := tlvStream.Encode(&extraBytesWriter); err != nil {
×
72
                return err
×
73
        }
×
74

UNCOV
75
        da.ExtraData = ExtraOpaqueData(extraBytesWriter.Bytes())
×
UNCOV
76

×
UNCOV
77
        return WriteBytes(w, da.ExtraData)
×
78
}
79

80
// Decode deserializes the serialized DynAck stored in the passed io.Reader into
81
// the target DynAck using the deserialization rules defined by the passed
82
// protocol version.
83
//
84
// This is a part of the lnwire.Message interface.
UNCOV
85
func (da *DynAck) Decode(r io.Reader, _ uint32) error {
×
UNCOV
86
        // Parse out main message.
×
UNCOV
87
        if err := ReadElements(r, &da.ChanID); err != nil {
×
UNCOV
88
                return err
×
UNCOV
89
        }
×
90

91
        // Parse out TLV records.
UNCOV
92
        var tlvRecords ExtraOpaqueData
×
UNCOV
93
        if err := ReadElement(r, &tlvRecords); err != nil {
×
94
                return err
×
95
        }
×
96

97
        // Prepare receiving buffers to be filled by TLV extraction.
UNCOV
98
        var localNonceScratch Musig2Nonce
×
UNCOV
99
        localNonce := tlv.MakeStaticRecord(
×
UNCOV
100
                DALocalMusig2Pubnonce, &localNonceScratch, musig2.PubNonceSize,
×
UNCOV
101
                nonceTypeEncoder, nonceTypeDecoder,
×
UNCOV
102
        )
×
UNCOV
103

×
UNCOV
104
        // Create set of Records to read TLV bytestream into.
×
UNCOV
105
        records := []tlv.Record{localNonce}
×
UNCOV
106
        tlv.SortRecords(records)
×
UNCOV
107

×
UNCOV
108
        // Read TLV stream into record set.
×
UNCOV
109
        extraBytesReader := bytes.NewReader(tlvRecords)
×
UNCOV
110
        tlvStream, err := tlv.NewStream(records...)
×
UNCOV
111
        if err != nil {
×
112
                return err
×
113
        }
×
UNCOV
114
        typeMap, err := tlvStream.DecodeWithParsedTypesP2P(extraBytesReader)
×
UNCOV
115
        if err != nil {
×
UNCOV
116
                return err
×
UNCOV
117
        }
×
118

119
        // Check the results of the TLV Stream decoding and appropriately set
120
        // message fields.
UNCOV
121
        if val, ok := typeMap[DALocalMusig2Pubnonce]; ok && val == nil {
×
UNCOV
122
                da.LocalNonce = fn.Some(localNonceScratch)
×
UNCOV
123
        }
×
124

UNCOV
125
        if len(tlvRecords) != 0 {
×
UNCOV
126
                da.ExtraData = tlvRecords
×
UNCOV
127
        }
×
128

UNCOV
129
        return nil
×
130
}
131

132
// MsgType returns the MessageType code which uniquely identifies this message
133
// as a DynAck on the wire.
134
//
135
// This is part of the lnwire.Message interface.
UNCOV
136
func (da *DynAck) MsgType() MessageType {
×
UNCOV
137
        return MsgDynAck
×
UNCOV
138
}
×
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc