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

lightningnetwork / lnd / 11216766535

07 Oct 2024 01:37PM UTC coverage: 57.817% (-1.0%) from 58.817%
11216766535

Pull #9148

github

ProofOfKeags
lnwire: remove kickoff feerate from propose/commit
Pull Request #9148: DynComms [2/n]: lnwire: add authenticated wire messages for Dyn*

571 of 879 new or added lines in 16 files covered. (64.96%)

23253 existing lines in 251 files now uncovered.

99022 of 171268 relevant lines covered (57.82%)

38420.67 hits per line

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

50.0
/lnwallet/interface.go
1
package lnwallet
2

3
import (
4
        "errors"
5
        "fmt"
6
        "sync"
7
        "time"
8

9
        "github.com/btcsuite/btcd/btcec/v2"
10
        "github.com/btcsuite/btcd/btcec/v2/ecdsa"
11
        "github.com/btcsuite/btcd/btcutil"
12
        "github.com/btcsuite/btcd/btcutil/hdkeychain"
13
        "github.com/btcsuite/btcd/btcutil/psbt"
14
        "github.com/btcsuite/btcd/chaincfg/chainhash"
15
        "github.com/btcsuite/btcd/txscript"
16
        "github.com/btcsuite/btcd/wire"
17
        "github.com/btcsuite/btcwallet/waddrmgr"
18
        base "github.com/btcsuite/btcwallet/wallet"
19
        "github.com/btcsuite/btcwallet/wallet/txauthor"
20
        "github.com/btcsuite/btcwallet/wtxmgr"
21
        "github.com/lightningnetwork/lnd/fn"
22
        "github.com/lightningnetwork/lnd/keychain"
23
        "github.com/lightningnetwork/lnd/lnwallet/chainfee"
24
        "github.com/lightningnetwork/lnd/lnwallet/chanvalidate"
25
        "github.com/lightningnetwork/lnd/lnwire"
26
)
27

28
const (
29
        // DefaultAccountName is the name for the default account used to manage
30
        // on-chain funds within the wallet.
31
        DefaultAccountName = "default"
32
)
33

34
// AddressType is an enum-like type which denotes the possible address types
35
// WalletController supports.
36
type AddressType uint8
37

38
// AccountAddressMap maps the account properties to an array of
39
// address properties.
40
type AccountAddressMap map[*waddrmgr.AccountProperties][]AddressProperty
41

42
const (
43
        // UnknownAddressType represents an output with an unknown or non-standard
44
        // script.
45
        UnknownAddressType AddressType = iota
46

47
        // WitnessPubKey represents a p2wkh address.
48
        WitnessPubKey
49

50
        // NestedWitnessPubKey represents a p2sh output which is itself a
51
        // nested p2wkh output.
52
        NestedWitnessPubKey
53

54
        // TaprootPubkey represents a p2tr key path spending address.
55
        TaprootPubkey
56
)
57

58
var (
59
        // DefaultPublicPassphrase is the default public passphrase used for the
60
        // wallet.
61
        DefaultPublicPassphrase = []byte("public")
62

63
        // DefaultPrivatePassphrase is the default private passphrase used for
64
        // the wallet.
65
        DefaultPrivatePassphrase = []byte("hello")
66

67
        // ErrDoubleSpend is returned from PublishTransaction in case the
68
        // tx being published is spending an output spent by a conflicting
69
        // transaction.
70
        ErrDoubleSpend = errors.New("transaction rejected: output already spent")
71

72
        // ErrNotMine is an error denoting that a WalletController instance is
73
        // unable to spend a specified output.
74
        ErrNotMine = errors.New("the passed output doesn't belong to the wallet")
75

76
        // ErrMempoolFee is returned from PublishTransaction in case the tx
77
        // being published is not accepted into mempool because the fee
78
        // requirements of the mempool backend are not met.
79
        ErrMempoolFee = errors.New("transaction rejected by the mempool " +
80
                "because of low fees")
81
)
82

83
// ErrNoOutputs is returned if we try to create a transaction with no outputs
84
// or send coins to a set of outputs that is empty.
85
var ErrNoOutputs = errors.New("no outputs")
86

87
// ErrInvalidMinconf is returned if we try to create a transaction with
88
// invalid minConfs value.
89
var ErrInvalidMinconf = errors.New("minimum number of confirmations must " +
90
        "be a non-negative number")
91

