• 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/channel_announcement_2.go
1
package lnwire
2

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

7
        "github.com/btcsuite/btcd/chaincfg"
8
        "github.com/btcsuite/btcd/chaincfg/chainhash"
9
        "github.com/lightningnetwork/lnd/tlv"
10
)
11

12
// ChannelAnnouncement2 message is used to announce the existence of a taproot
13
// channel between two peers in the network.
14
type ChannelAnnouncement2 struct {
15
        // Signature is a Schnorr signature over the TLV stream of the message.
16
        Signature Sig
17

18
        // ChainHash denotes the target chain that this channel was opened
19
        // within. This value should be the genesis hash of the target chain.
20
        ChainHash tlv.RecordT[tlv.TlvType0, chainhash.Hash]
21

22
        // Features is the feature vector that encodes the features supported
23
        // by the target node. This field can be used to signal the type of the
24
        // channel, or modifications to the fields that would normally follow
25
        // this vector.
26
        Features tlv.RecordT[tlv.TlvType2, RawFeatureVector]
27

28
        // ShortChannelID is the unique description of the funding transaction,
29
        // or where exactly it's located within the target blockchain.
30
        ShortChannelID tlv.RecordT[tlv.TlvType4, ShortChannelID]
31

32
        // Capacity is the number of satoshis of the capacity of this channel.
33
        // It must be less than or equal to the value of the on-chain funding
34
        // output.
35
        Capacity tlv.RecordT[tlv.TlvType6, uint64]
36

37
        // NodeID1 is the numerically-lesser public key ID of one of the channel
38
        // operators.
39
        NodeID1 tlv.RecordT[tlv.TlvType8, [33]byte]
40

41
        // NodeID2 is the numerically-greater public key ID of one of the
42
        // channel operators.
43
        NodeID2 tlv.RecordT[tlv.TlvType10, [33]byte]
44

45
        // BitcoinKey1 is the public key of the key used by Node1 in the
46
        // construction of the on-chain funding transaction. This is an optional
47
        // field and only needs to be set if the 4-of-4 MuSig construction was
48
        // used in the creation of the message signature.
49
        BitcoinKey1 tlv.OptionalRecordT[tlv.TlvType12, [33]byte]
50

51
        // BitcoinKey2 is the public key of the key used by Node2 in the
52
        // construction of the on-chain funding transaction. This is an optional
53
        // field and only needs to be set if the 4-of-4 MuSig construction was
54
        // used in the creation of the message signature.
55
        BitcoinKey2 tlv.OptionalRecordT[tlv.TlvType14, [33]byte]
56

57
        // MerkleRootHash is the hash used to create the optional tweak in the
58
        // funding output. If this is not set but the bitcoin keys are, then
59
        // the funding output is a pure 2-of-2 MuSig aggregate public key.
60
        MerkleRootHash tlv.OptionalRecordT[tlv.TlvType16, [32]byte]
61

62
        // ExtraOpaqueData is the set of data that was appended to this
63
        // message, some of which we may not actually know how to iterate or
64
        // parse. By holding onto this data, we ensure that we're able to
65
        // properly validate the set of signatures that cover these new fields,
66
        // and ensure we're able to make upgrades to the network in a forwards
67
        // compatible manner.
68
        ExtraOpaqueData ExtraOpaqueData
69
}
70

71
// Decode deserializes a serialized AnnounceSignatures1 stored in the passed
72
// io.Reader observing the specified protocol version.
73
//
74
// This is part of the lnwire.Message interface.
UNCOV
75
func (c *ChannelAnnouncement2) Decode(r io.Reader, _ uint32) error {
×
UNCOV
76
        err := ReadElement(r, &c.Signature)
×
UNCOV
77
        if err != nil {
×
UNCOV
78
                return err
×
UNCOV
79
        }
×
UNCOV
80
        c.Signature.ForceSchnorr()
×
UNCOV
81

×
UNCOV
82
        return c.DecodeTLVRecords(r)
×
83
}
84

