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

lightningnetwork / lnd / 13035292482

29 Jan 2025 03:59PM UTC coverage: 49.3% (-9.5%) from 58.777%
13035292482

Pull #9456

github

mohamedawnallah
docs: update release-notes-0.19.0.md

In this commit, we warn users about the removal
of RPCs `SendToRoute`, `SendToRouteSync`, `SendPayment`,
and `SendPaymentSync` in the next release 0.20.
Pull Request #9456: lnrpc+docs: deprecate warning `SendToRoute`, `SendToRouteSync`, `SendPayment`, and `SendPaymentSync` in Release 0.19

100634 of 204126 relevant lines covered (49.3%)

1.54 hits per line

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

78.23
/lnwallet/chanfunding/canned_assembler.go
1
package chanfunding
2

3
import (
4
        "fmt"
5

6
        "github.com/btcsuite/btcd/btcec/v2"
7
        "github.com/btcsuite/btcd/btcec/v2/schnorr/musig2"
8
        "github.com/btcsuite/btcd/btcutil"
9
        "github.com/btcsuite/btcd/chaincfg/chainhash"
10
        "github.com/btcsuite/btcd/wire"
11
        "github.com/lightningnetwork/lnd/fn/v2"
12
        "github.com/lightningnetwork/lnd/input"
13
        "github.com/lightningnetwork/lnd/keychain"
14
)
15

16
// NewShimIntent creates a new ShimIntent. This is only used for testing.
17
func NewShimIntent(localAmt, remoteAmt btcutil.Amount,
18
        localKey *keychain.KeyDescriptor, remoteKey *btcec.PublicKey,
19
        chanPoint *wire.OutPoint, thawHeight uint32, musig2 bool) *ShimIntent {
×
20

×
21
        return &ShimIntent{
×
22
                localFundingAmt:  localAmt,
×
23
                remoteFundingAmt: remoteAmt,
×
24
                localKey:         localKey,
×
25
                remoteKey:        remoteKey,
×
26
                chanPoint:        chanPoint,
×
27
                thawHeight:       thawHeight,
×
28
                musig2:           musig2,
×
29
        }
×
30
}
×
31

32
// ShimIntent is an intent created by the CannedAssembler which represents a
33
// funding output to be created that was constructed outside the wallet. This
34
// might be used when a hardware wallet, or a channel factory is the entity
35
// crafting the funding transaction, and not lnd.
36
type ShimIntent struct {
37
        // localFundingAmt is the final amount we put into the funding output.
38
        localFundingAmt btcutil.Amount
39

40
        // remoteFundingAmt is the final amount the remote party put into the
41
        // funding output.
42
        remoteFundingAmt btcutil.Amount
43

44
        // localKey is our multi-sig key.
45
        localKey *keychain.KeyDescriptor
46

47
        // remoteKey is the remote party's multi-sig key.
48
        remoteKey *btcec.PublicKey
49

50
        // chanPoint is the final channel point for the to be created channel.
51
        chanPoint *wire.OutPoint
52

53
        // thawHeight, if non-zero is the height where this channel will become
54
        // a normal channel. Until this height, it's considered frozen, so it
55
        // can only be cooperatively closed by the responding party.
56
        thawHeight uint32
57

58
        // musig2 determines if the funding output should use musig2 to
59
        // generate an aggregate key to use as the taproot-native multi-sig
60
        // output.
61
        musig2 bool
62

63
        // tapscriptRoot is the root of the tapscript tree that will be used to
64
        // create the funding output. This field will only be utilized if the
65
        // MuSig2 flag above is set to true.
66
        //
67
        // TODO(roasbeef): fold above into new chan type? sum type like thing,
68
        // includes the tapscript root, etc
69
        tapscriptRoot fn.Option[chainhash.Hash]
70
}
71

72
// FundingOutput returns the witness script, and the output that creates the
73
// funding output.
74
//
75
// NOTE: This method satisfies the chanfunding.Intent interface.
76
func (s *ShimIntent) FundingOutput() ([]byte, *wire.TxOut, error) {
3✔
77
        if s.localKey == nil || s.remoteKey == nil {
6✔
78
                return nil, nil, fmt.Errorf("unable to create witness " +
3✔
79
                        "script, no funding keys")
3✔
80
        }
3✔
81

82
        totalAmt := s.localFundingAmt + s.remoteFundingAmt
3✔
83

3✔
84
        // If musig2 is active, then we'll return a single aggregated key
3✔
85
        // rather than using the "existing" funding script.
3✔
86
        if s.musig2 {
6✔
87
                // Similar to the existing p2wsh script, we'll always ensure
3✔
88
                // the keys are sorted before use.
3✔
89
                return input.GenTaprootFundingScript(
3✔
90
                        s.localKey.PubKey, s.remoteKey, int64(totalAmt),
3✔
91
                        s.tapscriptRoot,
3✔
92
                )
3✔
93
        }
3✔
94

95
        return input.GenFundingPkScript(
3✔
96
                s.localKey.PubKey.SerializeCompressed(),
3✔
97
                s.remoteKey.SerializeCompressed(),
3✔
98
                int64(totalAmt),
3✔
99
        )
3✔
100
}
101