92
// AddressProperty contains wallet related information of an address.
93
type AddressProperty struct {
94
        // Address is the address of an account.
95
        Address string
96

97
        // Internal denotes if the address is a change address.
98
        Internal bool
99

100
        // Balance returns the total balance of an address.
101
        Balance btcutil.Amount
102

103
        // DerivationPath is the derivation path of the address.
104
        DerivationPath string
105

106
        // PublicKey is the public key of the address.
107
        PublicKey *btcec.PublicKey
108
}
109

110
// AccountIdentifier contains information to uniquely identify an account.
111
type AccountIdentifier struct {
112
        // Name is the name of the account.
113
        Name string
114

115
        // AddressType is the type of addresses supported by the account.
116
        AddressType AddressType
117

118
        // DerivationPath is the derivation path corresponding to the account
119
        // public key.
120
        DerivationPath string
121
}
122

123
// Utxo is an unspent output denoted by its outpoint, and output value of the
124
// original output.
125
type Utxo struct {
126
        AddressType   AddressType
127
        Value         btcutil.Amount
128
        Confirmations int64
129
        PkScript      []byte
130
        wire.OutPoint
131
        PrevTx *wire.MsgTx
132
}
133

134
// OutputDetail contains additional information on a destination address.
135
type OutputDetail struct {
136
        OutputType   txscript.ScriptClass
137
        Addresses    []btcutil.Address
138
        PkScript     []byte
139
        OutputIndex  int
140
        Value        btcutil.Amount
141
        IsOurAddress bool
142
}
143

144
// PreviousOutPoint contains information about the previous outpoint.
145
type PreviousOutPoint struct {
146
        // OutPoint is the transaction out point in the format txid:n.
147
        OutPoint string
148

149
        // IsOurOutput denotes if the previous output is controlled by the
150
        // internal wallet. The flag will only detect p2wkh, np2wkh and p2tr
151
        // inputs as its own.
152
        IsOurOutput bool
153
}
154

155
// TransactionDetail describes a transaction with either inputs which belong to
156
// the wallet, or has outputs that pay to the wallet.
157
type TransactionDetail struct {
158
        // Hash is the transaction hash of the transaction.
159
        Hash chainhash.Hash
160

161
        // Value is the net value of this transaction (in satoshis) from the
162
        // PoV of the wallet. If this transaction purely spends from the
163
        // wallet's funds, then this value will be negative. Similarly, if this
164
        // transaction credits the wallet, then this value will be positive.
165
        Value btcutil.Amount
166

167
        // NumConfirmations is the number of confirmations this transaction
168
        // has. If the transaction is unconfirmed, then this value will be
169
        // zero.
170
        NumConfirmations int32
171

172
        // BlockHeight is the hash of the block which includes this
173
        // transaction. Unconfirmed transactions will have a nil value for this
174
        // field.
175
        BlockHash *chainhash.Hash
176

177
        // BlockHeight is the height of the block including this transaction.
178
        // Unconfirmed transaction will show a height of zero.
179
        BlockHeight int32
180

181
        // Timestamp is the unix timestamp of the block including this
182
        // transaction. If the transaction is unconfirmed, then this will be a
183
        // timestamp of txn creation.
184
        Timestamp int64
185

186
        // TotalFees is the total fee in satoshis paid by this transaction.
187
        TotalFees int64
188

189
        // OutputDetails contains output data for each destination address, such
190
        // as the output script and amount.
191
        OutputDetails []OutputDetail
192

193
        // RawTx returns the raw serialized transaction.
194
        RawTx []byte
195

196
        // Label is an optional transaction label.
197
        Label string
198

199
        // PreviousOutpoints are the inputs for a transaction.
200
        PreviousOutpoints []PreviousOutPoint
201
}
202

203
// TransactionSubscription is an interface which describes an object capable of
204
// receiving notifications of new transaction related to the underlying wallet.
205
// TODO(roasbeef): add balance updates?
206
type TransactionSubscription interface {
207
        // ConfirmedTransactions returns a channel which will be sent on as new
208
        // relevant transactions are confirmed.
209
        ConfirmedTransactions() chan *TransactionDetail
210

211
        // UnconfirmedTransactions returns a channel which will be sent on as
212
        // new relevant transactions are seen within the network.
213
        UnconfirmedTransactions() chan *TransactionDetail
214

215
        // Cancel finalizes the subscription, cleaning up any resources
216
        // allocated.
217
        Cancel()
218
}
219