85
// DecodeTLVRecords decodes only the TLV section of the message.
UNCOV
86
func (c *ChannelAnnouncement2) DecodeTLVRecords(r io.Reader) error {
×
UNCOV
87
        // First extract into extra opaque data.
×
UNCOV
88
        var tlvRecords ExtraOpaqueData
×
UNCOV
89
        if err := ReadElements(r, &tlvRecords); err != nil {
×
90
                return err
×
91
        }
×
92

UNCOV
93
        var (
×
UNCOV
94
                chainHash      = tlv.ZeroRecordT[tlv.TlvType0, [32]byte]()
×
UNCOV
95
                btcKey1        = tlv.ZeroRecordT[tlv.TlvType12, [33]byte]()
×
UNCOV
96
                btcKey2        = tlv.ZeroRecordT[tlv.TlvType14, [33]byte]()
×
UNCOV
97
                merkleRootHash = tlv.ZeroRecordT[tlv.TlvType16, [32]byte]()
×
UNCOV
98
        )
×
UNCOV
99
        typeMap, err := tlvRecords.ExtractRecords(
×
UNCOV
100
                &chainHash, &c.Features, &c.ShortChannelID, &c.Capacity,
×
UNCOV
101
                &c.NodeID1, &c.NodeID2, &btcKey1, &btcKey2, &merkleRootHash,
×
UNCOV
102
        )
×
UNCOV
103
        if err != nil {
×
UNCOV
104
                return err
×
UNCOV
105
        }
×
106

107
        // By default, the chain-hash is the bitcoin mainnet genesis block hash.
UNCOV
108
        c.ChainHash.Val = *chaincfg.MainNetParams.GenesisHash
×
UNCOV
109
        if _, ok := typeMap[c.ChainHash.TlvType()]; ok {
×
UNCOV
110
                c.ChainHash.Val = chainHash.Val
×
UNCOV
111
        }
×
112

UNCOV
113
        if _, ok := typeMap[c.BitcoinKey1.TlvType()]; ok {
×
UNCOV
114
                c.BitcoinKey1 = tlv.SomeRecordT(btcKey1)
×
UNCOV
115
        }
×
116

UNCOV
117
        if _, ok := typeMap[c.BitcoinKey2.TlvType()]; ok {
×
UNCOV
118
                c.BitcoinKey2 = tlv.SomeRecordT(btcKey2)
×
UNCOV
119
        }
×
120

UNCOV
121
        if _, ok := typeMap[c.MerkleRootHash.TlvType()]; ok {
×
UNCOV
122
                c.MerkleRootHash = tlv.SomeRecordT(merkleRootHash)
×
UNCOV
123
        }
×
124

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

UNCOV
129
        return nil
×
130
}
131

132
// Encode serializes the target AnnounceSignatures1 into the passed io.Writer
133
// observing the protocol version specified.
134
//
135
// This is part of the lnwire.Message interface.
UNCOV
136
func (c *ChannelAnnouncement2) Encode(w *bytes.Buffer, _ uint32) error {
×
UNCOV
137
        _, err := w.Write(c.Signature.RawBytes())
×
UNCOV
138
        if err != nil {
×
139
                return err
×
140
        }
×
UNCOV
141
        _, err = c.DataToSign()
×
UNCOV
142
        if err != nil {
×
143
                return err
×
144
        }
×
145

UNCOV
146
        return WriteBytes(w, c.ExtraOpaqueData)
×
147
}
148

