sweep+cnct+nursery+rpc: extract DetermineFeePerKw to func, add FeePreference

In this commit, we extract the existing determineFeePerKw method on the
RPC server into a new file in the sweep package. Along the way, we
consolidate code by introducing a new FeePreference struct, which allows
the caller to express their fee preference either in blocks to
confirmation, or a direct fee rate. This move takes a small step to
father decoupling calls in the main RPC server.
This commit is contained in:
Olaoluwa Osuntokun 2018-11-17 20:44:34 -08:00
parent 77262ff699
commit 73c9c2ee15
No known key found for this signature in database
GPG Key ID: CE58F7F8E20FD9A2
4 changed files with 112 additions and 61 deletions

View File

@ -476,7 +476,10 @@ func (h *htlcSuccessResolver) Resolve() (ContractResolver, error) {
// TODO: Use time-based sweeper and result chan.
var err error
h.sweepTx, err = h.Sweeper.CreateSweepTx(
[]sweep.Input{&input}, sweepConfTarget, 0,
[]sweep.Input{&input},
sweep.FeePreference{
ConfTarget: sweepConfTarget,
}, 0,
)
if err != nil {
return nil, err
@ -1270,7 +1273,10 @@ func (c *commitSweepResolver) Resolve() (ContractResolver, error) {
//
// TODO: Use time-based sweeper and result chan.
c.sweepTx, err = c.Sweeper.CreateSweepTx(
[]sweep.Input{&input}, sweepConfTarget, 0,
[]sweep.Input{&input},
sweep.FeePreference{
ConfTarget: sweepConfTarget,
}, 0,
)
if err != nil {
return nil, err

View File

@ -39,6 +39,7 @@ import (
"github.com/lightningnetwork/lnd/macaroons"
"github.com/lightningnetwork/lnd/routing"
"github.com/lightningnetwork/lnd/signal"
"github.com/lightningnetwork/lnd/sweep"
"github.com/lightningnetwork/lnd/zpay32"
"github.com/tv42/zbase32"
"golang.org/x/net/context"
@ -637,53 +638,7 @@ func (r *rpcServer) sendCoinsOnChain(paymentMap map[string]int64,
}
txHash := tx.TxHash()
return &txHash, err
}
// determineFeePerKw will determine the fee in sat/kw that should be paid given
// an estimator, a confirmation target, and a manual value for sat/byte. A value
// is chosen based on the two free parameters as one, or both of them can be
// zero.
func determineFeePerKw(feeEstimator lnwallet.FeeEstimator, targetConf int32,
feePerByte int64) (lnwallet.SatPerKWeight, error) {
switch {
// If the target number of confirmations is set, then we'll use that to
// consult our fee estimator for an adequate fee.
case targetConf != 0:
feePerKw, err := feeEstimator.EstimateFeePerKW(
uint32(targetConf),
)
if err != nil {
return 0, fmt.Errorf("unable to query fee "+
"estimator: %v", err)
}
return feePerKw, nil
// If a manual sat/byte fee rate is set, then we'll use that directly.
// We'll need to convert it to sat/kw as this is what we use internally.
case feePerByte != 0:
feePerKW := lnwallet.SatPerKVByte(feePerByte * 1000).FeePerKWeight()
if feePerKW < lnwallet.FeePerKwFloor {
rpcsLog.Infof("Manual fee rate input of %d sat/kw is "+
"too low, using %d sat/kw instead", feePerKW,
lnwallet.FeePerKwFloor)
feePerKW = lnwallet.FeePerKwFloor
}
return feePerKW, nil
// Otherwise, we'll attempt a relaxed confirmation target for the
// transaction
default:
feePerKw, err := feeEstimator.EstimateFeePerKW(6)
if err != nil {
return 0, fmt.Errorf("unable to query fee estimator: "+
"%v", err)
}
return feePerKw, nil
}
return &txHash, nil
}
// ListUnspent returns useful information about each unspent output owned by
@ -803,8 +758,12 @@ func (r *rpcServer) SendCoins(ctx context.Context,
// Based on the passed fee related parameters, we'll determine an
// appropriate fee rate for this transaction.
feePerKw, err := determineFeePerKw(
r.server.cc.feeEstimator, in.TargetConf, in.SatPerByte,
satPerKw := lnwallet.SatPerKVByte(in.SatPerByte * 1000).FeePerKWeight()
feePerKw, err := sweep.DetermineFeePerKw(
r.server.cc.feeEstimator, sweep.FeePreference{
ConfTarget: uint32(in.TargetConf),
FeeRate: satPerKw,
},
)
if err != nil {
return nil, err
@ -831,8 +790,12 @@ func (r *rpcServer) SendMany(ctx context.Context,
// Based on the passed fee related parameters, we'll determine an
// appropriate fee rate for this transaction.
feePerKw, err := determineFeePerKw(
r.server.cc.feeEstimator, in.TargetConf, in.SatPerByte,
satPerKw := lnwallet.SatPerKVByte(in.SatPerByte * 1000).FeePerKWeight()
feePerKw, err := sweep.DetermineFeePerKw(
r.server.cc.feeEstimator, sweep.FeePreference{
ConfTarget: uint32(in.TargetConf),
FeeRate: satPerKw,
},
)
if err != nil {
return nil, err
@ -1167,8 +1130,12 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest,
// Based on the passed fee related parameters, we'll determine an
// appropriate fee rate for the funding transaction.
feeRate, err := determineFeePerKw(
r.server.cc.feeEstimator, in.TargetConf, in.SatPerByte,
satPerKw := lnwallet.SatPerKVByte(in.SatPerByte * 1000).FeePerKWeight()
feeRate, err := sweep.DetermineFeePerKw(
r.server.cc.feeEstimator, sweep.FeePreference{
ConfTarget: uint32(in.TargetConf),
FeeRate: satPerKw,
},
)
if err != nil {
return err
@ -1314,8 +1281,12 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context,
// Based on the passed fee related parameters, we'll determine an
// appropriate fee rate for the funding transaction.
feeRate, err := determineFeePerKw(
r.server.cc.feeEstimator, in.TargetConf, in.SatPerByte,
satPerKw := lnwallet.SatPerKVByte(in.SatPerByte * 1000).FeePerKWeight()
feeRate, err := sweep.DetermineFeePerKw(
r.server.cc.feeEstimator, sweep.FeePreference{
ConfTarget: uint32(in.TargetConf),
FeeRate: satPerKw,
},
)
if err != nil {
return nil, err
@ -1503,8 +1474,14 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
// Based on the passed fee related parameters, we'll determine
// an appropriate fee rate for the cooperative closure
// transaction.
feeRate, err := determineFeePerKw(
r.server.cc.feeEstimator, in.TargetConf, in.SatPerByte,
satPerKw := lnwallet.SatPerKVByte(
in.SatPerByte * 1000,
).FeePerKWeight()
feeRate, err := sweep.DetermineFeePerKw(
r.server.cc.feeEstimator, sweep.FeePreference{
ConfTarget: uint32(in.TargetConf),
FeeRate: satPerKw,
},
)
if err != nil {
return err

View File

@ -750,10 +750,10 @@ func (s *UtxoSweeper) waitForSpend(outpoint wire.OutPoint,
// - Make handling re-orgs easier.
// - Thwart future possible fee sniping attempts.
// - Make us blend in with the bitcoind wallet.
func (s *UtxoSweeper) CreateSweepTx(inputs []Input, confTarget uint32,
func (s *UtxoSweeper) CreateSweepTx(inputs []Input, feePref FeePreference,
currentBlockHeight uint32) (*wire.MsgTx, error) {
feePerKw, err := s.cfg.FeeEstimator.EstimateFeePerKW(confTarget)
feePerKw, err := DetermineFeePerKw(s.cfg.FeeEstimator, feePref)
if err != nil {
return nil, err
}

68
sweep/walletsweep.go Normal file
View File

@ -0,0 +1,68 @@
package sweep
import (
"fmt"
"github.com/lightningnetwork/lnd/lnwallet"
)
// FeePreference allows callers to express their time value for inclusion of a
// transaction into a block via either a confirmation target, or a fee rate.
type FeePreference struct {
// ConfTarget if non-zero, signals a fee preference expressed in the
// number of desired blocks between first broadcast, and confirmation.
ConfTarget uint32
// FeeRate if non-zero, signals a fee pre fence expressed in the fee
// rate expressed in sat/kw for a particular transaction.
FeeRate lnwallet.SatPerKWeight
}
// DetermineFeePerKw will determine the fee in sat/kw that should be paid given
// an estimator, a confirmation target, and a manual value for sat/byte. A
// value is chosen based on the two free parameters as one, or both of them can
// be zero.
func DetermineFeePerKw(feeEstimator lnwallet.FeeEstimator,
feePref FeePreference) (lnwallet.SatPerKWeight, error) {
switch {
// If the target number of confirmations is set, then we'll use that to
// consult our fee estimator for an adequate fee.
case feePref.ConfTarget != 0:
feePerKw, err := feeEstimator.EstimateFeePerKW(
uint32(feePref.ConfTarget),
)
if err != nil {
return 0, fmt.Errorf("unable to query fee "+
"estimator: %v", err)
}
return feePerKw, nil
// If a manual sat/byte fee rate is set, then we'll use that directly.
// We'll need to convert it to sat/kw as this is what we use
// internally.
case feePref.FeeRate != 0:
feePerKW := feePref.FeeRate
if feePerKW < lnwallet.FeePerKwFloor {
log.Infof("Manual fee rate input of %d sat/kw is "+
"too low, using %d sat/kw instead", feePerKW,
lnwallet.FeePerKwFloor)
feePerKW = lnwallet.FeePerKwFloor
}
return feePerKW, nil
// Otherwise, we'll attempt a relaxed confirmation target for the
// transaction
default:
feePerKw, err := feeEstimator.EstimateFeePerKW(6)
if err != nil {
return 0, fmt.Errorf("unable to query fee estimator: "+
"%v", err)
}
return feePerKw, nil
}
}