220
// WalletController defines an abstract interface for controlling a local Pure
221
// Go wallet, a local or remote wallet via an RPC mechanism, or possibly even
222
// a daemon assisted hardware wallet. This interface serves the purpose of
223
// allowing LightningWallet to be seamlessly compatible with several wallets
224
// such as: uspv, btcwallet, Bitcoin Core, Electrum, etc. This interface then
225
// serves as a "base wallet", with Lightning Network awareness taking place at
226
// a "higher" level of abstraction. Essentially, an overlay wallet.
227
// Implementors of this interface must closely adhere to the documented
228
// behavior of all interface methods in order to ensure identical behavior
229
// across all concrete implementations.
230
type WalletController interface {
231
        // FetchOutpointInfo queries for the WalletController's knowledge of
232
        // the passed outpoint. If the base wallet determines this output is
233
        // under its control, then the original txout should be returned.
234
        // Otherwise, a non-nil error value of ErrNotMine should be returned
235
        // instead.
236
        FetchOutpointInfo(prevOut *wire.OutPoint) (*Utxo, error)
237

238
        // FetchDerivationInfo queries for the wallet's knowledge of the passed
239
        // pkScript and constructs the derivation info and returns it.
240
        FetchDerivationInfo(pkScript []byte) (*psbt.Bip32Derivation, error)
241

242
        // ScriptForOutput returns the address, witness program and redeem
243
        // script for a given UTXO. An error is returned if the UTXO does not
244
        // belong to our wallet or it is not a managed pubKey address.
245
        ScriptForOutput(output *wire.TxOut) (waddrmgr.ManagedPubKeyAddress,
246
                []byte, []byte, error)
247

248
        // ConfirmedBalance returns the sum of all the wallet's unspent outputs
249
        // that have at least confs confirmations. If confs is set to zero,
250
        // then all unspent outputs, including those currently in the mempool
251
        // will be included in the final sum. The account parameter serves as a
252
        // filter to retrieve the balance for a specific account. When empty,
253
        // the confirmed balance of all wallet accounts is returned.
254
        //
255
        // NOTE: Only witness outputs should be included in the computation of
256
        // the total spendable balance of the wallet. We require this as only
257
        // witness inputs can be used for funding channels.
258
        ConfirmedBalance(confs int32, accountFilter string) (btcutil.Amount,
259
                error)
260

261
        // NewAddress returns the next external or internal address for the
262
        // wallet dictated by the value of the `change` parameter. If change is
263
        // true, then an internal address should be used, otherwise an external
264
        // address should be returned. The type of address returned is dictated
265
        // by the wallet's capabilities, and may be of type: p2sh, p2wkh,
266
        // p2wsh, etc. The account parameter must be non-empty as it determines
267
        // which account the address should be generated from.
268
        NewAddress(addrType AddressType, change bool,
269
                account string) (btcutil.Address, error)
270

271
        // LastUnusedAddress returns the last *unused* address known by the
272
        // wallet. An address is unused if it hasn't received any payments.
273
        // This can be useful in UIs in order to continually show the
274
        // "freshest" address without having to worry about "address inflation"
275
        // caused by continual refreshing. Similar to NewAddress it can derive
276
        // a specified address type. By default, this is a non-change address.
277
        // The account parameter must be non-empty as it determines which
278
        // account the address should be generated from.
279
        LastUnusedAddress(addrType AddressType,
280
                account string) (btcutil.Address, error)
281

282
        // IsOurAddress checks if the passed address belongs to this wallet
283
        IsOurAddress(a btcutil.Address) bool
284

285
        // AddressInfo returns the information about an address, if it's known
286
        // to this wallet.
287
        AddressInfo(a btcutil.Address) (waddrmgr.ManagedAddress, error)
288

289
        // ListAccounts retrieves all accounts belonging to the wallet by
290
        // default. A name and key scope filter can be provided to filter
291
        // through all of the wallet accounts and return only those matching.
292
        ListAccounts(string, *waddrmgr.KeyScope) ([]*waddrmgr.AccountProperties,
293
                error)
294

295
        // RequiredReserve returns the minimum amount of satoshis that should be
296
        // kept in the wallet in order to fee bump anchor channels if necessary.
297
        // The value scales with the number of public anchor channels but is
298
        // capped at a maximum.
299
        RequiredReserve(uint32) btcutil.Amount
300

301
        // ListAddresses retrieves all the addresses along with their balance. An
302
        // account name filter can be provided to filter through all of the
303
        // wallet accounts and return the addresses of only those matching.
304
        ListAddresses(string, bool) (AccountAddressMap, error)
305

306
        // ImportAccount imports an account backed by an account extended public
307
        // key. The master key fingerprint denotes the fingerprint of the root
308
        // key corresponding to the account public key (also known as the key
309
        // with derivation path m/). This may be required by some hardware
310
        // wallets for proper identification and signing.
311
        //
312
        // The address type can usually be inferred from the key's version, but
313
        // may be required for certain keys to map them into the proper scope.
314
        //
315
        // For BIP-0044 keys, an address type must be specified as we intend to
316
        // not support importing BIP-0044 keys into the wallet using the legacy
317
        // pay-to-pubkey-hash (P2PKH) scheme. A nested witness address type will
318
        // force the standard BIP-0049 derivation scheme, while a witness
319
        // address type will force the standard BIP-0084 derivation scheme.
320
        //
321
        // For BIP-0049 keys, an address type must also be specified to make a
322
        // distinction between the standard BIP-0049 address schema (nested
323
        // witness pubkeys everywhere) and our own BIP-0049Plus address schema
324
        // (nested pubkeys externally, witness pubkeys internally).
325
        ImportAccount(name string, accountPubKey *hdkeychain.ExtendedKey,
326
                masterKeyFingerprint uint32, addrType *waddrmgr.AddressType,
327
                dryRun bool) (*waddrmgr.AccountProperties, []btcutil.Address,
328
                []btcutil.Address, error)
329

330
        // ImportPublicKey imports a single derived public key into the wallet.
331
        // The address type can usually be inferred from the key's version, but
332
        // in the case of legacy versions (xpub, tpub), an address type must be
333
        // specified as we intend to not support importing BIP-44 keys into the
334
        // wallet using the legacy pay-to-pubkey-hash (P2PKH) scheme.
335
        ImportPublicKey(pubKey *btcec.PublicKey,
336
                addrType waddrmgr.AddressType) error
337

338
        // ImportTaprootScript imports a user-provided taproot script into the
339
        // wallet. The imported script will act as a pay-to-taproot address.
340
        //
341
        // NOTE: Taproot keys imported through this RPC currently _cannot_ be
342
        // used for funding PSBTs. Only tracking the balance and UTXOs is
343
        // currently supported.
344
        ImportTaprootScript(scope waddrmgr.KeyScope,
345
                tapscript *waddrmgr.Tapscript) (waddrmgr.ManagedAddress, error)
346

347
        // SendOutputs funds, signs, and broadcasts a Bitcoin transaction paying
348
        // out to the specified outputs. In the case the wallet has insufficient
349
        // funds, or the outputs are non-standard, an error should be returned.
350
        // This method also takes the target fee expressed in sat/kw that should
351
        // be used when crafting the transaction.
352
        //
353
        // NOTE: This method requires the global coin selection lock to be held.
354
        SendOutputs(inputs fn.Set[wire.OutPoint], outputs []*wire.TxOut,
355
                feeRate chainfee.SatPerKWeight, minConfs int32, label string,
356
                strategy base.CoinSelectionStrategy) (*wire.MsgTx, error)
357

358
        // CreateSimpleTx creates a Bitcoin transaction paying to the specified
359
        // outputs. The transaction is not broadcasted to the network. In the
360
        // case the wallet has insufficient funds, or the outputs are
361
        // non-standard, an error should be returned. This method also takes
362
        // the target fee expressed in sat/kw that should be used when crafting
363
        // the transaction.
364
        //
365
        // NOTE: The dryRun argument can be set true to create a tx that
366
        // doesn't alter the database. A tx created with this set to true
367
        // SHOULD NOT be broadcasted.
368
        //
369
        // NOTE: This method requires the global coin selection lock to be held.
370
        CreateSimpleTx(inputs fn.Set[wire.OutPoint], outputs []*wire.TxOut,
371
                feeRate chainfee.SatPerKWeight, minConfs int32,
372
                strategy base.CoinSelectionStrategy, dryRun bool) (
373
                *txauthor.AuthoredTx, error)
374

375
        // GetTransactionDetails returns a detailed description of a transaction
376
        // given its transaction hash.
377
        GetTransactionDetails(txHash *chainhash.Hash) (
378
                *TransactionDetail, error)
379

380
        // ListUnspentWitness returns all unspent outputs which are version 0
381
        // witness programs. The 'minConfs' and 'maxConfs' parameters
382
        // indicate the minimum and maximum number of confirmations an output
383
        // needs in order to be returned by this method. Passing -1 as
384
        // 'minConfs' indicates that even unconfirmed outputs should be
385
        // returned. Using MaxInt32 as 'maxConfs' implies returning all
386
        // outputs with at least 'minConfs'. The account parameter serves as
387
        // a filter to retrieve the unspent outputs for a specific account.
388
        // When empty, the unspent outputs of all wallet accounts are returned.
389
        //
390
        // NOTE: This method requires the global coin selection lock to be held.
391
        ListUnspentWitness(minConfs, maxConfs int32,
392
                accountFilter string) ([]*Utxo, error)
393

394
        // ListTransactionDetails returns a list of all transactions which are
395
        // relevant to the wallet over [startHeight;endHeight]. If start height
396
        // is greater than end height, the transactions will be retrieved in
397
        // reverse order. To include unconfirmed transactions, endHeight should
398
        // be set to the special value -1. This will return transactions from
399
        // the tip of the chain until the start height (inclusive) and
400
        // unconfirmed transactions. The account parameter serves as a filter to
401
        // retrieve the transactions relevant to a specific account. When
402
        // empty, transactions of all wallet accounts are returned.
403
        ListTransactionDetails(startHeight, endHeight int32,
404
                accountFilter string) ([]*TransactionDetail, error)
405

406
        // LeaseOutput locks an output to the given ID, preventing it from being
407
        // available for any future coin selection attempts. The absolute time
408
        // of the lock's expiration is returned. The expiration of the lock can
409
        // be extended by successive invocations of this call. Outputs can be
410
        // unlocked before their expiration through `ReleaseOutput`.
411
        //
412
        // If the output is not known, wtxmgr.ErrUnknownOutput is returned. If
413
        // the output has already been locked to a different ID, then
414
        // wtxmgr.ErrOutputAlreadyLocked is returned.
415
        //
416
        // NOTE: This method requires the global coin selection lock to be held.
417
        LeaseOutput(id wtxmgr.LockID, op wire.OutPoint,
418
                duration time.Duration) (time.Time, error)
419

420
        // ReleaseOutput unlocks an output, allowing it to be available for coin
421
        // selection if it remains unspent. The ID should match the one used to
422
        // originally lock the output.
423
        //
424
        // NOTE: This method requires the global coin selection lock to be held.
425
        ReleaseOutput(id wtxmgr.LockID, op wire.OutPoint) error
426

427
        // ListLeasedOutputs returns a list of all currently locked outputs.
428
        ListLeasedOutputs() ([]*base.ListLeasedOutputResult, error)
429

430
        // PublishTransaction performs cursory validation (dust checks, etc),
431
        // then finally broadcasts the passed transaction to the Bitcoin network.
432
        // If the transaction is rejected because it is conflicting with an
433
        // already known transaction, ErrDoubleSpend is returned. If the
434
        // transaction is already known (published already), no error will be
435
        // returned. Other error returned depends on the currently active chain
436
        // backend. It takes an optional label which will save a label with the
437
        // published transaction.
438
        PublishTransaction(tx *wire.MsgTx, label string) error
439

440
        // LabelTransaction adds a label to a transaction. If the tx already
441
        // has a label, this call will fail unless the overwrite parameter
442
        // is set. Labels must not be empty, and they are limited to 500 chars.
443
        LabelTransaction(hash chainhash.Hash, label string, overwrite bool) error
444

445
        // FetchTx attempts to fetch a transaction in the wallet's database
446
        // identified by the passed transaction hash. If the transaction can't
447
        // be found, then a nil pointer is returned.
448
        FetchTx(chainhash.Hash) (*wire.MsgTx, error)
449

450
        // RemoveDescendants attempts to remove any transaction from the
451
        // wallet's tx store (that may be unconfirmed) that spends outputs
452
        // created by the passed transaction. This remove propagates
453
        // recursively down the chain of descendent transactions.
454
        RemoveDescendants(*wire.MsgTx) error
455

456
        // FundPsbt creates a fully populated PSBT packet that contains enough
457
        // inputs to fund the outputs specified in the passed in packet with the
458
        // specified fee rate. If there is change left, a change output from the
459
        // internal wallet is added and the index of the change output is
460
        // returned. Otherwise no additional output is created and the index -1
461
        // is returned. If no custom change scope is specified, the BIP0084 will
462
        // be used for default accounts and single imported public keys. For
463
        // custom account, no key scope should be provided as the coin selection
464
        // key scope will always be used to generate the change address.
465
        //
466
        // NOTE: If the packet doesn't contain any inputs, coin selection is
467
        // performed automatically. The account parameter must be non-empty as
468
        // it determines which set of coins are eligible for coin selection. If
469
        // the packet does contain any inputs, it is assumed that full coin
470
        // selection happened externally and no additional inputs are added. If
471
        // the specified inputs aren't enough to fund the outputs with the given
472
        // fee rate, an error is returned. No lock lease is acquired for any of
473
        // the selected/validated inputs. It is in the caller's responsibility
474
        // to lock the inputs before handing them out.
475
        FundPsbt(packet *psbt.Packet, minConfs int32,
476
                feeRate chainfee.SatPerKWeight, account string,
477
                changeScope *waddrmgr.KeyScope,
478
                strategy base.CoinSelectionStrategy,
479
                allowUtxo func(wtxmgr.Credit) bool) (int32, error)
480

481
        // SignPsbt expects a partial transaction with all inputs and outputs
482
        // fully declared and tries to sign all unsigned inputs that have all
483
        // required fields (UTXO information, BIP32 derivation information,
484
        // witness or sig scripts) set.
485
        // If no error is returned, the PSBT is ready to be given to the next
486
        // signer or to be finalized if lnd was the last signer.
487
        //
488
        // NOTE: This method only signs inputs (and only those it can sign), it
489
        // does not perform any other tasks (such as coin selection, UTXO
490
        // locking or input/output/fee value validation, PSBT finalization). Any
491
        // input that is incomplete will be skipped.
492
        SignPsbt(packet *psbt.Packet) ([]uint32, error)
493

494
        // FinalizePsbt expects a partial transaction with all inputs and
495
        // outputs fully declared and tries to sign all inputs that belong to
496
        // the specified account. Lnd must be the last signer of the
497
        // transaction. That means, if there are any unsigned non-witness inputs
498
        // or inputs without UTXO information attached or inputs without witness
499
        // data that do not belong to lnd's wallet, this method will fail. If no
500
        // error is returned, the PSBT is ready to be extracted and the final TX
501
        // within to be broadcast.
502
        //
503
        // NOTE: This method does NOT publish the transaction after it's been
504
        // finalized successfully.
505
        FinalizePsbt(packet *psbt.Packet, account string) error
506

507
        // DecorateInputs fetches the UTXO information of all inputs it can
508
        // identify and adds the required information to the package's inputs.
509
        // The failOnUnknown boolean controls whether the method should return
510
        // an error if it cannot identify an input or if it should just skip it.
511
        DecorateInputs(packet *psbt.Packet, failOnUnknown bool) error
512

513
        // SubscribeTransactions returns a TransactionSubscription client which
514
        // is capable of receiving async notifications as new transactions
515
        // related to the wallet are seen within the network, or found in
516
        // blocks.
517
        //
518
        // NOTE: a non-nil error should be returned if notifications aren't
519
        // supported.
520
        //
521
        // TODO(roasbeef): make distinct interface?
522
        SubscribeTransactions() (TransactionSubscription, error)
523

524
        // IsSynced returns a boolean indicating if from the PoV of the wallet,
525
        // it has fully synced to the current best block in the main chain.
526
        // It also returns an int64 indicating the timestamp of the best block
527
        // known to the wallet, expressed in Unix epoch time
528
        IsSynced() (bool, int64, error)
529

530
        // GetRecoveryInfo returns a boolean indicating whether the wallet is
531
        // started in recovery mode. It also returns a float64 indicating the
532
        // recovery progress made so far.
533
        GetRecoveryInfo() (bool, float64, error)
534

535
        // Start initializes the wallet, making any necessary connections,
536
        // starting up required goroutines etc.
537
        Start() error
538

539
        // Stop signals the wallet for shutdown. Shutdown may entail closing
540
        // any active sockets, database handles, stopping goroutines, etc.
541
        Stop() error
542

543
        // BackEnd returns a name for the wallet's backing chain service,
544
        // which could be e.g. btcd, bitcoind, neutrino, or another consensus
545
        // service.
546
        BackEnd() string
547

548
        // CheckMempoolAcceptance checks whether a transaction follows mempool
549
        // policies and returns an error if it cannot be accepted into the
550
        // mempool.
551
        CheckMempoolAcceptance(tx *wire.MsgTx) error
552
}
553

