multi: replace DefaultDustLimit with script-specific DustLimitForSize

This commit updates call-sites to use the proper dust limits for
various script types. This also updates the default dust limit used
in the funding flow to be 354 satoshis instead of 573 satoshis.
This commit is contained in:
eugene 2021-09-23 15:40:37 -04:00
parent 3385d38414
commit fdcd726f9a
No known key found for this signature in database
GPG key ID: 118759E83439A9B1
27 changed files with 330 additions and 154 deletions

View file

@ -174,15 +174,6 @@ const (
BtcToLtcConversionRate = 60 BtcToLtcConversionRate = 60
) )
// DefaultBtcChannelConstraints is the default set of channel constraints that are
// meant to be used when initially funding a Bitcoin channel.
//
// TODO(halseth): make configurable at startup?
var DefaultBtcChannelConstraints = channeldb.ChannelConstraints{
DustLimit: lnwallet.DefaultDustLimit(),
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
}
// DefaultLtcChannelConstraints is the default set of channel constraints that are // DefaultLtcChannelConstraints is the default set of channel constraints that are
// meant to be used when initially funding a Litecoin channel. // meant to be used when initially funding a Litecoin channel.
var DefaultLtcChannelConstraints = channeldb.ChannelConstraints{ var DefaultLtcChannelConstraints = channeldb.ChannelConstraints{
@ -235,6 +226,19 @@ type ChainControl struct {
MinHtlcIn lnwire.MilliSatoshi MinHtlcIn lnwire.MilliSatoshi
} }
// GenDefaultBtcChannelConstraints generates the default set of channel
// constraints that are to be used when funding a Bitcoin channel.
func GenDefaultBtcConstraints() channeldb.ChannelConstraints {
// We use the dust limit for the maximally sized witness program with
// a 40-byte data push.
dustLimit := lnwallet.DustLimitForSize(input.UnknownWitnessSize)
return channeldb.ChannelConstraints{
DustLimit: dustLimit,
MaxAcceptedHtlcs: input.MaxHTLCNumber / 2,
}
}
// NewChainControl attempts to create a ChainControl instance according // NewChainControl attempts to create a ChainControl instance according
// to the parameters in the passed configuration. Currently three // to the parameters in the passed configuration. Currently three
// branches of ChainControl instances exist: one backed by a running btcd // branches of ChainControl instances exist: one backed by a running btcd
@ -674,7 +678,7 @@ func NewChainControl(cfg *Config, blockCache *blockcache.BlockCache) (
cc.Wc = wc cc.Wc = wc
// Select the default channel constraints for the primary chain. // Select the default channel constraints for the primary chain.
channelConstraints := DefaultBtcChannelConstraints channelConstraints := GenDefaultBtcConstraints()
if cfg.PrimaryChain() == LitecoinChain { if cfg.PrimaryChain() == LitecoinChain {
channelConstraints = DefaultLtcChannelConstraints channelConstraints = DefaultLtcChannelConstraints
} }

View file

@ -3114,19 +3114,10 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
maxCSV = f.cfg.MaxLocalCSVDelay maxCSV = f.cfg.MaxLocalCSVDelay
} }
// We'll determine our dust limit depending on which chain is active.
var ourDustLimit btcutil.Amount
switch f.cfg.RegisteredChains.PrimaryChain() {
case chainreg.BitcoinChain:
ourDustLimit = lnwallet.DefaultDustLimit()
case chainreg.LitecoinChain:
ourDustLimit = chainreg.DefaultLitecoinDustLimit
}
log.Infof("Initiating fundingRequest(local_amt=%v "+ log.Infof("Initiating fundingRequest(local_amt=%v "+
"(subtract_fees=%v), push_amt=%v, chain_hash=%v, peer=%x, "+ "(subtract_fees=%v), push_amt=%v, chain_hash=%v, peer=%x, "+
"dust_limit=%v, min_confs=%v)", localAmt, msg.SubtractFees, "min_confs=%v)", localAmt, msg.SubtractFees, msg.PushAmt,
msg.PushAmt, msg.ChainHash, peerKey.SerializeCompressed(), msg.ChainHash, peerKey.SerializeCompressed(), msg.MinConfs)
ourDustLimit, msg.MinConfs)
// We set the channel flags to indicate whether we want this channel to // We set the channel flags to indicate whether we want this channel to
// be announced to the network. // be announced to the network.
@ -3300,6 +3291,12 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
// request to the remote peer, kicking off the funding workflow. // request to the remote peer, kicking off the funding workflow.
ourContribution := reservation.OurContribution() ourContribution := reservation.OurContribution()
// Fetch our dust limit which is part of the default channel
// constraints, and log it.
ourDustLimit := ourContribution.DustLimit
log.Infof("Dust limit for pendingID(%x): %v", chanID, ourDustLimit)
// Finally, we'll use the current value of the channels and our default // Finally, we'll use the current value of the channels and our default
// policy to determine of required commitment constraints for the // policy to determine of required commitment constraints for the
// remote party. // remote party.
@ -3313,7 +3310,7 @@ func (f *Manager) handleInitFundingMsg(msg *InitFundingMsg) {
PendingChannelID: chanID, PendingChannelID: chanID,
FundingAmount: capacity, FundingAmount: capacity,
PushAmount: msg.PushAmt, PushAmount: msg.PushAmt,
DustLimit: ourContribution.DustLimit, DustLimit: ourDustLimit,
MaxValueInFlight: maxValue, MaxValueInFlight: maxValue,
ChannelReserve: chanReserve, ChannelReserve: chanReserve,
HtlcMinimum: minHtlcIn, HtlcMinimum: minHtlcIn,

View file

@ -276,7 +276,7 @@ func createTestWallet(cdb *channeldb.DB, netParams *chaincfg.Params,
ChainIO: bio, ChainIO: bio,
FeeEstimator: estimator, FeeEstimator: estimator,
NetParams: *netParams, NetParams: *netParams,
DefaultConstraints: chainreg.DefaultBtcChannelConstraints, DefaultConstraints: chainreg.GenDefaultBtcConstraints(),
}) })
if err != nil { if err != nil {
return nil, err return nil, err

11
go.mod
View file

@ -5,13 +5,14 @@ require (
github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e // indirect github.com/NebulousLabs/fastrand v0.0.0-20181203155948-6fb6489aac4e // indirect
github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82 github.com/NebulousLabs/go-upnp v0.0.0-20180202185039-29b680b06c82
github.com/Yawning/aez v0.0.0-20180114000226-4dad034d9db2 github.com/Yawning/aez v0.0.0-20180114000226-4dad034d9db2
github.com/btcsuite/btcd v0.22.0-beta.0.20210803133449-f5a1fb9965e4 github.com/btcsuite/btcd v0.22.0-beta.0.20210916191717-f8e6854197cd
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.20210527170813-e2ba6805a890 github.com/btcsuite/btcutil v1.0.3-0.20210527170813-e2ba6805a890
github.com/btcsuite/btcutil/psbt v1.0.3-0.20210527170813-e2ba6805a890 github.com/btcsuite/btcutil/psbt v1.0.3-0.20210527170813-e2ba6805a890
github.com/btcsuite/btcwallet v0.12.1-0.20210826004415-4ef582f76b02 github.com/btcsuite/btcwallet v0.12.1-0.20210826004415-4ef582f76b02
github.com/btcsuite/btcwallet/wallet/txauthor v1.0.2-0.20210803004036-eebed51155ec github.com/btcsuite/btcwallet/wallet/txauthor v1.1.0
github.com/btcsuite/btcwallet/wallet/txrules v1.0.0 github.com/btcsuite/btcwallet/wallet/txrules v1.1.0
github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0 // indirect
github.com/btcsuite/btcwallet/walletdb v1.3.6-0.20210803004036-eebed51155ec github.com/btcsuite/btcwallet/walletdb v1.3.6-0.20210803004036-eebed51155ec
github.com/btcsuite/btcwallet/wtxmgr v1.3.1-0.20210822222949-9b5a201c344c github.com/btcsuite/btcwallet/wtxmgr v1.3.1-0.20210822222949-9b5a201c344c
github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f github.com/coreos/go-systemd v0.0.0-20190719114852-fd7a80b32e1f
@ -37,7 +38,7 @@ require (
github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2 // indirect github.com/juju/testing v0.0.0-20190723135506-ce30eb24acd2 // indirect
github.com/juju/utils v0.0.0-20180820210520-bf9cc5bdd62d // indirect github.com/juju/utils v0.0.0-20180820210520-bf9cc5bdd62d // indirect
github.com/juju/version v0.0.0-20180108022336-b64dbd566305 // indirect github.com/juju/version v0.0.0-20180108022336-b64dbd566305 // indirect
github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec github.com/kkdai/bstream v1.0.0
github.com/lightninglabs/neutrino v0.12.1 github.com/lightninglabs/neutrino v0.12.1
github.com/lightninglabs/protobuf-hex-display v1.4.3-hex-display github.com/lightninglabs/protobuf-hex-display v1.4.3-hex-display
github.com/lightningnetwork/lightning-onion v1.0.2-0.20210520211913-522b799e65b1 github.com/lightningnetwork/lightning-onion v1.0.2-0.20210520211913-522b799e65b1
@ -56,7 +57,7 @@ require (
github.com/urfave/cli v1.20.0 github.com/urfave/cli v1.20.0
go.etcd.io/etcd/client/pkg/v3 v3.5.0 go.etcd.io/etcd/client/pkg/v3 v3.5.0
go.etcd.io/etcd/client/v3 v3.5.0 go.etcd.io/etcd/client/v3 v3.5.0
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 golang.org/x/crypto v0.0.0-20210921155107-089bfa567519
golang.org/x/net v0.0.0-20210913180222-943fd674d43e golang.org/x/net v0.0.0-20210913180222-943fd674d43e
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 // indirect golang.org/x/sys v0.0.0-20210915083310-ed5796bab164 // indirect

19
go.sum
View file

@ -76,8 +76,9 @@ github.com/btcsuite/btcd v0.0.0-20190629003639-c26ffa870fd8/go.mod h1:3J08xEfcug
github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI= github.com/btcsuite/btcd v0.0.0-20190824003749-130ea5bddde3/go.mod h1:3J08xEfcugPacsc34/LKRU2yO7YmuT8yt28J8k2+rrI=
github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ= github.com/btcsuite/btcd v0.20.1-beta/go.mod h1:wVuoA8VJLEcwgqHBwHmzLRazpKxTv13Px/pDuV7OomQ=
github.com/btcsuite/btcd v0.21.0-beta.0.20201208033208-6bd4c64a54fa/go.mod h1:Sv4JPQ3/M+teHz9Bo5jBpkNcP0x6r7rdihlNL/7tTAs= github.com/btcsuite/btcd v0.21.0-beta.0.20201208033208-6bd4c64a54fa/go.mod h1:Sv4JPQ3/M+teHz9Bo5jBpkNcP0x6r7rdihlNL/7tTAs=
github.com/btcsuite/btcd v0.22.0-beta.0.20210803133449-f5a1fb9965e4 h1:EmyLrldY44jDVa3dQ2iscj1S6ExuVJhRzCZBOXo93r0=
github.com/btcsuite/btcd v0.22.0-beta.0.20210803133449-f5a1fb9965e4/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA= github.com/btcsuite/btcd v0.22.0-beta.0.20210803133449-f5a1fb9965e4/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA=
github.com/btcsuite/btcd v0.22.0-beta.0.20210916191717-f8e6854197cd h1:Nq1fLF6IA8XfW0HTpLaVZoDKazt05J1C2AAeswYloBE=
github.com/btcsuite/btcd v0.22.0-beta.0.20210916191717-f8e6854197cd/go.mod h1:9n5ntfhhHQBIhUvlhDvD3Qg6fRUj4jkN0VB8L8svzOA=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f h1:bAs4lUbRJpnnkd9VhRV3jjAVU7DJVjMaK+IsvSeZvFo=
github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA= github.com/btcsuite/btclog v0.0.0-20170628155309-84c8d2346e9f/go.mod h1:TdznJufoqS23FtqVCzL0ZqgP5MqXbb4fg/WgDys70nA=
github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg= github.com/btcsuite/btcutil v0.0.0-20190425235716-9e5f4b9a998d/go.mod h1:+5NJ2+qvTyV9exUAL/rxXi3DcLg2Ts+ymUAY5y4NvMg=
@ -92,13 +93,15 @@ github.com/btcsuite/btcwallet v0.12.1-0.20210826004415-4ef582f76b02 h1:Q8Scm1SXN
github.com/btcsuite/btcwallet v0.12.1-0.20210826004415-4ef582f76b02/go.mod h1:SdqXKJoEEi5LJq6zU67PcKiyqF97AcUOfBfyQHC7rqQ= github.com/btcsuite/btcwallet v0.12.1-0.20210826004415-4ef582f76b02/go.mod h1:SdqXKJoEEi5LJq6zU67PcKiyqF97AcUOfBfyQHC7rqQ=
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/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= 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.2-0.20210803004036-eebed51155ec h1:nuO8goa4gbgDM4iegCztF7mTq8io9NT1DAMoPrEI6S4= github.com/btcsuite/btcwallet/wallet/txauthor v1.1.0 h1:8pO0pvPX1rFRfRiol4oV6kX7dY5y4chPwhfVwUfvwtk=
github.com/btcsuite/btcwallet/wallet/txauthor v1.0.2-0.20210803004036-eebed51155ec/go.mod h1:VufDts7bd/zs3GV13f/lXc/0lXrPnvxD/NvmpG/FEKU= github.com/btcsuite/btcwallet/wallet/txauthor v1.1.0/go.mod h1:ktYuJyumYtwG+QQ832Q+kqvxWJRAei3Nqs5qhSn4nww=
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/txrules v1.1.0 h1:Vg8G8zhNVjaCdwJg2QOmLoWn4RTP7K0J9xlwY8CJnLY=
github.com/btcsuite/btcwallet/wallet/txrules v1.1.0/go.mod h1:Zn9UTqpiTH+HOd5BLzSBzULzlOPmcoeyQIA0cp0WbQQ=
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.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/wallet/txsizes v1.0.1-0.20210519225359-6ab9b615576f/go.mod h1:pauEU8UuMFiThe5PB3EO+gO5kx87Me5NvdQDsTuq6cs=
github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0 h1:wZnOolEAeNOHzHTnznw/wQv+j35ftCIokNrnOTOU5o8=
github.com/btcsuite/btcwallet/wallet/txsizes v1.1.0/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/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU= github.com/btcsuite/btcwallet/walletdb v1.3.5/go.mod h1:oJDxAEUHVtnmIIBaa22wSBPTVcs6hUp5NKWmI8xDwwU=
github.com/btcsuite/btcwallet/walletdb v1.3.6-0.20210803004036-eebed51155ec h1:zcAU3Ij8SmqaE+ITtS76fua2Niq7DRNp46sJRhi8PiI= github.com/btcsuite/btcwallet/walletdb v1.3.6-0.20210803004036-eebed51155ec h1:zcAU3Ij8SmqaE+ITtS76fua2Niq7DRNp46sJRhi8PiI=
@ -408,8 +411,9 @@ github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQL
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v0.0.0-20161212061736-f391b8402d23/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec h1:n1NeQ3SgUHyISrjFFoO5dR748Is8dBL9qpaTNfphQrs=
github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4= github.com/kkdai/bstream v0.0.0-20181106074824-b3251f7901ec/go.mod h1:J+Gs4SYgM6CZQHDETBtE9HaSEkGmuNXF86RwHhHUvq4=
github.com/kkdai/bstream v1.0.0 h1:Se5gHwgp2VT2uHfDrkbbgbgEvV9cimLELwrPJctSjg8=
github.com/kkdai/bstream v1.0.0/go.mod h1:FDnDOHt5Yx4p3FaHcioFT0QjDOtgUpvjeZqAs+NVZZA=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I= github.com/klauspost/compress v1.10.10 h1:a/y8CglcM7gLGYmlbP/stPE5sR3hbhFRUjCBfd/0B3I=
github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.10.10/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
@ -674,8 +678,9 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh
golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20201002170205-7f63de1d35b0/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I= golang.org/x/crypto v0.0.0-20201203163018-be400aefbc4c/go.mod h1:jdWPYTVW3xRLrWPugEBEK3UY2ZEsg3UU495nc5E+M+I=
golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210616213533-5ff15b29337e/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97 h1:/UOmuWzQfxxo9UtlXMwuQU8CMgg1eZXqTRwkSQJWKOI=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519 h1:7I4JAnoQBe7ZtJcBaYHi5UtiO8tQHbUSXxL+pnGRANg=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190306152737-a1d7652674e8/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8= golang.org/x/exp v0.0.0-20190510132918-efd6b22b2522/go.mod h1:ZjyILWgesfNpC6sMxTJOJm9Kp84zZh5NQWvqDGG3Qr8=

View file

@ -45,6 +45,55 @@ func WitnessScriptHash(witnessScript []byte) ([]byte, error) {
return bldr.Script() return bldr.Script()
} }
// WitnessPubKeyHash generates a pay-to-witness-pubkey-hash public key script
// paying to a version 0 witness program containing the passed serialized
// public key.
func WitnessPubKeyHash(pubkey []byte) ([]byte, error) {
bldr := txscript.NewScriptBuilder()
bldr.AddOp(txscript.OP_0)
pkhash := btcutil.Hash160(pubkey)
bldr.AddData(pkhash)
return bldr.Script()
}
// GenerateP2SH generates a pay-to-script-hash public key script paying to the
// passed redeem script.
func GenerateP2SH(script []byte) ([]byte, error) {
bldr := txscript.NewScriptBuilder()
bldr.AddOp(txscript.OP_HASH160)
scripthash := btcutil.Hash160(script)
bldr.AddData(scripthash)
bldr.AddOp(txscript.OP_EQUAL)
return bldr.Script()
}
// GenerateP2PKH generates a pay-to-public-key-hash public key script paying to
// the passed serialized public key.
func GenerateP2PKH(pubkey []byte) ([]byte, error) {
bldr := txscript.NewScriptBuilder()
bldr.AddOp(txscript.OP_DUP)
bldr.AddOp(txscript.OP_HASH160)
pkhash := btcutil.Hash160(pubkey)
bldr.AddData(pkhash)
bldr.AddOp(txscript.OP_EQUALVERIFY)
bldr.AddOp(txscript.OP_CHECKSIG)
return bldr.Script()
}
// GenerateUnknownWitness generates the maximum-sized witness public key script
// consisting of a version push and a 40-byte data push.
func GenerateUnknownWitness() ([]byte, error) {
bldr := txscript.NewScriptBuilder()
bldr.AddOp(txscript.OP_0)
witnessScript := make([]byte, 40)
bldr.AddData(witnessScript)
return bldr.Script()
}
// GenMultiSigScript generates the non-p2sh'd multisig script for 2 of 2 // GenMultiSigScript generates the non-p2sh'd multisig script for 2 of 2
// pubkeys. // pubkeys.
func GenMultiSigScript(aPub, bPub []byte) ([]byte, error) { func GenMultiSigScript(aPub, bPub []byte) ([]byte, error) {

View file

@ -41,11 +41,20 @@ const (
// - P2WSHWitnessProgram: 34 bytes // - P2WSHWitnessProgram: 34 bytes
NestedP2WSHSize = 1 + P2WSHSize NestedP2WSHSize = 1 + P2WSHSize
// UnknownWitnessSize 42 bytes
// - OP_x: 1 byte
// - OP_DATA: 1 byte (max-size length)
// - max-size: 40 bytes
UnknownWitnessSize = 1 + 1 + 40
// P2PKHSize 25 bytes
P2PKHSize = 25
// P2PKHOutputSize 34 bytes // P2PKHOutputSize 34 bytes
// - value: 8 bytes // - value: 8 bytes
// - var_int: 1 byte (pkscript_length) // - var_int: 1 byte (pkscript_length)
// - pkscript (p2pkh): 25 bytes // - pkscript (p2pkh): 25 bytes
P2PKHOutputSize = 8 + 1 + 25 P2PKHOutputSize = 8 + 1 + P2PKHSize
// P2WKHOutputSize 31 bytes // P2WKHOutputSize 31 bytes
// - value: 8 bytes // - value: 8 bytes
@ -59,11 +68,14 @@ const (
// - pkscript (p2wsh): 34 bytes // - pkscript (p2wsh): 34 bytes
P2WSHOutputSize = 8 + 1 + P2WSHSize P2WSHOutputSize = 8 + 1 + P2WSHSize
// P2SHSize 23 bytes
P2SHSize = 23
// P2SHOutputSize 32 bytes // P2SHOutputSize 32 bytes
// - value: 8 bytes // - value: 8 bytes
// - var_int: 1 byte (pkscript_length) // - var_int: 1 byte (pkscript_length)
// - pkscript (p2sh): 23 bytes // - pkscript (p2sh): 23 bytes
P2SHOutputSize = 8 + 1 + 23 P2SHOutputSize = 8 + 1 + P2SHSize
// P2PKHScriptSigSize 108 bytes // P2PKHScriptSigSize 108 bytes
// - OP_DATA: 1 byte (signature length) // - OP_DATA: 1 byte (signature length)

View file

@ -16,6 +16,7 @@ import (
"github.com/davecgh/go-spew/spew" "github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/chainreg" "github.com/lightningnetwork/lnd/chainreg"
"github.com/lightningnetwork/lnd/funding" "github.com/lightningnetwork/lnd/funding"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lncfg" "github.com/lightningnetwork/lnd/lncfg"
"github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc"
@ -417,12 +418,15 @@ func testListChannels(net *lntest.NetworkHarness, t *harnessTest) {
// Check the returned response is correct. // Check the returned response is correct.
aliceChannel := resp.Channels[0] aliceChannel := resp.Channels[0]
// Calculate the dust limit we'll use for the test.
dustLimit := lnwallet.DustLimitForSize(input.UnknownWitnessSize)
// defaultConstraints is a ChannelConstraints with default values. It is // defaultConstraints is a ChannelConstraints with default values. It is
// used to test against Alice's local channel constraints. // used to test against Alice's local channel constraints.
defaultConstraints := &lnrpc.ChannelConstraints{ defaultConstraints := &lnrpc.ChannelConstraints{
CsvDelay: 4, CsvDelay: 4,
ChanReserveSat: 1000, ChanReserveSat: 1000,
DustLimitSat: uint64(lnwallet.DefaultDustLimit()), DustLimitSat: uint64(dustLimit),
MaxPendingAmtMsat: 99000000, MaxPendingAmtMsat: 99000000,
MinHtlcMsat: 1, MinHtlcMsat: 1,
MaxAcceptedHtlcs: bobRemoteMaxHtlcs, MaxAcceptedHtlcs: bobRemoteMaxHtlcs,
@ -438,7 +442,7 @@ func testListChannels(net *lntest.NetworkHarness, t *harnessTest) {
customizedConstraints := &lnrpc.ChannelConstraints{ customizedConstraints := &lnrpc.ChannelConstraints{
CsvDelay: 4, CsvDelay: 4,
ChanReserveSat: 1000, ChanReserveSat: 1000,
DustLimitSat: uint64(lnwallet.DefaultDustLimit()), DustLimitSat: uint64(dustLimit),
MaxPendingAmtMsat: 99000000, MaxPendingAmtMsat: 99000000,
MinHtlcMsat: customizedMinHtlc, MinHtlcMsat: customizedMinHtlc,
MaxAcceptedHtlcs: aliceRemoteMaxHtlcs, MaxAcceptedHtlcs: aliceRemoteMaxHtlcs,

View file

@ -219,7 +219,7 @@ func CoinSelectSubtractFees(feeRate chainfee.SatPerKWeight, amt,
// If the the output is too small after subtracting the fee, the coin // If the the output is too small after subtracting the fee, the coin
// selection cannot be performed with an amount this small. // selection cannot be performed with an amount this small.
if outputAmt <= dustLimit { if outputAmt < dustLimit {
return nil, 0, 0, fmt.Errorf("output amount(%v) after "+ return nil, 0, 0, fmt.Errorf("output amount(%v) after "+
"subtracting fees(%v) below dust limit(%v)", outputAmt, "subtracting fees(%v) below dust limit(%v)", outputAmt,
requiredFeeNoChange, dustLimit) requiredFeeNoChange, dustLimit)
@ -233,7 +233,7 @@ func CoinSelectSubtractFees(feeRate chainfee.SatPerKWeight, amt,
// If adding a change output leads to both outputs being above // If adding a change output leads to both outputs being above
// the dust limit, we'll add the change output. Otherwise we'll // the dust limit, we'll add the change output. Otherwise we'll
// go with the no change tx we originally found. // go with the no change tx we originally found.
if newChange > dustLimit && newOutput > dustLimit { if newChange >= dustLimit && newOutput >= dustLimit {
outputAmt = newOutput outputAmt = newOutput
changeAmt = newChange changeAmt = newChange
} }

View file

@ -383,7 +383,7 @@ func TestCoinSelectSubtractFees(t *testing.T) {
{ {
TxOut: wire.TxOut{ TxOut: wire.TxOut{
PkScript: p2wkhScript, PkScript: p2wkhScript,
Value: int64(fundingFee(feeRate, 1, false) + dustLimit), Value: int64(fundingFee(feeRate, 1, false) + dustLimit - 1),
}, },
}, },
}, },

View file

@ -304,7 +304,7 @@ func (w *WalletAssembler) ProvisionChannel(r *Request) (Intent, error) {
// Sanity check: The addition of the outputs should not lead to the // Sanity check: The addition of the outputs should not lead to the
// creation of dust. // creation of dust.
if changeAmt != 0 && changeAmt <= w.cfg.DustLimit { if changeAmt != 0 && changeAmt < w.cfg.DustLimit {
return fmt.Errorf("change amount(%v) after coin "+ return fmt.Errorf("change amount(%v) after coin "+
"select is below dust limit(%v)", changeAmt, "select is below dust limit(%v)", changeAmt,
w.cfg.DustLimit) w.cfg.DustLimit)

View file

@ -1,13 +1,50 @@
package lnwallet package lnwallet
import ( import (
"github.com/btcsuite/btcd/mempool"
"github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/btcsuite/btcwallet/wallet/txrules"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
) )
// DefaultDustLimit is used to calculate the dust HTLC amount which will be // DustLimitForSize retrieves the dust limit for a given pkscript size. Given
// send to other node during funding process. // the size, it automatically determines whether the script is a witness script
func DefaultDustLimit() btcutil.Amount { // or not. It calls btcd's GetDustThreshold method under the hood. It must be
return txrules.GetDustThreshold(input.P2WSHSize, txrules.DefaultRelayFeePerKb) // called with a proper size parameter or else a panic occurs.
func DustLimitForSize(scriptSize int) btcutil.Amount {
var (
dustlimit btcutil.Amount
pkscript []byte
)
// With the size of the script, determine which type of pkscript to
// create. This will be used in the call to GetDustThreshold. We pass
// in an empty byte slice since the contents of the script itself don't
// matter.
switch scriptSize {
case input.P2WPKHSize:
pkscript, _ = input.WitnessPubKeyHash([]byte{})
case input.P2WSHSize:
pkscript, _ = input.WitnessScriptHash([]byte{})
case input.P2SHSize:
pkscript, _ = input.GenerateP2SH([]byte{})
case input.P2PKHSize:
pkscript, _ = input.GenerateP2PKH([]byte{})
case input.UnknownWitnessSize:
pkscript, _ = input.GenerateUnknownWitness()
default:
panic("invalid script size")
}
// Call GetDustThreshold with a TxOut containing the generated
// pkscript.
txout := &wire.TxOut{PkScript: pkscript}
dustlimit = btcutil.Amount(mempool.GetDustThreshold(txout))
return dustlimit
} }

View file

@ -0,0 +1,56 @@
package lnwallet
import (
"testing"
"github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/input"
"github.com/stretchr/testify/require"
)
// TestDustLimitForSize tests that we receive the expected dust limits for
// various script types from btcd's GetDustThreshold function.
func TestDustLimitForSize(t *testing.T) {
t.Parallel()
tests := []struct {
name string
size int
expectedLimit btcutil.Amount
}{
{
name: "p2pkh dust limit",
size: input.P2PKHSize,
expectedLimit: btcutil.Amount(546),
},
{
name: "p2sh dust limit",
size: input.P2SHSize,
expectedLimit: btcutil.Amount(540),
},
{
name: "p2wpkh dust limit",
size: input.P2WPKHSize,
expectedLimit: btcutil.Amount(294),
},
{
name: "p2wsh dust limit",
size: input.P2WSHSize,
expectedLimit: btcutil.Amount(330),
},
{
name: "unknown witness limit",
size: input.UnknownWitnessSize,
expectedLimit: btcutil.Amount(354),
},
}
for _, test := range tests {
test := test
t.Run(test.name, func(t *testing.T) {
dustlimit := DustLimitForSize(test.size)
require.Equal(t, test.expectedLimit, dustlimit)
})
}
}

View file

@ -205,6 +205,9 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
feeMSat += 2 * lnwire.NewMSatFromSatoshis(anchorSize) feeMSat += 2 * lnwire.NewMSatFromSatoshis(anchorSize)
} }
// Used to cut down on verbosity.
defaultDust := wallet.Cfg.DefaultConstraints.DustLimit
// If we're the responder to a single-funder reservation, then we have // If we're the responder to a single-funder reservation, then we have
// no initial balance in the channel unless the remote party is pushing // no initial balance in the channel unless the remote party is pushing
// some funds to us within the first commitment state. // some funds to us within the first commitment state.
@ -218,7 +221,7 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
if int64(theirBalance) < 0 { if int64(theirBalance) < 0 {
return nil, ErrFunderBalanceDust( return nil, ErrFunderBalanceDust(
int64(commitFee), int64(theirBalance.ToSatoshis()), int64(commitFee), int64(theirBalance.ToSatoshis()),
int64(2*DefaultDustLimit()), int64(2*defaultDust),
) )
} }
} else { } else {
@ -247,7 +250,7 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
if int64(ourBalance) < 0 { if int64(ourBalance) < 0 {
return nil, ErrFunderBalanceDust( return nil, ErrFunderBalanceDust(
int64(commitFee), int64(ourBalance), int64(commitFee), int64(ourBalance),
int64(2*DefaultDustLimit()), int64(2*defaultDust),
) )
} }
} }
@ -257,21 +260,21 @@ func NewChannelReservation(capacity, localFundingAmt btcutil.Amount,
// reject this channel creation request. // reject this channel creation request.
// //
// TODO(roasbeef): reject if 30% goes to fees? dust channel // TODO(roasbeef): reject if 30% goes to fees? dust channel
if initiator && ourBalance.ToSatoshis() <= 2*DefaultDustLimit() { if initiator && ourBalance.ToSatoshis() <= 2*defaultDust {
return nil, ErrFunderBalanceDust( return nil, ErrFunderBalanceDust(
int64(commitFee), int64(commitFee),
int64(ourBalance.ToSatoshis()), int64(ourBalance.ToSatoshis()),
int64(2*DefaultDustLimit()), int64(2*defaultDust),
) )
} }
// Similarly we ensure their balance is reasonable if we are not the // Similarly we ensure their balance is reasonable if we are not the
// initiator. // initiator.
if !initiator && theirBalance.ToSatoshis() <= 2*DefaultDustLimit() { if !initiator && theirBalance.ToSatoshis() <= 2*defaultDust {
return nil, ErrFunderBalanceDust( return nil, ErrFunderBalanceDust(
int64(commitFee), int64(commitFee),
int64(theirBalance.ToSatoshis()), int64(theirBalance.ToSatoshis()),
int64(2*DefaultDustLimit()), int64(2*defaultDust),
) )
} }

View file

@ -446,7 +446,7 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness,
} }
aliceChanReservation.SetNumConfsRequired(numReqConfs) aliceChanReservation.SetNumConfsRequired(numReqConfs)
channelConstraints := &channeldb.ChannelConstraints{ channelConstraints := &channeldb.ChannelConstraints{
DustLimit: lnwallet.DefaultDustLimit(), DustLimit: alice.Cfg.DefaultConstraints.DustLimit,
ChanReserve: fundingAmount / 100, ChanReserve: fundingAmount / 100,
MaxPendingAmount: lnwire.NewMSatFromSatoshis(fundingAmount), MaxPendingAmount: lnwire.NewMSatFromSatoshis(fundingAmount),
MinHTLC: 1, MinHTLC: 1,
@ -896,7 +896,7 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness,
} }
aliceChanReservation.SetNumConfsRequired(numReqConfs) aliceChanReservation.SetNumConfsRequired(numReqConfs)
channelConstraints := &channeldb.ChannelConstraints{ channelConstraints := &channeldb.ChannelConstraints{
DustLimit: lnwallet.DefaultDustLimit(), DustLimit: alice.Cfg.DefaultConstraints.DustLimit,
ChanReserve: fundingAmt / 100, ChanReserve: fundingAmt / 100,
MaxPendingAmount: lnwire.NewMSatFromSatoshis(fundingAmt), MaxPendingAmount: lnwire.NewMSatFromSatoshis(fundingAmt),
MinHTLC: 1, MinHTLC: 1,

View file

@ -542,16 +542,19 @@ func testSpendValidation(t *testing.T, tweakless bool) {
Privkeys: []*btcec.PrivateKey{aliceKeyPriv}, Privkeys: []*btcec.PrivateKey{aliceKeyPriv},
} }
// Calculate the dust limit we'll use for the test.
dustLimit := DustLimitForSize(input.UnknownWitnessSize)
aliceChanCfg := &channeldb.ChannelConfig{ aliceChanCfg := &channeldb.ChannelConfig{
ChannelConstraints: channeldb.ChannelConstraints{ ChannelConstraints: channeldb.ChannelConstraints{
DustLimit: DefaultDustLimit(), DustLimit: dustLimit,
CsvDelay: csvTimeout, CsvDelay: csvTimeout,
}, },
} }
bobChanCfg := &channeldb.ChannelConfig{ bobChanCfg := &channeldb.ChannelConfig{
ChannelConstraints: channeldb.ChannelConstraints{ ChannelConstraints: channeldb.ChannelConstraints{
DustLimit: DefaultDustLimit(), DustLimit: dustLimit,
CsvDelay: csvTimeout, CsvDelay: csvTimeout,
}, },
} }

View file

@ -689,12 +689,15 @@ func (l *LightningWallet) handleFundingReserveRequest(req *InitFundingReserveMsg
// If no chanFunder was provided, then we'll assume the default // If no chanFunder was provided, then we'll assume the default
// assembler, which is backed by the wallet's internal coin selection. // assembler, which is backed by the wallet's internal coin selection.
if req.ChanFunder == nil { if req.ChanFunder == nil {
// We use the P2WSH dust limit since it is larger than the
// P2WPKH dust limit and to avoid threading through two
// different dust limits.
cfg := chanfunding.WalletConfig{ cfg := chanfunding.WalletConfig{
CoinSource: &CoinSource{l}, CoinSource: &CoinSource{l},
CoinSelectLocker: l, CoinSelectLocker: l,
CoinLocker: l, CoinLocker: l,
Signer: l.Cfg.Signer, Signer: l.Cfg.Signer,
DustLimit: DefaultDustLimit(), DustLimit: DustLimitForSize(input.P2WSHSize),
} }
req.ChanFunder = chanfunding.NewWalletAssembler(cfg) req.ChanFunder = chanfunding.NewWalletAssembler(cfg)
} }

View file

@ -1227,8 +1227,7 @@ func (r *rpcServer) SendCoins(ctx context.Context,
// pay to the change address created above if we needed to // pay to the change address created above if we needed to
// reserve any value, the rest will go to targetAddr. // reserve any value, the rest will go to targetAddr.
sweepTxPkg, err := sweep.CraftSweepAllTx( sweepTxPkg, err := sweep.CraftSweepAllTx(
feePerKw, lnwallet.DefaultDustLimit(), feePerKw, uint32(bestHeight), nil, targetAddr, wallet,
uint32(bestHeight), nil, targetAddr, wallet,
wallet, wallet.WalletController, wallet, wallet.WalletController,
r.server.cc.FeeEstimator, r.server.cc.Signer, r.server.cc.FeeEstimator, r.server.cc.Signer,
minConfs, minConfs,
@ -1280,9 +1279,9 @@ func (r *rpcServer) SendCoins(ctx context.Context,
} }
sweepTxPkg, err = sweep.CraftSweepAllTx( sweepTxPkg, err = sweep.CraftSweepAllTx(
feePerKw, lnwallet.DefaultDustLimit(), feePerKw, uint32(bestHeight), outputs,
uint32(bestHeight), outputs, targetAddr, wallet, targetAddr, wallet, wallet,
wallet, wallet.WalletController, wallet.WalletController,
r.server.cc.FeeEstimator, r.server.cc.Signer, r.server.cc.FeeEstimator, r.server.cc.Signer,
minConfs, minConfs,
) )

View file

@ -1150,7 +1150,7 @@ func (s *UtxoSweeper) getInputLists(cluster inputCluster,
if len(retryInputs) > 0 { if len(retryInputs) > 0 {
var err error var err error
allSets, err = generateInputPartitionings( allSets, err = generateInputPartitionings(
append(retryInputs, newInputs...), s.relayFeeRate, append(retryInputs, newInputs...),
cluster.sweepFeeRate, s.cfg.MaxInputsPerTx, cluster.sweepFeeRate, s.cfg.MaxInputsPerTx,
s.cfg.Wallet, s.cfg.Wallet,
) )
@ -1161,8 +1161,8 @@ func (s *UtxoSweeper) getInputLists(cluster inputCluster,
// Create sets for just the new inputs. // Create sets for just the new inputs.
newSets, err := generateInputPartitionings( newSets, err := generateInputPartitionings(
newInputs, s.relayFeeRate, cluster.sweepFeeRate, newInputs, cluster.sweepFeeRate, s.cfg.MaxInputsPerTx,
s.cfg.MaxInputsPerTx, s.cfg.Wallet, s.cfg.Wallet,
) )
if err != nil { if err != nil {
return nil, fmt.Errorf("input partitionings: %v", err) return nil, fmt.Errorf("input partitionings: %v", err)
@ -1193,7 +1193,7 @@ func (s *UtxoSweeper) sweep(inputs inputSet, feeRate chainfee.SatPerKWeight,
// Create sweep tx. // Create sweep tx.
tx, err := createSweepTx( tx, err := createSweepTx(
inputs, nil, s.currentOutputScript, uint32(currentHeight), inputs, nil, s.currentOutputScript, uint32(currentHeight),
feeRate, dustLimit(s.relayFeeRate), s.cfg.Signer, feeRate, s.cfg.Signer,
) )
if err != nil { if err != nil {
return fmt.Errorf("create sweep tx: %v", err) return fmt.Errorf("create sweep tx: %v", err)
@ -1488,7 +1488,7 @@ func (s *UtxoSweeper) CreateSweepTx(inputs []input.Input, feePref FeePreference,
return createSweepTx( return createSweepTx(
inputs, nil, pkScript, currentBlockHeight, feePerKw, inputs, nil, pkScript, currentBlockHeight, feePerKw,
dustLimit(s.relayFeeRate), s.cfg.Signer, s.cfg.Signer,
) )
} }

View file

@ -136,7 +136,8 @@ func createSweeperTestContext(t *testing.T) *sweeperTestContext {
Store: store, Store: store,
Signer: &mock.DummySigner{}, Signer: &mock.DummySigner{},
GenSweepScript: func() ([]byte, error) { GenSweepScript: func() ([]byte, error) {
script := []byte{outputScriptCount} script := make([]byte, input.P2WPKHSize)
script[0] = outputScriptCount
outputScriptCount++ outputScriptCount++
return script, nil return script, nil
}, },
@ -1801,6 +1802,24 @@ func TestRequiredTxOuts(t *testing.T) {
locktime2 := uint32(52) locktime2 := uint32(52)
locktime3 := uint32(53) locktime3 := uint32(53)
aPkScript := make([]byte, input.P2WPKHSize)
aPkScript[0] = 'a'
bPkScript := make([]byte, input.P2WSHSize)
bPkScript[0] = 'b'
cPkScript := make([]byte, input.P2PKHSize)
cPkScript[0] = 'c'
dPkScript := make([]byte, input.P2SHSize)
dPkScript[0] = 'd'
ePkScript := make([]byte, input.UnknownWitnessSize)
ePkScript[0] = 'e'
fPkScript := make([]byte, input.P2WSHSize)
fPkScript[0] = 'f'
testCases := []struct { testCases := []struct {
name string name string
inputs []*testInput inputs []*testInput
@ -1815,7 +1834,7 @@ func TestRequiredTxOuts(t *testing.T) {
{ {
BaseInput: inputs[0], BaseInput: inputs[0],
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("aaa"), PkScript: aPkScript,
Value: 100000, Value: 100000,
}, },
}, },
@ -1836,7 +1855,7 @@ func TestRequiredTxOuts(t *testing.T) {
// output must be the first one. // output must be the first one.
require.Equal(t, 2, len(tx.TxOut)) require.Equal(t, 2, len(tx.TxOut))
out := tx.TxOut[0] out := tx.TxOut[0]
require.Equal(t, []byte("aaa"), out.PkScript) require.Equal(t, aPkScript, out.PkScript)
require.Equal(t, int64(100000), out.Value) require.Equal(t, int64(100000), out.Value)
}, },
}, },
@ -1848,13 +1867,13 @@ func TestRequiredTxOuts(t *testing.T) {
{ {
BaseInput: inputs[0], BaseInput: inputs[0],
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("aaa"), PkScript: aPkScript,
// Fee will be about 5340 sats. // Fee will be about 5340 sats.
// Subtract a bit more to // Subtract a bit more to
// ensure no dust change output // ensure no dust change output
// is manifested. // is manifested.
Value: inputs[0].SignDesc().Output.Value - 5600, Value: inputs[0].SignDesc().Output.Value - 6300,
}, },
}, },
}, },
@ -1871,10 +1890,10 @@ func TestRequiredTxOuts(t *testing.T) {
require.Equal(t, 1, len(tx.TxOut)) require.Equal(t, 1, len(tx.TxOut))
out := tx.TxOut[0] out := tx.TxOut[0]
require.Equal(t, []byte("aaa"), out.PkScript) require.Equal(t, aPkScript, out.PkScript)
require.Equal( require.Equal(
t, t,
inputs[0].SignDesc().Output.Value-5600, inputs[0].SignDesc().Output.Value-6300,
out.Value, out.Value,
) )
}, },
@ -1897,7 +1916,7 @@ func TestRequiredTxOuts(t *testing.T) {
// The second input requires a TxOut. // The second input requires a TxOut.
BaseInput: inputs[0], BaseInput: inputs[0],
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("aaa"), PkScript: aPkScript,
Value: inputs[0].SignDesc().Output.Value, Value: inputs[0].SignDesc().Output.Value,
}, },
}, },
@ -1916,7 +1935,7 @@ func TestRequiredTxOuts(t *testing.T) {
// The required TxOut should be the first one. // The required TxOut should be the first one.
out := tx.TxOut[0] out := tx.TxOut[0]
require.Equal(t, []byte("aaa"), out.PkScript) require.Equal(t, aPkScript, out.PkScript)
require.Equal( require.Equal(
t, inputs[0].SignDesc().Output.Value, t, inputs[0].SignDesc().Output.Value,
out.Value, out.Value,
@ -1947,7 +1966,7 @@ func TestRequiredTxOuts(t *testing.T) {
{ {
BaseInput: inputs[0], BaseInput: inputs[0],
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("aaa"), PkScript: aPkScript,
Value: inputs[0].SignDesc().Output.Value, Value: inputs[0].SignDesc().Output.Value,
}, },
}, },
@ -1965,7 +1984,7 @@ func TestRequiredTxOuts(t *testing.T) {
require.Equal(t, 2, len(tx.TxOut)) require.Equal(t, 2, len(tx.TxOut))
out := tx.TxOut[0] out := tx.TxOut[0]
require.Equal(t, []byte("aaa"), out.PkScript) require.Equal(t, aPkScript, out.PkScript)
require.Equal( require.Equal(
t, inputs[0].SignDesc().Output.Value, t, inputs[0].SignDesc().Output.Value,
out.Value, out.Value,
@ -1980,21 +1999,21 @@ func TestRequiredTxOuts(t *testing.T) {
{ {
BaseInput: inputs[0], BaseInput: inputs[0],
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("aaa"), PkScript: aPkScript,
Value: inputs[0].SignDesc().Output.Value, Value: inputs[0].SignDesc().Output.Value,
}, },
}, },
{ {
BaseInput: inputs[1], BaseInput: inputs[1],
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("bbb"), PkScript: bPkScript,
Value: inputs[1].SignDesc().Output.Value, Value: inputs[1].SignDesc().Output.Value,
}, },
}, },
{ {
BaseInput: inputs[2], BaseInput: inputs[2],
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("ccc"), PkScript: cPkScript,
Value: inputs[2].SignDesc().Output.Value, Value: inputs[2].SignDesc().Output.Value,
}, },
}, },
@ -2041,7 +2060,7 @@ func TestRequiredTxOuts(t *testing.T) {
BaseInput: inputs[0], BaseInput: inputs[0],
locktime: &locktime1, locktime: &locktime1,
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("aaa"), PkScript: aPkScript,
Value: inputs[0].SignDesc().Output.Value, Value: inputs[0].SignDesc().Output.Value,
}, },
}, },
@ -2049,7 +2068,7 @@ func TestRequiredTxOuts(t *testing.T) {
BaseInput: inputs[1], BaseInput: inputs[1],
locktime: &locktime1, locktime: &locktime1,
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("bbb"), PkScript: bPkScript,
Value: inputs[1].SignDesc().Output.Value, Value: inputs[1].SignDesc().Output.Value,
}, },
}, },
@ -2057,7 +2076,7 @@ func TestRequiredTxOuts(t *testing.T) {
BaseInput: inputs[2], BaseInput: inputs[2],
locktime: &locktime2, locktime: &locktime2,
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("ccc"), PkScript: cPkScript,
Value: inputs[2].SignDesc().Output.Value, Value: inputs[2].SignDesc().Output.Value,
}, },
}, },
@ -2065,7 +2084,7 @@ func TestRequiredTxOuts(t *testing.T) {
BaseInput: inputs[3], BaseInput: inputs[3],
locktime: &locktime2, locktime: &locktime2,
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("ddd"), PkScript: dPkScript,
Value: inputs[3].SignDesc().Output.Value, Value: inputs[3].SignDesc().Output.Value,
}, },
}, },
@ -2073,7 +2092,7 @@ func TestRequiredTxOuts(t *testing.T) {
BaseInput: inputs[4], BaseInput: inputs[4],
locktime: &locktime3, locktime: &locktime3,
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("eee"), PkScript: ePkScript,
Value: inputs[4].SignDesc().Output.Value, Value: inputs[4].SignDesc().Output.Value,
}, },
}, },
@ -2081,7 +2100,7 @@ func TestRequiredTxOuts(t *testing.T) {
BaseInput: inputs[5], BaseInput: inputs[5],
locktime: &locktime3, locktime: &locktime3,
reqTxOut: &wire.TxOut{ reqTxOut: &wire.TxOut{
PkScript: []byte("fff"), PkScript: fPkScript,
Value: inputs[5].SignDesc().Output.Value, Value: inputs[5].SignDesc().Output.Value,
}, },
}, },

View file

@ -7,7 +7,6 @@ import (
"github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/btcsuite/btcwallet/wallet/txrules"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
@ -109,9 +108,6 @@ func (t *txInputSetState) clone() txInputSetState {
type txInputSet struct { type txInputSet struct {
txInputSetState txInputSetState
// dustLimit is the minimum output value of the tx.
dustLimit btcutil.Amount
// maxInputs is the maximum number of inputs that will be accepted in // maxInputs is the maximum number of inputs that will be accepted in
// the set. // the set.
maxInputs int maxInputs int
@ -121,25 +117,15 @@ type txInputSet struct {
wallet Wallet wallet Wallet
} }
func dustLimit(relayFee chainfee.SatPerKWeight) btcutil.Amount {
return txrules.GetDustThreshold(
input.P2WPKHSize,
btcutil.Amount(relayFee.FeePerKVByte()),
)
}
// newTxInputSet constructs a new, empty input set. // newTxInputSet constructs a new, empty input set.
func newTxInputSet(wallet Wallet, feePerKW, func newTxInputSet(wallet Wallet, feePerKW chainfee.SatPerKWeight,
relayFee chainfee.SatPerKWeight, maxInputs int) *txInputSet { maxInputs int) *txInputSet {
dustLimit := dustLimit(relayFee)
state := txInputSetState{ state := txInputSetState{
feeRate: feePerKW, feeRate: feePerKW,
} }
b := txInputSet{ b := txInputSet{
dustLimit: dustLimit,
maxInputs: maxInputs, maxInputs: maxInputs,
wallet: wallet, wallet: wallet,
txInputSetState: state, txInputSetState: state,
@ -153,7 +139,7 @@ func newTxInputSet(wallet Wallet, feePerKW,
func (t *txInputSet) enoughInput() bool { func (t *txInputSet) enoughInput() bool {
// If we have a change output above dust, then we certainly have enough // If we have a change output above dust, then we certainly have enough
// inputs to the transaction. // inputs to the transaction.
if t.changeOutput >= t.dustLimit { if t.changeOutput >= lnwallet.DustLimitForSize(input.P2WPKHSize) {
return true return true
} }
@ -192,8 +178,12 @@ func (t *txInputSet) addToState(inp input.Input, constraints addConstraints) *tx
// If the input comes with a required tx out that is below dust, we // If the input comes with a required tx out that is below dust, we
// won't add it. // won't add it.
reqOut := inp.RequiredTxOut() reqOut := inp.RequiredTxOut()
if reqOut != nil && btcutil.Amount(reqOut.Value) < t.dustLimit { if reqOut != nil {
return nil // Fetch the dust limit for this output.
dustLimit := lnwallet.DustLimitForSize(len(reqOut.PkScript))
if btcutil.Amount(reqOut.Value) < dustLimit {
return nil
}
} }
// Clone the current set state. // Clone the current set state.

View file

@ -14,14 +14,9 @@ import (
func TestTxInputSet(t *testing.T) { func TestTxInputSet(t *testing.T) {
const ( const (
feeRate = 1000 feeRate = 1000
relayFee = 300
maxInputs = 10 maxInputs = 10
) )
set := newTxInputSet(nil, feeRate, relayFee, maxInputs) set := newTxInputSet(nil, feeRate, maxInputs)
if set.dustLimit != 537 {
t.Fatalf("incorrect dust limit")
}
// Create a 300 sat input. The fee to sweep this input to a P2WKH output // Create a 300 sat input. The fee to sweep this input to a P2WKH output
// is 439 sats. That means that this input yields -139 sats and we // is 439 sats. That means that this input yields -139 sats and we
@ -66,16 +61,15 @@ func TestTxInputSet(t *testing.T) {
func TestTxInputSetFromWallet(t *testing.T) { func TestTxInputSetFromWallet(t *testing.T) {
const ( const (
feeRate = 500 feeRate = 500
relayFee = 300
maxInputs = 10 maxInputs = 10
) )
wallet := &mockWallet{} wallet := &mockWallet{}
set := newTxInputSet(wallet, feeRate, relayFee, maxInputs) set := newTxInputSet(wallet, feeRate, maxInputs)
// Add a 700 sat input to the set. It yields positively, but doesn't // Add a 500 sat input to the set. It yields positively, but doesn't
// reach the output dust limit. // reach the output dust limit.
if !set.add(createP2WKHInput(700), constraintsRegular) { if !set.add(createP2WKHInput(500), constraintsRegular) {
t.Fatal("expected add of positively yielding input to succeed") t.Fatal("expected add of positively yielding input to succeed")
} }
if set.enoughInput() { if set.enoughInput() {
@ -138,13 +132,9 @@ func (r *reqInput) RequiredTxOut() *wire.TxOut {
func TestTxInputSetRequiredOutput(t *testing.T) { func TestTxInputSetRequiredOutput(t *testing.T) {
const ( const (
feeRate = 1000 feeRate = 1000
relayFee = 300
maxInputs = 10 maxInputs = 10
) )
set := newTxInputSet(nil, feeRate, relayFee, maxInputs) set := newTxInputSet(nil, feeRate, maxInputs)
if set.dustLimit != 537 {
t.Fatalf("incorrect dust limit")
}
// Attempt to add an input with a required txout below the dust limit. // Attempt to add an input with a required txout below the dust limit.
// This should fail since we cannot trim such outputs. // This should fail since we cannot trim such outputs.
@ -152,7 +142,7 @@ func TestTxInputSetRequiredOutput(t *testing.T) {
Input: createP2WKHInput(500), Input: createP2WKHInput(500),
txOut: &wire.TxOut{ txOut: &wire.TxOut{
Value: 500, Value: 500,
PkScript: make([]byte, 33), PkScript: make([]byte, input.P2PKHSize),
}, },
} }
require.False(t, set.add(inp, constraintsRegular), require.False(t, set.add(inp, constraintsRegular),
@ -164,7 +154,7 @@ func TestTxInputSetRequiredOutput(t *testing.T) {
Input: createP2WKHInput(1000), Input: createP2WKHInput(1000),
txOut: &wire.TxOut{ txOut: &wire.TxOut{
Value: 1000, Value: 1000,
PkScript: make([]byte, 22), PkScript: make([]byte, input.P2WPKHSize),
}, },
} }
require.True(t, set.add(inp, constraintsRegular), "failed adding input") require.True(t, set.add(inp, constraintsRegular), "failed adding input")

View file

@ -10,6 +10,7 @@ import (
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
) )
@ -37,8 +38,8 @@ type inputSet []input.Input
// inputs are skipped. No input sets with a total value after fees below the // inputs are skipped. No input sets with a total value after fees below the
// dust limit are returned. // dust limit are returned.
func generateInputPartitionings(sweepableInputs []txInput, func generateInputPartitionings(sweepableInputs []txInput,
relayFeePerKW, feePerKW chainfee.SatPerKWeight, feePerKW chainfee.SatPerKWeight, maxInputsPerTx int,
maxInputsPerTx int, wallet Wallet) ([]inputSet, error) { wallet Wallet) ([]inputSet, error) {
// Sort input by yield. We will start constructing input sets starting // Sort input by yield. We will start constructing input sets starting
// with the highest yield inputs. This is to prevent the construction // with the highest yield inputs. This is to prevent the construction
@ -85,9 +86,7 @@ func generateInputPartitionings(sweepableInputs []txInput,
// Start building a set of positive-yield tx inputs under the // Start building a set of positive-yield tx inputs under the
// condition that the tx will be published with the specified // condition that the tx will be published with the specified
// fee rate. // fee rate.
txInputs := newTxInputSet( txInputs := newTxInputSet(wallet, feePerKW, maxInputsPerTx)
wallet, feePerKW, relayFeePerKW, maxInputsPerTx,
)
// From the set of sweepable inputs, keep adding inputs to the // From the set of sweepable inputs, keep adding inputs to the
// input set until the tx output value no longer goes up or the // input set until the tx output value no longer goes up or the
@ -111,10 +110,12 @@ func generateInputPartitionings(sweepableInputs []txInput,
// continuing with the remaining inputs will only lead to sets // continuing with the remaining inputs will only lead to sets
// with an even lower output value. // with an even lower output value.
if !txInputs.enoughInput() { if !txInputs.enoughInput() {
// The change output is always a p2wpkh here.
dl := lnwallet.DustLimitForSize(input.P2WPKHSize)
log.Debugf("Set value %v (r=%v, c=%v) below dust "+ log.Debugf("Set value %v (r=%v, c=%v) below dust "+
"limit of %v", txInputs.totalOutput(), "limit of %v", txInputs.totalOutput(),
txInputs.requiredOutput, txInputs.changeOutput, txInputs.requiredOutput, txInputs.changeOutput,
txInputs.dustLimit) dl)
return sets, nil return sets, nil
} }
@ -135,8 +136,8 @@ func generateInputPartitionings(sweepableInputs []txInput,
// sending any leftover change to the change script. // sending any leftover change to the change script.
func createSweepTx(inputs []input.Input, outputs []*wire.TxOut, func createSweepTx(inputs []input.Input, outputs []*wire.TxOut,
changePkScript []byte, currentBlockHeight uint32, changePkScript []byte, currentBlockHeight uint32,
feePerKw chainfee.SatPerKWeight, dustLimit btcutil.Amount, feePerKw chainfee.SatPerKWeight, signer input.Signer) (*wire.MsgTx,
signer input.Signer) (*wire.MsgTx, error) { error) {
inputs, estimator := getWeightEstimate(inputs, outputs, feePerKw) inputs, estimator := getWeightEstimate(inputs, outputs, feePerKw)
txFee := estimator.fee() txFee := estimator.fee()
@ -227,16 +228,20 @@ func createSweepTx(inputs []input.Input, outputs []*wire.TxOut,
// sweep tx has a change output. // sweep tx has a change output.
changeAmt := totalInput - requiredOutput - txFee changeAmt := totalInput - requiredOutput - txFee
// We'll calculate the dust limit for the given changePkScript since it
// is variable.
changeLimit := lnwallet.DustLimitForSize(len(changePkScript))
// The txn will sweep the amount after fees to the pkscript generated // The txn will sweep the amount after fees to the pkscript generated
// above. // above.
if changeAmt >= dustLimit { if changeAmt >= changeLimit {
sweepTx.AddTxOut(&wire.TxOut{ sweepTx.AddTxOut(&wire.TxOut{
PkScript: changePkScript, PkScript: changePkScript,
Value: int64(changeAmt), Value: int64(changeAmt),
}) })
} else { } else {
log.Infof("Change amt %v below dustlimit %v, not adding "+ log.Infof("Change amt %v below dustlimit %v, not adding "+
"change output", changeAmt, dustLimit) "change output", changeAmt, changeLimit)
} }
// We'll default to using the current block height as locktime, if none // We'll default to using the current block height as locktime, if none

View file

@ -165,8 +165,8 @@ type DeliveryAddr struct {
// output, as specified by the change address. The sweep transaction will be // output, as specified by the change address. The sweep transaction will be
// crafted with the target fee rate, and will use the utxoSource and // crafted with the target fee rate, and will use the utxoSource and
// outpointLocker as sources for wallet funds. // outpointLocker as sources for wallet funds.
func CraftSweepAllTx(feeRate chainfee.SatPerKWeight, dustLimit btcutil.Amount, func CraftSweepAllTx(feeRate chainfee.SatPerKWeight, blockHeight uint32,
blockHeight uint32, deliveryAddrs []DeliveryAddr, changeAddr btcutil.Address, deliveryAddrs []DeliveryAddr, changeAddr btcutil.Address,
coinSelectLocker CoinSelectionLocker, utxoSource UtxoSource, coinSelectLocker CoinSelectionLocker, utxoSource UtxoSource,
outpointLocker OutpointLocker, feeEstimator chainfee.Estimator, outpointLocker OutpointLocker, feeEstimator chainfee.Estimator,
signer input.Signer, minConfs int32) (*WalletSweepPackage, error) { signer input.Signer, minConfs int32) (*WalletSweepPackage, error) {
@ -302,7 +302,7 @@ func CraftSweepAllTx(feeRate chainfee.SatPerKWeight, dustLimit btcutil.Amount,
// respects our fee preference and targets all the UTXOs of the wallet. // respects our fee preference and targets all the UTXOs of the wallet.
sweepTx, err := createSweepTx( sweepTx, err := createSweepTx(
inputsToSweep, txOuts, changePkScript, blockHeight, feeRate, inputsToSweep, txOuts, changePkScript, blockHeight, feeRate,
dustLimit, signer, signer,
) )
if err != nil { if err != nil {
unlockOutputs() unlockOutputs()

View file

@ -288,8 +288,8 @@ func TestCraftSweepAllTxCoinSelectFail(t *testing.T) {
utxoLocker := newMockOutpointLocker() utxoLocker := newMockOutpointLocker()
_, err := CraftSweepAllTx( _, err := CraftSweepAllTx(
0, 100, 10, nil, nil, coinSelectLocker, utxoSource, 0, 10, nil, nil, coinSelectLocker, utxoSource, utxoLocker, nil,
utxoLocker, nil, nil, 0, nil, 0,
) )
// Since we instructed the coin select locker to fail above, we should // Since we instructed the coin select locker to fail above, we should
@ -314,8 +314,8 @@ func TestCraftSweepAllTxUnknownWitnessType(t *testing.T) {
utxoLocker := newMockOutpointLocker() utxoLocker := newMockOutpointLocker()
_, err := CraftSweepAllTx( _, err := CraftSweepAllTx(
0, 100, 10, nil, nil, coinSelectLocker, utxoSource, 0, 10, nil, nil, coinSelectLocker, utxoSource, utxoLocker, nil,
utxoLocker, nil, nil, 0, nil, 0,
) )
// Since passed in a p2wsh output, which is unknown, we should fail to // Since passed in a p2wsh output, which is unknown, we should fail to
@ -349,7 +349,7 @@ func TestCraftSweepAllTx(t *testing.T) {
utxoLocker := newMockOutpointLocker() utxoLocker := newMockOutpointLocker()
sweepPkg, err := CraftSweepAllTx( sweepPkg, err := CraftSweepAllTx(
0, 100, 10, nil, deliveryAddr, coinSelectLocker, utxoSource, 0, 10, nil, deliveryAddr, coinSelectLocker, utxoSource,
utxoLocker, feeEstimator, signer, 0, utxoLocker, feeEstimator, signer, 0,
) )
if err != nil { if err != nil {

View file

@ -300,7 +300,7 @@ func TestBackupTask(t *testing.T) {
expSweepCommitRewardLocal int64 = 197390 expSweepCommitRewardLocal int64 = 197390
expSweepCommitRewardRemote int64 = 98437 expSweepCommitRewardRemote int64 = 98437
sweepFeeRateNoRewardRemoteDust chainfee.SatPerKWeight = 227500 sweepFeeRateNoRewardRemoteDust chainfee.SatPerKWeight = 227500
sweepFeeRateRewardRemoteDust chainfee.SatPerKWeight = 175000 sweepFeeRateRewardRemoteDust chainfee.SatPerKWeight = 175350
) )
if chanType.HasAnchors() { if chanType.HasAnchors() {
expSweepCommitNoRewardBoth = 299236 expSweepCommitNoRewardBoth = 299236
@ -309,8 +309,8 @@ func TestBackupTask(t *testing.T) {
expSweepCommitRewardBoth = 296112 expSweepCommitRewardBoth = 296112
expSweepCommitRewardLocal = 197389 expSweepCommitRewardLocal = 197389
expSweepCommitRewardRemote = 98433 expSweepCommitRewardRemote = 98433
sweepFeeRateNoRewardRemoteDust = 225000 sweepFeeRateNoRewardRemoteDust = 225400
sweepFeeRateRewardRemoteDust = 173750 sweepFeeRateRewardRemoteDust = 174100
} }
backupTaskTests = append(backupTaskTests, []backupTaskTest{ backupTaskTests = append(backupTaskTests, []backupTaskTest{

View file

@ -6,6 +6,7 @@ import (
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btcutil" "github.com/btcsuite/btcutil"
"github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/watchtower/blob" "github.com/lightningnetwork/lnd/watchtower/blob"
@ -165,10 +166,9 @@ func (p *Policy) ComputeAltruistOutput(totalAmt btcutil.Amount,
sweepAmt := totalAmt - txFee sweepAmt := totalAmt - txFee
// TODO(conner): replace w/ configurable dust limit // TODO(conner): replace w/ configurable dust limit
dustLimit := lnwallet.DefaultDustLimit() // Check that the created outputs won't be dusty. The sweep pkscript is
// currently a p2wpkh, so we'll use that script's dust limit.
// Check that the created outputs won't be dusty. if sweepAmt < lnwallet.DustLimitForSize(input.P2WPKHSize) {
if sweepAmt <= dustLimit {
return 0, ErrCreatesDust return 0, ErrCreatesDust
} }
@ -199,10 +199,9 @@ func (p *Policy) ComputeRewardOutputs(totalAmt btcutil.Amount,
sweepAmt := totalAmt - rewardAmt - txFee sweepAmt := totalAmt - rewardAmt - txFee
// TODO(conner): replace w/ configurable dust limit // TODO(conner): replace w/ configurable dust limit
dustLimit := lnwallet.DefaultDustLimit() // Check that the created outputs won't be dusty. The sweep pkscript is
// currently a p2wpkh, so we'll use that script's dust limit.
// Check that the created outputs won't be dusty. if sweepAmt < lnwallet.DustLimitForSize(input.P2WPKHSize) {
if sweepAmt <= dustLimit {
return 0, 0, ErrCreatesDust return 0, 0, ErrCreatesDust
} }