Merge pull request #8891 from yyforyongyu/fix-fee-estimator

chainfee: allow specifying min relay feerate from the API source
This commit is contained in:
Oliver Gugger authored and GitHub committed 2024-07-25 11:40:18 -06:00
commit b40f165310
43 files changed
+298 -435

No files matched your search

-16
View File
@@ -27,19 +27,3 @@ func DisableLog() {
func UseLogger(logger btclog.Logger) { func UseLogger(logger btclog.Logger) {
log = logger log = logger
} }
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
return logClosure(c)
}
+3 -3
View File
@@ -10,6 +10,7 @@ import (
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnutils"
) )
// Swapper is an interface that allows the chanbackup.SubSwapper to update the // Swapper is an interface that allows the chanbackup.SubSwapper to update the
@@ -278,9 +279,8 @@ func (s *SubSwapper) backupUpdater() {
) )
for i, closedChan := range chanUpdate.ClosedChans { for i, closedChan := range chanUpdate.ClosedChans {
log.Debugf("Removing channel %v from backup "+ log.Debugf("Removing channel %v from backup "+
"state", newLogClosure(func() string { "state", lnutils.NewLogClosure(
return chanUpdate.ClosedChans[i].String() chanUpdate.ClosedChans[i].String))
}))
delete(s.backupState, closedChan) delete(s.backupState, closedChan)
+3 -4
View File
@@ -4,9 +4,9 @@ import (
"net" "net"
"github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lnutils"
) )
// ChannelRestorer is an interface that allows the Recover method to map the // ChannelRestorer is an interface that allows the Recover method to map the
@@ -63,9 +63,8 @@ func Recover(backups []Single, restorer ChannelRestorer,
log.Infof("Attempting to connect to node=%x (addrs=%v) to "+ log.Infof("Attempting to connect to node=%x (addrs=%v) to "+
"restore ChannelPoint(%v)", "restore ChannelPoint(%v)",
backup.RemoteNodePub.SerializeCompressed(), backup.RemoteNodePub.SerializeCompressed(),
newLogClosure(func() string { lnutils.SpewLogClosure(backups[i].Addresses),
return spew.Sdump(backups[i].Addresses) backup.FundingOutpoint)
}), backup.FundingOutpoint)
err = peerConnector.ConnectPeer( err = peerConnector.ConnectPeer(
backup.RemoteNodePub, backup.Addresses, backup.RemoteNodePub, backup.Addresses,
+6 -13
View File
@@ -13,13 +13,13 @@ import (
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/labels" "github.com/lightningnetwork/lnd/labels"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
) )
@@ -732,9 +732,8 @@ justiceTxBroadcast:
} }
finalTx := justiceTxs.spendAll finalTx := justiceTxs.spendAll
brarLog.Debugf("Broadcasting justice tx: %v", newLogClosure(func() string { brarLog.Debugf("Broadcasting justice tx: %v", lnutils.SpewLogClosure(
return spew.Sdump(finalTx) finalTx))
}))
// We'll now attempt to broadcast the transaction which finalized the // We'll now attempt to broadcast the transaction which finalized the
// channel's retribution against the cheating counter party. // channel's retribution against the cheating counter party.
@@ -857,9 +856,7 @@ Loop:
brarLog.Debugf("Broadcasting justice tx "+ brarLog.Debugf("Broadcasting justice tx "+
"spending commitment outs: %v", "spending commitment outs: %v",
newLogClosure(func() string { lnutils.SpewLogClosure(tx))
return spew.Sdump(tx)
}))
err = b.cfg.PublishTransaction(tx, label) err = b.cfg.PublishTransaction(tx, label)
if err != nil { if err != nil {
@@ -874,9 +871,7 @@ Loop:
brarLog.Debugf("Broadcasting justice tx "+ brarLog.Debugf("Broadcasting justice tx "+
"spending HTLC outs: %v", "spending HTLC outs: %v",
newLogClosure(func() string { lnutils.SpewLogClosure(tx))
return spew.Sdump(tx)
}))
err = b.cfg.PublishTransaction(tx, label) err = b.cfg.PublishTransaction(tx, label)
if err != nil { if err != nil {
@@ -891,9 +886,7 @@ Loop:
brarLog.Debugf("Broadcasting justice tx "+ brarLog.Debugf("Broadcasting justice tx "+
"spending second-level HTLC output: %v", "spending second-level HTLC output: %v",
newLogClosure(func() string { lnutils.SpewLogClosure(tx))
return spew.Sdump(tx)
}))
err = b.cfg.PublishTransaction(tx, label) err = b.cfg.PublishTransaction(tx, label)
if err != nil { if err != nil {
+2 -1
View File
@@ -20,6 +20,7 @@ import (
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
) )
@@ -1254,7 +1255,7 @@ func (c *chainWatcher) dispatchContractBreach(spendEvent *chainntnfs.SpendDetail
spendHeight := uint32(spendEvent.SpendingHeight) spendHeight := uint32(spendEvent.SpendingHeight)
log.Debugf("Punishment breach retribution created: %v", log.Debugf("Punishment breach retribution created: %v",
newLogClosure(func() string { lnutils.NewLogClosure(func() string {
retribution.KeyRing.LocalHtlcKey = nil retribution.KeyRing.LocalHtlcKey = nil
retribution.KeyRing.RemoteHtlcKey = nil retribution.KeyRing.RemoteHtlcKey = nil
retribution.KeyRing.ToLocalKey = nil retribution.KeyRing.ToLocalKey = nil
+7 -21
View File
@@ -14,7 +14,6 @@ import (
"github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/chaincfg/chainhash"
"github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/txscript"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/fn"
@@ -24,6 +23,7 @@ import (
"github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/labels" "github.com/lightningnetwork/lnd/labels"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/sweep" "github.com/lightningnetwork/lnd/sweep"
@@ -465,10 +465,8 @@ func (c *ChannelArbitrator) Start(state *chanArbStartState) error {
} }
log.Debugf("Starting ChannelArbitrator(%v), htlc_set=%v, state=%v", log.Debugf("Starting ChannelArbitrator(%v), htlc_set=%v, state=%v",
c.cfg.ChanPoint, newLogClosure(func() string { c.cfg.ChanPoint, lnutils.SpewLogClosure(c.activeHTLCs),
return spew.Sdump(c.activeHTLCs) state.currentState)
}), state.currentState,
)
// Set our state from our starting state. // Set our state from our starting state.
c.state = state.currentState c.state = state.currentState
@@ -958,10 +956,7 @@ func (c *ChannelArbitrator) stateStep(
// Otherwise, we'll log that we checked the HTLC actions as the // Otherwise, we'll log that we checked the HTLC actions as the
// commitment transaction has already been broadcast. // commitment transaction has already been broadcast.
log.Tracef("ChannelArbitrator(%v): logging chain_actions=%v", log.Tracef("ChannelArbitrator(%v): logging chain_actions=%v",
c.cfg.ChanPoint, c.cfg.ChanPoint, lnutils.SpewLogClosure(chainActions))
newLogClosure(func() string {
return spew.Sdump(chainActions)
}))
// Depending on the type of trigger, we'll either "tunnel" // Depending on the type of trigger, we'll either "tunnel"
// through to a farther state, or just proceed linearly to the // through to a farther state, or just proceed linearly to the
@@ -1096,10 +1091,7 @@ func (c *ChannelArbitrator) stateStep(
// channel resolution state. // channel resolution state.
log.Infof("Broadcasting force close transaction %v, "+ log.Infof("Broadcasting force close transaction %v, "+
"ChannelPoint(%v): %v", closeTx.TxHash(), "ChannelPoint(%v): %v", closeTx.TxHash(),
c.cfg.ChanPoint, c.cfg.ChanPoint, lnutils.SpewLogClosure(closeTx))
newLogClosure(func() string {
return spew.Sdump(closeTx)
}))
// At this point, we'll now broadcast the commitment // At this point, we'll now broadcast the commitment
// transaction itself. // transaction itself.
@@ -1224,9 +1216,7 @@ func (c *ChannelArbitrator) stateStep(
if len(pktsToSend) != 0 { if len(pktsToSend) != 0 {
log.Debugf("ChannelArbitrator(%v): sending "+ log.Debugf("ChannelArbitrator(%v): sending "+
"resolution message=%v", c.cfg.ChanPoint, "resolution message=%v", c.cfg.ChanPoint,
newLogClosure(func() string { lnutils.SpewLogClosure(pktsToSend))
return spew.Sdump(pktsToSend)
}))
err := c.cfg.DeliverResolutionMsg(pktsToSend...) err := c.cfg.DeliverResolutionMsg(pktsToSend...)
if err != nil { if err != nil {
@@ -2741,11 +2731,7 @@ func (c *ChannelArbitrator) notifyContractUpdate(upd *ContractUpdate) {
c.unmergedSet[upd.HtlcKey] = newHtlcSet(upd.Htlcs) c.unmergedSet[upd.HtlcKey] = newHtlcSet(upd.Htlcs)
log.Tracef("ChannelArbitrator(%v): fresh set of htlcs=%v", log.Tracef("ChannelArbitrator(%v): fresh set of htlcs=%v",
c.cfg.ChanPoint, c.cfg.ChanPoint, lnutils.SpewLogClosure(upd))
newLogClosure(func() string {
return spew.Sdump(upd)
}),
)
} }
// updateActiveHTLCs merges the unmerged set of HTLCs from the link with // updateActiveHTLCs merges the unmerged set of HTLCs from the link with
-16
View File
@@ -51,19 +51,3 @@ func UseBreachLogger(logger btclog.Logger) {
func UseNurseryLogger(logger btclog.Logger) { func UseNurseryLogger(logger btclog.Logger) {
utxnLog = logger utxnLog = logger
} }
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
return logClosure(c)
}
+2 -4
View File
@@ -18,6 +18,7 @@ import (
"github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/labels" "github.com/lightningnetwork/lnd/labels"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/sweep" "github.com/lightningnetwork/lnd/sweep"
) )
@@ -947,10 +948,7 @@ func (u *UtxoNursery) waitForSweepConf(classHeight uint32,
func (u *UtxoNursery) sweepCribOutput(classHeight uint32, baby *babyOutput) error { func (u *UtxoNursery) sweepCribOutput(classHeight uint32, baby *babyOutput) error {
utxnLog.Infof("Publishing CLTV-delayed HTLC output using timeout tx "+ utxnLog.Infof("Publishing CLTV-delayed HTLC output using timeout tx "+
"(txid=%v): %v", baby.timeoutTx.TxHash(), "(txid=%v): %v", baby.timeoutTx.TxHash(),
newLogClosure(func() string { lnutils.SpewLogClosure(baby.timeoutTx))
return spew.Sdump(baby.timeoutTx)
}),
)
// We'll now broadcast the HTLC transaction, then wait for it to be // We'll now broadcast the HTLC transaction, then wait for it to be
// confirmed before transitioning it to kindergarten. // confirmed before transitioning it to kindergarten.
+2 -5
View File
@@ -14,8 +14,8 @@ import (
"github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil/bech32" "github.com/btcsuite/btcd/btcutil/bech32"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/autopilot" "github.com/lightningnetwork/lnd/autopilot"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/tor" "github.com/lightningnetwork/lnd/tor"
"github.com/miekg/dns" "github.com/miekg/dns"
@@ -431,10 +431,7 @@ search:
} }
log.Tracef("Retrieved SRV records from dns seed: %v", log.Tracef("Retrieved SRV records from dns seed: %v",
newLogClosure(func() string { lnutils.SpewLogClosure(addrs))
return spew.Sdump(addrs)
}),
)
// Next, we'll need to issue an A record request for each of // Next, we'll need to issue an A record request for each of
// the nodes, skipping it if nothing comes back. // the nodes, skipping it if nothing comes back.
-16
View File
@@ -27,19 +27,3 @@ func DisableLog() {
func UseLogger(logger btclog.Logger) { func UseLogger(logger btclog.Logger) {
log = logger log = logger
} }
// logClosure is used to provide a closure over expensive logging operations
// so don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
return logClosure(c)
}
@@ -55,6 +55,24 @@
# Improvements # Improvements
## Functional Updates ## Functional Updates
* A new field, `min_relay_feerate`, is [now
expected](https://github.com/lightningnetwork/lnd/pull/8891) in the response
from querying the external fee estimation URL. The new response should have
the format,
```json
{
"fee_by_block_target": {
"2": 5076,
"3": 4228,
"26": 4200
},
"min_relay_feerate": 1000
}
```
All units are `sats/kvB`. If the new field `min_relay_feerate` is not set,
the default floor feerate (1012 sats/kvB) will be used.
## RPC Updates ## RPC Updates
* [`xImportMissionControl`](https://github.com/lightningnetwork/lnd/pull/8779) * [`xImportMissionControl`](https://github.com/lightningnetwork/lnd/pull/8779)
+1 -2
View File
@@ -12,7 +12,6 @@ import (
"github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/davecgh/go-spew/spew"
"github.com/go-errors/errors" "github.com/go-errors/errors"
"github.com/lightningnetwork/lnd/batch" "github.com/lightningnetwork/lnd/batch"
"github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chainntnfs"
@@ -1432,7 +1431,7 @@ func (b *Builder) processUpdate(msg interface{},
} }
log.Tracef("New channel update applied: %v", log.Tracef("New channel update applied: %v",
newLogClosure(func() string { return spew.Sdump(msg) })) lnutils.SpewLogClosure(msg))
b.stats.incNumChannelUpdates() b.stats.incNumChannelUpdates()
default: default:
-16
View File
@@ -29,19 +29,3 @@ func DisableLog() {
func UseLogger(logger btclog.Logger) { func UseLogger(logger btclog.Logger) {
log = logger log = logger
} }
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
return logClosure(c)
}
+7 -10
View File
@@ -5,11 +5,11 @@ import (
"fmt" "fmt"
"sync" "sync"
"github.com/davecgh/go-spew/spew"
"github.com/go-errors/errors" "github.com/go-errors/errors"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/htlcswitch/hop"
"github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
) )
@@ -800,9 +800,8 @@ func (cm *circuitMap) CommitCircuits(circuits ...*PaymentCircuit) (
inKeys = append(inKeys, circuit.Incoming) inKeys = append(inKeys, circuit.Incoming)
} }
log.Tracef("Committing fresh circuits: %v", newLogClosure(func() string { log.Tracef("Committing fresh circuits: %v", lnutils.SpewLogClosure(
return spew.Sdump(inKeys) inKeys))
}))
actions := &CircuitFwdActions{} actions := &CircuitFwdActions{}
@@ -948,9 +947,8 @@ func (cm *circuitMap) OpenCircuits(keystones ...Keystone) error {
return nil return nil
} }
log.Tracef("Opening finalized circuits: %v", newLogClosure(func() string { log.Tracef("Opening finalized circuits: %v", lnutils.SpewLogClosure(
return spew.Sdump(keystones) keystones))
}))
// Check that all keystones correspond to committed-but-unopened // Check that all keystones correspond to committed-but-unopened
// circuits. // circuits.
@@ -1078,9 +1076,8 @@ func (cm *circuitMap) CloseCircuit(outKey CircuitKey) (*PaymentCircuit, error) {
// circuit was already cleaned up at a different point in time. // circuit was already cleaned up at a different point in time.
func (cm *circuitMap) DeleteCircuits(inKeys ...CircuitKey) error { func (cm *circuitMap) DeleteCircuits(inKeys ...CircuitKey) error {
log.Tracef("Deleting resolved circuits: %v", newLogClosure(func() string { log.Tracef("Deleting resolved circuits: %v", lnutils.SpewLogClosure(
return spew.Sdump(inKeys) inKeys))
}))
var ( var (
closingCircuits = make(map[CircuitKey]struct{}) closingCircuits = make(map[CircuitKey]struct{})
+4 -8
View File
@@ -13,7 +13,6 @@ import (
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/btcsuite/btclog" "github.com/btcsuite/btclog"
"github.com/davecgh/go-spew/spew"
"github.com/go-errors/errors" "github.com/go-errors/errors"
"github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/build"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
@@ -25,6 +24,7 @@ import (
"github.com/lightningnetwork/lnd/invoices" "github.com/lightningnetwork/lnd/invoices"
"github.com/lightningnetwork/lnd/lnpeer" "github.com/lightningnetwork/lnd/lnpeer"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnutils"
"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/lnwire" "github.com/lightningnetwork/lnd/lnwire"
@@ -2536,13 +2536,9 @@ func (l *channelLink) updateCommitTx() error {
l.log.Tracef("revocation window exhausted, unable to send: "+ l.log.Tracef("revocation window exhausted, unable to send: "+
"%v, pend_updates=%v, dangling_closes%v", "%v, pend_updates=%v, dangling_closes%v",
l.channel.PendingLocalUpdateCount(), l.channel.PendingLocalUpdateCount(),
newLogClosure(func() string { lnutils.SpewLogClosure(l.openedCircuits),
return spew.Sdump(l.openedCircuits) lnutils.SpewLogClosure(l.closedCircuits))
}),
newLogClosure(func() string {
return spew.Sdump(l.closedCircuits)
}),
)
return nil return nil
} else if err != nil { } else if err != nil {
return err return err
-16
View File
@@ -31,19 +31,3 @@ func UseLogger(logger btclog.Logger) {
log = logger log = logger
hop.UseLogger(logger) hop.UseLogger(logger)
} }
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
return logClosure(c)
}
+8 -10
View File
@@ -21,6 +21,7 @@ import (
"github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/htlcswitch/hop"
"github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/kvdb"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnutils"
"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/lnwire" "github.com/lightningnetwork/lnd/lnwire"
@@ -613,9 +614,8 @@ func (s *Switch) SendHTLC(firstHop lnwire.ShortChannelID, attemptID uint64,
func (s *Switch) UpdateForwardingPolicies( func (s *Switch) UpdateForwardingPolicies(
chanPolicies map[wire.OutPoint]models.ForwardingPolicy) { chanPolicies map[wire.OutPoint]models.ForwardingPolicy) {
log.Tracef("Updating link policies: %v", newLogClosure(func() string { log.Tracef("Updating link policies: %v", lnutils.SpewLogClosure(
return spew.Sdump(chanPolicies) chanPolicies))
}))
s.indexMtx.RLock() s.indexMtx.RLock()
@@ -1213,9 +1213,8 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error {
) )
log.Warnf("unable to find err source for "+ log.Warnf("unable to find err source for "+
"outgoing_link=%v, errors=%v", "outgoing_link=%v, errors=%v",
packet.outgoingChanID, newLogClosure(func() string { packet.outgoingChanID,
return spew.Sdump(linkErrs) lnutils.SpewLogClosure(linkErrs))
}))
} }
log.Tracef("incoming HTLC(%x) violated "+ log.Tracef("incoming HTLC(%x) violated "+
@@ -1994,10 +1993,9 @@ out:
continue continue
} }
log.Tracef("Acked %d settle fails: %v", len(s.pendingSettleFails), log.Tracef("Acked %d settle fails: %v",
newLogClosure(func() string { len(s.pendingSettleFails),
return spew.Sdump(s.pendingSettleFails) lnutils.SpewLogClosure(s.pendingSettleFails))
}))
// Reset the pendingSettleFails buffer while keeping acquired // Reset the pendingSettleFails buffer while keeping acquired
// memory. // memory.
-16
View File
@@ -27,19 +27,3 @@ func DisableLog() {
func UseLogger(logger btclog.Logger) { func UseLogger(logger btclog.Logger) {
log = logger log = logger
} }
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string // nolint:unused
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure { // nolint:unused
return logClosure(c)
}
+2 -5
View File
@@ -15,11 +15,11 @@ import (
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/chaincfg"
"github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcd/wire"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/invoices" "github.com/lightningnetwork/lnd/invoices"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/netann" "github.com/lightningnetwork/lnd/netann"
"github.com/lightningnetwork/lnd/routing" "github.com/lightningnetwork/lnd/routing"
@@ -473,10 +473,7 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig,
} }
log.Tracef("[addinvoice] adding new invoice %v", log.Tracef("[addinvoice] adding new invoice %v",
newLogClosure(func() string { lnutils.SpewLogClosure(newInvoice))
return spew.Sdump(newInvoice)
}),
)
// With all sanity checks passed, write the invoice to the database. // With all sanity checks passed, write the invoice to the database.
_, err = cfg.AddInvoice(ctx, newInvoice, paymentHash) _, err = cfg.AddInvoice(ctx, newInvoice, paymentHash)
-16
View File
@@ -27,19 +27,3 @@ func DisableLog() {
func UseLogger(logger btclog.Logger) { func UseLogger(logger btclog.Logger) {
log = logger log = logger
} }
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
return logClosure(c)
}
+18 -6
View File
@@ -33,6 +33,9 @@ type WebFeeService interface {
// target. // target.
SetFeeRate(feeRate chainfee.SatPerKWeight, conf uint32) SetFeeRate(feeRate chainfee.SatPerKWeight, conf uint32)
// SetMinRelayFeerate sets a min relay feerate.
SetMinRelayFeerate(fee chainfee.SatPerKVByte)
// Reset resets the fee rate map to the default value. // Reset resets the fee rate map to the default value.
Reset() Reset()
} }
@@ -52,8 +55,9 @@ const (
type FeeService struct { type FeeService struct {
*testing.T *testing.T
feeRateMap map[uint32]uint32 feeRateMap map[uint32]uint32
url string minRelayFeerate chainfee.SatPerKVByte
url string
srv *http.Server srv *http.Server
wg sync.WaitGroup wg sync.WaitGroup
@@ -79,6 +83,7 @@ func NewFeeService(t *testing.T) *FeeService {
f.feeRateMap = map[uint32]uint32{ f.feeRateMap = map[uint32]uint32{
feeServiceTarget: DefaultFeeRateSatPerKw, feeServiceTarget: DefaultFeeRateSatPerKw,
} }
f.minRelayFeerate = chainfee.FeePerKwFloor.FeePerKVByte()
listenAddr := fmt.Sprintf(":%v", port) listenAddr := fmt.Sprintf(":%v", port)
mux := http.NewServeMux() mux := http.NewServeMux()
@@ -113,10 +118,9 @@ func (f *FeeService) handleRequest(w http.ResponseWriter, _ *http.Request) {
defer f.lock.Unlock() defer f.lock.Unlock()
bytes, err := json.Marshal( bytes, err := json.Marshal(
struct { chainfee.WebAPIResponse{
Fees map[uint32]uint32 `json:"fee_by_block_target"` FeeByBlockTarget: f.feeRateMap,
}{ MinRelayFeerate: f.minRelayFeerate,
Fees: f.feeRateMap,
}, },
) )
require.NoErrorf(f, err, "cannot serialize estimates") require.NoErrorf(f, err, "cannot serialize estimates")
@@ -143,6 +147,14 @@ func (f *FeeService) SetFeeRate(fee chainfee.SatPerKWeight, conf uint32) {
f.feeRateMap[conf] = uint32(fee.FeePerKVByte()) f.feeRateMap[conf] = uint32(fee.FeePerKVByte())
} }
// SetMinRelayFeerate sets a min relay feerate.
func (f *FeeService) SetMinRelayFeerate(fee chainfee.SatPerKVByte) {
f.lock.Lock()
defer f.lock.Unlock()
f.minRelayFeerate = fee
}
// Reset resets the fee rate map to the default value. // Reset resets the fee rate map to the default value.
func (f *FeeService) Reset() { func (f *FeeService) Reset() {
f.lock.Lock() f.lock.Lock()
+6
View File
@@ -860,6 +860,12 @@ func (h *HarnessTest) SetFeeEstimateWithConf(
h.feeService.SetFeeRate(fee, conf) h.feeService.SetFeeRate(fee, conf)
} }
// SetMinRelayFeerate sets a min relay fee rate to be returned from fee
// estimator.
func (h *HarnessTest) SetMinRelayFeerate(fee chainfee.SatPerKVByte) {
h.feeService.SetMinRelayFeerate(fee)
}
// validateNodeState checks that the node doesn't have any uncleaned states // validateNodeState checks that the node doesn't have any uncleaned states
// which will affect its following tests. // which will affect its following tests.
func (h *HarnessTest) validateNodeState(hn *node.HarnessNode) error { func (h *HarnessTest) validateNodeState(hn *node.HarnessNode) error {
+27
View File
@@ -0,0 +1,27 @@
package lnutils
import "github.com/davecgh/go-spew/spew"
// LogClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type LogClosure func() string
// String invokes the underlying function and returns the result.
func (c LogClosure) String() string {
return c()
}
// NewLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func NewLogClosure(c func() string) LogClosure {
return LogClosure(c)
}
// SpewLogClosure takes an interface and returns the string of it created from
// `spew.Sdump` in a LogClosure.
func SpewLogClosure(a any) LogClosure {
return func() string {
return spew.Sdump(a)
}
}
+92 -42
View File
@@ -10,10 +10,12 @@ import (
"net" "net"
"net/http" "net/http"
"sync" "sync"
"sync/atomic"
"time" "time"
"github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/btcutil"
"github.com/btcsuite/btcd/rpcclient" "github.com/btcsuite/btcd/rpcclient"
"github.com/lightningnetwork/lnd/lnutils"
) )
const ( const (
@@ -628,9 +630,10 @@ var _ Estimator = (*BitcoindEstimator)(nil)
// implementation of this interface in order to allow the WebAPIEstimator to // implementation of this interface in order to allow the WebAPIEstimator to
// be fully generic in its logic. // be fully generic in its logic.
type WebAPIFeeSource interface { type WebAPIFeeSource interface {
// GetFeeMap will query the web API, parse the response and return a // GetFeeInfo will query the web API, parse the response into a
// map of confirmation targets to sat/kw fees. // WebAPIResponse which contains a map of confirmation targets to
GetFeeMap() (map[uint32]uint32, error) // sat/kw fees and min relay feerate.
GetFeeInfo() (WebAPIResponse, error)
} }
// SparseConfFeeSource is an implementation of the WebAPIFeeSource that utilizes // SparseConfFeeSource is an implementation of the WebAPIFeeSource that utilizes
@@ -642,30 +645,43 @@ type SparseConfFeeSource struct {
URL string URL string
} }
// WebAPIResponse is the response returned by the fee estimation API.
type WebAPIResponse struct {
// FeeByBlockTarget is a map of confirmation targets to sat/kvb fees.
FeeByBlockTarget map[uint32]uint32 `json:"fee_by_block_target"`
// MinRelayFeerate is the minimum relay fee in sat/kvb.
MinRelayFeerate SatPerKVByte `json:"min_relay_feerate"`
}
// parseResponse attempts to parse the body of the response generated by the // parseResponse attempts to parse the body of the response generated by the
// above query URL. Typically this will be JSON, but the specifics are left to // above query URL. Typically this will be JSON, but the specifics are left to
// the WebAPIFeeSource implementation. // the WebAPIFeeSource implementation.
func (s SparseConfFeeSource) parseResponse(r io.Reader) ( func (s SparseConfFeeSource) parseResponse(r io.Reader) (
map[uint32]uint32, error) { WebAPIResponse, error) {
type jsonResp struct { resp := WebAPIResponse{
FeeByBlockTarget map[uint32]uint32 `json:"fee_by_block_target"`
}
resp := jsonResp{
FeeByBlockTarget: make(map[uint32]uint32), FeeByBlockTarget: make(map[uint32]uint32),
MinRelayFeerate: 0,
} }
jsonReader := json.NewDecoder(r) jsonReader := json.NewDecoder(r)
if err := jsonReader.Decode(&resp); err != nil { if err := jsonReader.Decode(&resp); err != nil {
return nil, err return WebAPIResponse{}, err
} }
return resp.FeeByBlockTarget, nil if resp.MinRelayFeerate == 0 {
log.Errorf("No min relay fee rate available, using default %v",
FeePerKwFloor)
resp.MinRelayFeerate = FeePerKwFloor.FeePerKVByte()
}
return resp, nil
} }
// GetFeeMap will query the web API, parse the response and return a map of // GetFeeInfo will query the web API, parse the response and return a map of
// confirmation targets to sat/kw fees. // confirmation targets to sat/kw fees and min relay feerate in a parsed
func (s SparseConfFeeSource) GetFeeMap() (map[uint32]uint32, error) { // response.
func (s SparseConfFeeSource) GetFeeInfo() (WebAPIResponse, error) {
// Rather than use the default http.Client, we'll make a custom one // Rather than use the default http.Client, we'll make a custom one
// which will allow us to control how long we'll wait to read the // which will allow us to control how long we'll wait to read the
// response from the service. This way, if the service is down or // response from the service. This way, if the service is down or
@@ -688,20 +704,20 @@ func (s SparseConfFeeSource) GetFeeMap() (map[uint32]uint32, error) {
if err != nil { if err != nil {
log.Errorf("unable to query web api for fee response: %v", log.Errorf("unable to query web api for fee response: %v",
err) err)
return nil, err return WebAPIResponse{}, err
} }
defer resp.Body.Close() defer resp.Body.Close()
// Once we've obtained the response, we'll instruct the WebAPIFeeSource // Once we've obtained the response, we'll instruct the WebAPIFeeSource
// to parse out the body to obtain our final result. // to parse out the body to obtain our final result.
feesByBlockTarget, err := s.parseResponse(resp.Body) parsedResp, err := s.parseResponse(resp.Body)
if err != nil { if err != nil {
log.Errorf("unable to parse fee api response: %v", err) log.Errorf("unable to parse fee api response: %v", err)
return nil, err return WebAPIResponse{}, err
} }
return feesByBlockTarget, nil return parsedResp, nil
} }
// A compile-time assertion to ensure that SparseConfFeeSource implements the // A compile-time assertion to ensure that SparseConfFeeSource implements the
@@ -711,8 +727,8 @@ var _ WebAPIFeeSource = (*SparseConfFeeSource)(nil)
// WebAPIEstimator is an implementation of the Estimator interface that // WebAPIEstimator is an implementation of the Estimator interface that
// queries an HTTP-based fee estimation from an existing web API. // queries an HTTP-based fee estimation from an existing web API.
type WebAPIEstimator struct { type WebAPIEstimator struct {
started sync.Once started atomic.Bool
stopped sync.Once stopped atomic.Bool
// apiSource is the backing web API source we'll use for our queries. // apiSource is the backing web API source we'll use for our queries.
apiSource WebAPIFeeSource apiSource WebAPIFeeSource
@@ -726,6 +742,7 @@ type WebAPIEstimator struct {
// rather than re-querying the API, to prevent an inadvertent DoS attack. // rather than re-querying the API, to prevent an inadvertent DoS attack.
feesMtx sync.Mutex feesMtx sync.Mutex
feeByBlockTarget map[uint32]uint32 feeByBlockTarget map[uint32]uint32
minRelayFeerate SatPerKVByte
// noCache determines whether the web estimator should cache fee // noCache determines whether the web estimator should cache fee
// estimates. // estimates.
@@ -777,6 +794,12 @@ func NewWebAPIEstimator(api WebAPIFeeSource, noCache bool,
func (w *WebAPIEstimator) EstimateFeePerKW(numBlocks uint32) ( func (w *WebAPIEstimator) EstimateFeePerKW(numBlocks uint32) (
SatPerKWeight, error) { SatPerKWeight, error) {
// If the estimator hasn't been started yet, we'll return an error as
// we can't provide a fee estimate.
if !w.started.Load() {
return 0, fmt.Errorf("estimator not started")
}
if numBlocks > MaxBlockTarget { if numBlocks > MaxBlockTarget {
numBlocks = MaxBlockTarget numBlocks = MaxBlockTarget
} else if numBlocks < minBlockTarget { } else if numBlocks < minBlockTarget {
@@ -816,28 +839,33 @@ func (w *WebAPIEstimator) EstimateFeePerKW(numBlocks uint32) (
// //
// NOTE: This method is part of the Estimator interface. // NOTE: This method is part of the Estimator interface.
func (w *WebAPIEstimator) Start() error { func (w *WebAPIEstimator) Start() error {
log.Infof("Starting Web API fee estimator...")
// Return an error if it's already been started.
if w.started.Load() {
return fmt.Errorf("web API fee estimator already started")
}
defer w.started.Store(true)
// During startup we'll query the API to initialize the fee map.
w.updateFeeEstimates()
// No update loop is needed when we don't cache. // No update loop is needed when we don't cache.
if w.noCache { if w.noCache {
return nil return nil
} }
var err error feeUpdateTimeout := w.randomFeeUpdateTimeout()
w.started.Do(func() {
log.Infof("Starting web API fee estimator")
feeUpdateTimeout := w.randomFeeUpdateTimeout() log.Infof("Web API fee estimator using update timeout of %v",
feeUpdateTimeout)
log.Infof("Web API fee estimator using update timeout of %v", w.updateFeeTicker = time.NewTicker(feeUpdateTimeout)
feeUpdateTimeout)
w.updateFeeTicker = time.NewTicker(feeUpdateTimeout) w.wg.Add(1)
w.updateFeeEstimates() go w.feeUpdateManager()
w.wg.Add(1) return nil
go w.feeUpdateManager()
})
return err
} }
// Stop stops any spawned goroutines and cleans up the resources used by the // Stop stops any spawned goroutines and cleans up the resources used by the
@@ -845,19 +873,22 @@ func (w *WebAPIEstimator) Start() error {
// //
// NOTE: This method is part of the Estimator interface. // NOTE: This method is part of the Estimator interface.
func (w *WebAPIEstimator) Stop() error { func (w *WebAPIEstimator) Stop() error {
log.Infof("Stopping web API fee estimator")
if w.stopped.Swap(true) {
return fmt.Errorf("web API fee estimator already stopped")
}
// Update loop is not running when we don't cache. // Update loop is not running when we don't cache.
if w.noCache { if w.noCache {
return nil return nil
} }
w.stopped.Do(func() { w.updateFeeTicker.Stop()
log.Infof("Stopping web API fee estimator")
w.updateFeeTicker.Stop() close(w.quit)
w.wg.Wait()
close(w.quit)
w.wg.Wait()
})
return nil return nil
} }
@@ -866,7 +897,19 @@ func (w *WebAPIEstimator) Stop() error {
// //
// NOTE: This method is part of the Estimator interface. // NOTE: This method is part of the Estimator interface.
func (w *WebAPIEstimator) RelayFeePerKW() SatPerKWeight { func (w *WebAPIEstimator) RelayFeePerKW() SatPerKWeight {
return FeePerKwFloor if !w.started.Load() {
log.Error("WebAPIEstimator not started")
}
// Get fee estimates now if we don't refresh periodically.
if w.noCache {
w.updateFeeEstimates()
}
log.Infof("Web API returning %v for min relay feerate",
w.minRelayFeerate)
return w.minRelayFeerate.FeePerKWeight()
} }
// randomFeeUpdateTimeout returns a random timeout between minFeeUpdateTimeout // randomFeeUpdateTimeout returns a random timeout between minFeeUpdateTimeout
@@ -956,14 +999,21 @@ func (w *WebAPIEstimator) getCachedFee(numBlocks uint32) (uint32, error) {
func (w *WebAPIEstimator) updateFeeEstimates() { func (w *WebAPIEstimator) updateFeeEstimates() {
// Once we've obtained the response, we'll instruct the WebAPIFeeSource // Once we've obtained the response, we'll instruct the WebAPIFeeSource
// to parse out the body to obtain our final result. // to parse out the body to obtain our final result.
feesByBlockTarget, err := w.apiSource.GetFeeMap() resp, err := w.apiSource.GetFeeInfo()
if err != nil { if err != nil {
log.Errorf("unable to get fee response: %v", err) log.Errorf("unable to get fee response: %v", err)
return return
} }
log.Debugf("Received response from source: %s", lnutils.NewLogClosure(
func() string {
resp, _ := json.Marshal(resp)
return string(resp)
}))
w.feesMtx.Lock() w.feesMtx.Lock()
w.feeByBlockTarget = feesByBlockTarget w.feeByBlockTarget = resp.FeeByBlockTarget
w.minRelayFeerate = resp.MinRelayFeerate
w.feesMtx.Unlock() w.feesMtx.Unlock()
} }
+57 -12
View File
@@ -107,17 +107,20 @@ func TestSparseConfFeeSource(t *testing.T) {
2: 42, 2: 42,
3: 54321, 3: 54321,
} }
testJSON := map[string]map[uint32]uint32{ testMinRelayFee := SatPerKVByte(1000)
"fee_by_block_target": testFees, testResp := WebAPIResponse{
MinRelayFeerate: testMinRelayFee,
FeeByBlockTarget: testFees,
} }
jsonResp, err := json.Marshal(testJSON)
jsonResp, err := json.Marshal(testResp)
require.NoError(t, err, "unable to marshal JSON API response") require.NoError(t, err, "unable to marshal JSON API response")
reader := bytes.NewReader(jsonResp) reader := bytes.NewReader(jsonResp)
// Finally, ensure the expected map is returned without error. // Finally, ensure the expected map is returned without error.
fees, err := feeSource.parseResponse(reader) resp, err := feeSource.parseResponse(reader)
require.NoError(t, err, "unable to parse API response") require.NoError(t, err, "unable to parse API response")
require.Equal(t, testFees, fees, "unexpected fee map returned") require.Equal(t, testResp, resp, "unexpected resp returned")
// Test parsing an improperly formatted JSON API response. // Test parsing an improperly formatted JSON API response.
badFees := map[string]uint32{"hi": 12345, "hello": 42, "satoshi": 54321} badFees := map[string]uint32{"hi": 12345, "hello": 42, "satoshi": 54321}
@@ -131,6 +134,45 @@ func TestSparseConfFeeSource(t *testing.T) {
require.Error(t, err, "expected error when parsing bad JSON") require.Error(t, err, "expected error when parsing bad JSON")
} }
// TestFeeSourceCompatibility checks that when a fee source doesn't return a
// `min_relay_feerate` field in its response, the floor feerate is used.
//
// NOTE: Field `min_relay_feerate` was added in v0.18.3.
func TestFeeSourceCompatibility(t *testing.T) {
t.Parallel()
// Test that GenQueryURL returns the URL as is.
url := "test"
feeSource := SparseConfFeeSource{URL: url}
// Test parsing a properly formatted JSON API response.
//
// Create the resp without the `min_relay_feerate` field.
testFees := map[uint32]uint32{
1: 12345,
}
testResp := struct {
// FeeByBlockTarget is a map of confirmation targets to sat/kvb
// fees.
FeeByBlockTarget map[uint32]uint32 `json:"fee_by_block_target"`
}{
FeeByBlockTarget: testFees,
}
jsonResp, err := json.Marshal(testResp)
require.NoError(t, err, "unable to marshal JSON API response")
reader := bytes.NewReader(jsonResp)
// Ensure the expected map is returned without error.
resp, err := feeSource.parseResponse(reader)
require.NoError(t, err, "unable to parse API response")
require.Equal(t, testResp.FeeByBlockTarget, resp.FeeByBlockTarget,
"unexpected resp returned")
// Expect the floor feerate to be used.
require.Equal(t, FeePerKwFloor.FeePerKVByte(), resp.MinRelayFeerate)
}
// TestWebAPIFeeEstimator checks that the WebAPIFeeEstimator returns fee rates // TestWebAPIFeeEstimator checks that the WebAPIFeeEstimator returns fee rates
// as expected. // as expected.
func TestWebAPIFeeEstimator(t *testing.T) { func TestWebAPIFeeEstimator(t *testing.T) {
@@ -194,25 +236,28 @@ func TestWebAPIFeeEstimator(t *testing.T) {
// This will create a `feeByBlockTarget` map with the following values, // This will create a `feeByBlockTarget` map with the following values,
// - 2: 4000 sat/kb // - 2: 4000 sat/kb
// - 6: 2000 sat/kb. // - 6: 2000 sat/kb.
feeRateResp := map[uint32]uint32{ feeRates := map[uint32]uint32{
minTarget: maxFeeRate, minTarget: maxFeeRate,
maxTarget: minFeeRate, maxTarget: minFeeRate,
} }
resp := WebAPIResponse{
FeeByBlockTarget: feeRates,
}
// Create a mock fee source and mock its returned map. // Create a mock fee source and mock its returned map.
feeSource := &mockFeeSource{} feeSource := &mockFeeSource{}
feeSource.On("GetFeeMap").Return(feeRateResp, nil) feeSource.On("GetFeeInfo").Return(resp, nil)
estimator, _ := NewWebAPIEstimator( estimator, _ := NewWebAPIEstimator(
feeSource, false, minFeeUpdateTimeout, maxFeeUpdateTimeout, feeSource, false, minFeeUpdateTimeout, maxFeeUpdateTimeout,
) )
// Test that requesting a fee when no fees have been cached won't fail. // Test that when the estimator is not started, an error is returned.
feeRate, err := estimator.EstimateFeePerKW(5) feeRate, err := estimator.EstimateFeePerKW(5)
require.NoErrorf(t, err, "expected no error") require.Error(t, err, "expected an error")
require.Equalf(t, FeePerKwFloor, feeRate, "expected fee rate floor "+ require.Zero(t, feeRate, "expected zero fee rate")
"returned when no cached fee rate found")
// Start the estimator.
require.NoError(t, estimator.Start(), "unable to start fee estimator") require.NoError(t, estimator.Start(), "unable to start fee estimator")
for _, tc := range testCases { for _, tc := range testCases {
@@ -234,7 +279,7 @@ func TestWebAPIFeeEstimator(t *testing.T) {
exp := SatPerKVByte(tc.expectedFeeRate).FeePerKWeight() exp := SatPerKVByte(tc.expectedFeeRate).FeePerKWeight()
require.Equalf(t, exp, est, "target %v failed, fee "+ require.Equalf(t, exp, est, "target %v failed, fee "+
"map is %v", tc.target, feeRateResp) "map is %v", tc.target, feeRate)
}) })
} }
+2 -2
View File
@@ -12,10 +12,10 @@ type mockFeeSource struct {
// WebAPIFeeSource interface. // WebAPIFeeSource interface.
var _ WebAPIFeeSource = (*mockFeeSource)(nil) var _ WebAPIFeeSource = (*mockFeeSource)(nil)
func (m *mockFeeSource) GetFeeMap() (map[uint32]uint32, error) { func (m *mockFeeSource) GetFeeInfo() (WebAPIResponse, error) {
args := m.Called() args := m.Called()
return args.Get(0).(map[uint32]uint32), args.Error(1) return args.Get(0).(WebAPIResponse), args.Error(1)
} }
// MockEstimator implements the `Estimator` interface and is used by // MockEstimator implements the `Estimator` interface and is used by
+1 -1
View File
@@ -53,7 +53,7 @@ func (s SatPerKVByte) FeePerKWeight() SatPerKWeight {
// String returns a human-readable string of the fee rate. // String returns a human-readable string of the fee rate.
func (s SatPerKVByte) String() string { func (s SatPerKVByte) String() string {
return fmt.Sprintf("%v sat/kb", int64(s)) return fmt.Sprintf("%v sat/kvb", int64(s))
} }
// SatPerKWeight represents a fee rate in sat/kw. // SatPerKWeight represents a fee rate in sat/kw.
+2 -4
View File
@@ -15,6 +15,7 @@ import (
"github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/htlcswitch"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/labels" "github.com/lightningnetwork/lnd/labels"
"github.com/lightningnetwork/lnd/lnutils"
"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/lnwire" "github.com/lightningnetwork/lnd/lnwire"
@@ -869,10 +870,7 @@ func (c *ChanCloser) ReceiveClosingSigned( //nolint:funlen
// With the closing transaction crafted, we'll now broadcast it // With the closing transaction crafted, we'll now broadcast it
// to the network. // to the network.
chancloserLog.Infof("Broadcasting cooperative close tx: %v", chancloserLog.Infof("Broadcasting cooperative close tx: %v",
newLogClosure(func() string { lnutils.SpewLogClosure(closeTx))
return spew.Sdump(closeTx)
}),
)
// Create a close channel label. // Create a close channel label.
chanID := c.cfg.Channel.ShortChanID() chanID := c.cfg.Channel.ShortChanID()
-16
View File
@@ -23,19 +23,3 @@ func DisableLog() {
func UseLogger(logger btclog.Logger) { func UseLogger(logger btclog.Logger) {
chancloserLog = logger chancloserLog = logger
} }
// logClosure is used to provide a closure over expensive logging operations
// so they aren't performed when the logging level doesn't warrant it.
type logClosure func() string
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
return logClosure(c)
}
+8 -26
View File
@@ -29,6 +29,7 @@ import (
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/keychain"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/shachain" "github.com/lightningnetwork/lnd/shachain"
@@ -1869,10 +1870,7 @@ func (lc *LightningChannel) restoreCommitState(
lc.localCommitChain.addCommitment(localCommit) lc.localCommitChain.addCommitment(localCommit)
lc.log.Tracef("starting local commitment: %v", lc.log.Tracef("starting local commitment: %v",
newLogClosure(func() string { lnutils.SpewLogClosure(lc.localCommitChain.tail()))
return spew.Sdump(lc.localCommitChain.tail())
}),
)
// We'll also do the same for the remote commitment chain. // We'll also do the same for the remote commitment chain.
remoteCommit, err := lc.diskCommitToMemCommit( remoteCommit, err := lc.diskCommitToMemCommit(
@@ -1885,10 +1883,7 @@ func (lc *LightningChannel) restoreCommitState(
lc.remoteCommitChain.addCommitment(remoteCommit) lc.remoteCommitChain.addCommitment(remoteCommit)
lc.log.Tracef("starting remote commitment: %v", lc.log.Tracef("starting remote commitment: %v",
newLogClosure(func() string { lnutils.SpewLogClosure(lc.remoteCommitChain.tail()))
return spew.Sdump(lc.remoteCommitChain.tail())
}),
)
var ( var (
pendingRemoteCommit *commitment pendingRemoteCommit *commitment
@@ -1920,10 +1915,7 @@ func (lc *LightningChannel) restoreCommitState(
lc.remoteCommitChain.addCommitment(pendingRemoteCommit) lc.remoteCommitChain.addCommitment(pendingRemoteCommit)
lc.log.Debugf("pending remote commitment: %v", lc.log.Debugf("pending remote commitment: %v",
newLogClosure(func() string { lnutils.SpewLogClosure(lc.remoteCommitChain.tip()))
return spew.Sdump(lc.remoteCommitChain.tip())
}),
)
// We'll also re-create the set of commitment keys needed to // We'll also re-create the set of commitment keys needed to
// fully re-derive the state. // fully re-derive the state.
@@ -3245,12 +3237,8 @@ func (lc *LightningChannel) fetchParent(entry *PaymentDescriptor,
return nil, fmt.Errorf("unable to find parent entry "+ return nil, fmt.Errorf("unable to find parent entry "+
"%d in %v update log: %v\nUpdatelog: %v", "%d in %v update log: %v\nUpdatelog: %v",
entry.ParentIndex, logName, entry.ParentIndex, logName,
newLogClosure(func() string { lnutils.SpewLogClosure(entry),
return spew.Sdump(entry) lnutils.SpewLogClosure(updateLog))
}), newLogClosure(func() string {
return spew.Sdump(updateLog)
}),
)
// The parent add height should never be zero at this point. If // The parent add height should never be zero at this point. If
// that's the case we probably forgot to send a new commitment. // that's the case we probably forgot to send a new commitment.
@@ -4249,10 +4237,7 @@ func (lc *LightningChannel) SignNextCommitment() (*NewCommitState, error) {
"their_balance=%v, commit_tx: %v", "their_balance=%v, commit_tx: %v",
newCommitView.ourBalance, newCommitView.ourBalance,
newCommitView.theirBalance, newCommitView.theirBalance,
newLogClosure(func() string { lnutils.SpewLogClosure(newCommitView.txn))
return spew.Sdump(newCommitView.txn)
}),
)
// With the commitment view constructed, if there are any HTLC's, we'll // With the commitment view constructed, if there are any HTLC's, we'll
// need to generate signatures of each of them for the remote party's // need to generate signatures of each of them for the remote party's
@@ -5209,10 +5194,7 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSigs *CommitSigs) error {
lc.log.Tracef("local chain: our_balance=%v, "+ lc.log.Tracef("local chain: our_balance=%v, "+
"their_balance=%v, commit_tx: %v", "their_balance=%v, commit_tx: %v",
localCommitmentView.ourBalance, localCommitmentView.theirBalance, localCommitmentView.ourBalance, localCommitmentView.theirBalance,
newLogClosure(func() string { lnutils.SpewLogClosure(localCommitmentView.txn))
return spew.Sdump(localCommitmentView.txn)
}),
)
// As an optimization, we'll generate a series of jobs for the worker // As an optimization, we'll generate a series of jobs for the worker
// pool to verify each of the HTLC signatures presented. Once // pool to verify each of the HTLC signatures presented. Once
-16
View File
@@ -36,19 +36,3 @@ func UseLogger(logger btclog.Logger) {
chain.UseLogger(logger) chain.UseLogger(logger)
chainfee.UseLogger(logger) chainfee.UseLogger(logger)
} }
// logClosure is used to provide a closure over expensive logging operations
// so don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
return logClosure(c)
}
-16
View File
@@ -208,19 +208,3 @@ func SetSubLogger(root *build.RotatingLogWriter, subsystem string,
useLogger(logger) useLogger(logger)
} }
} }
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
return logClosure(c)
}
+2 -4
View File
@@ -2156,7 +2156,7 @@ func (p *Brontide) logWireMessage(msg lnwire.Message, read bool) {
summaryPrefix = "Sending" summaryPrefix = "Sending"
} }
p.log.Debugf("%v", newLogClosure(func() string { p.log.Debugf("%v", lnutils.NewLogClosure(func() string {
// Debug summary of message. // Debug summary of message.
summary := messageSummary(msg) summary := messageSummary(msg)
if len(summary) > 0 { if len(summary) > 0 {
@@ -2184,9 +2184,7 @@ func (p *Brontide) logWireMessage(msg lnwire.Message, read bool) {
prefix = "writeMessage to peer" prefix = "writeMessage to peer"
} }
p.log.Tracef(prefix+": %v", newLogClosure(func() string { p.log.Tracef(prefix+": %v", lnutils.SpewLogClosure(msg))
return spew.Sdump(msg)
}))
} }
// writeMessage writes and flushes the target lnwire.Message to the remote peer. // writeMessage writes and flushes the target lnwire.Message to the remote peer.
-16
View File
@@ -22,19 +22,3 @@ func DisableLog() {
func UseLogger(logger btclog.Logger) { func UseLogger(logger btclog.Logger) {
peerLog = logger peerLog = logger
} }
// logClosure is used to provide a closure over expensive logging operations
// so they aren't performed when the logging level doesn't warrant it.
type logClosure func() string
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
return logClosure(c)
}
-16
View File
@@ -31,19 +31,3 @@ func UseLogger(logger btclog.Logger) {
log = logger log = logger
chainview.UseLogger(logger) chainview.UseLogger(logger)
} }
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
return logClosure(c)
}
+2 -1
View File
@@ -13,6 +13,7 @@ import (
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/feature" "github.com/lightningnetwork/lnd/feature"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/record"
"github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/routing/route"
@@ -728,7 +729,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig,
edge.capacity, edge.capacity,
) )
log.Trace(newLogClosure(func() string { log.Trace(lnutils.NewLogClosure(func() string {
return fmt.Sprintf("path finding probability: fromnode=%v,"+ return fmt.Sprintf("path finding probability: fromnode=%v,"+
" tonode=%v, amt=%v, cap=%v, probability=%v", " tonode=%v, amt=%v, cap=%v, probability=%v",
fromVertex, toNodeDist.node, amountToSend, fromVertex, toNodeDist.node, amountToSend,
+2 -2
View File
@@ -5,11 +5,11 @@ import (
"github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcec/v2"
"github.com/btcsuite/btclog" "github.com/btcsuite/btclog"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/build"
"github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb"
"github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/channeldb/models"
"github.com/lightningnetwork/lnd/graph" "github.com/lightningnetwork/lnd/graph"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/routing/route" "github.com/lightningnetwork/lnd/routing/route"
) )
@@ -432,7 +432,7 @@ func (p *paymentSession) UpdateAdditionalEdge(msg *lnwire.ChannelUpdate,
policy.FeeProportionalMillionths = lnwire.MilliSatoshi(msg.FeeRate) policy.FeeProportionalMillionths = lnwire.MilliSatoshi(msg.FeeRate)
log.Debugf("New private channel update applied: %v", log.Debugf("New private channel update applied: %v",
newLogClosure(func() string { return spew.Sdump(msg) })) lnutils.SpewLogClosure(msg))
return true return true
} }
+8 -13
View File
@@ -21,6 +21,7 @@ import (
"github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/htlcswitch"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/record"
@@ -669,10 +670,7 @@ func (r *ChannelRouter) FindRoute(req *RouteRequest) (*route.Route, float64,
} }
go log.Tracef("Obtained path to send %v to %x: %v", go log.Tracef("Obtained path to send %v to %x: %v",
req.Amount, req.Target, newLogClosure(func() string { req.Amount, req.Target, lnutils.SpewLogClosure(route))
return spew.Sdump(route)
}),
)
return route, probability, nil return route, probability, nil
} }
@@ -704,7 +702,7 @@ func generateSphinxPacket(rt *route.Route, paymentHash []byte,
} }
log.Tracef("Constructed per-hop payloads for payment_hash=%x: %v", log.Tracef("Constructed per-hop payloads for payment_hash=%x: %v",
paymentHash[:], newLogClosure(func() string { paymentHash, lnutils.NewLogClosure(func() string {
path := make( path := make(
[]sphinx.OnionHop, sphinxPath.TrueRouteLength(), []sphinx.OnionHop, sphinxPath.TrueRouteLength(),
) )
@@ -734,7 +732,7 @@ func generateSphinxPacket(rt *route.Route, paymentHash []byte,
} }
log.Tracef("Generated sphinx packet: %v", log.Tracef("Generated sphinx packet: %v",
newLogClosure(func() string { lnutils.NewLogClosure(func() string {
// We make a copy of the ephemeral key and unset the // We make a copy of the ephemeral key and unset the
// internal curve here in order to keep the logs from // internal curve here in order to keep the logs from
// getting noisy. // getting noisy.
@@ -945,8 +943,8 @@ func (r *ChannelRouter) SendPaymentAsync(ctx context.Context,
// spewPayment returns a log closures that provides a spewed string // spewPayment returns a log closures that provides a spewed string
// representation of the passed payment. // representation of the passed payment.
func spewPayment(payment *LightningPayment) logClosure { func spewPayment(payment *LightningPayment) lnutils.LogClosure {
return newLogClosure(func() string { return lnutils.NewLogClosure(func() string {
// Make a copy of the payment with a nilled Curve // Make a copy of the payment with a nilled Curve
// before spewing. // before spewing.
var routeHints [][]zpay32.HopHint var routeHints [][]zpay32.HopHint
@@ -1090,11 +1088,8 @@ func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route,
return nil, err return nil, err
} }
log.Tracef("Dispatching SendToRoute for HTLC hash %v: %v", log.Tracef("Dispatching SendToRoute for HTLC hash %v: %v", htlcHash,
htlcHash, newLogClosure(func() string { lnutils.SpewLogClosure(rt))
return spew.Sdump(rt)
}),
)
// Since the HTLC hashes and preimages are specified manually over the // Since the HTLC hashes and preimages are specified manually over the
// RPC for SendToRoute requests, we don't have to worry about creating // RPC for SendToRoute requests, we don't have to worry about creating
+2 -3
View File
@@ -63,6 +63,7 @@ import (
"github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc"
"github.com/lightningnetwork/lnd/lnrpc/walletrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc"
"github.com/lightningnetwork/lnd/lntypes" "github.com/lightningnetwork/lnd/lntypes"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/btcwallet" "github.com/lightningnetwork/lnd/lnwallet/btcwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
@@ -5845,9 +5846,7 @@ func (r *rpcServer) LookupInvoice(ctx context.Context,
} }
rpcsLog.Tracef("[lookupinvoice] located invoice %v", rpcsLog.Tracef("[lookupinvoice] located invoice %v",
newLogClosure(func() string { lnutils.SpewLogClosure(invoice))
return spew.Sdump(invoice)
}))
rpcInvoice, err := invoicesrpc.CreateRPCInvoice( rpcInvoice, err := invoicesrpc.CreateRPCInvoice(
&invoice, r.cfg.ActiveNetParams.Params, &invoice, r.cfg.ActiveNetParams.Params,
+2 -5
View File
@@ -12,7 +12,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/btcwallet/chain" "github.com/btcsuite/btcwallet/chain"
"github.com/davecgh/go-spew/spew"
"github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
@@ -313,10 +312,8 @@ func (t *TxPublisher) isNeutrinoBackend() bool {
// //
// NOTE: part of the Bumper interface. // NOTE: part of the Bumper interface.
func (t *TxPublisher) Broadcast(req *BumpRequest) (<-chan *BumpResult, error) { func (t *TxPublisher) Broadcast(req *BumpRequest) (<-chan *BumpResult, error) {
log.Tracef("Received broadcast request: %s", newLogClosure( log.Tracef("Received broadcast request: %s", lnutils.SpewLogClosure(
func() string { req))
return spew.Sdump(req)
})())
// Attempt an initial broadcast which is guaranteed to comply with the // Attempt an initial broadcast which is guaranteed to comply with the
// RBF rules. // RBF rules.
-16
View File
@@ -27,19 +27,3 @@ func DisableLog() {
func UseLogger(logger btclog.Logger) { func UseLogger(logger btclog.Logger) {
log = logger log = logger
} }
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure {
return logClosure(c)
}
+2 -4
View File
@@ -13,6 +13,7 @@ import (
"github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/chainntnfs"
"github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/fn"
"github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/input"
"github.com/lightningnetwork/lnd/lnutils"
"github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwallet/chainfee"
) )
@@ -1376,10 +1377,7 @@ func (s *UtxoSweeper) handleInputSpent(spend *chainntnfs.SpendDetail) {
log.Debugf("Detected third party spend related to in flight "+ log.Debugf("Detected third party spend related to in flight "+
"inputs (is_ours=%v): %v", isOurTx, "inputs (is_ours=%v): %v", isOurTx,
newLogClosure(func() string { lnutils.SpewLogClosure(spend.SpendingTx))
return spew.Sdump(spend.SpendingTx)
}),
)
} }
// We now use the spending tx to update the state of the inputs. // We now use the spending tx to update the state of the inputs.
-16
View File
@@ -43,19 +43,3 @@ func UseLogger(logger btclog.Logger) {
migration7.UseLogger(logger) migration7.UseLogger(logger)
migration8.UseLogger(logger) migration8.UseLogger(logger)
} }
// logClosure is used to provide a closure over expensive logging operations so
// don't have to be performed when the logging level doesn't warrant it.
type logClosure func() string // nolint:unused
// String invokes the underlying function and returns the result.
func (c logClosure) String() string {
return c()
}
// newLogClosure returns a new closure over a function that returns a string
// which itself provides a Stringer interface so that it can be used with the
// logging system.
func newLogClosure(c func() string) logClosure { // nolint:unused
return logClosure(c)
}