149
// DataToSign encodes the data to be signed into the ExtraOpaqueData member and
150
// returns it.
UNCOV
151
func (c *ChannelAnnouncement2) DataToSign() ([]byte, error) {
×
UNCOV
152
        // The chain-hash record is only included if it is _not_ equal to the
×
UNCOV
153
        // bitcoin mainnet genisis block hash.
×
UNCOV
154
        var recordProducers []tlv.RecordProducer
×
UNCOV
155
        if !c.ChainHash.Val.IsEqual(chaincfg.MainNetParams.GenesisHash) {
×
UNCOV
156
                hash := tlv.ZeroRecordT[tlv.TlvType0, [32]byte]()
×
UNCOV
157
                hash.Val = c.ChainHash.Val
×
UNCOV
158

×
UNCOV
159
                recordProducers = append(recordProducers, &hash)
×
UNCOV
160
        }
×
161

UNCOV
162
        recordProducers = append(recordProducers,
×
UNCOV
163
                &c.Features, &c.ShortChannelID, &c.Capacity, &c.NodeID1,
×
UNCOV
164
                &c.NodeID2,
×
UNCOV
165
        )
×
UNCOV
166

×
UNCOV
167
        c.BitcoinKey1.WhenSome(func(key tlv.RecordT[tlv.TlvType12, [33]byte]) {
×
UNCOV
168
                recordProducers = append(recordProducers, &key)
×
UNCOV
169
        })
×
170

UNCOV
171
        c.BitcoinKey2.WhenSome(func(key tlv.RecordT[tlv.TlvType14, [33]byte]) {
×
UNCOV
172
                recordProducers = append(recordProducers, &key)
×
UNCOV
173
        })
×
174

UNCOV
175
        c.MerkleRootHash.WhenSome(
×
UNCOV
176
                func(hash tlv.RecordT[tlv.TlvType16, [32]byte]) {
×
UNCOV
177
                        recordProducers = append(recordProducers, &hash)
×
UNCOV
178
                },
×
179
        )
180

UNCOV
181
        err := EncodeMessageExtraData(&c.ExtraOpaqueData, recordProducers...)
×
UNCOV
182
        if err != nil {
×
183
                return nil, err
×
184
        }
×
185

UNCOV
186
        return c.ExtraOpaqueData, nil
×
187
}
188

189
// MsgType returns the integer uniquely identifying this message type on the
190
// wire.
191
//
192
// This is part of the lnwire.Message interface.
UNCOV
193
func (c *ChannelAnnouncement2) MsgType() MessageType {
×
UNCOV
194
        return MsgChannelAnnouncement2
×
UNCOV
195
}
×
196

197
// A compile time check to ensure ChannelAnnouncement2 implements the
198
// lnwire.Message interface.
199
var _ Message = (*ChannelAnnouncement2)(nil)
200

201
// Node1KeyBytes returns the bytes representing the public key of node 1 in the
202
// channel.
203
//
204
// NOTE: This is part of the ChannelAnnouncement interface.
205
func (c *ChannelAnnouncement2) Node1KeyBytes() [33]byte {
×
206
        return c.NodeID1.Val
×
207
}
×
208

209
// Node2KeyBytes returns the bytes representing the public key of node 2 in the
210
// channel.
211
//
212
// NOTE: This is part of the ChannelAnnouncement interface.
213
func (c *ChannelAnnouncement2) Node2KeyBytes() [33]byte {
×
214
        return c.NodeID2.Val
×
215
}
×
216

217
// GetChainHash returns the hash of the chain which this channel's funding
218
// transaction is confirmed in.
219
//
220
// NOTE: This is part of the ChannelAnnouncement interface.
221
func (c *ChannelAnnouncement2) GetChainHash() chainhash.Hash {
×
222
        return c.ChainHash.Val
×
223
}
×
224

225
// SCID returns the short channel ID of the channel.
226
//
227
// NOTE: This is part of the ChannelAnnouncement interface.
228
func (c *ChannelAnnouncement2) SCID() ShortChannelID {
×
229
        return c.ShortChannelID.Val
×
230
}
×
231

232
// A compile-time check to ensure that ChannelAnnouncement2 implements the
233
// ChannelAnnouncement interface.
234
var _ ChannelAnnouncement = (*ChannelAnnouncement2)(nil)
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