github.com/decred/dcrlnd@v0.7.6/lnwallet/interface.go (about) 1 package lnwallet 2 3 import ( 4 "errors" 5 "fmt" 6 "sync" 7 "time" 8 9 "decred.org/dcrwallet/v4/wallet" 10 "decred.org/dcrwallet/v4/wallet/txauthor" 11 "github.com/decred/dcrd/chaincfg/chainhash" 12 "github.com/decred/dcrd/dcrec/secp256k1/v4" 13 "github.com/decred/dcrd/dcrec/secp256k1/v4/ecdsa" 14 "github.com/decred/dcrd/dcrutil/v4" 15 "github.com/decred/dcrd/hdkeychain/v3" 16 "github.com/decred/dcrd/txscript/v4/stdaddr" 17 "github.com/decred/dcrd/wire" 18 "github.com/decred/dcrlnd/btcwalletcompat" 19 "github.com/decred/dcrlnd/internal/psbt" 20 "github.com/decred/dcrlnd/keychain" 21 "github.com/decred/dcrlnd/lnwallet/chainfee" 22 ) 23 24 const ( 25 // DefaultAccountName is the name for the default account used to manage 26 // on-chain funds within the wallet. 27 DefaultAccountName = "default" 28 ) 29 30 // AddressType is an enum-like type which denotes the possible address types 31 // WalletController supports. 32 type AddressType uint8 33 34 const ( 35 // WitnessPubKey represents a p2wkh address. 36 // TODO(decred) remove this type of address 37 WitnessPubKey AddressType = iota 38 39 // NestedWitnessPubKey represents a p2sh output which is itself a 40 // nested p2wkh output. 41 // TODO(decred) remove this type of address 42 NestedWitnessPubKey 43 44 // PubKeyHash represents a p2pkh address 45 PubKeyHash 46 47 // ScriptHash represents a p2sh address 48 ScriptHash 49 50 // UnknownAddressType represents an output with an unknown or non-standard 51 // script. 52 UnknownAddressType 53 ) 54 55 var ( 56 // DefaultPublicPassphrase is the default public passphrase used for the 57 // wallet. 58 DefaultPublicPassphrase = []byte("public") 59 60 // DefaultPrivatePassphrase is the default private passphrase used for 61 // the wallet. 62 DefaultPrivatePassphrase = []byte("hello") 63 64 // ErrDoubleSpend is returned from PublishTransaction in case the 65 // tx being published is spending an output spent by a conflicting 66 // transaction. 67 ErrDoubleSpend = errors.New("transaction rejected: output already spent") 68 69 // ErrNotMine is an error denoting that a WalletController instance is 70 // unable to spend a specified output. 71 ErrNotMine = errors.New("the passed output doesn't belong to the wallet") 72 ) 73 74 // ErrNoOutputs is returned if we try to create a transaction with no outputs 75 // or send coins to a set of outputs that is empty. 76 var ErrNoOutputs = errors.New("no outputs") 77 78 // LockID is equivalent to btcsuite/btcwallet/wtxmgr LockID type. 79 type LockID [32]byte 80 81 // ErrInvalidMinconf is returned if we try to create a transaction with 82 // invalid minConfs value. 83 var ErrInvalidMinconf = errors.New("minimum number of confirmations must " + 84 "be a non-negative number") 85 86 // Utxo is an unspent output denoted by its outpoint, and output value of the 87 // original output. 88 type Utxo struct { 89 AddressType AddressType 90 Value dcrutil.Amount 91 Confirmations int64 92 PkScript []byte 93 wire.OutPoint 94 95 // TODO(decred) this needs to include ScriptVersion. Then this version needs 96 // to be filled and used everywhere instead of DefaultScriptVersion. 97 98 Derivation *psbt.Bip32Derivation 99 PrevTx *wire.MsgTx 100 } 101 102 // TransactionDetail describes a transaction with either inputs which belong to 103 // the wallet, or has outputs that pay to the wallet. 104 type TransactionDetail struct { 105 // Hash is the transaction hash of the transaction. 106 Hash chainhash.Hash 107 108 // Value is the net value of this transaction (in atoms) from the 109 // PoV of the wallet. If this transaction purely spends from the 110 // wallet's funds, then this value will be negative. Similarly, if this 111 // transaction credits the wallet, then this value will be positive. 112 Value dcrutil.Amount 113 114 // NumConfirmations is the number of confirmations this transaction 115 // has. If the transaction is unconfirmed, then this value will be 116 // zero. 117 NumConfirmations int32 118 119 // BlockHeight is the hash of the block which includes this 120 // transaction. Unconfirmed transactions will have a nil value for this 121 // field. 122 BlockHash *chainhash.Hash 123 124 // BlockHeight is the height of the block including this transaction. 125 // Unconfirmed transaction will show a height of zero. 126 BlockHeight int32 127 128 // Timestamp is the unix timestamp of the block including this 129 // transaction. If the transaction is unconfirmed, then this will be a 130 // timestamp of txn creation. 131 Timestamp int64 132 133 // TotalFees is the total fee in atoms paid by this transaction. 134 TotalFees int64 135 136 // DestAddresses are the destinations for a transaction 137 DestAddresses []stdaddr.Address 138 139 // RawTx returns the raw serialized transaction. 140 RawTx []byte 141 142 // Label is an optional transaction label. 143 Label string 144 } 145 146 // TransactionSubscription is an interface which describes an object capable of 147 // receiving notifications of new transaction related to the underlying wallet. 148 // TODO(roasbeef): add balance updates? 149 type TransactionSubscription interface { 150 // ConfirmedTransactions returns a channel which will be sent on as new 151 // relevant transactions are confirmed. 152 ConfirmedTransactions() chan *TransactionDetail 153 154 // UnconfirmedTransactions returns a channel which will be sent on as 155 // new relevant transactions are seen within the network. 156 UnconfirmedTransactions() chan *TransactionDetail 157 158 // Cancel finalizes the subscription, cleaning up any resources 159 // allocated. 160 Cancel() 161 } 162 163 // WalletController defines an abstract interface for controlling a local Pure 164 // Go wallet, a local or remote wallet via an RPC mechanism, or possibly even 165 // a daemon assisted hardware wallet. This interface serves the purpose of 166 // allowing LightningWallet to be seamlessly compatible with several wallets 167 // such as: uspv, dcrwallet, etc. This interface then serves as a "base wallet", 168 // with Lightning Network awareness taking place at a "higher" level of 169 // abstraction. Essentially, an overlay wallet. Implementors of this interface 170 // must closely adhere to the documented behavior of all interface methods in 171 // order to ensure identical behavior across all concrete implementations. 172 type WalletController interface { 173 // FetchInputInfo queries for the WalletController's knowledge of the 174 // passed outpoint. If the base wallet determines this output is under 175 // its control, then the original txout should be returned. Otherwise, 176 // a non-nil error value of ErrNotMine should be returned instead. 177 FetchInputInfo(prevOut *wire.OutPoint) (*Utxo, error) 178 179 // ScriptForOutput returns the address, witness program and redeem 180 // script for a given UTXO. An error is returned if the UTXO does not 181 // belong to our wallet or it is not a managed pubKey address. 182 ScriptForOutput(output *wire.TxOut) (btcwalletcompat.ManagedPubKeyAddress, 183 []byte, []byte, error) 184 185 // ConfirmedBalance returns the sum of all the wallet's unspent outputs 186 // that have at least confs confirmations. If confs is set to zero, 187 // then all unspent outputs, including those currently in the mempool 188 // will be included in the final sum. The account parameter serves as a 189 // filter to retrieve the balance for a specific account. When empty, 190 // the confirmed balance of all wallet accounts is returned. 191 // 192 // NOTE: Only witness outputs should be included in the computation of 193 // the total spendable balance of the wallet. We require this as only 194 // witness inputs can be used for funding channels. 195 ConfirmedBalance(confs int32, accountFilter string) (dcrutil.Amount, 196 error) 197 198 // NewAddress returns the next external or internal address for the 199 // wallet dictated by the value of the `change` parameter. If change is 200 // true, then an internal address should be used, otherwise an external 201 // address should be returned. The type of address returned is dictated 202 // by the wallet's capabilities, and may be of type: p2sh, p2wkh, 203 // p2wsh, etc. The account parameter must be non-empty as it determines 204 // which account the address should be generated from. 205 NewAddress(addrType AddressType, change bool, 206 account string) (stdaddr.Address, error) 207 208 // LastUnusedAddress returns the last *unused* address known by the 209 // wallet. An address is unused if it hasn't received any payments. 210 // This can be useful in UIs in order to continually show the 211 // "freshest" address without having to worry about "address inflation" 212 // caused by continual refreshing. Similar to NewAddress it can derive 213 // a specified address type. By default, this is a non-change address. 214 // The account parameter must be non-empty as it determines which 215 // account the address should be generated from. 216 LastUnusedAddress(addrType AddressType, 217 account string) (stdaddr.Address, error) 218 219 // IsOurAddress checks if the passed address belongs to this wallet 220 IsOurAddress(a stdaddr.Address) bool 221 222 // AddressInfo returns the information about an address, if it's known 223 // to this wallet. 224 AddressInfo(a stdaddr.Address) (btcwalletcompat.ManagedAddress, error) 225 226 // ListAccounts retrieves all accounts belonging to the wallet by 227 // default. A name filter can be provided to filter through all of the 228 // wallet accounts and return only those matching. 229 ListAccounts(string) ([]wallet.AccountProperties, error) 230 231 // ImportAccount imports an account backed by an account extended public 232 // key. The master key fingerprint denotes the fingerprint of the root 233 // key corresponding to the account public key (also known as the key 234 // with derivation path m/). This may be required by some hardware 235 // wallets for proper identification and signing. 236 ImportAccount(name string, accountPubKey *hdkeychain.ExtendedKey, 237 dryRun bool) (*wallet.AccountProperties, []stdaddr.Address, 238 []stdaddr.Address, error) 239 240 // ImportPublicKey imports a single derived public key into the wallet. 241 ImportPublicKey(pubKey *secp256k1.PublicKey) error 242 243 // SendOutputs funds, signs, and broadcasts a Decred transaction paying 244 // out to the specified outputs. In the case the wallet has insufficient 245 // funds, or the outputs are non-standard, an error should be returned. 246 // This method also takes the target fee expressed in atoms/kB that should 247 // be used when crafting the transaction. 248 // 249 // NOTE: This method requires the global coin selection lock to be held. 250 SendOutputs(outputs []*wire.TxOut, feeRate chainfee.AtomPerKByte, 251 minConfs int32, label, fromAccount string) (*wire.MsgTx, error) 252 253 // CreateSimpleTx creates a Bitcoin transaction paying to the specified 254 // outputs. The transaction is not broadcasted to the network. In the 255 // case the wallet has insufficient funds, or the outputs are 256 // non-standard, an error should be returned. This method also takes 257 // the target fee expressed in sat/kw that should be used when crafting 258 // the transaction. 259 // 260 // NOTE: The dryRun argument can be set true to create a tx that 261 // doesn't alter the database. A tx created with this set to true 262 // SHOULD NOT be broadcasted. 263 // 264 // NOTE: This method requires the global coin selection lock to be held. 265 CreateSimpleTx(outputs []*wire.TxOut, feeRate chainfee.AtomPerKByte, 266 minConfs int32, dryRun bool) (*txauthor.AuthoredTx, error) 267 268 // ListUnspentWitness returns all unspent outputs which are version 0 269 // witness programs. The 'minConfs' and 'maxConfs' parameters 270 // indicate the minimum and maximum number of confirmations an output 271 // needs in order to be returned by this method. Passing -1 as 272 // 'minConfs' indicates that even unconfirmed outputs should be 273 // returned. Using MaxInt32 as 'maxConfs' implies returning all 274 // outputs with at least 'minConfs'. The account parameter serves as 275 // a filter to retrieve the unspent outputs for a specific account. 276 // When empty, the unspent outputs of all wallet accounts are returned. 277 // 278 // NOTE: This method requires the global coin selection lock to be held. 279 ListUnspentWitness(minConfs, maxConfs int32, 280 accountFilter string) ([]*Utxo, error) 281 282 // ListTransactionDetails returns a list of all transactions which are 283 // relevant to the wallet over [startHeight;endHeight]. If start height 284 // is greater than end height, the transactions will be retrieved in 285 // reverse order. To include unconfirmed transactions, endHeight should 286 // be set to the special value -1. This will return transactions from 287 // the tip of the chain until the start height (inclusive) and 288 // unconfirmed transactions. The account parameter serves as a filter to 289 // retrieve the transactions relevant to a specific account. When 290 // empty, transactions of all wallet accounts are returned. 291 ListTransactionDetails(startHeight, endHeight int32, 292 accountFilter string) ([]*TransactionDetail, error) 293 294 // LockOutpoint marks an outpoint as locked meaning it will no longer 295 // be deemed as eligible for coin selection. Locking outputs are 296 // utilized in order to avoid race conditions when selecting inputs for 297 // usage when funding a channel. 298 // 299 // NOTE: This method requires the global coin selection lock to be held. 300 LockOutpoint(o wire.OutPoint) 301 302 // UnlockOutpoint unlocks a previously locked output, marking it 303 // eligible for coin selection. 304 // 305 // NOTE: This method requires the global coin selection lock to be held. 306 UnlockOutpoint(o wire.OutPoint) 307 308 // LeaseOutput locks an output to the given ID, preventing it from being 309 // available for any future coin selection attempts. The absolute time 310 // of the lock's expiration is returned. The expiration of the lock can 311 // be extended by successive invocations of this call. Outputs can be 312 // unlocked before their expiration through `ReleaseOutput`. 313 // 314 // If the output is not known, wtxmgr.ErrUnknownOutput is returned. If 315 // the output has already been locked to a different ID, then 316 // wtxmgr.ErrOutputAlreadyLocked is returned. 317 // 318 // NOTE: This method requires the global coin selection lock to be held. 319 LeaseOutput(id LockID, op wire.OutPoint, 320 duration time.Duration) (time.Time, error) 321 322 // ReleaseOutput unlocks an output, allowing it to be available for coin 323 // selection if it remains unspent. The ID should match the one used to 324 // originally lock the output. 325 // 326 // NOTE: This method requires the global coin selection lock to be held. 327 ReleaseOutput(id LockID, op wire.OutPoint) error 328 329 // ListLeasedOutputs returns a list of all currently locked outputs. 330 ListLeasedOutputs() ([]*LockedOutput, error) 331 332 // PublishTransaction performs cursory validation (dust checks, etc), 333 // then finally broadcasts the passed transaction to the Decred network. 334 // If the transaction is rejected because it is conflicting with an 335 // already known transaction, ErrDoubleSpend is returned. If the 336 // transaction is already known (published already), no error will be 337 // returned. Other error returned depends on the currently active chain 338 // backend. It takes an optional label which will save a label with the 339 // published transaction. 340 PublishTransaction(tx *wire.MsgTx, label string) error 341 342 // AbandonDoubleSpends removes all unconfirmed transactions that also 343 // spend any of the specified outpoints from the wallet. This is used 344 // to fix issues when an input used in multiple different sweep 345 // transactions gets confirmed in one of them (rendering the other 346 // transactions invalid). 347 AbandonDoubleSpends(spentOutpoints ...*wire.OutPoint) error 348 349 // LabelTransaction adds a label to a transaction. If the tx already 350 // has a label, this call will fail unless the overwrite parameter is 351 // set. Labels must not be empty, and they are limited to 500 chars. 352 LabelTransaction(hash chainhash.Hash, label string, overwrite bool) error 353 354 // FetchTx attempts to fetch a transaction in the wallet's database 355 // identified by the passed transaction hash. If the transaction can't 356 // be found, then a nil pointer is returned. 357 FetchTx(chainhash.Hash) (*wire.MsgTx, error) 358 359 // RemoveDescendants attempts to remove any transaction from the 360 // wallet's tx store (that may be unconfirmed) that spends outputs 361 // created by the passed transaction. This remove propagates 362 // recursively down the chain of descendent transactions. 363 RemoveDescendants(*wire.MsgTx) error 364 365 // FundPsbt creates a fully populated PSBT packet that contains enough 366 // inputs to fund the outputs specified in the passed in packet with the 367 // specified fee rate. If there is change left, a change output from the 368 // internal wallet is added and the index of the change output is 369 // returned. Otherwise no additional output is created and the index -1 370 // is returned. 371 // 372 // NOTE: If the packet doesn't contain any inputs, coin selection is 373 // performed automatically. The account parameter must be non-empty as 374 // it determines which set of coins are eligible for coin selection. If 375 // the packet does contain any inputs, it is assumed that full coin 376 // selection happened externally and no additional inputs are added. If 377 // the specified inputs aren't enough to fund the outputs with the given 378 // fee rate, an error is returned. No lock lease is acquired for any of 379 // the selected/validated inputs. It is in the caller's responsibility 380 // to lock the inputs before handing them out. 381 FundPsbt(packet *psbt.Packet, minConfs int32, 382 feeRate chainfee.AtomPerKByte, account string) (int32, error) 383 384 // SignPsbt expects a partial transaction with all inputs and outputs 385 // fully declared and tries to sign all unsigned inputs that have all 386 // required fields (UTXO information, BIP32 derivation information, 387 // witness or sig scripts) set. 388 // If no error is returned, the PSBT is ready to be given to the next 389 // signer or to be finalized if lnd was the last signer. 390 // 391 // NOTE: This method only signs inputs (and only those it can sign), it 392 // does not perform any other tasks (such as coin selection, UTXO 393 // locking or input/output/fee value validation, PSBT finalization). Any 394 // input that is incomplete will be skipped. 395 SignPsbt(packet *psbt.Packet) error 396 397 // FinalizePsbt expects a partial transaction with all inputs and 398 // outputs fully declared and tries to sign all inputs that belong to 399 // the wallet. Lnd must be the last signer of the transaction. That 400 // means, if there are any unsigned non-witness inputs or inputs without 401 // UTXO information attached or inputs without witness data that do not 402 // belong to lnd's wallet, this method will fail. If no error is 403 // returned, the PSBT is ready to be extracted and the final TX within 404 // to be broadcast. 405 // 406 // NOTE: This method does NOT publish the transaction after it's been 407 // finalized successfully. 408 FinalizePsbt(packet *psbt.Packet) error 409 410 // SubscribeTransactions returns a TransactionSubscription client which 411 // is capable of receiving async notifications as new transactions 412 // related to the wallet are seen within the network, or found in 413 // blocks. 414 // 415 // NOTE: a non-nil error should be returned if notifications aren't 416 // supported. 417 // 418 // TODO(roasbeef): make distinct interface? 419 SubscribeTransactions() (TransactionSubscription, error) 420 421 // IsSynced returns a boolean indicating if from the PoV of the wallet, 422 // it has fully synced to the current best block in the main chain. 423 // It also returns an int64 indicating the timestamp of the best block 424 // known to the wallet, expressed in Unix epoch time 425 IsSynced() (bool, int64, error) 426 427 // InitialSyncChannel returns a channel that is closed once the wallet 428 // has performed its initial sync procedures, is caught up to the 429 // network and potentially ready for use. 430 InitialSyncChannel() <-chan struct{} 431 432 // BestBlock returns the block height, block hash and timestamp for the 433 // tip of the main chain as viewed by the internal wallet controller. 434 BestBlock() (int64, chainhash.Hash, int64, error) 435 436 // GetRecoveryInfo returns a boolean indicating whether the wallet is 437 // started in recovery mode. It also returns a float64 indicating the 438 // recovery progress made so far. 439 GetRecoveryInfo() (bool, float64, error) 440 441 // Start initializes the wallet, making any necessary connections, 442 // starting up required goroutines etc. 443 Start() error 444 445 // Stop signals the wallet for shutdown. Shutdown may entail closing 446 // any active sockets, database handles, stopping goroutines, etc. 447 Stop() error 448 449 // BackEnd returns a name for the wallet's backing chain service, 450 // which could be e.g. dcrd or another consensus service. 451 BackEnd() string 452 } 453 454 // BlockChainIO is a dedicated source which will be used to obtain queries 455 // related to the current state of the blockchain. The data returned by each of 456 // the defined methods within this interface should always return the most up 457 // to date data possible. 458 // 459 // TODO(roasbeef): move to diff package perhaps? 460 // TODO(roasbeef): move publish txn here? 461 type BlockChainIO interface { 462 // GetBestBlock returns the current height and block hash of the valid 463 // most-work chain the implementation is aware of. 464 GetBestBlock() (*chainhash.Hash, int32, error) 465 466 // GetUtxo attempts to return the passed outpoint if it's still a 467 // member of the utxo set. The passed height hint should be the "birth 468 // height" of the passed outpoint. The script passed should be the 469 // script that the outpoint creates. In the case that the output is in 470 // the UTXO set, then the output corresponding to that output is 471 // returned. Otherwise, a non-nil error will be returned. 472 // As for some backends this call can initiate a rescan, the passed 473 // cancel channel can be closed to abort the call. 474 GetUtxo(op *wire.OutPoint, pkScript []byte, heightHint uint32, 475 cancel <-chan struct{}) (*wire.TxOut, error) 476 477 // GetBlockHash returns the hash of the block in the best blockchain 478 // at the given height. 479 GetBlockHash(blockHeight int64) (*chainhash.Hash, error) 480 481 // GetBlock returns the block in the main chain identified by the given 482 // hash. 483 GetBlock(blockHash *chainhash.Hash) (*wire.MsgBlock, error) 484 } 485 486 // Messageinput.Signer represents an abstract object capable of signing arbitrary 487 // messages. The capabilities of this interface are used to sign announcements 488 // to the network, or just arbitrary messages that leverage the wallet's keys 489 // to attest to some message. 490 type MessageSigner interface { 491 // SignMessage attempts to sign a target message with the private key 492 // described in the key locator. If the target private key is unable to 493 // be found, then an error will be returned. The actual digest signed is 494 // the chainhash of the passed message. 495 SignMessage(keyLoc keychain.KeyLocator, msg []byte, 496 doubleHash bool) (*ecdsa.Signature, error) 497 } 498 499 // WalletDriver represents a "driver" for a particular concrete 500 // WalletController implementation. A driver is identified by a globally unique 501 // string identifier along with a 'New()' method which is responsible for 502 // initializing a particular WalletController concrete implementation. 503 type WalletDriver struct { 504 // WalletType is a string which uniquely identifies the 505 // WalletController that this driver, drives. 506 WalletType string 507 508 // New creates a new instance of a concrete WalletController 509 // implementation given a variadic set up arguments. The function takes 510 // a variadic number of interface parameters in order to provide 511 // initialization flexibility, thereby accommodating several potential 512 // WalletController implementations. 513 New func(args ...interface{}) (WalletController, error) 514 515 // BackEnds returns a list of available chain service drivers for the 516 // wallet driver. 517 BackEnds func() []string 518 } 519 520 var ( 521 wallets = make(map[string]*WalletDriver) 522 registerMtx sync.Mutex 523 ) 524 525 // RegisteredWallets returns a slice of all currently registered notifiers. 526 // 527 // NOTE: This function is safe for concurrent access. 528 func RegisteredWallets() []*WalletDriver { 529 registerMtx.Lock() 530 defer registerMtx.Unlock() 531 532 registeredWallets := make([]*WalletDriver, 0, len(wallets)) 533 for _, wallet := range wallets { 534 registeredWallets = append(registeredWallets, wallet) 535 } 536 537 return registeredWallets 538 } 539 540 // RegisterWallet registers a WalletDriver which is capable of driving a 541 // concrete WalletController interface. In the case that this driver has 542 // already been registered, an error is returned. 543 // 544 // NOTE: This function is safe for concurrent access. 545 func RegisterWallet(driver *WalletDriver) error { 546 registerMtx.Lock() 547 defer registerMtx.Unlock() 548 549 if _, ok := wallets[driver.WalletType]; ok { 550 return fmt.Errorf("wallet already registered") 551 } 552 553 wallets[driver.WalletType] = driver 554 555 return nil 556 } 557 558 // SupportedWallets returns a slice of strings that represents the wallet 559 // drivers that have been registered and are therefore supported. 560 // 561 // NOTE: This function is safe for concurrent access. 562 func SupportedWallets() []string { 563 registerMtx.Lock() 564 defer registerMtx.Unlock() 565 566 supportedWallets := make([]string, 0, len(wallets)) 567 for walletName := range wallets { 568 supportedWallets = append(supportedWallets, walletName) 569 } 570 571 return supportedWallets 572 } 573 574 // WalletDriverForName returns the wallet driver for the given wallet type name. 575 // Returns nil if the wallet driver does not exist. 576 func WalletDriverForName(name string) *WalletDriver { 577 registerMtx.Lock() 578 defer registerMtx.Unlock() 579 580 for walletName, driver := range wallets { 581 if walletName == name { 582 return driver 583 } 584 } 585 586 return nil 587 588 }