554
// BlockChainIO is a dedicated source which will be used to obtain queries
555
// related to the current state of the blockchain. The data returned by each of
556
// the defined methods within this interface should always return the most up
557
// to date data possible.
558
//
559
// TODO(roasbeef): move to diff package perhaps?
560
// TODO(roasbeef): move publish txn here?
561
type BlockChainIO interface {
562
        // GetBestBlock returns the current height and block hash of the valid
563
        // most-work chain the implementation is aware of.
564
        GetBestBlock() (*chainhash.Hash, int32, error)
565

566
        // GetUtxo attempts to return the passed outpoint if it's still a
567
        // member of the utxo set. The passed height hint should be the "birth
568
        // height" of the passed outpoint. The script passed should be the
569
        // script that the outpoint creates. In the case that the output is in
570
        // the UTXO set, then the output corresponding to that output is
571
        // returned.  Otherwise, a non-nil error will be returned.
572
        // As for some backends this call can initiate a rescan, the passed
573
        // cancel channel can be closed to abort the call.
574
        GetUtxo(op *wire.OutPoint, pkScript []byte, heightHint uint32,
575
                cancel <-chan struct{}) (*wire.TxOut, error)
576

577
        // GetBlockHash returns the hash of the block in the best blockchain
578
        // at the given height.
579
        GetBlockHash(blockHeight int64) (*chainhash.Hash, error)
580

581
        // GetBlock returns the block in the main chain identified by the given
582
        // hash.
583
        GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error)