102
// TaprootInternalKey may return the internal key for a MuSig2 funding output,
103
// but only if this is actually a MuSig2 channel.
104
func (s *ShimIntent) TaprootInternalKey() fn.Option[*btcec.PublicKey] {
3✔
105
        if !s.musig2 {
6✔
106
                return fn.None[*btcec.PublicKey]()
3✔
107
        }
3✔
108

109
        // Similar to the existing p2wsh script, we'll always ensure the keys
110
        // are sorted before use. Since we're only interested in the internal
111
        // key, we don't need to take into account any tapscript root.
112
        //
113
        // We ignore the error here as this is only called after FundingOutput
114
        // is called.
115
        combinedKey, _, _, _ := musig2.AggregateKeys(
3✔
116
                []*btcec.PublicKey{s.localKey.PubKey, s.remoteKey}, true,
3✔
117
        )
3✔
118

3✔
119
        return fn.Some(combinedKey.PreTweakedKey)
3✔
120
}
121

122
// Cancel allows the caller to cancel a funding Intent at any time.  This will
123
// return any resources such as coins back to the eligible pool to be used in
124
// order channel fundings.
125
//
126
// NOTE: This method satisfies the chanfunding.Intent interface.
127
func (s *ShimIntent) Cancel() {
3✔
128
}
3✔
129

130
// LocalFundingAmt is the amount we put into the channel. This may differ from
131
// the local amount requested, as depending on coin selection, we may bleed
132
// from of that LocalAmt into fees to minimize change.
133
//
134
// NOTE: This method satisfies the chanfunding.Intent interface.
135
func (s *ShimIntent) LocalFundingAmt() btcutil.Amount {
3✔
136
        return s.localFundingAmt
3✔
137
}
3✔
138

139
// RemoteFundingAmt is the amount the remote party put into the channel.
140
//
141
// NOTE: This method satisfies the chanfunding.Intent interface.
142
func (s *ShimIntent) RemoteFundingAmt() btcutil.Amount {
3✔
143
        return s.remoteFundingAmt
3✔
144
}
3✔
145

146
// ChanPoint returns the final outpoint that will create the funding output
147
// described above.
148
//
149
// NOTE: This method satisfies the chanfunding.Intent interface.
150
func (s *ShimIntent) ChanPoint() (*wire.OutPoint, error) {
3✔
151
        if s.chanPoint == nil {
3✔
152
                return nil, fmt.Errorf("chan point unknown, funding output " +
×
153
                        "not constructed")
×
154
        }
×
155

156
        return s.chanPoint, nil
3✔
157
}
158

159
// ThawHeight returns the height where this channel goes back to being a normal
160
// channel.
161
func (s *ShimIntent) ThawHeight() uint32 {
3✔
162
        return s.thawHeight
3✔
163
}
3✔
164

165
// Inputs returns all inputs to the final funding transaction that we
166
// know about. For the ShimIntent this will always be none, since it is funded
167
// externally.
168
func (s *ShimIntent) Inputs() []wire.OutPoint {
3✔
169
        return nil
3✔
170
}
3✔
171

172
// Outputs returns all outputs of the final funding transaction that we
173
// know about. Since this is an externally funded channel, the channel output
174
// is the only known one.
175
func (s *ShimIntent) Outputs() []*wire.TxOut {
3✔
176
        _, txOut, err := s.FundingOutput()
3✔
177
        if err != nil {
6✔
178
                log.Warnf("Unable to find funding output for shim intent: %v",
3✔
179
                        err)
3✔
180

3✔
181
                // Failed finding funding output, return empty list of known
3✔
182
                // outputs.
3✔
183
                return nil
3✔
184
        }
3✔
185

186
        return []*wire.TxOut{txOut}
3✔
187
}
188

189
// FundingKeys couples our multi-sig key along with the remote party's key.
190
type FundingKeys struct {
191
        // LocalKey is our multi-sig key.
192
        LocalKey *keychain.KeyDescriptor
193

194
        // RemoteKey is the multi-sig key of the remote party.
195
        RemoteKey *btcec.PublicKey
196
}
197

198
// MultiSigKeys returns the committed multi-sig keys, but only if they've been
199
// specified/provided.
200
func (s *ShimIntent) MultiSigKeys() (*FundingKeys, error) {
3✔
201
        if s.localKey == nil || s.remoteKey == nil {
3✔
202
                return nil, fmt.Errorf("unknown funding keys")
×
203
        }
×
204

205
        return &FundingKeys{
3✔
206
                LocalKey:  s.localKey,
3✔
207
                RemoteKey: s.remoteKey,
3✔
208
        }, nil
3✔
209
}
210

