diff --git a/chainreg/chainregistry.go b/chainreg/chainregistry.go index 13d3db1838..2002572c0c 100644 --- a/chainreg/chainregistry.go +++ b/chainreg/chainregistry.go @@ -113,6 +113,10 @@ type Config struct { // LoaderOptions holds functional wallet db loader options. LoaderOptions []btcwallet.LoaderOption + + // CoinSelectionStrategy is the strategy that is used for selecting + // coins when funding a transaction. + CoinSelectionStrategy wallet.CoinSelectionStrategy } const ( @@ -278,14 +282,15 @@ func NewChainControl(cfg *Config, blockCache *blockcache.BlockCache) ( } walletConfig := &btcwallet.Config{ - PrivatePass: cfg.PrivateWalletPw, - PublicPass: cfg.PublicWalletPw, - Birthday: cfg.Birthday, - RecoveryWindow: cfg.RecoveryWindow, - NetParams: cfg.ActiveNetParams.Params, - CoinType: cfg.ActiveNetParams.CoinType, - Wallet: cfg.Wallet, - LoaderOptions: cfg.LoaderOptions, + PrivatePass: cfg.PrivateWalletPw, + PublicPass: cfg.PublicWalletPw, + Birthday: cfg.Birthday, + RecoveryWindow: cfg.RecoveryWindow, + NetParams: cfg.ActiveNetParams.Params, + CoinType: cfg.ActiveNetParams.CoinType, + Wallet: cfg.Wallet, + LoaderOptions: cfg.LoaderOptions, + CoinSelectionStrategy: cfg.CoinSelectionStrategy, } var err error diff --git a/config.go b/config.go index 232c90bed7..e9223f7348 100644 --- a/config.go +++ b/config.go @@ -154,6 +154,10 @@ const ( // channel state updates that is accumulated before signing a new // commitment. defaultChannelCommitBatchSize = 10 + + // defaultCoinSelectionStrategy is the coin selection strategy that is + // used by default to fund transactions. + defaultCoinSelectionStrategy = "largest" ) var ( @@ -297,6 +301,8 @@ type Config struct { ResetWalletTransactions bool `long:"reset-wallet-transactions" description:"Removes all transaction history from the on-chain wallet on startup, forcing a full chain rescan starting at the wallet's birthday. Implements the same functionality as btcwallet's dropwtxmgr command. Should be set to false after successful execution to avoid rescanning on every restart of lnd."` + CoinSelectionStrategy string `long:"coin-selection-strategy" description:"The strategy to use for selecting coins for wallet transactions." choice:"largest" choice:"random"` + PaymentsExpirationGracePeriod time.Duration `long:"payments-expiration-grace-period" description:"A period to wait before force closing channels with outgoing htlcs that have timed-out and are a result of this node initiated payments."` TrickleDelay int `long:"trickledelay" description:"Time in milliseconds between each release of announcements to the network"` ChanEnableTimeout time.Duration `long:"chan-enable-timeout" description:"The duration that a peer connection must be stable before attempting to send a channel update to reenable or cancel a pending disables of the peer's channels on the network."` @@ -547,6 +553,7 @@ func DefaultConfig() Config { ActiveNetParams: chainreg.BitcoinTestNetParams, ChannelCommitInterval: defaultChannelCommitInterval, ChannelCommitBatchSize: defaultChannelCommitBatchSize, + CoinSelectionStrategy: defaultCoinSelectionStrategy, } } diff --git a/go.mod b/go.mod index 996de439b4..18ab47f3dd 100644 --- a/go.mod +++ b/go.mod @@ -9,10 +9,10 @@ require ( github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/btcutil v1.0.3-0.20210514234026-faeebcb9abbe github.com/btcsuite/btcutil/psbt v1.0.3-0.20210514234026-faeebcb9abbe - github.com/btcsuite/btcwallet v0.12.0 - github.com/btcsuite/btcwallet/wallet/txauthor v1.0.1-0.20210329233242-e0607006dce6 + github.com/btcsuite/btcwallet v0.12.1-0.20210519225359-6ab9b615576f + github.com/btcsuite/btcwallet/wallet/txauthor v1.0.1-0.20210519225359-6ab9b615576f github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 - github.com/btcsuite/btcwallet/wallet/txsizes v1.0.1-0.20210329233242-e0607006dce6 // indirect + github.com/btcsuite/btcwallet/wallet/txsizes v1.0.1-0.20210519225359-6ab9b615576f // indirect github.com/btcsuite/btcwallet/walletdb v1.3.5 github.com/btcsuite/btcwallet/wtxmgr v1.3.0 github.com/davecgh/go-spew v1.1.1 diff --git a/go.sum b/go.sum index 2a1978a048..e76e667161 100644 --- a/go.sum +++ b/go.sum @@ -39,16 +39,16 @@ github.com/btcsuite/btcutil v1.0.3-0.20210514234026-faeebcb9abbe/go.mod h1:0DVlH github.com/btcsuite/btcutil/psbt v1.0.3-0.20201208143702-a53e38424cce/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= github.com/btcsuite/btcutil/psbt v1.0.3-0.20210514234026-faeebcb9abbe h1:+zkzfj2bGHMOuxxf8xG3d5mDvd7phT7IyVv+8sQizqc= github.com/btcsuite/btcutil/psbt v1.0.3-0.20210514234026-faeebcb9abbe/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= -github.com/btcsuite/btcwallet v0.12.0 h1:0kT0rDN8vNcAvuHp2qUS/hLsfa0VUn2dNQ2GvM9ozBA= -github.com/btcsuite/btcwallet v0.12.0/go.mod h1:f1HuBGov5+OTp40Gh1vA+tvF6d7bbuLFTceJMRB7fXw= +github.com/btcsuite/btcwallet v0.12.1-0.20210519225359-6ab9b615576f h1:Me6OOQP2ZYttZuViKXHVegXPKz2n42zNbHI3ljPeqwU= +github.com/btcsuite/btcwallet v0.12.1-0.20210519225359-6ab9b615576f/go.mod h1:f1HuBGov5+OTp40Gh1vA+tvF6d7bbuLFTceJMRB7fXw= github.com/btcsuite/btcwallet/wallet/txauthor v1.0.0/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= -github.com/btcsuite/btcwallet/wallet/txauthor v1.0.1-0.20210329233242-e0607006dce6 h1:mO7NxcfgLe75paLDHx+LWNG5BskiDQigHnSVT2KvNZA= -github.com/btcsuite/btcwallet/wallet/txauthor v1.0.1-0.20210329233242-e0607006dce6/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= +github.com/btcsuite/btcwallet/wallet/txauthor v1.0.1-0.20210519225359-6ab9b615576f h1:uzCtWqLJ6dlufUhpmoNgaegF87Pb9kOwPmpFYEi2up4= +github.com/btcsuite/btcwallet/wallet/txauthor v1.0.1-0.20210519225359-6ab9b615576f/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 h1:2VsfS0sBedcM5KmDzRMT3+b6xobqWveZGvjb+jFez5w= github.com/btcsuite/btcwallet/wallet/txrules v1.0.0/go.mod h1:UwQE78yCerZ313EXZwEiu3jNAtfXj2n2+c8RWiE/WNA= github.com/btcsuite/btcwallet/wallet/txsizes v1.0.0/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= -github.com/btcsuite/btcwallet/wallet/txsizes v1.0.1-0.20210329233242-e0607006dce6 h1:n9SLPLz2PRg2X+lnWxioxTmtAa2ZqjR8EwL/tZD7BAY= -github.com/btcsuite/btcwallet/wallet/txsizes v1.0.1-0.20210329233242-e0607006dce6/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= +github.com/btcsuite/btcwallet/wallet/txsizes v1.0.1-0.20210519225359-6ab9b615576f h1:bzrmHuQ3ZGWWhGDyTL0OqihQWXGXSXNuBPkDoDB8SS4= +github.com/btcsuite/btcwallet/wallet/txsizes v1.0.1-0.20210519225359-6ab9b615576f/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs= github.com/btcsuite/btcwallet/walletdb v1.3.4/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= github.com/btcsuite/btcwallet/walletdb v1.3.5-0.20210513043850-3a2f12e3a954/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= github.com/btcsuite/btcwallet/walletdb v1.3.5 h1:SoxUPLgJUkyO1XqON6X7x+rjHJoIpRQov8o8X6gNoz8= diff --git a/lnd.go b/lnd.go index 81831ffd01..c1edf1eed4 100644 --- a/lnd.go +++ b/lnd.go @@ -700,6 +700,19 @@ func Main(cfg *Config, lisCfg ListenerCfg, interceptor signal.Interceptor) error }, } + // Parse coin selection strategy. + switch cfg.CoinSelectionStrategy { + case "largest": + chainControlCfg.CoinSelectionStrategy = wallet.CoinSelectionLargest + + case "random": + chainControlCfg.CoinSelectionStrategy = wallet.CoinSelectionRandom + + default: + return fmt.Errorf("unknown coin selection strategy %v", + cfg.CoinSelectionStrategy) + } + activeChainControl, cleanup, err := chainreg.NewChainControl( chainControlCfg, blockCache, ) diff --git a/lnwallet/btcwallet/btcwallet.go b/lnwallet/btcwallet/btcwallet.go index 8cf9a84594..46286a3227 100644 --- a/lnwallet/btcwallet/btcwallet.go +++ b/lnwallet/btcwallet/btcwallet.go @@ -647,7 +647,8 @@ func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut, } return b.wallet.SendOutputs( - outputs, nil, defaultAccount, minConfs, feeSatPerKB, label, + outputs, nil, defaultAccount, minConfs, feeSatPerKB, + b.cfg.CoinSelectionStrategy, label, ) } @@ -697,7 +698,8 @@ func (b *BtcWallet) CreateSimpleTx(outputs []*wire.TxOut, } return b.wallet.CreateSimpleTx( - nil, defaultAccount, outputs, minConfs, feeSatPerKB, dryRun, + nil, defaultAccount, outputs, minConfs, feeSatPerKB, + b.cfg.CoinSelectionStrategy, dryRun, ) } @@ -1100,7 +1102,10 @@ func (b *BtcWallet) FundPsbt(packet *psbt.Packet, // Let the wallet handle coin selection and/or fee estimation based on // the partial TX information in the packet. - return b.wallet.FundPsbt(packet, keyScope, accountNum, feeSatPerKB) + return b.wallet.FundPsbt( + packet, keyScope, accountNum, feeSatPerKB, + b.cfg.CoinSelectionStrategy, + ) } // FinalizePsbt expects a partial transaction with all inputs and outputs fully diff --git a/lnwallet/btcwallet/config.go b/lnwallet/btcwallet/config.go index 953d846158..d898326713 100644 --- a/lnwallet/btcwallet/config.go +++ b/lnwallet/btcwallet/config.go @@ -74,6 +74,10 @@ type Config struct { // LoaderOptions holds functional wallet db loader options. LoaderOptions []LoaderOption + + // CoinSelectionStrategy is the strategy that is used for selecting + // coins when funding a transaction. + CoinSelectionStrategy wallet.CoinSelectionStrategy } // NetworkDir returns the directory name of a network directory to hold wallet diff --git a/lnwallet/chanfunding/wallet_assembler.go b/lnwallet/chanfunding/wallet_assembler.go index ee335f324a..5045628532 100644 --- a/lnwallet/chanfunding/wallet_assembler.go +++ b/lnwallet/chanfunding/wallet_assembler.go @@ -250,7 +250,9 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) { "sat/kw as fee rate", int64(r.FeeRate)) // Find all unlocked unspent witness outputs that satisfy the - // minimum number of confirmations required. + // minimum number of confirmations required. Coin selection in + // this function currently ignores the configured coin selection + // strategy. coins, err := w.cfg.CoinSource.ListCoins( r.MinConfs, math.MaxInt32, ) diff --git a/sample-lnd.conf b/sample-lnd.conf index 2cfe971641..39377e0799 100644 --- a/sample-lnd.conf +++ b/sample-lnd.conf @@ -112,6 +112,10 @@ ; write access to all invoice related RPCs. ; invoicemacaroonpath=~/.lnd/data/chain/bitcoin/simnet/invoice.macaroon +; The strategy to use for selecting coins for wallet transactions. Options are +; 'largest' and 'random'. +; coin-selection-strategy=largest + ; A period to wait before for closing channels with outgoing htlcs that have ; timed out and are a result of this nodes instead payment. In addition to our ; current block based deadline, is specified this grace period will also be taken diff --git a/sweep/tx_input_set.go b/sweep/tx_input_set.go index 90715be50b..dc2d6af2e2 100644 --- a/sweep/tx_input_set.go +++ b/sweep/tx_input_set.go @@ -332,7 +332,8 @@ func (t *txInputSet) tryAddWalletInputsIfNeeded() error { } // Retrieve wallet utxos. Only consider confirmed utxos to prevent - // problems around RBF rules for unconfirmed inputs. + // problems around RBF rules for unconfirmed inputs. This currently + // ignores the configured coin selection strategy. utxos, err := t.wallet.ListUnspentWitnessFromDefaultAccount( 1, math.MaxInt32, )