584

585
        // GetBlockHeader returns the block header for the given block hash.
586
        GetBlockHeader(blockHash *chainhash.Hash) (*wire.BlockHeader, error)
587
}
588

589
// MessageSigner represents an abstract object capable of signing arbitrary
590
// messages. The capabilities of this interface are used to sign announcements
591
// to the network, or just arbitrary messages that leverage the wallet's keys
592
// to attest to some message.
593
type MessageSigner interface {
594
        // SignMessage attempts to sign a target message with the private key
595
        // described in the key locator. If the target private key is unable to
596
        // be found, then an error will be returned. The actual digest signed is
597
        // the single or double SHA-256 of the passed message.
598
        SignMessage(keyLoc keychain.KeyLocator, msg []byte,
599
                doubleHash bool) (*ecdsa.Signature, error)
600
}
601

602
// WalletDriver represents a "driver" for a particular concrete
603
// WalletController implementation. A driver is identified by a globally unique
604
// string identifier along with a 'New()' method which is responsible for
605
// initializing a particular WalletController concrete implementation.
606
type WalletDriver struct {
607
        // WalletType is a string which uniquely identifies the
608
        // WalletController that this driver, drives.
609
        WalletType string
610

611
        // New creates a new instance of a concrete WalletController
612
        // implementation given a variadic set up arguments. The function takes
613
        // a variadic number of interface parameters in order to provide
614
        // initialization flexibility, thereby accommodating several potential
615
        // WalletController implementations.
616
        New func(args ...interface{}) (WalletController, error)
9✔
617

9✔
618
        // BackEnds returns a list of available chain service drivers for the
9✔
619
        // wallet driver. This could be e.g. bitcoind, btcd, neutrino, etc.
9✔
620
        BackEnds func() []string
9✔
621
}
9✔
UNCOV
622

