Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

multi: switch to sat/kw fees #1644

Merged
merged 4 commits into from
Aug 10, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 5 additions & 5 deletions breacharbiter.go
Original file line number Diff line number Diff line change
Expand Up @@ -1015,13 +1015,13 @@ func (b *breachArbiter) createJusticeTx(
spendableOutputs = append(spendableOutputs, input)
}

txVSize := int64(weightEstimate.VSize())
return b.sweepSpendableOutputsTxn(txVSize, spendableOutputs...)
txWeight := int64(weightEstimate.Weight())
return b.sweepSpendableOutputsTxn(txWeight, spendableOutputs...)
}

// sweepSpendableOutputsTxn creates a signed transaction from a sequence of
// spendable outputs by sweeping the funds into a single p2wkh output.
func (b *breachArbiter) sweepSpendableOutputsTxn(txVSize int64,
func (b *breachArbiter) sweepSpendableOutputsTxn(txWeight int64,
inputs ...SpendableOutput) (*wire.MsgTx, error) {

// First, we obtain a new public key script from the wallet which we'll
Expand All @@ -1041,11 +1041,11 @@ func (b *breachArbiter) sweepSpendableOutputsTxn(txVSize int64,

// We'll actually attempt to target inclusion within the next two
// blocks as we'd like to sweep these funds back into our wallet ASAP.
feePerVSize, err := b.cfg.Estimator.EstimateFeePerVSize(2)
feePerKw, err := b.cfg.Estimator.EstimateFeePerKW(2)
if err != nil {
return nil, err
}
txFee := feePerVSize.FeeForVSize(txVSize)
txFee := feePerKw.FeeForWeight(txWeight)

// TODO(roasbeef): already start to siphon their funds into fees
sweepAmt := int64(totalAmt - txFee)
Expand Down
7 changes: 3 additions & 4 deletions breacharbiter_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1351,7 +1351,7 @@ func createTestArbiter(t *testing.T, contractBreaches chan *ContractBreachEvent,
ba := newBreachArbiter(&BreachConfig{
CloseLink: func(_ *wire.OutPoint, _ htlcswitch.ChannelCloseType) {},
DB: db,
Estimator: &lnwallet.StaticFeeEstimator{FeeRate: 50},
Estimator: &lnwallet.StaticFeeEstimator{FeePerKW: 12500},
GenSweepScript: func() ([]byte, error) { return nil, nil },
ContractBreaches: contractBreaches,
Signer: signer,
Expand Down Expand Up @@ -1491,12 +1491,11 @@ func createInitChannels(revocationWindow int) (*lnwallet.LightningChannel, *lnwa
return nil, nil, nil, err
}

estimator := &lnwallet.StaticFeeEstimator{FeeRate: 50}
feePerVSize, err := estimator.EstimateFeePerVSize(1)
estimator := &lnwallet.StaticFeeEstimator{FeePerKW: 12500}
feePerKw, err := estimator.EstimateFeePerKW(1)
if err != nil {
return nil, nil, nil, err
}
feePerKw := feePerVSize.FeePerKWeight()

// TODO(roasbeef): need to factor in commit fee?
aliceCommit := channeldb.ChannelCommitment{
Expand Down
26 changes: 16 additions & 10 deletions chainregistry.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,21 @@ const (
defaultBitcoinBaseFeeMSat = lnwire.MilliSatoshi(1000)
defaultBitcoinFeeRate = lnwire.MilliSatoshi(1)
defaultBitcoinTimeLockDelta = 144
defaultBitcoinStaticFeeRate = lnwallet.SatPerVByte(50)

defaultLitecoinMinHTLCMSat = lnwire.MilliSatoshi(1000)
defaultLitecoinBaseFeeMSat = lnwire.MilliSatoshi(1000)
defaultLitecoinFeeRate = lnwire.MilliSatoshi(1)
defaultLitecoinTimeLockDelta = 576
defaultLitecoinStaticFeeRate = lnwallet.SatPerVByte(200)
defaultLitecoinDustLimit = btcutil.Amount(54600)

// defaultBitcoinStaticFeePerKW is the fee rate of 50 sat/vbyte
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

👍

// expressed in sat/kw.
defaultBitcoinStaticFeePerKW = lnwallet.SatPerKWeight(12500)

// defaultLitecoinStaticFeePerKW is the fee rate of 200 sat/vbyte
// expressed in sat/kw.
defaultLitecoinStaticFeePerKW = lnwallet.SatPerKWeight(50000)

// btcToLtcConversionRate is a fixed ratio used in order to scale up
// payments when running on the Litecoin chain.
btcToLtcConversionRate = 60
Expand Down Expand Up @@ -141,7 +147,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
TimeLockDelta: cfg.Bitcoin.TimeLockDelta,
}
cc.feeEstimator = lnwallet.StaticFeeEstimator{
FeeRate: defaultBitcoinStaticFeeRate,
FeePerKW: defaultBitcoinStaticFeePerKW,
}
case litecoinChain:
cc.routingPolicy = htlcswitch.ForwardingPolicy{
Expand All @@ -151,7 +157,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
TimeLockDelta: cfg.Litecoin.TimeLockDelta,
}
cc.feeEstimator = lnwallet.StaticFeeEstimator{
FeeRate: defaultLitecoinStaticFeeRate,
FeePerKW: defaultLitecoinStaticFeePerKW,
}
default:
return nil, nil, fmt.Errorf("Default routing policy for "+
Expand Down Expand Up @@ -337,9 +343,9 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
// if we're using bitcoind as a backend, then we can
// use live fee estimates, rather than a statically
// coded value.
fallBackFeeRate := lnwallet.SatPerVByte(25)
fallBackFeeRate := lnwallet.SatPerKVByte(25 * 1000)
cc.feeEstimator, err = lnwallet.NewBitcoindFeeEstimator(
*rpcConfig, fallBackFeeRate,
*rpcConfig, fallBackFeeRate.FeePerKWeight(),
)
if err != nil {
return nil, nil, err
Expand All @@ -354,9 +360,9 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
// if we're using litecoind as a backend, then we can
// use live fee estimates, rather than a statically
// coded value.
fallBackFeeRate := lnwallet.SatPerVByte(25)
fallBackFeeRate := lnwallet.SatPerKVByte(25 * 1000)
cc.feeEstimator, err = lnwallet.NewBitcoindFeeEstimator(
*rpcConfig, fallBackFeeRate,
*rpcConfig, fallBackFeeRate.FeePerKWeight(),
)
if err != nil {
return nil, nil, err
Expand Down Expand Up @@ -457,9 +463,9 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
// if we're using btcd as a backend, then we can use
// live fee estimates, rather than a statically coded
// value.
fallBackFeeRate := lnwallet.SatPerVByte(25)
fallBackFeeRate := lnwallet.SatPerKVByte(25 * 1000)
cc.feeEstimator, err = lnwallet.NewBtcdFeeEstimator(
*rpcConfig, fallBackFeeRate,
*rpcConfig, fallBackFeeRate.FeePerKWeight(),
)
if err != nil {
return nil, nil, err
Expand Down
28 changes: 14 additions & 14 deletions contractcourt/contract_resolvers.go
Original file line number Diff line number Diff line change
Expand Up @@ -451,27 +451,27 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
return nil, err
}

// With out address obtained, we'll query for an
// With our address obtained, we'll query for an
// estimate to be confirmed at ease.
//
// TODO(roasbeef): signal up if fee would be too large
// to sweep singly, need to batch
feePerVSize, err := h.FeeEstimator.EstimateFeePerVSize(6)
feePerKw, err := h.FeeEstimator.EstimateFeePerKW(6)
if err != nil {
return nil, err
}

log.Debugf("%T(%x): using %v sat/vbyte to sweep htlc"+
log.Debugf("%T(%x): using %v sat/kw to sweep htlc"+
"incoming+remote htlc confirmed", h,
h.payHash[:], int64(feePerVSize))
h.payHash[:], int64(feePerKw))

// Using a weight estimator, we'll compute the total
// fee required, and from that the value we'll end up
// with.
totalVSize := (&lnwallet.TxWeightEstimator{}).
totalWeight := (&lnwallet.TxWeightEstimator{}).
AddWitnessInput(lnwallet.OfferedHtlcSuccessWitnessSize).
AddP2WKHOutput().VSize()
totalFees := feePerVSize.FeeForVSize(int64(totalVSize))
AddP2WKHOutput().Weight()
totalFees := feePerKw.FeeForWeight(int64(totalWeight))
sweepAmt := h.htlcResolution.SweepSignDesc.Output.Value -
int64(totalFees)

Expand Down Expand Up @@ -1253,18 +1253,18 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
// First, we'll estimate the total weight so we can compute
// fees properly. We'll use a lax estimate, as this output is
// in no immediate danger.
feePerVSize, err := c.FeeEstimator.EstimateFeePerVSize(6)
feePerKw, err := c.FeeEstimator.EstimateFeePerKW(6)
if err != nil {
return nil, err
}

log.Debugf("%T(%v): using %v sat/vsize for sweep tx", c,
c.chanPoint, int64(feePerVSize))
log.Debugf("%T(%v): using %v sat/kw for sweep tx", c,
c.chanPoint, int64(feePerKw))

totalVSize := (&lnwallet.TxWeightEstimator{}).
AddP2PKHInput().
AddP2WKHOutput().VSize()
totalFees := feePerVSize.FeeForVSize(int64(totalVSize))
totalWeight := (&lnwallet.TxWeightEstimator{}).
AddP2WKHInput().
AddP2WKHOutput().Weight()
totalFees := feePerKw.FeeForWeight(int64(totalWeight))
sweepAmt := signDesc.Output.Value - int64(totalFees)

c.sweepTx = wire.NewMsgTx(2)
Expand Down
30 changes: 6 additions & 24 deletions fundingmanager.go
Original file line number Diff line number Diff line change
Expand Up @@ -8,10 +8,6 @@ import (
"sync/atomic"
"time"

"google.golang.org/grpc"

"golang.org/x/crypto/salsa20"

"github.com/btcsuite/btcd/btcec"
"github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/wire"
Expand All @@ -28,6 +24,8 @@ import (
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing"
"golang.org/x/crypto/salsa20"
"google.golang.org/grpc"
)

const (
Expand Down Expand Up @@ -68,11 +66,6 @@ const (
// currently accepted on the Litecoin chain within the Lightning
// Protocol.
maxLtcFundingAmount = maxBtcFundingAmount * btcToLtcConversionRate

// minCommitFeePerKw is the smallest fee rate that we should propose
// for a new fee update. We'll use this as a fee floor when proposing
// and accepting updates.
minCommitFeePerKw = 253
)

var (
Expand Down Expand Up @@ -1028,8 +1021,8 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
reservation, err := f.cfg.Wallet.InitChannelReservation(
amt, 0, msg.PushAmount,
lnwallet.SatPerKWeight(msg.FeePerKiloWeight), 0,
fmsg.peer.IdentityKey(), fmsg.peer.Address(),
&chainHash, msg.ChannelFlags,
fmsg.peer.IdentityKey(), fmsg.peer.Address(), &chainHash,
msg.ChannelFlags,
)
if err != nil {
fndgLog.Errorf("Unable to initialize reservation: %v", err)
Expand Down Expand Up @@ -2543,23 +2536,12 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
// commitment transaction confirmed by the next few blocks (conf target
// of 3). We target the near blocks here to ensure that we'll be able
// to execute a timely unilateral channel closure if needed.
feePerVSize, err := f.cfg.FeeEstimator.EstimateFeePerVSize(3)
commitFeePerKw, err := f.cfg.FeeEstimator.EstimateFeePerKW(3)
if err != nil {
msg.err <- err
return
}

// If the converted fee-per-kw is below the current widely used policy
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nice 😎

// floor, then we'll use the floor instead.
commitFeePerKw := feePerVSize.FeePerKWeight()
if commitFeePerKw < minCommitFeePerKw {
fndgLog.Infof("Proposed fee rate of %v sat/kw is below min "+
"of %v sat/kw, using fee floor", int64(commitFeePerKw),
int64(minCommitFeePerKw))

commitFeePerKw = minCommitFeePerKw
}

// We set the channel flags to indicate whether we want this channel to
// be announced to the network.
var channelFlags lnwire.FundingFlag
Expand All @@ -2573,7 +2555,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
// request will fail, and be aborted.
reservation, err := f.cfg.Wallet.InitChannelReservation(
capacity, localAmt, msg.pushAmt, commitFeePerKw,
msg.fundingFeePerVSize, peerKey, msg.peer.Address(),
msg.fundingFeePerKw, peerKey, msg.peer.Address(),
&msg.chainHash, channelFlags,
)
if err != nil {
Expand Down
2 changes: 1 addition & 1 deletion fundingmanager_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
addr *lnwire.NetAddress, tempTestDir string) (*testNode, error) {

netParams := activeNetParams.Params
estimator := lnwallet.StaticFeeEstimator{FeeRate: 250}
estimator := lnwallet.StaticFeeEstimator{FeePerKW: 62500}

chainNotifier := &mockNotifier{
oneConfChannel: make(chan *chainntnfs.TxConfirmation, 1),
Expand Down
24 changes: 3 additions & 21 deletions htlcswitch/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,11 +35,6 @@ const (
// TODO(roasbeef): must be < default delta
expiryGraceDelta = 2

// minCommitFeePerKw is the smallest fee rate that we should propose
// for a new fee update. We'll use this as a fee floor when proposing
// and accepting updates.
minCommitFeePerKw = 253

// DefaultMinLinkFeeUpdateTimeout represents the minimum interval in
// which a link should propose to update its commitment fee rate.
DefaultMinLinkFeeUpdateTimeout = 10 * time.Minute
Expand Down Expand Up @@ -495,26 +490,13 @@ func (l *channelLink) EligibleToForward() bool {
// this is the native rate used when computing the fee for commitment
// transactions, and the second-level HTLC transactions.
func (l *channelLink) sampleNetworkFee() (lnwallet.SatPerKWeight, error) {
// We'll first query for the sat/vbyte recommended to be confirmed
// within 3 blocks.
feePerVSize, err := l.cfg.FeeEstimator.EstimateFeePerVSize(3)
// We'll first query for the sat/kw recommended to be confirmed within 3
// blocks.
feePerKw, err := l.cfg.FeeEstimator.EstimateFeePerKW(3)
if err != nil {
return 0, err
}

// Once we have this fee rate, we'll convert to sat-per-kw.
feePerKw := feePerVSize.FeePerKWeight()

// If the returned feePerKw is less than the current widely used
// policy, then we'll use that instead as a floor.
if feePerKw < minCommitFeePerKw {
log.Debugf("Proposed fee rate of %v sat/kw is below min "+
"of %v sat/kw, using fee floor", int64(feePerKw),
int64(minCommitFeePerKw))

feePerKw = minCommitFeePerKw
}

log.Debugf("ChannelLink(%v): sampled fee rate for 3 block conf: %v "+
"sat/kw", l, int64(feePerKw))

Expand Down
Loading