From 9d2eeb63049fa1cfca35ebd4b6e76bb2a3a938bc Mon Sep 17 00:00:00 2001 From: Wilmer Paulino Date: Fri, 27 Jul 2018 18:20:58 -0700 Subject: [PATCH] multi: update to latest fee estimation interface --- breacharbiter_test.go | 7 +- chainregistry.go | 26 ++++--- fundingmanager.go | 30 ++------- fundingmanager_test.go | 2 +- htlcswitch/link.go | 24 +------ htlcswitch/link_test.go | 47 ++++--------- htlcswitch/mock.go | 6 +- htlcswitch/test_utils.go | 9 +-- lntest/harness.go | 6 +- lnwallet/btcwallet/btcwallet.go | 8 +-- lnwallet/channel_test.go | 5 +- lnwallet/interface.go | 12 ++-- lnwallet/interface_test.go | 101 +++++++++++++++------------- lnwallet/test_utils.go | 5 +- mock.go | 2 +- peer.go | 9 +-- peer_test.go | 13 ++-- pilot.go | 7 +- routing/chainview/interface_test.go | 2 +- server.go | 28 ++++---- test_utils.go | 5 +- 21 files changed, 150 insertions(+), 204 deletions(-) diff --git a/breacharbiter_test.go b/breacharbiter_test.go index 03de6b16f..8f6c90a33 100644 --- a/breacharbiter_test.go +++ b/breacharbiter_test.go @@ -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, @@ -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{ diff --git a/chainregistry.go b/chainregistry.go index 873efaa27..efde6fba7 100644 --- a/chainregistry.go +++ b/chainregistry.go @@ -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 + // 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 @@ -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{ @@ -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 "+ @@ -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 @@ -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 @@ -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 diff --git a/fundingmanager.go b/fundingmanager.go index fa414545a..8576205c0 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -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" @@ -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 ( @@ -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 ( @@ -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) @@ -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 - // 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 @@ -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 { diff --git a/fundingmanager_test.go b/fundingmanager_test.go index deb08f0f2..d37f21954 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -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), diff --git a/htlcswitch/link.go b/htlcswitch/link.go index b75f3af51..df33da84e 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -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 @@ -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)) diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index bd4dc5972..24b80530a 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -1726,14 +1726,11 @@ func TestChannelLinkBandwidthConsistency(t *testing.T) { coreLink.cfg.HodlMask = hodl.MaskFromFlags(hodl.ExitSettle) coreLink.cfg.DebugHTLC = true - estimator := &lnwallet.StaticFeeEstimator{ - FeeRate: 24, - } - feeRate, err := estimator.EstimateFeePerVSize(1) + estimator := &lnwallet.StaticFeeEstimator{FeePerKW: 6000} + feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to query fee estimator: %v", err) } - feePerKw := feeRate.FeePerKWeight() htlcFee := lnwire.NewMSatFromSatoshis( feePerKw.FeeForWeight(lnwallet.HtlcWeight), ) @@ -2140,14 +2137,11 @@ func TestChannelLinkBandwidthConsistencyOverflow(t *testing.T) { aliceMsgs = coreLink.cfg.Peer.(*mockPeer).sentMsgs ) - estimator := &lnwallet.StaticFeeEstimator{ - FeeRate: 24, - } - feeRate, err := estimator.EstimateFeePerVSize(1) + estimator := &lnwallet.StaticFeeEstimator{FeePerKW: 6000} + feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to query fee estimator: %v", err) } - feePerKw := feeRate.FeePerKWeight() var htlcID uint64 addLinkHTLC := func(id uint64, amt lnwire.MilliSatoshi) [32]byte { @@ -2390,17 +2384,15 @@ func TestChannelLinkTrimCircuitsPending(t *testing.T) { // Compute the static fees that will be used to determine the // correctness of Alice's bandwidth when forwarding HTLCs. - estimator := &lnwallet.StaticFeeEstimator{ - FeeRate: 24, - } - feeRate, err := estimator.EstimateFeePerVSize(1) + estimator := &lnwallet.StaticFeeEstimator{FeePerKW: 6000} + feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to query fee estimator: %v", err) } defaultCommitFee := alice.channel.StateSnapshot().CommitFee htlcFee := lnwire.NewMSatFromSatoshis( - feeRate.FeePerKWeight().FeeForWeight(lnwallet.HtlcWeight), + feePerKw.FeeForWeight(lnwallet.HtlcWeight), ) // The starting bandwidth of the channel should be exactly the amount @@ -2666,17 +2658,15 @@ func TestChannelLinkTrimCircuitsNoCommit(t *testing.T) { // Compute the static fees that will be used to determine the // correctness of Alice's bandwidth when forwarding HTLCs. - estimator := &lnwallet.StaticFeeEstimator{ - FeeRate: 24, - } - feeRate, err := estimator.EstimateFeePerVSize(1) + estimator := &lnwallet.StaticFeeEstimator{FeePerKW: 6000} + feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to query fee estimator: %v", err) } defaultCommitFee := alice.channel.StateSnapshot().CommitFee htlcFee := lnwire.NewMSatFromSatoshis( - feeRate.FeePerKWeight().FeeForWeight(lnwallet.HtlcWeight), + feePerKw.FeeForWeight(lnwallet.HtlcWeight), ) // The starting bandwidth of the channel should be exactly the amount @@ -2926,14 +2916,11 @@ func TestChannelLinkBandwidthChanReserve(t *testing.T) { aliceMsgs = coreLink.cfg.Peer.(*mockPeer).sentMsgs ) - estimator := &lnwallet.StaticFeeEstimator{ - FeeRate: 24, - } - feeRate, err := estimator.EstimateFeePerVSize(1) + estimator := &lnwallet.StaticFeeEstimator{FeePerKW: 6000} + feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to query fee estimator: %v", err) } - feePerKw := feeRate.FeePerKWeight() htlcFee := lnwire.NewMSatFromSatoshis( feePerKw.FeeForWeight(lnwallet.HtlcWeight), ) @@ -3460,15 +3447,9 @@ func TestChannelLinkUpdateCommitFee(t *testing.T) { startingFeeRate := channels.aliceToBob.CommitFeeRate() - // Convert starting fee rate to sat/vbyte. This is usually a - // lossy conversion, but since the startingFeeRate is - // 6000 sat/kw in this case, we won't lose precision. - startingFeeRateSatPerVByte := lnwallet.SatPerVByte( - startingFeeRate * 4 / 1000) - // Next, we'll send the first fee rate response to Alice. select { - case n.feeEstimator.byteFeeIn <- startingFeeRateSatPerVByte: + case n.feeEstimator.byteFeeIn <- startingFeeRate: case <-time.After(time.Second * 5): t.Fatalf("alice didn't query for the new network fee") } @@ -3497,7 +3478,7 @@ func TestChannelLinkUpdateCommitFee(t *testing.T) { // fee update. newFeeRate := startingFeeRate * 3 select { - case n.feeEstimator.byteFeeIn <- startingFeeRateSatPerVByte * 3: + case n.feeEstimator.byteFeeIn <- newFeeRate: case <-time.After(time.Second * 5): t.Fatalf("alice didn't query for the new network fee") } diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go index 9d3a29389..3dcfa8763 100644 --- a/htlcswitch/mock.go +++ b/htlcswitch/mock.go @@ -58,12 +58,14 @@ func (m *mockPreimageCache) SubscribeUpdates() *contractcourt.WitnessSubscriptio } type mockFeeEstimator struct { - byteFeeIn chan lnwallet.SatPerVByte + byteFeeIn chan lnwallet.SatPerKWeight quit chan struct{} } -func (m *mockFeeEstimator) EstimateFeePerVSize(numBlocks uint32) (lnwallet.SatPerVByte, error) { +func (m *mockFeeEstimator) EstimateFeePerKW( + numBlocks uint32) (lnwallet.SatPerKWeight, error) { + select { case feeRate := <-m.byteFeeIn: return feeRate, nil diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index 46bf718f0..7838e1292 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -271,14 +271,11 @@ func createTestChannel(alicePrivKey, bobPrivKey []byte, return nil, nil, nil, nil, err } - estimator := &lnwallet.StaticFeeEstimator{ - FeeRate: 24, - } - feePerVSize, err := estimator.EstimateFeePerVSize(1) + estimator := &lnwallet.StaticFeeEstimator{FeePerKW: 6000} + feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { return nil, nil, nil, nil, err } - feePerKw := feePerVSize.FeePerKWeight() commitFee := feePerKw.FeeForWeight(724) const broadcastHeight = 1 @@ -873,7 +870,7 @@ func newThreeHopNetwork(t testing.TB, aliceChannel, firstBobChannel, carolDecoder := newMockIteratorDecoder() feeEstimator := &mockFeeEstimator{ - byteFeeIn: make(chan lnwallet.SatPerVByte), + byteFeeIn: make(chan lnwallet.SatPerKWeight), quit: make(chan struct{}), } diff --git a/lntest/harness.go b/lntest/harness.go index 517645b2d..60c0f4ef4 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -172,7 +172,8 @@ func (n *NetworkHarness) SetUp(lndArgs []string) error { PkScript: addrScript, Value: btcutil.SatoshiPerBitcoin, } - if _, err := n.Miner.SendOutputs([]*wire.TxOut{output}, 30); err != nil { + _, err = n.Miner.SendOutputs([]*wire.TxOut{output}, 7500) + if err != nil { return err } } @@ -1159,7 +1160,8 @@ func (n *NetworkHarness) sendCoins(ctx context.Context, amt btcutil.Amount, PkScript: addrScript, Value: int64(amt), } - if _, err := n.Miner.SendOutputs([]*wire.TxOut{output}, 30); err != nil { + _, err = n.Miner.SendOutputs([]*wire.TxOut{output}, 7500) + if err != nil { return err } diff --git a/lnwallet/btcwallet/btcwallet.go b/lnwallet/btcwallet/btcwallet.go index cc946e428..92bcbfa25 100644 --- a/lnwallet/btcwallet/btcwallet.go +++ b/lnwallet/btcwallet/btcwallet.go @@ -272,11 +272,11 @@ func (b *BtcWallet) GetPrivKey(a btcutil.Address) (*btcec.PrivateKey, error) { // // This is a part of the WalletController interface. func (b *BtcWallet) SendOutputs(outputs []*wire.TxOut, - feeRate lnwallet.SatPerVByte) (*chainhash.Hash, error) { + feeRate lnwallet.SatPerKWeight) (*chainhash.Hash, error) { - // The fee rate is passed in using units of sat/vbyte, so we'll scale - // this up to sat/KB as the SendOutputs method requires this unit. - feeSatPerKB := btcutil.Amount(feeRate * 1000) + // Convert our fee rate from sat/kw to sat/kb since it's required by + // SendOutputs. + feeSatPerKB := btcutil.Amount(feeRate.FeePerKVByte()) return b.wallet.SendOutputs(outputs, defaultAccount, 1, feeSatPerKB) } diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go index 9da2ee919..b596befbb 100644 --- a/lnwallet/channel_test.go +++ b/lnwallet/channel_test.go @@ -1131,12 +1131,11 @@ func TestHTLCSigNumber(t *testing.T) { } // Calculate two values that will be below and above Bob's dust limit. - estimator := &StaticFeeEstimator{24} - feePerVSize, err := estimator.EstimateFeePerVSize(1) + estimator := &StaticFeeEstimator{FeePerKW: 6000} + feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to get fee: %v", err) } - feePerKw := feePerVSize.FeePerKWeight() belowDust := btcutil.Amount(500) + htlcTimeoutFee(feePerKw) aboveDust := btcutil.Amount(1400) + htlcSuccessFee(feePerKw) diff --git a/lnwallet/interface.go b/lnwallet/interface.go index 0aad560ad..073cd9137 100644 --- a/lnwallet/interface.go +++ b/lnwallet/interface.go @@ -154,13 +154,13 @@ type WalletController interface { // error should be returned. GetPrivKey(a btcutil.Address) (*btcec.PrivateKey, error) - // SendOutputs funds, signs, and broadcasts a Bitcoin transaction - // paying out to the specified outputs. In the case the wallet has - // insufficient funds, or the outputs are non-standard, an error should - // be returned. This method also takes the target fee expressed in - // sat/vbyte that should be used when crafting the transaction. + // SendOutputs funds, signs, and broadcasts a Bitcoin transaction paying + // out to the specified outputs. In the case the wallet has insufficient + // funds, or the outputs are non-standard, an error should be returned. + // This method also takes the target fee expressed in sat/kw that should + // be used when crafting the transaction. SendOutputs(outputs []*wire.TxOut, - feeRate SatPerVByte) (*chainhash.Hash, error) + feeRate SatPerKWeight) (*chainhash.Hash, error) // ListUnspentWitness returns all unspent outputs which are version 0 // witness programs. The 'confirms' parameter indicates the minimum diff --git a/lnwallet/interface_test.go b/lnwallet/interface_test.go index eb3d3b507..4f304bc15 100644 --- a/lnwallet/interface_test.go +++ b/lnwallet/interface_test.go @@ -186,7 +186,7 @@ func loadTestCredits(miner *rpctest.Harness, w *lnwallet.LightningWallet, Value: int64(satoshiPerOutput), PkScript: script, } - if _, err := miner.SendOutputs([]*wire.TxOut{output}, 10); err != nil { + if _, err := miner.SendOutputs([]*wire.TxOut{output}, 2500); err != nil { return err } } @@ -249,7 +249,7 @@ func createTestWallet(tempTestDir string, miningNode *rpctest.Harness, WalletController: wc, Signer: signer, ChainIO: bio, - FeeEstimator: lnwallet.StaticFeeEstimator{FeeRate: 10}, + FeeEstimator: lnwallet.StaticFeeEstimator{FeePerKW: 2500}, DefaultConstraints: channeldb.ChannelConstraints{ DustLimit: 500, MaxPendingAmount: lnwire.NewMSatFromSatoshis(btcutil.SatoshiPerBitcoin) * 100, @@ -290,14 +290,14 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness, // Alice initiates a channel funded with 5 BTC for each side, so 10 BTC // total. She also generates 2 BTC in change. - feeRate, err := alice.Cfg.FeeEstimator.EstimateFeePerVSize(1) + feePerKw, err := alice.Cfg.FeeEstimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to query fee estimator: %v", err) } - feePerKw := feeRate.FeePerKWeight() aliceChanReservation, err := alice.InitChannelReservation( - fundingAmount*2, fundingAmount, 0, feePerKw, feeRate, - bobPub, bobAddr, chainHash, lnwire.FFAnnounceChannel) + fundingAmount*2, fundingAmount, 0, feePerKw, feePerKw, bobPub, + bobAddr, chainHash, lnwire.FFAnnounceChannel, + ) if err != nil { t.Fatalf("unable to initialize funding reservation: %v", err) } @@ -325,9 +325,10 @@ func testDualFundingReservationWorkflow(miner *rpctest.Harness, // Bob does the same, generating his own contribution. He then also // receives' Alice's contribution, and consumes that so we can continue // the funding process. - bobChanReservation, err := bob.InitChannelReservation(fundingAmount*2, - fundingAmount, 0, feePerKw, feeRate, alicePub, aliceAddr, - chainHash, lnwire.FFAnnounceChannel) + bobChanReservation, err := bob.InitChannelReservation( + fundingAmount*2, fundingAmount, 0, feePerKw, feePerKw, alicePub, + aliceAddr, chainHash, lnwire.FFAnnounceChannel, + ) if err != nil { t.Fatalf("bob unable to init channel reservation: %v", err) } @@ -471,14 +472,13 @@ func testFundingTransactionLockedOutputs(miner *rpctest.Harness, if err != nil { t.Fatalf("unable to create amt: %v", err) } - feeRate, err := alice.Cfg.FeeEstimator.EstimateFeePerVSize(1) + feePerKw, err := alice.Cfg.FeeEstimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to query fee estimator: %v", err) } - feePerKw := feeRate.FeePerKWeight() - _, err = alice.InitChannelReservation(fundingAmount, - fundingAmount, 0, feePerKw, feeRate, bobPub, bobAddr, chainHash, - lnwire.FFAnnounceChannel, + _, err = alice.InitChannelReservation( + fundingAmount, fundingAmount, 0, feePerKw, feePerKw, bobPub, + bobAddr, chainHash, lnwire.FFAnnounceChannel, ) if err != nil { t.Fatalf("unable to initialize funding reservation 1: %v", err) @@ -491,9 +491,10 @@ func testFundingTransactionLockedOutputs(miner *rpctest.Harness, if err != nil { t.Fatalf("unable to create amt: %v", err) } - failedReservation, err := alice.InitChannelReservation(amt, amt, 0, - feePerKw, feeRate, bobPub, bobAddr, chainHash, - lnwire.FFAnnounceChannel) + failedReservation, err := alice.InitChannelReservation( + amt, amt, 0, feePerKw, feePerKw, bobPub, bobAddr, chainHash, + lnwire.FFAnnounceChannel, + ) if err == nil { t.Fatalf("not error returned, should fail on coin selection") } @@ -508,28 +509,28 @@ func testFundingTransactionLockedOutputs(miner *rpctest.Harness, func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness, alice, _ *lnwallet.LightningWallet, t *testing.T) { - feeRate, err := alice.Cfg.FeeEstimator.EstimateFeePerVSize(1) + feePerKw, err := alice.Cfg.FeeEstimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to query fee estimator: %v", err) } - feePerKw := feeRate.FeePerKWeight() // Create a reservation for 44 BTC. fundingAmount, err := btcutil.NewAmount(44) if err != nil { t.Fatalf("unable to create amt: %v", err) } - chanReservation, err := alice.InitChannelReservation(fundingAmount, - fundingAmount, 0, feePerKw, feeRate, bobPub, bobAddr, chainHash, - lnwire.FFAnnounceChannel) + chanReservation, err := alice.InitChannelReservation( + fundingAmount, fundingAmount, 0, feePerKw, feePerKw, bobPub, + bobAddr, chainHash, lnwire.FFAnnounceChannel, + ) if err != nil { t.Fatalf("unable to initialize funding reservation: %v", err) } // Attempt to create another channel with 44 BTC, this should fail. - _, err = alice.InitChannelReservation(fundingAmount, - fundingAmount, 0, feePerKw, feeRate, bobPub, bobAddr, chainHash, - lnwire.FFAnnounceChannel, + _, err = alice.InitChannelReservation( + fundingAmount, fundingAmount, 0, feePerKw, feePerKw, bobPub, + bobAddr, chainHash, lnwire.FFAnnounceChannel, ) if _, ok := err.(*lnwallet.ErrInsufficientFunds); !ok { t.Fatalf("coin selection succeeded should have insufficient funds: %v", @@ -560,7 +561,7 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness, // Request to fund a new channel should now succeed. _, err = alice.InitChannelReservation(fundingAmount, fundingAmount, - 0, feePerKw, feeRate, bobPub, bobAddr, chainHash, + 0, feePerKw, feePerKw, bobPub, bobAddr, chainHash, lnwire.FFAnnounceChannel) if err != nil { t.Fatalf("unable to initialize funding reservation: %v", err) @@ -570,15 +571,15 @@ func testFundingCancellationNotEnoughFunds(miner *rpctest.Harness, func testCancelNonExistentReservation(miner *rpctest.Harness, alice, _ *lnwallet.LightningWallet, t *testing.T) { - feeRate, err := alice.Cfg.FeeEstimator.EstimateFeePerVSize(1) + feePerKw, err := alice.Cfg.FeeEstimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to query fee estimator: %v", err) } // Create our own reservation, give it some ID. res, err := lnwallet.NewChannelReservation( - 10000, 10000, feeRate.FeePerKWeight(), alice, - 22, 10, &testHdSeed, lnwire.FFAnnounceChannel, + 10000, 10000, feePerKw, alice, 22, 10, &testHdSeed, + lnwire.FFAnnounceChannel, ) if err != nil { t.Fatalf("unable to create res: %v", err) @@ -597,14 +598,17 @@ func testReservationInitiatorBalanceBelowDustCancel(miner *rpctest.Harness, // We'll attempt to create a new reservation with an extremely high fee // rate. This should push our balance into the negative and result in a // failure to create the reservation. - fundingAmount, err := btcutil.NewAmount(4) + const numBTC = 4 + fundingAmount, err := btcutil.NewAmount(numBTC) if err != nil { t.Fatalf("unable to create amt: %v", err) } - feePerVSize := lnwallet.SatPerVByte(btcutil.SatoshiPerBitcoin * 4 / 100) - feePerKw := feePerVSize.FeePerKWeight() + + feePerKw := lnwallet.SatPerKWeight( + numBTC * numBTC * btcutil.SatoshiPerBitcoin, + ) _, err = alice.InitChannelReservation( - fundingAmount, fundingAmount, 0, feePerKw, feePerVSize, bobPub, + fundingAmount, fundingAmount, 0, feePerKw, feePerKw, bobPub, bobAddr, chainHash, lnwire.FFAnnounceChannel, ) switch { @@ -672,14 +676,14 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, t.Fatalf("unable to create amt: %v", err) } pushAmt := lnwire.NewMSatFromSatoshis(btcutil.SatoshiPerBitcoin) - feeRate, err := alice.Cfg.FeeEstimator.EstimateFeePerVSize(1) + feePerKw, err := alice.Cfg.FeeEstimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to query fee estimator: %v", err) } - feePerKw := feeRate.FeePerKWeight() - aliceChanReservation, err := alice.InitChannelReservation(fundingAmt, - fundingAmt, pushAmt, feePerKw, feeRate, bobPub, bobAddr, chainHash, - lnwire.FFAnnounceChannel) + aliceChanReservation, err := alice.InitChannelReservation( + fundingAmt, fundingAmt, pushAmt, feePerKw, feePerKw, bobPub, + bobAddr, chainHash, lnwire.FFAnnounceChannel, + ) if err != nil { t.Fatalf("unable to init channel reservation: %v", err) } @@ -707,9 +711,10 @@ func testSingleFunderReservationWorkflow(miner *rpctest.Harness, // Next, Bob receives the initial request, generates a corresponding // reservation initiation, then consume Alice's contribution. - bobChanReservation, err := bob.InitChannelReservation(fundingAmt, 0, - pushAmt, feePerKw, feeRate, alicePub, aliceAddr, chainHash, - lnwire.FFAnnounceChannel) + bobChanReservation, err := bob.InitChannelReservation( + fundingAmt, 0, pushAmt, feePerKw, feePerKw, alicePub, aliceAddr, + chainHash, lnwire.FFAnnounceChannel, + ) if err != nil { t.Fatalf("unable to create bob reservation: %v", err) } @@ -891,7 +896,7 @@ func testListTransactionDetails(miner *rpctest.Harness, Value: outputAmt, PkScript: script, } - txid, err := miner.SendOutputs([]*wire.TxOut{output}, 10) + txid, err := miner.SendOutputs([]*wire.TxOut{output}, 2500) if err != nil { t.Fatalf("unable to send coinbase: %v", err) } @@ -994,7 +999,7 @@ func testListTransactionDetails(miner *rpctest.Harness, t.Fatalf("unable to make output script: %v", err) } burnOutput := wire.NewTxOut(outputAmt, outputScript) - burnTXID, err := alice.SendOutputs([]*wire.TxOut{burnOutput}, 10) + burnTXID, err := alice.SendOutputs([]*wire.TxOut{burnOutput}, 2500) if err != nil { t.Fatalf("unable to create burn tx: %v", err) } @@ -1108,7 +1113,7 @@ func testTransactionSubscriptions(miner *rpctest.Harness, Value: outputAmt, PkScript: script, } - txid, err := miner.SendOutputs([]*wire.TxOut{output}, 10) + txid, err := miner.SendOutputs([]*wire.TxOut{output}, 2500) if err != nil { t.Fatalf("unable to send coinbase: %v", err) } @@ -1308,7 +1313,7 @@ func testPublishTransaction(r *rpctest.Harness, Value: btcutil.SatoshiPerBitcoin, PkScript: keyScript, } - txid, err := alice.SendOutputs([]*wire.TxOut{newOutput}, 10) + txid, err := alice.SendOutputs([]*wire.TxOut{newOutput}, 2500) if err != nil { t.Fatalf("unable to create output: %v", err) } @@ -1553,7 +1558,7 @@ func testSignOutputUsingTweaks(r *rpctest.Harness, Value: btcutil.SatoshiPerBitcoin, PkScript: keyScript, } - txid, err := alice.SendOutputs([]*wire.TxOut{newOutput}, 10) + txid, err := alice.SendOutputs([]*wire.TxOut{newOutput}, 2500) if err != nil { t.Fatalf("unable to create output: %v", err) } @@ -1679,7 +1684,7 @@ func testReorgWalletBalance(r *rpctest.Harness, w *lnwallet.LightningWallet, Value: 1e8, PkScript: script, } - txid, err := w.SendOutputs([]*wire.TxOut{output}, 10) + txid, err := w.SendOutputs([]*wire.TxOut{output}, 2500) if err != nil { t.Fatalf("unable to send outputs: %v", err) } @@ -2073,7 +2078,7 @@ func runTests(t *testing.T, walletDriver *lnwallet.WalletDriver, } case "neutrino": - feeEstimator = lnwallet.StaticFeeEstimator{FeeRate: 250} + feeEstimator = lnwallet.StaticFeeEstimator{FeePerKW: 62500} // Set some package-level variable to speed up // operation for tests. diff --git a/lnwallet/test_utils.go b/lnwallet/test_utils.go index 03cd85135..c11aa69d4 100644 --- a/lnwallet/test_utils.go +++ b/lnwallet/test_utils.go @@ -229,12 +229,11 @@ func CreateTestChannels() (*LightningChannel, *LightningChannel, func(), error) return nil, nil, nil, err } - estimator := &StaticFeeEstimator{24} - feePerVSize, err := estimator.EstimateFeePerVSize(1) + estimator := &StaticFeeEstimator{FeePerKW: 6000} + feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { return nil, nil, nil, err } - feePerKw := feePerVSize.FeePerKWeight() commitFee := calcStaticFee(0) aliceCommit := channeldb.ChannelCommitment{ diff --git a/mock.go b/mock.go index cd0461e8c..e4b563ad7 100644 --- a/mock.go +++ b/mock.go @@ -224,7 +224,7 @@ func (*mockWalletController) GetPrivKey(a btcutil.Address) (*btcec.PrivateKey, e } func (*mockWalletController) SendOutputs(outputs []*wire.TxOut, - _ lnwallet.SatPerVByte) (*chainhash.Hash, error) { + _ lnwallet.SatPerKWeight) (*chainhash.Hash, error) { return nil, nil } diff --git a/peer.go b/peer.go index ffc4cd286..09a172913 100644 --- a/peer.go +++ b/peer.go @@ -1658,18 +1658,13 @@ func (p *peer) fetchActiveChanCloser(chanID lnwire.ChannelID) (*channelCloser, e // In order to begin fee negotiations, we'll first compute our // target ideal fee-per-kw. We'll set this to a lax value, as // we weren't the ones that initiated the channel closure. - feePerVSize, err := p.server.cc.feeEstimator.EstimateFeePerVSize(6) + feePerKw, err := p.server.cc.feeEstimator.EstimateFeePerKW(6) if err != nil { peerLog.Errorf("unable to query fee estimator: %v", err) return nil, fmt.Errorf("unable to estimate fee") } - // We'll then convert the sat per weight to sat per k/w as this - // is the native unit used within the protocol when dealing - // with fees. - targetFeePerKw := feePerVSize.FeePerKWeight() - _, startingHeight, err := p.server.cc.chainIO.GetBestBlock() if err != nil { peerLog.Errorf("unable to obtain best block: %v", err) @@ -1685,7 +1680,7 @@ func (p *peer) fetchActiveChanCloser(chanID lnwire.ChannelID) (*channelCloser, e quit: p.quit, }, deliveryAddr, - targetFeePerKw, + feePerKw, uint32(startingHeight), nil, ) diff --git a/peer_test.go b/peer_test.go index 2b7112870..ffeb5951c 100644 --- a/peer_test.go +++ b/peer_test.go @@ -169,12 +169,11 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) { dummyDeliveryScript), } - estimator := lnwallet.StaticFeeEstimator{FeeRate: 50} - feeRate, err := estimator.EstimateFeePerVSize(1) + estimator := lnwallet.StaticFeeEstimator{FeePerKW: 12500} + feePerKw, err := estimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to query fee estimator: %v", err) } - feePerKw := feeRate.FeePerKWeight() fee := responderChan.CalcFee(feePerKw) closeSig, _, _, err := responderChan.CreateCloseProposal(fee, dummyDeliveryScript, initiatorDeliveryScript) @@ -460,14 +459,12 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) { msg: respShutdown, } - estimator := lnwallet.StaticFeeEstimator{FeeRate: 50} - initiatorIdealFeeRate, err := estimator.EstimateFeePerVSize(1) + estimator := lnwallet.StaticFeeEstimator{FeePerKW: 12500} + initiatorIdealFeeRate, err := estimator.EstimateFeePerKW(1) if err != nil { t.Fatalf("unable to query fee estimator: %v", err) } - initiatorIdealFee := responderChan.CalcFee( - initiatorIdealFeeRate.FeePerKWeight(), - ) + initiatorIdealFee := responderChan.CalcFee(initiatorIdealFeeRate) increasedFee := btcutil.Amount(float64(initiatorIdealFee) * 2.5) closeSig, _, _, err := responderChan.CreateCloseProposal( increasedFee, dummyDeliveryScript, initiatorDeliveryScript, diff --git a/pilot.go b/pilot.go index e956359ee..b1d8f0a90 100644 --- a/pilot.go +++ b/pilot.go @@ -80,7 +80,7 @@ func (c *chanController) OpenChannel(target *btcec.PublicKey, // With the connection established, we'll now establish our connection // to the target peer, waiting for the first update before we exit. - feePerVSize, err := c.server.cc.feeEstimator.EstimateFeePerVSize(3) + feePerKw, err := c.server.cc.feeEstimator.EstimateFeePerKW(3) if err != nil { return err } @@ -88,8 +88,9 @@ func (c *chanController) OpenChannel(target *btcec.PublicKey, // TODO(halseth): make configurable? minHtlc := lnwire.NewMSatFromSatoshis(1) - updateStream, errChan := c.server.OpenChannel(target, amt, 0, - minHtlc, feePerVSize, false, 0) + updateStream, errChan := c.server.OpenChannel( + target, amt, 0, minHtlc, feePerKw, false, 0, + ) select { case err := <-errChan: diff --git a/routing/chainview/interface_test.go b/routing/chainview/interface_test.go index 7691daf14..d00950347 100644 --- a/routing/chainview/interface_test.go +++ b/routing/chainview/interface_test.go @@ -92,7 +92,7 @@ func getTestTXID(miner *rpctest.Harness) (*chainhash.Hash, error) { PkScript: script, }, } - return miner.SendOutputs(outputs, 10) + return miner.SendOutputs(outputs, 2500) } func locateOutput(tx *wire.MsgTx, script []byte) (*wire.OutPoint, *wire.TxOut, error) { diff --git a/server.go b/server.go index 233fe2d54..76d54512f 100644 --- a/server.go +++ b/server.go @@ -2537,7 +2537,7 @@ type openChanReq struct { pushAmt lnwire.MilliSatoshi - fundingFeePerVSize lnwallet.SatPerVByte + fundingFeePerKw lnwallet.SatPerKWeight private bool @@ -2685,7 +2685,7 @@ func (s *server) DisconnectPeer(pubKey *btcec.PublicKey) error { // NOTE: This function is safe for concurrent access. func (s *server) OpenChannel(nodeKey *btcec.PublicKey, localAmt btcutil.Amount, pushAmt, minHtlc lnwire.MilliSatoshi, - fundingFeePerVSize lnwallet.SatPerVByte, private bool, + fundingFeePerKw lnwallet.SatPerKWeight, private bool, remoteCsvDelay uint16) (chan *lnrpc.OpenStatusUpdate, chan error) { // The updateChan will have a buffer of 2, since we expect a @@ -2723,9 +2723,9 @@ func (s *server) OpenChannel(nodeKey *btcec.PublicKey, // If the fee rate wasn't specified, then we'll use a default // confirmation target. - if fundingFeePerVSize == 0 { + if fundingFeePerKw == 0 { estimator := s.cc.feeEstimator - fundingFeePerVSize, err = estimator.EstimateFeePerVSize(6) + fundingFeePerKw, err = estimator.EstimateFeePerKW(6) if err != nil { errChan <- err return updateChan, errChan @@ -2737,16 +2737,16 @@ func (s *server) OpenChannel(nodeKey *btcec.PublicKey, // instead of blocking on this request which is exported as a // synchronous request to the outside world. req := &openChanReq{ - targetPubkey: nodeKey, - chainHash: *activeNetParams.GenesisHash, - localFundingAmt: localAmt, - fundingFeePerVSize: fundingFeePerVSize, - pushAmt: pushAmt, - private: private, - minHtlc: minHtlc, - remoteCsvDelay: remoteCsvDelay, - updates: updateChan, - err: errChan, + targetPubkey: nodeKey, + chainHash: *activeNetParams.GenesisHash, + localFundingAmt: localAmt, + fundingFeePerKw: fundingFeePerKw, + pushAmt: pushAmt, + private: private, + minHtlc: minHtlc, + remoteCsvDelay: remoteCsvDelay, + updates: updateChan, + err: errChan, } // TODO(roasbeef): pass in chan that's closed if/when funding succeeds diff --git a/test_utils.go b/test_utils.go index 0de7f0f80..f6338bfb5 100644 --- a/test_utils.go +++ b/test_utils.go @@ -201,12 +201,11 @@ func createTestPeer(notifier chainntnfs.ChainNotifier, return nil, 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, nil, err } - feePerKw := feePerVSize.FeePerKWeight() // TODO(roasbeef): need to factor in commit fee? aliceCommit := channeldb.ChannelCommitment{