211
// A compile-time check to ensure ShimIntent adheres to the Intent interface.
212
var _ Intent = (*ShimIntent)(nil)
213

214
// CannedAssembler is a type of chanfunding.Assembler wherein the funding
215
// transaction is constructed outside of lnd, and may already exist. This
216
// Assembler serves as a shim which gives the funding flow the only thing it
217
// actually needs to proceed: the channel point.
218
type CannedAssembler struct {
219
        // fundingAmt is the total amount of coins in the funding output.
220
        fundingAmt btcutil.Amount
221

222
        // localKey is our multi-sig key.
223
        localKey *keychain.KeyDescriptor
224

225
        // remoteKey is the remote party's multi-sig key.
226
        remoteKey *btcec.PublicKey
227

228
        // chanPoint is the final channel point for the to be created channel.
229
        chanPoint wire.OutPoint
230

231
        // initiator indicates if we're the initiator or the channel or not.
232
        initiator bool
233

234
        // thawHeight, if non-zero is the height where this channel will become
235
        // a normal channel. Until this height, it's considered frozen, so it
236
        // can only be cooperatively closed by the responding party.
237
        thawHeight uint32
238

239
        // musig2 determines if the funding output should use musig2 to
240
        // generate an aggregate key to use as the taproot-native multi-sig
241
        // output.
242
        musig2 bool
243
}
244

245
// NewCannedAssembler creates a new CannedAssembler from the material required
246
// to construct a funding output and channel point.
247
//
248
// TODO(roasbeef): pass in chan type instead?
249
func NewCannedAssembler(thawHeight uint32, chanPoint wire.OutPoint,
250
        fundingAmt btcutil.Amount, localKey *keychain.KeyDescriptor,
251
        remoteKey *btcec.PublicKey, initiator, musig2 bool) *CannedAssembler {
3✔
252

3✔
253
        return &CannedAssembler{
3✔
254
                initiator:  initiator,
3✔
255
                localKey:   localKey,
3✔
256
                remoteKey:  remoteKey,
3✔
257
                fundingAmt: fundingAmt,
3✔
258
                chanPoint:  chanPoint,
3✔
259
                thawHeight: thawHeight,
3✔
260
                musig2:     musig2,
3✔
261
        }
3✔
262
}
3✔
263

264
// ProvisionChannel creates a new ShimIntent given the passed funding Request.
265
// The returned intent is immediately able to provide the channel point and
266
// funding output as they've already been created outside lnd.
267
//
268
// NOTE: This method satisfies the chanfunding.Assembler interface.
269
func (c *CannedAssembler) ProvisionChannel(req *Request) (Intent, error) {
3✔
270
        // We'll exit out if SubtractFees is set as the funding transaction has
3✔
271
        // already been assembled, so we don't influence coin selection.
3✔
272
        if req.SubtractFees {
3✔
273
                return nil, fmt.Errorf("SubtractFees ignored, funding " +
×
274
                        "transaction is frozen")
×
275
        }
×
276

277
        // We'll exit out if FundUpToMaxAmt or MinFundAmt is set as the funding
278
        // transaction has already been assembled, so we don't influence coin
279
        // selection.
280
        if req.FundUpToMaxAmt != 0 || req.MinFundAmt != 0 {
3✔
281
                return nil, fmt.Errorf("FundUpToMaxAmt and MinFundAmt " +
×
282
                        "ignored, funding transaction is frozen")
×
283
        }
×
284

285
        intent := &ShimIntent{
3✔
286
                localKey:   c.localKey,
3✔
287
                remoteKey:  c.remoteKey,
3✔
288
                chanPoint:  &c.chanPoint,
3✔
289
                thawHeight: c.thawHeight,
3✔
290
                musig2:     c.musig2,
3✔
291
        }
3✔
292

3✔
293
        if c.initiator {
6✔
294
                intent.localFundingAmt = c.fundingAmt
3✔
295
        } else {
6✔
296
                intent.remoteFundingAmt = c.fundingAmt
3✔
297
        }
3✔
298

299
        // A simple sanity check to ensure the provisioned request matches the
300
        // re-made shim intent.
301
        if req.LocalAmt+req.RemoteAmt != c.fundingAmt {
3✔
302
                return nil, fmt.Errorf("intent doesn't match canned "+
×
303
                        "assembler: local_amt=%v, remote_amt=%v, funding_amt=%v",
×
304
                        req.LocalAmt, req.RemoteAmt, c.fundingAmt)
×
305
        }
×
306

307
        return intent, nil
3✔
308
}
309

310
// A compile-time assertion to ensure CannedAssembler meets the Assembler
311
// interface.
312
var _ Assembler = (*CannedAssembler)(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