From 42f4afef752abf572b2c091ada24163caced5eda Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Mon, 29 Mar 2021 15:23:46 +0200 Subject: [PATCH] multi: add random coin selection --- chainreg/chainregistry.go | 21 +++++++++++++-------- config.go | 7 +++++++ go.mod | 6 +++--- go.sum | 12 ++++++------ lnd.go | 13 +++++++++++++ lnwallet/btcwallet/btcwallet.go | 11 ++++++++--- lnwallet/btcwallet/config.go | 4 ++++ lnwallet/chanfunding/wallet_assembler.go | 4 +++- sample-lnd.conf | 4 ++++ sweep/tx_input_set.go | 3 ++- 10 files changed, 63 insertions(+), 22 deletions(-) diff --git a/chainreg/chainregistry.go b/chainreg/chainregistry.go index 13d3db18..2002572c 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 232c90be..e9223f73 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 996de439..18ab47f3 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 2a1978a0..e76e6671 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 81831ffd..c1edf1ee 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 8cf9a845..46286a32 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 953d8461..d8983267 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 ee335f32..50456285 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 2cfe9716..39377e07 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 90715be5..dc2d6af2 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, )