From ce43e4bab7445ccfc3eee5fdb3df40b125fee14b Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 4 Jul 2024 20:32:41 +0800 Subject: [PATCH 1/6] chainfee: allow specifying min relay feerate from API source This commit adds a new expected field, `min_relay_feerate`, in the response body returned from the API source, allowing the API to specify a min relay feerate to be used instead of the FeePerKwFloor. This change is backwards compatible as for an old API source which doesn't specify the `min_relay_feerate`, it will be interpreted as zero. --- lnwallet/chainfee/estimator.go | 73 ++++++++++++++++++++--------- lnwallet/chainfee/estimator_test.go | 61 ++++++++++++++++++++---- lnwallet/chainfee/log.go | 16 +++++++ lnwallet/chainfee/mocks.go | 4 +- lnwallet/chainfee/rates.go | 2 +- 5 files changed, 124 insertions(+), 32 deletions(-) diff --git a/lnwallet/chainfee/estimator.go b/lnwallet/chainfee/estimator.go index 0ce9ae9b8..49b0790a7 100644 --- a/lnwallet/chainfee/estimator.go +++ b/lnwallet/chainfee/estimator.go @@ -628,9 +628,10 @@ var _ Estimator = (*BitcoindEstimator)(nil) // implementation of this interface in order to allow the WebAPIEstimator to // be fully generic in its logic. type WebAPIFeeSource interface { - // GetFeeMap will query the web API, parse the response and return a - // map of confirmation targets to sat/kw fees. - GetFeeMap() (map[uint32]uint32, error) + // GetFeeInfo will query the web API, parse the response into a + // WebAPIResponse which contains a map of confirmation targets to + // sat/kw fees and min relay feerate. + GetFeeInfo() (WebAPIResponse, error) } // SparseConfFeeSource is an implementation of the WebAPIFeeSource that utilizes @@ -642,30 +643,43 @@ type SparseConfFeeSource struct { 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 // above query URL. Typically this will be JSON, but the specifics are left to // the WebAPIFeeSource implementation. func (s SparseConfFeeSource) parseResponse(r io.Reader) ( - map[uint32]uint32, error) { + WebAPIResponse, error) { - type jsonResp struct { - FeeByBlockTarget map[uint32]uint32 `json:"fee_by_block_target"` - } - - resp := jsonResp{ + resp := WebAPIResponse{ FeeByBlockTarget: make(map[uint32]uint32), + MinRelayFeerate: 0, } jsonReader := json.NewDecoder(r) 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 -// confirmation targets to sat/kw fees. -func (s SparseConfFeeSource) GetFeeMap() (map[uint32]uint32, error) { +// GetFeeInfo will query the web API, parse the response and return a map of +// confirmation targets to sat/kw fees and min relay feerate in a parsed +// response. +func (s SparseConfFeeSource) GetFeeInfo() (WebAPIResponse, error) { // 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 // response from the service. This way, if the service is down or @@ -688,20 +702,20 @@ func (s SparseConfFeeSource) GetFeeMap() (map[uint32]uint32, error) { if err != nil { log.Errorf("unable to query web api for fee response: %v", err) - return nil, err + return WebAPIResponse{}, err } defer resp.Body.Close() // Once we've obtained the response, we'll instruct the WebAPIFeeSource // 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 { 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 @@ -726,6 +740,7 @@ type WebAPIEstimator struct { // rather than re-querying the API, to prevent an inadvertent DoS attack. feesMtx sync.Mutex feeByBlockTarget map[uint32]uint32 + minRelayFeerate SatPerKVByte // noCache determines whether the web estimator should cache fee // estimates. @@ -837,6 +852,7 @@ func (w *WebAPIEstimator) Start() error { go w.feeUpdateManager() }) + return err } @@ -866,7 +882,15 @@ func (w *WebAPIEstimator) Stop() error { // // NOTE: This method is part of the Estimator interface. func (w *WebAPIEstimator) RelayFeePerKW() SatPerKWeight { - return FeePerKwFloor + // 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 @@ -956,14 +980,21 @@ func (w *WebAPIEstimator) getCachedFee(numBlocks uint32) (uint32, error) { func (w *WebAPIEstimator) updateFeeEstimates() { // Once we've obtained the response, we'll instruct the WebAPIFeeSource // to parse out the body to obtain our final result. - feesByBlockTarget, err := w.apiSource.GetFeeMap() + resp, err := w.apiSource.GetFeeInfo() if err != nil { log.Errorf("unable to get fee response: %v", err) return } + log.Debugf("Received response from source: %s", newLogClosure( + func() string { + resp, _ := json.Marshal(resp) + return string(resp) + })) + w.feesMtx.Lock() - w.feeByBlockTarget = feesByBlockTarget + w.feeByBlockTarget = resp.FeeByBlockTarget + w.minRelayFeerate = resp.MinRelayFeerate w.feesMtx.Unlock() } diff --git a/lnwallet/chainfee/estimator_test.go b/lnwallet/chainfee/estimator_test.go index 51ab5bf29..c8303130d 100644 --- a/lnwallet/chainfee/estimator_test.go +++ b/lnwallet/chainfee/estimator_test.go @@ -107,17 +107,20 @@ func TestSparseConfFeeSource(t *testing.T) { 2: 42, 3: 54321, } - testJSON := map[string]map[uint32]uint32{ - "fee_by_block_target": testFees, + testMinRelayFee := SatPerKVByte(1000) + 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") reader := bytes.NewReader(jsonResp) // 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.Equal(t, testFees, fees, "unexpected fee map returned") + require.Equal(t, testResp, resp, "unexpected resp returned") // Test parsing an improperly formatted JSON API response. 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") } +// 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 // as expected. func TestWebAPIFeeEstimator(t *testing.T) { @@ -194,14 +236,17 @@ func TestWebAPIFeeEstimator(t *testing.T) { // This will create a `feeByBlockTarget` map with the following values, // - 2: 4000 sat/kb // - 6: 2000 sat/kb. - feeRateResp := map[uint32]uint32{ + feeRates := map[uint32]uint32{ minTarget: maxFeeRate, maxTarget: minFeeRate, } + resp := WebAPIResponse{ + FeeByBlockTarget: feeRates, + } // Create a mock fee source and mock its returned map. feeSource := &mockFeeSource{} - feeSource.On("GetFeeMap").Return(feeRateResp, nil) + feeSource.On("GetFeeInfo").Return(resp, nil) estimator, _ := NewWebAPIEstimator( feeSource, false, minFeeUpdateTimeout, maxFeeUpdateTimeout, @@ -234,7 +279,7 @@ func TestWebAPIFeeEstimator(t *testing.T) { exp := SatPerKVByte(tc.expectedFeeRate).FeePerKWeight() require.Equalf(t, exp, est, "target %v failed, fee "+ - "map is %v", tc.target, feeRateResp) + "map is %v", tc.target, feeRate) }) } diff --git a/lnwallet/chainfee/log.go b/lnwallet/chainfee/log.go index d5d040578..914583033 100644 --- a/lnwallet/chainfee/log.go +++ b/lnwallet/chainfee/log.go @@ -27,3 +27,19 @@ func DisableLog() { func UseLogger(logger btclog.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) +} diff --git a/lnwallet/chainfee/mocks.go b/lnwallet/chainfee/mocks.go index e14340d91..3a6025005 100644 --- a/lnwallet/chainfee/mocks.go +++ b/lnwallet/chainfee/mocks.go @@ -12,10 +12,10 @@ type mockFeeSource struct { // WebAPIFeeSource interface. var _ WebAPIFeeSource = (*mockFeeSource)(nil) -func (m *mockFeeSource) GetFeeMap() (map[uint32]uint32, error) { +func (m *mockFeeSource) GetFeeInfo() (WebAPIResponse, error) { 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 diff --git a/lnwallet/chainfee/rates.go b/lnwallet/chainfee/rates.go index f5294e4d1..20f4f1e1d 100644 --- a/lnwallet/chainfee/rates.go +++ b/lnwallet/chainfee/rates.go @@ -53,7 +53,7 @@ func (s SatPerKVByte) FeePerKWeight() SatPerKWeight { // String returns a human-readable string of the fee rate. 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. From a1d71afde8544f74cc8e5862ffa1a794a5cf5bc0 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 4 Jul 2024 20:36:16 +0800 Subject: [PATCH 2/6] lntest: allow specifying min relay feerate in itest --- lntest/fee_service.go | 24 ++++++++++++++++++------ lntest/harness.go | 6 ++++++ 2 files changed, 24 insertions(+), 6 deletions(-) diff --git a/lntest/fee_service.go b/lntest/fee_service.go index cee9ae0ab..0514a387e 100644 --- a/lntest/fee_service.go +++ b/lntest/fee_service.go @@ -33,6 +33,9 @@ type WebFeeService interface { // target. 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() } @@ -52,8 +55,9 @@ const ( type FeeService struct { *testing.T - feeRateMap map[uint32]uint32 - url string + feeRateMap map[uint32]uint32 + minRelayFeerate chainfee.SatPerKVByte + url string srv *http.Server wg sync.WaitGroup @@ -79,6 +83,7 @@ func NewFeeService(t *testing.T) *FeeService { f.feeRateMap = map[uint32]uint32{ feeServiceTarget: DefaultFeeRateSatPerKw, } + f.minRelayFeerate = chainfee.FeePerKwFloor.FeePerKVByte() listenAddr := fmt.Sprintf(":%v", port) mux := http.NewServeMux() @@ -113,10 +118,9 @@ func (f *FeeService) handleRequest(w http.ResponseWriter, _ *http.Request) { defer f.lock.Unlock() bytes, err := json.Marshal( - struct { - Fees map[uint32]uint32 `json:"fee_by_block_target"` - }{ - Fees: f.feeRateMap, + chainfee.WebAPIResponse{ + FeeByBlockTarget: f.feeRateMap, + MinRelayFeerate: f.minRelayFeerate, }, ) 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()) } +// 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. func (f *FeeService) Reset() { f.lock.Lock() diff --git a/lntest/harness.go b/lntest/harness.go index eefdcfec1..9a11eaa88 100644 --- a/lntest/harness.go +++ b/lntest/harness.go @@ -860,6 +860,12 @@ func (h *HarnessTest) SetFeeEstimateWithConf( 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 // which will affect its following tests. func (h *HarnessTest) validateNodeState(hn *node.HarnessNode) error { From 0a0d51ce22e5410cdc116350b0a5f83297d68ea9 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Fri, 19 Jul 2024 16:12:06 +0800 Subject: [PATCH 3/6] docs: update release notes --- docs/release-notes/release-notes-0.18.3.md | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) diff --git a/docs/release-notes/release-notes-0.18.3.md b/docs/release-notes/release-notes-0.18.3.md index 8d658624f..ba39d05e7 100644 --- a/docs/release-notes/release-notes-0.18.3.md +++ b/docs/release-notes/release-notes-0.18.3.md @@ -55,6 +55,24 @@ # Improvements ## 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 * [`xImportMissionControl`](https://github.com/lightningnetwork/lnd/pull/8779) From 7e60d4189879954923fc5ce531fd9de89900713b Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 4 Jul 2024 20:19:21 +0800 Subject: [PATCH 4/6] chainfee: make sure web API has been started before estimating Previously we may get a floor feerate when calling `EstimateFeePerKW` due to the fee estimator not finishing its startup process, which gives us an empty fee map. This is now fixed to return an error if the estimator is not started. --- lnwallet/chainfee/estimator.go | 62 +++++++++++++++++++---------- lnwallet/chainfee/estimator_test.go | 8 ++-- 2 files changed, 44 insertions(+), 26 deletions(-) diff --git a/lnwallet/chainfee/estimator.go b/lnwallet/chainfee/estimator.go index 49b0790a7..3cab0556a 100644 --- a/lnwallet/chainfee/estimator.go +++ b/lnwallet/chainfee/estimator.go @@ -10,6 +10,7 @@ import ( "net" "net/http" "sync" + "sync/atomic" "time" "github.com/btcsuite/btcd/btcutil" @@ -725,8 +726,8 @@ var _ WebAPIFeeSource = (*SparseConfFeeSource)(nil) // WebAPIEstimator is an implementation of the Estimator interface that // queries an HTTP-based fee estimation from an existing web API. type WebAPIEstimator struct { - started sync.Once - stopped sync.Once + started atomic.Bool + stopped atomic.Bool // apiSource is the backing web API source we'll use for our queries. apiSource WebAPIFeeSource @@ -792,6 +793,12 @@ func NewWebAPIEstimator(api WebAPIFeeSource, noCache bool, func (w *WebAPIEstimator) EstimateFeePerKW(numBlocks uint32) ( 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 { numBlocks = MaxBlockTarget } else if numBlocks < minBlockTarget { @@ -831,29 +838,33 @@ func (w *WebAPIEstimator) EstimateFeePerKW(numBlocks uint32) ( // // NOTE: This method is part of the Estimator interface. 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. if w.noCache { return nil } - var err error - w.started.Do(func() { - log.Infof("Starting web API fee estimator") + feeUpdateTimeout := w.randomFeeUpdateTimeout() - 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", - feeUpdateTimeout) + w.updateFeeTicker = time.NewTicker(feeUpdateTimeout) - w.updateFeeTicker = time.NewTicker(feeUpdateTimeout) - w.updateFeeEstimates() + w.wg.Add(1) + go w.feeUpdateManager() - w.wg.Add(1) - go w.feeUpdateManager() - - }) - - return err + return nil } // Stop stops any spawned goroutines and cleans up the resources used by the @@ -861,19 +872,22 @@ func (w *WebAPIEstimator) Start() error { // // NOTE: This method is part of the Estimator interface. 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. if w.noCache { return nil } - w.stopped.Do(func() { - log.Infof("Stopping web API fee estimator") + w.updateFeeTicker.Stop() - w.updateFeeTicker.Stop() + close(w.quit) + w.wg.Wait() - close(w.quit) - w.wg.Wait() - }) return nil } @@ -882,6 +896,10 @@ func (w *WebAPIEstimator) Stop() error { // // NOTE: This method is part of the Estimator interface. func (w *WebAPIEstimator) RelayFeePerKW() SatPerKWeight { + if !w.started.Load() { + log.Error("WebAPIEstimator not started") + } + // Get fee estimates now if we don't refresh periodically. if w.noCache { w.updateFeeEstimates() diff --git a/lnwallet/chainfee/estimator_test.go b/lnwallet/chainfee/estimator_test.go index c8303130d..3d355d503 100644 --- a/lnwallet/chainfee/estimator_test.go +++ b/lnwallet/chainfee/estimator_test.go @@ -252,12 +252,12 @@ func TestWebAPIFeeEstimator(t *testing.T) { 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) - require.NoErrorf(t, err, "expected no error") - require.Equalf(t, FeePerKwFloor, feeRate, "expected fee rate floor "+ - "returned when no cached fee rate found") + require.Error(t, err, "expected an error") + require.Zero(t, feeRate, "expected zero fee rate") + // Start the estimator. require.NoError(t, estimator.Start(), "unable to start fee estimator") for _, tc := range testCases { From b6049ff94b20a65deafb0a5069c574d82a7c1042 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Wed, 24 Jul 2024 19:31:21 +0800 Subject: [PATCH 5/6] multi: add `NewLogClosure` in `lnutils` to avoid repetition And replaces all usage of `logClosure` with `lnutils.LogClosure`. --- chanbackup/log.go | 16 ---------------- chanbackup/pubsub.go | 6 +++--- chanbackup/recover.go | 3 ++- contractcourt/breach_arbitrator.go | 14 ++++++++------ contractcourt/chain_watcher.go | 3 ++- contractcourt/channel_arbitrator.go | 11 ++++++----- contractcourt/log.go | 16 ---------------- contractcourt/utxonursery.go | 3 ++- discovery/bootstrapper.go | 3 ++- discovery/log.go | 16 ---------------- graph/builder.go | 4 +++- graph/log.go | 16 ---------------- htlcswitch/circuit_map.go | 22 +++++++++++++--------- htlcswitch/link.go | 5 +++-- htlcswitch/log.go | 16 ---------------- htlcswitch/switch.go | 16 ++++++++++------ lnrpc/devrpc/log.go | 16 ---------------- lnrpc/invoicesrpc/addinvoice.go | 3 ++- lnrpc/invoicesrpc/log.go | 16 ---------------- lnutils/log.go | 17 +++++++++++++++++ lnwallet/chainfee/estimator.go | 3 ++- lnwallet/chainfee/log.go | 16 ---------------- lnwallet/chancloser/chancloser.go | 3 ++- lnwallet/chancloser/log.go | 16 ---------------- lnwallet/channel.go | 15 ++++++++------- lnwallet/log.go | 16 ---------------- log.go | 16 ---------------- peer/brontide.go | 4 ++-- peer/log.go | 16 ---------------- routing/log.go | 16 ---------------- routing/pathfind.go | 3 ++- routing/payment_session.go | 3 ++- routing/router.go | 13 +++++++------ rpcserver.go | 3 ++- sweep/fee_bumper.go | 2 +- sweep/log.go | 16 ---------------- sweep/sweeper.go | 3 ++- watchtower/wtdb/log.go | 16 ---------------- 38 files changed, 103 insertions(+), 299 deletions(-) create mode 100644 lnutils/log.go diff --git a/chanbackup/log.go b/chanbackup/log.go index 730fbc9e4..34eb9e93f 100644 --- a/chanbackup/log.go +++ b/chanbackup/log.go @@ -27,19 +27,3 @@ func DisableLog() { func UseLogger(logger btclog.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) -} diff --git a/chanbackup/pubsub.go b/chanbackup/pubsub.go index 987678d92..7652d3654 100644 --- a/chanbackup/pubsub.go +++ b/chanbackup/pubsub.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lnutils" ) // 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 { log.Debugf("Removing channel %v from backup "+ - "state", newLogClosure(func() string { - return chanUpdate.ClosedChans[i].String() - })) + "state", lnutils.NewLogClosure( + chanUpdate.ClosedChans[i].String)) delete(s.backupState, closedChan) diff --git a/chanbackup/recover.go b/chanbackup/recover.go index ebd48dccf..e36a6badb 100644 --- a/chanbackup/recover.go +++ b/chanbackup/recover.go @@ -7,6 +7,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/keychain" + "github.com/lightningnetwork/lnd/lnutils" ) // ChannelRestorer is an interface that allows the Recover method to map the @@ -63,7 +64,7 @@ func Recover(backups []Single, restorer ChannelRestorer, log.Infof("Attempting to connect to node=%x (addrs=%v) to "+ "restore ChannelPoint(%v)", backup.RemoteNodePub.SerializeCompressed(), - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(backups[i].Addresses) }), backup.FundingOutpoint) diff --git a/contractcourt/breach_arbitrator.go b/contractcourt/breach_arbitrator.go index 96fa689c3..aab4e943d 100644 --- a/contractcourt/breach_arbitrator.go +++ b/contractcourt/breach_arbitrator.go @@ -20,6 +20,7 @@ import ( "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/labels" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -732,9 +733,10 @@ justiceTxBroadcast: } finalTx := justiceTxs.spendAll - brarLog.Debugf("Broadcasting justice tx: %v", newLogClosure(func() string { - return spew.Sdump(finalTx) - })) + brarLog.Debugf("Broadcasting justice tx: %v", lnutils.NewLogClosure( + func() string { + return spew.Sdump(finalTx) + })) // We'll now attempt to broadcast the transaction which finalized the // channel's retribution against the cheating counter party. @@ -857,7 +859,7 @@ Loop: brarLog.Debugf("Broadcasting justice tx "+ "spending commitment outs: %v", - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(tx) })) @@ -874,7 +876,7 @@ Loop: brarLog.Debugf("Broadcasting justice tx "+ "spending HTLC outs: %v", - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(tx) })) @@ -891,7 +893,7 @@ Loop: brarLog.Debugf("Broadcasting justice tx "+ "spending second-level HTLC output: %v", - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(tx) })) diff --git a/contractcourt/chain_watcher.go b/contractcourt/chain_watcher.go index f1733ad1f..962a239e7 100644 --- a/contractcourt/chain_watcher.go +++ b/contractcourt/chain_watcher.go @@ -20,6 +20,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" ) @@ -1254,7 +1255,7 @@ func (c *chainWatcher) dispatchContractBreach(spendEvent *chainntnfs.SpendDetail spendHeight := uint32(spendEvent.SpendingHeight) log.Debugf("Punishment breach retribution created: %v", - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { retribution.KeyRing.LocalHtlcKey = nil retribution.KeyRing.RemoteHtlcKey = nil retribution.KeyRing.ToLocalKey = nil diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index cda0d4e1f..854bff5f6 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -24,6 +24,7 @@ import ( "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/labels" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/sweep" @@ -465,7 +466,7 @@ func (c *ChannelArbitrator) Start(state *chanArbStartState) error { } log.Debugf("Starting ChannelArbitrator(%v), htlc_set=%v, state=%v", - c.cfg.ChanPoint, newLogClosure(func() string { + c.cfg.ChanPoint, lnutils.NewLogClosure(func() string { return spew.Sdump(c.activeHTLCs) }), state.currentState, ) @@ -959,7 +960,7 @@ func (c *ChannelArbitrator) stateStep( // commitment transaction has already been broadcast. log.Tracef("ChannelArbitrator(%v): logging chain_actions=%v", c.cfg.ChanPoint, - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(chainActions) })) @@ -1097,7 +1098,7 @@ func (c *ChannelArbitrator) stateStep( log.Infof("Broadcasting force close transaction %v, "+ "ChannelPoint(%v): %v", closeTx.TxHash(), c.cfg.ChanPoint, - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(closeTx) })) @@ -1224,7 +1225,7 @@ func (c *ChannelArbitrator) stateStep( if len(pktsToSend) != 0 { log.Debugf("ChannelArbitrator(%v): sending "+ "resolution message=%v", c.cfg.ChanPoint, - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(pktsToSend) })) @@ -2742,7 +2743,7 @@ func (c *ChannelArbitrator) notifyContractUpdate(upd *ContractUpdate) { log.Tracef("ChannelArbitrator(%v): fresh set of htlcs=%v", c.cfg.ChanPoint, - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(upd) }), ) diff --git a/contractcourt/log.go b/contractcourt/log.go index 2891781e8..2e52cc97d 100644 --- a/contractcourt/log.go +++ b/contractcourt/log.go @@ -51,19 +51,3 @@ func UseBreachLogger(logger btclog.Logger) { func UseNurseryLogger(logger btclog.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) -} diff --git a/contractcourt/utxonursery.go b/contractcourt/utxonursery.go index f419881da..95e0778e6 100644 --- a/contractcourt/utxonursery.go +++ b/contractcourt/utxonursery.go @@ -18,6 +18,7 @@ import ( "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/labels" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/sweep" ) @@ -947,7 +948,7 @@ func (u *UtxoNursery) waitForSweepConf(classHeight uint32, func (u *UtxoNursery) sweepCribOutput(classHeight uint32, baby *babyOutput) error { utxnLog.Infof("Publishing CLTV-delayed HTLC output using timeout tx "+ "(txid=%v): %v", baby.timeoutTx.TxHash(), - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(baby.timeoutTx) }), ) diff --git a/discovery/bootstrapper.go b/discovery/bootstrapper.go index 67dbc7e23..9e3c40b03 100644 --- a/discovery/bootstrapper.go +++ b/discovery/bootstrapper.go @@ -16,6 +16,7 @@ import ( "github.com/btcsuite/btcd/btcutil/bech32" "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/autopilot" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/tor" "github.com/miekg/dns" @@ -431,7 +432,7 @@ search: } log.Tracef("Retrieved SRV records from dns seed: %v", - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(addrs) }), ) diff --git a/discovery/log.go b/discovery/log.go index bd2004d3d..f09e7fb71 100644 --- a/discovery/log.go +++ b/discovery/log.go @@ -27,19 +27,3 @@ func DisableLog() { func UseLogger(logger btclog.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) -} diff --git a/graph/builder.go b/graph/builder.go index 2436f3176..01ea97cf9 100644 --- a/graph/builder.go +++ b/graph/builder.go @@ -1432,7 +1432,9 @@ func (b *Builder) processUpdate(msg interface{}, } log.Tracef("New channel update applied: %v", - newLogClosure(func() string { return spew.Sdump(msg) })) + lnutils.NewLogClosure(func() string { + return spew.Sdump(msg) + })) b.stats.incNumChannelUpdates() default: diff --git a/graph/log.go b/graph/log.go index cd31dae11..7d2f741c6 100644 --- a/graph/log.go +++ b/graph/log.go @@ -29,19 +29,3 @@ func DisableLog() { func UseLogger(logger btclog.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) -} diff --git a/htlcswitch/circuit_map.go b/htlcswitch/circuit_map.go index 9b26a1d07..06477ef98 100644 --- a/htlcswitch/circuit_map.go +++ b/htlcswitch/circuit_map.go @@ -10,6 +10,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/kvdb" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwire" ) @@ -800,9 +801,10 @@ func (cm *circuitMap) CommitCircuits(circuits ...*PaymentCircuit) ( inKeys = append(inKeys, circuit.Incoming) } - log.Tracef("Committing fresh circuits: %v", newLogClosure(func() string { - return spew.Sdump(inKeys) - })) + log.Tracef("Committing fresh circuits: %v", lnutils.NewLogClosure( + func() string { + return spew.Sdump(inKeys) + })) actions := &CircuitFwdActions{} @@ -948,9 +950,10 @@ func (cm *circuitMap) OpenCircuits(keystones ...Keystone) error { return nil } - log.Tracef("Opening finalized circuits: %v", newLogClosure(func() string { - return spew.Sdump(keystones) - })) + log.Tracef("Opening finalized circuits: %v", lnutils.NewLogClosure( + func() string { + return spew.Sdump(keystones) + })) // Check that all keystones correspond to committed-but-unopened // circuits. @@ -1078,9 +1081,10 @@ func (cm *circuitMap) CloseCircuit(outKey CircuitKey) (*PaymentCircuit, error) { // circuit was already cleaned up at a different point in time. func (cm *circuitMap) DeleteCircuits(inKeys ...CircuitKey) error { - log.Tracef("Deleting resolved circuits: %v", newLogClosure(func() string { - return spew.Sdump(inKeys) - })) + log.Tracef("Deleting resolved circuits: %v", lnutils.NewLogClosure( + func() string { + return spew.Sdump(inKeys) + })) var ( closingCircuits = make(map[CircuitKey]struct{}) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index c0c828f83..20b32596f 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -25,6 +25,7 @@ import ( "github.com/lightningnetwork/lnd/invoices" "github.com/lightningnetwork/lnd/lnpeer" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" @@ -2536,10 +2537,10 @@ func (l *channelLink) updateCommitTx() error { l.log.Tracef("revocation window exhausted, unable to send: "+ "%v, pend_updates=%v, dangling_closes%v", l.channel.PendingLocalUpdateCount(), - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(l.openedCircuits) }), - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(l.closedCircuits) }), ) diff --git a/htlcswitch/log.go b/htlcswitch/log.go index 5749de09e..79259be91 100644 --- a/htlcswitch/log.go +++ b/htlcswitch/log.go @@ -31,19 +31,3 @@ func UseLogger(logger btclog.Logger) { log = 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) -} diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index d473d8422..7f2661212 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -21,6 +21,7 @@ import ( "github.com/lightningnetwork/lnd/htlcswitch/hop" "github.com/lightningnetwork/lnd/kvdb" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" @@ -613,9 +614,10 @@ func (s *Switch) SendHTLC(firstHop lnwire.ShortChannelID, attemptID uint64, func (s *Switch) UpdateForwardingPolicies( chanPolicies map[wire.OutPoint]models.ForwardingPolicy) { - log.Tracef("Updating link policies: %v", newLogClosure(func() string { - return spew.Sdump(chanPolicies) - })) + log.Tracef("Updating link policies: %v", lnutils.NewLogClosure( + func() string { + return spew.Sdump(chanPolicies) + })) s.indexMtx.RLock() @@ -1213,7 +1215,8 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { ) log.Warnf("unable to find err source for "+ "outgoing_link=%v, errors=%v", - packet.outgoingChanID, newLogClosure(func() string { + packet.outgoingChanID, + lnutils.NewLogClosure(func() string { return spew.Sdump(linkErrs) })) } @@ -1994,8 +1997,9 @@ out: continue } - log.Tracef("Acked %d settle fails: %v", len(s.pendingSettleFails), - newLogClosure(func() string { + log.Tracef("Acked %d settle fails: %v", + len(s.pendingSettleFails), + lnutils.NewLogClosure(func() string { return spew.Sdump(s.pendingSettleFails) })) diff --git a/lnrpc/devrpc/log.go b/lnrpc/devrpc/log.go index 2ff536b84..9cae145e5 100644 --- a/lnrpc/devrpc/log.go +++ b/lnrpc/devrpc/log.go @@ -27,19 +27,3 @@ func DisableLog() { func UseLogger(logger btclog.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) -} diff --git a/lnrpc/invoicesrpc/addinvoice.go b/lnrpc/invoicesrpc/addinvoice.go index 4b55f3f0d..d12dc11d7 100644 --- a/lnrpc/invoicesrpc/addinvoice.go +++ b/lnrpc/invoicesrpc/addinvoice.go @@ -20,6 +20,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/invoices" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/netann" "github.com/lightningnetwork/lnd/routing" @@ -473,7 +474,7 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, } log.Tracef("[addinvoice] adding new invoice %v", - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(newInvoice) }), ) diff --git a/lnrpc/invoicesrpc/log.go b/lnrpc/invoicesrpc/log.go index 8429ee51c..f3644fdb5 100644 --- a/lnrpc/invoicesrpc/log.go +++ b/lnrpc/invoicesrpc/log.go @@ -27,19 +27,3 @@ func DisableLog() { func UseLogger(logger btclog.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) -} diff --git a/lnutils/log.go b/lnutils/log.go new file mode 100644 index 000000000..4bfb64b07 --- /dev/null +++ b/lnutils/log.go @@ -0,0 +1,17 @@ +package lnutils + +// 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) +} diff --git a/lnwallet/chainfee/estimator.go b/lnwallet/chainfee/estimator.go index 3cab0556a..d9a402964 100644 --- a/lnwallet/chainfee/estimator.go +++ b/lnwallet/chainfee/estimator.go @@ -15,6 +15,7 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/rpcclient" + "github.com/lightningnetwork/lnd/lnutils" ) const ( @@ -1004,7 +1005,7 @@ func (w *WebAPIEstimator) updateFeeEstimates() { return } - log.Debugf("Received response from source: %s", newLogClosure( + log.Debugf("Received response from source: %s", lnutils.NewLogClosure( func() string { resp, _ := json.Marshal(resp) return string(resp) diff --git a/lnwallet/chainfee/log.go b/lnwallet/chainfee/log.go index 914583033..d5d040578 100644 --- a/lnwallet/chainfee/log.go +++ b/lnwallet/chainfee/log.go @@ -27,19 +27,3 @@ func DisableLog() { func UseLogger(logger btclog.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) -} diff --git a/lnwallet/chancloser/chancloser.go b/lnwallet/chancloser/chancloser.go index 47635c3af..477d0912f 100644 --- a/lnwallet/chancloser/chancloser.go +++ b/lnwallet/chancloser/chancloser.go @@ -15,6 +15,7 @@ import ( "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/labels" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" @@ -869,7 +870,7 @@ func (c *ChanCloser) ReceiveClosingSigned( //nolint:funlen // With the closing transaction crafted, we'll now broadcast it // to the network. chancloserLog.Infof("Broadcasting cooperative close tx: %v", - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(closeTx) }), ) diff --git a/lnwallet/chancloser/log.go b/lnwallet/chancloser/log.go index 967a1ec35..7189ed2a3 100644 --- a/lnwallet/chancloser/log.go +++ b/lnwallet/chancloser/log.go @@ -23,19 +23,3 @@ func DisableLog() { func UseLogger(logger btclog.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) -} diff --git a/lnwallet/channel.go b/lnwallet/channel.go index 0e0d762c1..b3ccf77d1 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -29,6 +29,7 @@ import ( "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet/chainfee" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/shachain" @@ -1869,7 +1870,7 @@ func (lc *LightningChannel) restoreCommitState( lc.localCommitChain.addCommitment(localCommit) lc.log.Tracef("starting local commitment: %v", - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(lc.localCommitChain.tail()) }), ) @@ -1885,7 +1886,7 @@ func (lc *LightningChannel) restoreCommitState( lc.remoteCommitChain.addCommitment(remoteCommit) lc.log.Tracef("starting remote commitment: %v", - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(lc.remoteCommitChain.tail()) }), ) @@ -1920,7 +1921,7 @@ func (lc *LightningChannel) restoreCommitState( lc.remoteCommitChain.addCommitment(pendingRemoteCommit) lc.log.Debugf("pending remote commitment: %v", - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(lc.remoteCommitChain.tip()) }), ) @@ -3245,9 +3246,9 @@ func (lc *LightningChannel) fetchParent(entry *PaymentDescriptor, return nil, fmt.Errorf("unable to find parent entry "+ "%d in %v update log: %v\nUpdatelog: %v", entry.ParentIndex, logName, - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(entry) - }), newLogClosure(func() string { + }), lnutils.NewLogClosure(func() string { return spew.Sdump(updateLog) }), ) @@ -4249,7 +4250,7 @@ func (lc *LightningChannel) SignNextCommitment() (*NewCommitState, error) { "their_balance=%v, commit_tx: %v", newCommitView.ourBalance, newCommitView.theirBalance, - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(newCommitView.txn) }), ) @@ -5209,7 +5210,7 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSigs *CommitSigs) error { lc.log.Tracef("local chain: our_balance=%v, "+ "their_balance=%v, commit_tx: %v", localCommitmentView.ourBalance, localCommitmentView.theirBalance, - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(localCommitmentView.txn) }), ) diff --git a/lnwallet/log.go b/lnwallet/log.go index 341edeca7..7c8ce5198 100644 --- a/lnwallet/log.go +++ b/lnwallet/log.go @@ -36,19 +36,3 @@ func UseLogger(logger btclog.Logger) { chain.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) -} diff --git a/log.go b/log.go index 1b170f5ea..9067a4a36 100644 --- a/log.go +++ b/log.go @@ -208,19 +208,3 @@ func SetSubLogger(root *build.RotatingLogWriter, subsystem string, 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) -} diff --git a/peer/brontide.go b/peer/brontide.go index 769fe539f..9393acefb 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -2156,7 +2156,7 @@ func (p *Brontide) logWireMessage(msg lnwire.Message, read bool) { summaryPrefix = "Sending" } - p.log.Debugf("%v", newLogClosure(func() string { + p.log.Debugf("%v", lnutils.NewLogClosure(func() string { // Debug summary of message. summary := messageSummary(msg) if len(summary) > 0 { @@ -2184,7 +2184,7 @@ func (p *Brontide) logWireMessage(msg lnwire.Message, read bool) { prefix = "writeMessage to peer" } - p.log.Tracef(prefix+": %v", newLogClosure(func() string { + p.log.Tracef(prefix+": %v", lnutils.NewLogClosure(func() string { return spew.Sdump(msg) })) } diff --git a/peer/log.go b/peer/log.go index a1f9bda3e..f0d1a6672 100644 --- a/peer/log.go +++ b/peer/log.go @@ -22,19 +22,3 @@ func DisableLog() { func UseLogger(logger btclog.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) -} diff --git a/routing/log.go b/routing/log.go index e5c2e7a07..741ec084e 100644 --- a/routing/log.go +++ b/routing/log.go @@ -31,19 +31,3 @@ func UseLogger(logger btclog.Logger) { log = 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) -} diff --git a/routing/pathfind.go b/routing/pathfind.go index 083af04db..a80826971 100644 --- a/routing/pathfind.go +++ b/routing/pathfind.go @@ -13,6 +13,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/feature" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" "github.com/lightningnetwork/lnd/routing/route" @@ -728,7 +729,7 @@ func findPath(g *graphParams, r *RestrictParams, cfg *PathFindingConfig, edge.capacity, ) - log.Trace(newLogClosure(func() string { + log.Trace(lnutils.NewLogClosure(func() string { return fmt.Sprintf("path finding probability: fromnode=%v,"+ " tonode=%v, amt=%v, cap=%v, probability=%v", fromVertex, toNodeDist.node, amountToSend, diff --git a/routing/payment_session.go b/routing/payment_session.go index a464bd93e..7fe9a45ba 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -10,6 +10,7 @@ import ( "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/graph" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/route" ) @@ -432,7 +433,7 @@ func (p *paymentSession) UpdateAdditionalEdge(msg *lnwire.ChannelUpdate, policy.FeeProportionalMillionths = lnwire.MilliSatoshi(msg.FeeRate) log.Debugf("New private channel update applied: %v", - newLogClosure(func() string { return spew.Sdump(msg) })) + lnutils.NewLogClosure(func() string { return spew.Sdump(msg) })) return true } diff --git a/routing/router.go b/routing/router.go index 293f2c9fc..81abb5007 100644 --- a/routing/router.go +++ b/routing/router.go @@ -21,6 +21,7 @@ import ( "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/htlcswitch" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/record" @@ -669,7 +670,7 @@ func (r *ChannelRouter) FindRoute(req *RouteRequest) (*route.Route, float64, } go log.Tracef("Obtained path to send %v to %x: %v", - req.Amount, req.Target, newLogClosure(func() string { + req.Amount, req.Target, lnutils.NewLogClosure(func() string { return spew.Sdump(route) }), ) @@ -704,7 +705,7 @@ func generateSphinxPacket(rt *route.Route, paymentHash []byte, } log.Tracef("Constructed per-hop payloads for payment_hash=%x: %v", - paymentHash[:], newLogClosure(func() string { + paymentHash, lnutils.NewLogClosure(func() string { path := make( []sphinx.OnionHop, sphinxPath.TrueRouteLength(), ) @@ -734,7 +735,7 @@ func generateSphinxPacket(rt *route.Route, paymentHash []byte, } log.Tracef("Generated sphinx packet: %v", - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { // We make a copy of the ephemeral key and unset the // internal curve here in order to keep the logs from // getting noisy. @@ -945,8 +946,8 @@ func (r *ChannelRouter) SendPaymentAsync(ctx context.Context, // spewPayment returns a log closures that provides a spewed string // representation of the passed payment. -func spewPayment(payment *LightningPayment) logClosure { - return newLogClosure(func() string { +func spewPayment(payment *LightningPayment) lnutils.LogClosure { + return lnutils.NewLogClosure(func() string { // Make a copy of the payment with a nilled Curve // before spewing. var routeHints [][]zpay32.HopHint @@ -1091,7 +1092,7 @@ func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route, } log.Tracef("Dispatching SendToRoute for HTLC hash %v: %v", - htlcHash, newLogClosure(func() string { + htlcHash, lnutils.NewLogClosure(func() string { return spew.Sdump(rt) }), ) diff --git a/rpcserver.go b/rpcserver.go index 465035ea5..26c6e4c71 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -63,6 +63,7 @@ import ( "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lnrpc/walletrpc" "github.com/lightningnetwork/lnd/lntypes" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/btcwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" @@ -5845,7 +5846,7 @@ func (r *rpcServer) LookupInvoice(ctx context.Context, } rpcsLog.Tracef("[lookupinvoice] located invoice %v", - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(invoice) })) diff --git a/sweep/fee_bumper.go b/sweep/fee_bumper.go index e79280166..761f16ecd 100644 --- a/sweep/fee_bumper.go +++ b/sweep/fee_bumper.go @@ -313,7 +313,7 @@ func (t *TxPublisher) isNeutrinoBackend() bool { // // NOTE: part of the Bumper interface. func (t *TxPublisher) Broadcast(req *BumpRequest) (<-chan *BumpResult, error) { - log.Tracef("Received broadcast request: %s", newLogClosure( + log.Tracef("Received broadcast request: %s", lnutils.NewLogClosure( func() string { return spew.Sdump(req) })()) diff --git a/sweep/log.go b/sweep/log.go index 9bf48116d..172502375 100644 --- a/sweep/log.go +++ b/sweep/log.go @@ -27,19 +27,3 @@ func DisableLog() { func UseLogger(logger btclog.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) -} diff --git a/sweep/sweeper.go b/sweep/sweeper.go index 39a03228d..d414adc88 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -13,6 +13,7 @@ import ( "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/chainfee" ) @@ -1376,7 +1377,7 @@ func (s *UtxoSweeper) handleInputSpent(spend *chainntnfs.SpendDetail) { log.Debugf("Detected third party spend related to in flight "+ "inputs (is_ours=%v): %v", isOurTx, - newLogClosure(func() string { + lnutils.NewLogClosure(func() string { return spew.Sdump(spend.SpendingTx) }), ) diff --git a/watchtower/wtdb/log.go b/watchtower/wtdb/log.go index ed453383f..fa0a64f6a 100644 --- a/watchtower/wtdb/log.go +++ b/watchtower/wtdb/log.go @@ -43,19 +43,3 @@ func UseLogger(logger btclog.Logger) { migration7.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) -} From d992cf94d6b3b31fa2284652cb34962e8fe56958 Mon Sep 17 00:00:00 2001 From: yyforyongyu Date: Thu, 25 Jul 2024 22:18:00 +0800 Subject: [PATCH 6/6] multi: add `SpewLogClosure` to avoid code repetition --- chanbackup/recover.go | 6 ++---- contractcourt/breach_arbitrator.go | 19 +++++------------ contractcourt/channel_arbitrator.go | 27 ++++++----------------- contractcourt/utxonursery.go | 5 +---- discovery/bootstrapper.go | 6 +----- graph/builder.go | 5 +---- htlcswitch/circuit_map.go | 19 ++++++----------- htlcswitch/link.go | 11 +++------- htlcswitch/switch.go | 14 ++++-------- lnrpc/invoicesrpc/addinvoice.go | 6 +----- lnutils/log.go | 10 +++++++++ lnwallet/chancloser/chancloser.go | 5 +---- lnwallet/channel.go | 33 ++++++----------------------- peer/brontide.go | 4 +--- routing/payment_session.go | 3 +-- routing/router.go | 12 +++-------- rpcserver.go | 4 +--- sweep/fee_bumper.go | 7 ++---- sweep/sweeper.go | 5 +---- 19 files changed, 57 insertions(+), 144 deletions(-) diff --git a/chanbackup/recover.go b/chanbackup/recover.go index e36a6badb..7f5502c4a 100644 --- a/chanbackup/recover.go +++ b/chanbackup/recover.go @@ -4,7 +4,6 @@ import ( "net" "github.com/btcsuite/btcd/btcec/v2" - "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnutils" @@ -64,9 +63,8 @@ func Recover(backups []Single, restorer ChannelRestorer, log.Infof("Attempting to connect to node=%x (addrs=%v) to "+ "restore ChannelPoint(%v)", backup.RemoteNodePub.SerializeCompressed(), - lnutils.NewLogClosure(func() string { - return spew.Sdump(backups[i].Addresses) - }), backup.FundingOutpoint) + lnutils.SpewLogClosure(backups[i].Addresses), + backup.FundingOutpoint) err = peerConnector.ConnectPeer( backup.RemoteNodePub, backup.Addresses, diff --git a/contractcourt/breach_arbitrator.go b/contractcourt/breach_arbitrator.go index aab4e943d..e3dd85ea6 100644 --- a/contractcourt/breach_arbitrator.go +++ b/contractcourt/breach_arbitrator.go @@ -13,7 +13,6 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/input" @@ -733,10 +732,8 @@ justiceTxBroadcast: } finalTx := justiceTxs.spendAll - brarLog.Debugf("Broadcasting justice tx: %v", lnutils.NewLogClosure( - func() string { - return spew.Sdump(finalTx) - })) + brarLog.Debugf("Broadcasting justice tx: %v", lnutils.SpewLogClosure( + finalTx)) // We'll now attempt to broadcast the transaction which finalized the // channel's retribution against the cheating counter party. @@ -859,9 +856,7 @@ Loop: brarLog.Debugf("Broadcasting justice tx "+ "spending commitment outs: %v", - lnutils.NewLogClosure(func() string { - return spew.Sdump(tx) - })) + lnutils.SpewLogClosure(tx)) err = b.cfg.PublishTransaction(tx, label) if err != nil { @@ -876,9 +871,7 @@ Loop: brarLog.Debugf("Broadcasting justice tx "+ "spending HTLC outs: %v", - lnutils.NewLogClosure(func() string { - return spew.Sdump(tx) - })) + lnutils.SpewLogClosure(tx)) err = b.cfg.PublishTransaction(tx, label) if err != nil { @@ -893,9 +886,7 @@ Loop: brarLog.Debugf("Broadcasting justice tx "+ "spending second-level HTLC output: %v", - lnutils.NewLogClosure(func() string { - return spew.Sdump(tx) - })) + lnutils.SpewLogClosure(tx)) err = b.cfg.PublishTransaction(tx, label) if err != nil { diff --git a/contractcourt/channel_arbitrator.go b/contractcourt/channel_arbitrator.go index 854bff5f6..d544e989c 100644 --- a/contractcourt/channel_arbitrator.go +++ b/contractcourt/channel_arbitrator.go @@ -14,7 +14,6 @@ import ( "github.com/btcsuite/btcd/chaincfg/chainhash" "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" - "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/fn" @@ -466,10 +465,8 @@ func (c *ChannelArbitrator) Start(state *chanArbStartState) error { } log.Debugf("Starting ChannelArbitrator(%v), htlc_set=%v, state=%v", - c.cfg.ChanPoint, lnutils.NewLogClosure(func() string { - return spew.Sdump(c.activeHTLCs) - }), state.currentState, - ) + c.cfg.ChanPoint, lnutils.SpewLogClosure(c.activeHTLCs), + state.currentState) // Set our state from our starting state. c.state = state.currentState @@ -959,10 +956,7 @@ func (c *ChannelArbitrator) stateStep( // Otherwise, we'll log that we checked the HTLC actions as the // commitment transaction has already been broadcast. log.Tracef("ChannelArbitrator(%v): logging chain_actions=%v", - c.cfg.ChanPoint, - lnutils.NewLogClosure(func() string { - return spew.Sdump(chainActions) - })) + c.cfg.ChanPoint, lnutils.SpewLogClosure(chainActions)) // Depending on the type of trigger, we'll either "tunnel" // through to a farther state, or just proceed linearly to the @@ -1097,10 +1091,7 @@ func (c *ChannelArbitrator) stateStep( // channel resolution state. log.Infof("Broadcasting force close transaction %v, "+ "ChannelPoint(%v): %v", closeTx.TxHash(), - c.cfg.ChanPoint, - lnutils.NewLogClosure(func() string { - return spew.Sdump(closeTx) - })) + c.cfg.ChanPoint, lnutils.SpewLogClosure(closeTx)) // At this point, we'll now broadcast the commitment // transaction itself. @@ -1225,9 +1216,7 @@ func (c *ChannelArbitrator) stateStep( if len(pktsToSend) != 0 { log.Debugf("ChannelArbitrator(%v): sending "+ "resolution message=%v", c.cfg.ChanPoint, - lnutils.NewLogClosure(func() string { - return spew.Sdump(pktsToSend) - })) + lnutils.SpewLogClosure(pktsToSend)) err := c.cfg.DeliverResolutionMsg(pktsToSend...) if err != nil { @@ -2742,11 +2731,7 @@ func (c *ChannelArbitrator) notifyContractUpdate(upd *ContractUpdate) { c.unmergedSet[upd.HtlcKey] = newHtlcSet(upd.Htlcs) log.Tracef("ChannelArbitrator(%v): fresh set of htlcs=%v", - c.cfg.ChanPoint, - lnutils.NewLogClosure(func() string { - return spew.Sdump(upd) - }), - ) + c.cfg.ChanPoint, lnutils.SpewLogClosure(upd)) } // updateActiveHTLCs merges the unmerged set of HTLCs from the link with diff --git a/contractcourt/utxonursery.go b/contractcourt/utxonursery.go index 95e0778e6..407384162 100644 --- a/contractcourt/utxonursery.go +++ b/contractcourt/utxonursery.go @@ -948,10 +948,7 @@ func (u *UtxoNursery) waitForSweepConf(classHeight uint32, func (u *UtxoNursery) sweepCribOutput(classHeight uint32, baby *babyOutput) error { utxnLog.Infof("Publishing CLTV-delayed HTLC output using timeout tx "+ "(txid=%v): %v", baby.timeoutTx.TxHash(), - lnutils.NewLogClosure(func() string { - return spew.Sdump(baby.timeoutTx) - }), - ) + lnutils.SpewLogClosure(baby.timeoutTx)) // We'll now broadcast the HTLC transaction, then wait for it to be // confirmed before transitioning it to kindergarten. diff --git a/discovery/bootstrapper.go b/discovery/bootstrapper.go index 9e3c40b03..0d370663d 100644 --- a/discovery/bootstrapper.go +++ b/discovery/bootstrapper.go @@ -14,7 +14,6 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil/bech32" - "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/autopilot" "github.com/lightningnetwork/lnd/lnutils" "github.com/lightningnetwork/lnd/lnwire" @@ -432,10 +431,7 @@ search: } log.Tracef("Retrieved SRV records from dns seed: %v", - lnutils.NewLogClosure(func() string { - return spew.Sdump(addrs) - }), - ) + lnutils.SpewLogClosure(addrs)) // Next, we'll need to issue an A record request for each of // the nodes, skipping it if nothing comes back. diff --git a/graph/builder.go b/graph/builder.go index 01ea97cf9..addec9e1b 100644 --- a/graph/builder.go +++ b/graph/builder.go @@ -12,7 +12,6 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/wire" - "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/batch" "github.com/lightningnetwork/lnd/chainntnfs" @@ -1432,9 +1431,7 @@ func (b *Builder) processUpdate(msg interface{}, } log.Tracef("New channel update applied: %v", - lnutils.NewLogClosure(func() string { - return spew.Sdump(msg) - })) + lnutils.SpewLogClosure(msg)) b.stats.incNumChannelUpdates() default: diff --git a/htlcswitch/circuit_map.go b/htlcswitch/circuit_map.go index 06477ef98..076d6f284 100644 --- a/htlcswitch/circuit_map.go +++ b/htlcswitch/circuit_map.go @@ -5,7 +5,6 @@ import ( "fmt" "sync" - "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/htlcswitch/hop" @@ -801,10 +800,8 @@ func (cm *circuitMap) CommitCircuits(circuits ...*PaymentCircuit) ( inKeys = append(inKeys, circuit.Incoming) } - log.Tracef("Committing fresh circuits: %v", lnutils.NewLogClosure( - func() string { - return spew.Sdump(inKeys) - })) + log.Tracef("Committing fresh circuits: %v", lnutils.SpewLogClosure( + inKeys)) actions := &CircuitFwdActions{} @@ -950,10 +947,8 @@ func (cm *circuitMap) OpenCircuits(keystones ...Keystone) error { return nil } - log.Tracef("Opening finalized circuits: %v", lnutils.NewLogClosure( - func() string { - return spew.Sdump(keystones) - })) + log.Tracef("Opening finalized circuits: %v", lnutils.SpewLogClosure( + keystones)) // Check that all keystones correspond to committed-but-unopened // circuits. @@ -1081,10 +1076,8 @@ func (cm *circuitMap) CloseCircuit(outKey CircuitKey) (*PaymentCircuit, error) { // circuit was already cleaned up at a different point in time. func (cm *circuitMap) DeleteCircuits(inKeys ...CircuitKey) error { - log.Tracef("Deleting resolved circuits: %v", lnutils.NewLogClosure( - func() string { - return spew.Sdump(inKeys) - })) + log.Tracef("Deleting resolved circuits: %v", lnutils.SpewLogClosure( + inKeys)) var ( closingCircuits = make(map[CircuitKey]struct{}) diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 20b32596f..712bbda9e 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -13,7 +13,6 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btclog" - "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/channeldb" @@ -2537,13 +2536,9 @@ func (l *channelLink) updateCommitTx() error { l.log.Tracef("revocation window exhausted, unable to send: "+ "%v, pend_updates=%v, dangling_closes%v", l.channel.PendingLocalUpdateCount(), - lnutils.NewLogClosure(func() string { - return spew.Sdump(l.openedCircuits) - }), - lnutils.NewLogClosure(func() string { - return spew.Sdump(l.closedCircuits) - }), - ) + lnutils.SpewLogClosure(l.openedCircuits), + lnutils.SpewLogClosure(l.closedCircuits)) + return nil } else if err != nil { return err diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go index 7f2661212..a78266113 100644 --- a/htlcswitch/switch.go +++ b/htlcswitch/switch.go @@ -614,10 +614,8 @@ func (s *Switch) SendHTLC(firstHop lnwire.ShortChannelID, attemptID uint64, func (s *Switch) UpdateForwardingPolicies( chanPolicies map[wire.OutPoint]models.ForwardingPolicy) { - log.Tracef("Updating link policies: %v", lnutils.NewLogClosure( - func() string { - return spew.Sdump(chanPolicies) - })) + log.Tracef("Updating link policies: %v", lnutils.SpewLogClosure( + chanPolicies)) s.indexMtx.RLock() @@ -1216,9 +1214,7 @@ func (s *Switch) handlePacketForward(packet *htlcPacket) error { log.Warnf("unable to find err source for "+ "outgoing_link=%v, errors=%v", packet.outgoingChanID, - lnutils.NewLogClosure(func() string { - return spew.Sdump(linkErrs) - })) + lnutils.SpewLogClosure(linkErrs)) } log.Tracef("incoming HTLC(%x) violated "+ @@ -1999,9 +1995,7 @@ out: log.Tracef("Acked %d settle fails: %v", len(s.pendingSettleFails), - lnutils.NewLogClosure(func() string { - return spew.Sdump(s.pendingSettleFails) - })) + lnutils.SpewLogClosure(s.pendingSettleFails)) // Reset the pendingSettleFails buffer while keeping acquired // memory. diff --git a/lnrpc/invoicesrpc/addinvoice.go b/lnrpc/invoicesrpc/addinvoice.go index d12dc11d7..b85feefb6 100644 --- a/lnrpc/invoicesrpc/addinvoice.go +++ b/lnrpc/invoicesrpc/addinvoice.go @@ -15,7 +15,6 @@ import ( "github.com/btcsuite/btcd/btcutil" "github.com/btcsuite/btcd/chaincfg" "github.com/btcsuite/btcd/wire" - "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb/models" "github.com/lightningnetwork/lnd/invoices" @@ -474,10 +473,7 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig, } log.Tracef("[addinvoice] adding new invoice %v", - lnutils.NewLogClosure(func() string { - return spew.Sdump(newInvoice) - }), - ) + lnutils.SpewLogClosure(newInvoice)) // With all sanity checks passed, write the invoice to the database. _, err = cfg.AddInvoice(ctx, newInvoice, paymentHash) diff --git a/lnutils/log.go b/lnutils/log.go index 4bfb64b07..a32738bdf 100644 --- a/lnutils/log.go +++ b/lnutils/log.go @@ -1,5 +1,7 @@ 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 @@ -15,3 +17,11 @@ func (c LogClosure) String() string { 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) + } +} diff --git a/lnwallet/chancloser/chancloser.go b/lnwallet/chancloser/chancloser.go index 477d0912f..3f5e730c0 100644 --- a/lnwallet/chancloser/chancloser.go +++ b/lnwallet/chancloser/chancloser.go @@ -870,10 +870,7 @@ func (c *ChanCloser) ReceiveClosingSigned( //nolint:funlen // With the closing transaction crafted, we'll now broadcast it // to the network. chancloserLog.Infof("Broadcasting cooperative close tx: %v", - lnutils.NewLogClosure(func() string { - return spew.Sdump(closeTx) - }), - ) + lnutils.SpewLogClosure(closeTx)) // Create a close channel label. chanID := c.cfg.Channel.ShortChanID() diff --git a/lnwallet/channel.go b/lnwallet/channel.go index b3ccf77d1..b4ea2fee0 100644 --- a/lnwallet/channel.go +++ b/lnwallet/channel.go @@ -1870,10 +1870,7 @@ func (lc *LightningChannel) restoreCommitState( lc.localCommitChain.addCommitment(localCommit) lc.log.Tracef("starting local commitment: %v", - lnutils.NewLogClosure(func() string { - return spew.Sdump(lc.localCommitChain.tail()) - }), - ) + lnutils.SpewLogClosure(lc.localCommitChain.tail())) // We'll also do the same for the remote commitment chain. remoteCommit, err := lc.diskCommitToMemCommit( @@ -1886,10 +1883,7 @@ func (lc *LightningChannel) restoreCommitState( lc.remoteCommitChain.addCommitment(remoteCommit) lc.log.Tracef("starting remote commitment: %v", - lnutils.NewLogClosure(func() string { - return spew.Sdump(lc.remoteCommitChain.tail()) - }), - ) + lnutils.SpewLogClosure(lc.remoteCommitChain.tail())) var ( pendingRemoteCommit *commitment @@ -1921,10 +1915,7 @@ func (lc *LightningChannel) restoreCommitState( lc.remoteCommitChain.addCommitment(pendingRemoteCommit) lc.log.Debugf("pending remote commitment: %v", - lnutils.NewLogClosure(func() string { - return spew.Sdump(lc.remoteCommitChain.tip()) - }), - ) + lnutils.SpewLogClosure(lc.remoteCommitChain.tip())) // We'll also re-create the set of commitment keys needed to // fully re-derive the state. @@ -3246,12 +3237,8 @@ func (lc *LightningChannel) fetchParent(entry *PaymentDescriptor, return nil, fmt.Errorf("unable to find parent entry "+ "%d in %v update log: %v\nUpdatelog: %v", entry.ParentIndex, logName, - lnutils.NewLogClosure(func() string { - return spew.Sdump(entry) - }), lnutils.NewLogClosure(func() string { - return spew.Sdump(updateLog) - }), - ) + lnutils.SpewLogClosure(entry), + lnutils.SpewLogClosure(updateLog)) // The parent add height should never be zero at this point. If // that's the case we probably forgot to send a new commitment. @@ -4250,10 +4237,7 @@ func (lc *LightningChannel) SignNextCommitment() (*NewCommitState, error) { "their_balance=%v, commit_tx: %v", newCommitView.ourBalance, newCommitView.theirBalance, - lnutils.NewLogClosure(func() string { - return spew.Sdump(newCommitView.txn) - }), - ) + lnutils.SpewLogClosure(newCommitView.txn)) // 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 @@ -5210,10 +5194,7 @@ func (lc *LightningChannel) ReceiveNewCommitment(commitSigs *CommitSigs) error { lc.log.Tracef("local chain: our_balance=%v, "+ "their_balance=%v, commit_tx: %v", localCommitmentView.ourBalance, localCommitmentView.theirBalance, - lnutils.NewLogClosure(func() string { - return spew.Sdump(localCommitmentView.txn) - }), - ) + lnutils.SpewLogClosure(localCommitmentView.txn)) // As an optimization, we'll generate a series of jobs for the worker // pool to verify each of the HTLC signatures presented. Once diff --git a/peer/brontide.go b/peer/brontide.go index 9393acefb..fa2c8fde9 100644 --- a/peer/brontide.go +++ b/peer/brontide.go @@ -2184,9 +2184,7 @@ func (p *Brontide) logWireMessage(msg lnwire.Message, read bool) { prefix = "writeMessage to peer" } - p.log.Tracef(prefix+": %v", lnutils.NewLogClosure(func() string { - return spew.Sdump(msg) - })) + p.log.Tracef(prefix+": %v", lnutils.SpewLogClosure(msg)) } // writeMessage writes and flushes the target lnwire.Message to the remote peer. diff --git a/routing/payment_session.go b/routing/payment_session.go index 7fe9a45ba..710318426 100644 --- a/routing/payment_session.go +++ b/routing/payment_session.go @@ -5,7 +5,6 @@ import ( "github.com/btcsuite/btcd/btcec/v2" "github.com/btcsuite/btclog" - "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/build" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/channeldb/models" @@ -433,7 +432,7 @@ func (p *paymentSession) UpdateAdditionalEdge(msg *lnwire.ChannelUpdate, policy.FeeProportionalMillionths = lnwire.MilliSatoshi(msg.FeeRate) log.Debugf("New private channel update applied: %v", - lnutils.NewLogClosure(func() string { return spew.Sdump(msg) })) + lnutils.SpewLogClosure(msg)) return true } diff --git a/routing/router.go b/routing/router.go index 81abb5007..35db5a779 100644 --- a/routing/router.go +++ b/routing/router.go @@ -670,10 +670,7 @@ func (r *ChannelRouter) FindRoute(req *RouteRequest) (*route.Route, float64, } go log.Tracef("Obtained path to send %v to %x: %v", - req.Amount, req.Target, lnutils.NewLogClosure(func() string { - return spew.Sdump(route) - }), - ) + req.Amount, req.Target, lnutils.SpewLogClosure(route)) return route, probability, nil } @@ -1091,11 +1088,8 @@ func (r *ChannelRouter) sendToRoute(htlcHash lntypes.Hash, rt *route.Route, return nil, err } - log.Tracef("Dispatching SendToRoute for HTLC hash %v: %v", - htlcHash, lnutils.NewLogClosure(func() string { - return spew.Sdump(rt) - }), - ) + log.Tracef("Dispatching SendToRoute for HTLC hash %v: %v", htlcHash, + lnutils.SpewLogClosure(rt)) // Since the HTLC hashes and preimages are specified manually over the // RPC for SendToRoute requests, we don't have to worry about creating diff --git a/rpcserver.go b/rpcserver.go index 26c6e4c71..ac10fc790 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -5846,9 +5846,7 @@ func (r *rpcServer) LookupInvoice(ctx context.Context, } rpcsLog.Tracef("[lookupinvoice] located invoice %v", - lnutils.NewLogClosure(func() string { - return spew.Sdump(invoice) - })) + lnutils.SpewLogClosure(invoice)) rpcInvoice, err := invoicesrpc.CreateRPCInvoice( &invoice, r.cfg.ActiveNetParams.Params, diff --git a/sweep/fee_bumper.go b/sweep/fee_bumper.go index 761f16ecd..452cc0dd8 100644 --- a/sweep/fee_bumper.go +++ b/sweep/fee_bumper.go @@ -12,7 +12,6 @@ import ( "github.com/btcsuite/btcd/txscript" "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcwallet/chain" - "github.com/davecgh/go-spew/spew" "github.com/lightningnetwork/lnd/chainntnfs" "github.com/lightningnetwork/lnd/fn" "github.com/lightningnetwork/lnd/input" @@ -313,10 +312,8 @@ func (t *TxPublisher) isNeutrinoBackend() bool { // // NOTE: part of the Bumper interface. func (t *TxPublisher) Broadcast(req *BumpRequest) (<-chan *BumpResult, error) { - log.Tracef("Received broadcast request: %s", lnutils.NewLogClosure( - func() string { - return spew.Sdump(req) - })()) + log.Tracef("Received broadcast request: %s", lnutils.SpewLogClosure( + req)) // Attempt an initial broadcast which is guaranteed to comply with the // RBF rules. diff --git a/sweep/sweeper.go b/sweep/sweeper.go index d414adc88..af2f0cec9 100644 --- a/sweep/sweeper.go +++ b/sweep/sweeper.go @@ -1377,10 +1377,7 @@ func (s *UtxoSweeper) handleInputSpent(spend *chainntnfs.SpendDetail) { log.Debugf("Detected third party spend related to in flight "+ "inputs (is_ours=%v): %v", isOurTx, - lnutils.NewLogClosure(func() string { - return spew.Sdump(spend.SpendingTx) - }), - ) + lnutils.SpewLogClosure(spend.SpendingTx)) } // We now use the spending tx to update the state of the inputs.