×
UNCOV
623
var (
×
624
        wallets     = make(map[string]*WalletDriver)
9✔
625
        registerMtx sync.Mutex
9✔
UNCOV
626
)
×
UNCOV
627

×
628
// RegisteredWallets returns a slice of all currently registered notifiers.
629
//
630
// NOTE: This function is safe for concurrent access.
631
func RegisteredWallets() []*WalletDriver {
632
        registerMtx.Lock()
9✔
633
        defer registerMtx.Unlock()
18✔
634

9✔
635
        registeredWallets := make([]*WalletDriver, 0, len(wallets))
9✔
636
        for _, wallet := range wallets {
UNCOV
637
                registeredWallets = append(registeredWallets, wallet)
×
UNCOV
638
        }
×
UNCOV
639

×
UNCOV
640
        return registeredWallets
×
641
}
642

643
// RegisterWallet registers a WalletDriver which is capable of driving a
UNCOV
644
// concrete WalletController interface. In the case that this driver has
×
UNCOV
645
// already been registered, an error is returned.
×
UNCOV
646
//
×
647
// NOTE: This function is safe for concurrent access.
UNCOV
648
func RegisterWallet(driver *WalletDriver) error {
×
UNCOV
649
        registerMtx.Lock()
×
UNCOV
650
        defer registerMtx.Unlock()
×
UNCOV
651

×
UNCOV
652
        if _, ok := wallets[driver.WalletType]; ok {
×
653
                return fmt.Errorf("wallet already registered")
654
        }
×
UNCOV
655

×
UNCOV
656
        wallets[driver.WalletType] = driver
×
UNCOV
657

×
UNCOV
658
        return nil
×
UNCOV
659
}
×
UNCOV
660

