multi: add random coin selection

This commit is contained in:
Joost Jager 2021-03-29 15:23:46 +02:00
parent 4f98cea820
commit 42f4afef75
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
10 changed files with 63 additions and 22 deletions

@ -113,6 +113,10 @@ type Config struct {
// LoaderOptions holds functional wallet db loader options. // LoaderOptions holds functional wallet db loader options.
LoaderOptions []btcwallet.LoaderOption LoaderOptions []btcwallet.LoaderOption
// CoinSelectionStrategy is the strategy that is used for selecting
// coins when funding a transaction.
CoinSelectionStrategy wallet.CoinSelectionStrategy
} }
const ( const (
@ -286,6 +290,7 @@ func NewChainControl(cfg *Config, blockCache *blockcache.BlockCache) (
CoinType: cfg.ActiveNetParams.CoinType, CoinType: cfg.ActiveNetParams.CoinType,
Wallet: cfg.Wallet, Wallet: cfg.Wallet,
LoaderOptions: cfg.LoaderOptions, LoaderOptions: cfg.LoaderOptions,
CoinSelectionStrategy: cfg.CoinSelectionStrategy,
} }
var err error var err error

@ -154,6 +154,10 @@ const (
// channel state updates that is accumulated before signing a new // channel state updates that is accumulated before signing a new
// commitment. // commitment.
defaultChannelCommitBatchSize = 10 defaultChannelCommitBatchSize = 10
// defaultCoinSelectionStrategy is the coin selection strategy that is
// used by default to fund transactions.
defaultCoinSelectionStrategy = "largest"
) )
var ( 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."` 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."` 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"` 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."` 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, ActiveNetParams: chainreg.BitcoinTestNetParams,
ChannelCommitInterval: defaultChannelCommitInterval, ChannelCommitInterval: defaultChannelCommitInterval,
ChannelCommitBatchSize: defaultChannelCommitBatchSize, ChannelCommitBatchSize: defaultChannelCommitBatchSize,
CoinSelectionStrategy: defaultCoinSelectionStrategy,
} }
} }

6
go.mod

@ -9,10 +9,10 @@ require (
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f
github.com/btcsuite/btcutil v1.0.3-0.20210514234026-faeebcb9abbe github.com/btcsuite/btcutil v1.0.3-0.20210514234026-faeebcb9abbe
github.com/btcsuite/btcutil/psbt 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 v0.12.1-0.20210519225359-6ab9b615576f
github.com/btcsuite/btcwallet/wallet/txauthor v1.0.1-0.20210329233242-e0607006dce6 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/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/walletdb v1.3.5
github.com/btcsuite/btcwallet/wtxmgr v1.3.0 github.com/btcsuite/btcwallet/wtxmgr v1.3.0
github.com/davecgh/go-spew v1.1.1 github.com/davecgh/go-spew v1.1.1

12
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.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 h1:+zkzfj2bGHMOuxxf8xG3d5mDvd7phT7IyVv+8sQizqc=
github.com/btcsuite/btcutil/psbt v1.0.3-0.20210514234026-faeebcb9abbe/go.mod h1:LVveMu4VaNSkIRTZu2+ut0HDBRuYjqGocxDMNS1KuGQ= 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.1-0.20210519225359-6ab9b615576f h1:Me6OOQP2ZYttZuViKXHVegXPKz2n42zNbHI3ljPeqwU=
github.com/btcsuite/btcwallet v0.12.0/go.mod h1:f1HuBGov5+OTp40Gh1vA+tvF6d7bbuLFTceJMRB7fXw= 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.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.20210519225359-6ab9b615576f h1:uzCtWqLJ6dlufUhpmoNgaegF87Pb9kOwPmpFYEi2up4=
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/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 h1:2VsfS0sBedcM5KmDzRMT3+b6xobqWveZGvjb+jFez5w=
github.com/btcsuite/btcwallet/wallet/txrules v1.0.0/go.mod h1:UwQE78yCerZ313EXZwEiu3jNAtfXj2n2+c8RWiE/WNA= 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.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.20210519225359-6ab9b615576f h1:bzrmHuQ3ZGWWhGDyTL0OqihQWXGXSXNuBPkDoDB8SS4=
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/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs=
github.com/btcsuite/btcwallet/walletdb v1.3.4/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= 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-0.20210513043850-3a2f12e3a954/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU=
github.com/btcsuite/btcwallet/walletdb v1.3.5 h1:SoxUPLgJUkyO1XqON6X7x+rjHJoIpRQov8o8X6gNoz8= github.com/btcsuite/btcwallet/walletdb v1.3.5 h1:SoxUPLgJUkyO1XqON6X7x+rjHJoIpRQov8o8X6gNoz8=

13
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( activeChainControl, cleanup, err := chainreg.NewChainControl(
chainControlCfg, blockCache, chainControlCfg, blockCache,
) )

@ -647,7 +647,8 @@ func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut,
} }
return b.wallet.SendOutputs( 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( 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 // Let the wallet handle coin selection and/or fee estimation based on
// the partial TX information in the packet. // 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 // FinalizePsbt expects a partial transaction with all inputs and outputs fully

@ -74,6 +74,10 @@ type Config struct {
// LoaderOptions holds functional wallet db loader options. // LoaderOptions holds functional wallet db loader options.
LoaderOptions []LoaderOption 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 // NetworkDir returns the directory name of a network directory to hold wallet

@ -250,7 +250,9 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) {
"sat/kw as fee rate", int64(r.FeeRate)) "sat/kw as fee rate", int64(r.FeeRate))
// Find all unlocked unspent witness outputs that satisfy the // 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( coins, err := w.cfg.CoinSource.ListCoins(
r.MinConfs, math.MaxInt32, r.MinConfs, math.MaxInt32,
) )

@ -112,6 +112,10 @@
; write access to all invoice related RPCs. ; write access to all invoice related RPCs.
; invoicemacaroonpath=~/.lnd/data/chain/bitcoin/simnet/invoice.macaroon ; 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 ; 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 ; 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 ; current block based deadline, is specified this grace period will also be taken

@ -332,7 +332,8 @@ func (t *txInputSet) tryAddWalletInputsIfNeeded() error {
} }
// Retrieve wallet utxos. Only consider confirmed utxos to prevent // 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( utxos, err := t.wallet.ListUnspentWitnessFromDefaultAccount(
1, math.MaxInt32, 1, math.MaxInt32,
) )