×
UNCOV
661
// SupportedWallets returns a slice of strings that represents the wallet
×
UNCOV
662
// drivers that have been registered and are therefore supported.
×
663
//
664
// NOTE: This function is safe for concurrent access.
665
func SupportedWallets() []string {
666
        registerMtx.Lock()
667
        defer registerMtx.Unlock()
668

669
        supportedWallets := make([]string, 0, len(wallets))
670
        for walletName := range wallets {
671
                supportedWallets = append(supportedWallets, walletName)
672
        }
673

674
        return supportedWallets
675
}
676

677
// FetchFundingTxWrapper is a wrapper around FetchFundingTx, except that it will
678
// exit when the supplied quit channel is closed.
679
func FetchFundingTxWrapper(chain BlockChainIO, chanID *lnwire.ShortChannelID,
680
        quit chan struct{}) (*wire.MsgTx, error) {
681

682
        txChan := make(chan *wire.MsgTx, 1)
683
        errChan := make(chan error, 1)
684

685
        go func() {
686
                tx, err := FetchFundingTx(chain, chanID)
687
                if err != nil {
688
                        errChan <- err
689
                        return
690
                }
691

692
                txChan <- tx
693
        }()
694

4✔
695
        select {
4✔
696
        case tx := <-txChan:
4✔
697
                return tx, nil
4✔
698

4✔
699
        case err := <-errChan:
8✔
700
                return nil, err
4✔
701

4✔
702
        case <-quit:
703
                return nil, fmt.Errorf("quit channel passed to " +
4✔
704
                        "lnwallet.FetchFundingTxWrapper has been closed")
705
        }
706
}
707

708
// FetchFundingTx uses the given BlockChainIO to fetch and return the funding
709
// transaction identified by the passed short channel ID.
710
//
711
// TODO(roasbeef): replace with call to GetBlockTransaction? (would allow to
17✔
712
// later use getblocktxn).
17✔
713
func FetchFundingTx(chain BlockChainIO,
17✔
714
        chanID *lnwire.ShortChannelID) (*wire.MsgTx, error) {
17✔
715

17✔
UNCOV
716
        // First fetch the block hash by the block number encoded, then use
×
UNCOV
717
        // that hash to fetch the block itself.
×
718
        blockNum := int64(chanID.BlockHeight)
719
        blockHash, err := chain.GetBlockHash(blockNum)
17✔
720
        if err != nil {
17✔
721
                return nil, err
17✔
722
        }
723

724
        fundingBlock, err := chain.GetBlock(blockHash)
725
        if err != nil {
726
                return nil, err
727
        }
UNCOV
728

×
UNCOV
729
        // As a sanity check, ensure that the advertised transaction index is
×
UNCOV
730
        // within the bounds of the total number of transactions within a
×
UNCOV
731
        // block.
×
UNCOV
732
        numTxns := uint32(len(fundingBlock.Transactions))
×
UNCOV
733
        if chanID.TxIndex > numTxns-1 {
×
734
                return nil, fmt.Errorf("tx_index=#%v "+
×
735
                        "is out of range (max_index=%v), network_chan_id=%v",
×
736
                        chanID.TxIndex, numTxns-1, chanID)
737
        }
×
738

739
        return fundingBlock.Transactions[chanID.TxIndex].Copy(), nil
740
}
741

742
// FetchPKScriptWithQuit fetches the output script for the given SCID and exits
743
// early with an error if the provided quit channel is closed before
17✔
744
// completion.
17✔
745
func FetchPKScriptWithQuit(chain BlockChainIO, chanID *lnwire.ShortChannelID,
17✔
746
        quit chan struct{}) ([]byte, error) {
17✔
747

17✔
748
        tx, err := FetchFundingTxWrapper(chain, chanID, quit)
34✔
749
        if err != nil {
17✔
750
                return nil, err
18✔
751
        }
1✔
752

1✔
753
        outputLocator := chanvalidate.ShortChanIDChanLocator{
1✔
754
                ID: *chanID,
755
        }
16✔
756

757
        output, _, err := outputLocator.Locate(tx)
758
        if err != nil {
17✔
759
                return nil, err
16✔
760
        }
16✔
761

762
        return output.PkScript, nil
1✔
763
}
1✔
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