Repository: lightningnetwork/lnd
Pull request #8504 (2024-02-28 00:48:59)

lnd/healthcheck: add checks after initialization + success/failure callbacks
## Change Description

This PR expands the `healthcheck` package such that it can support:
- the ability to specify callbacks to fire on success and reaching failure threshold.
- the ability to dynamically add observations (health check routines) after initializing the monitor.

The idea is to use this in the _**payment service**_ to health check a collection of _**lnd**_ backends. Such an application would like to spin up health checks as backends come online and then take some action on health check success/failure beyond just exiting. If these changes are not desired here, then we can always write a custom health checking library which suits these needs.

This change should be transparent to existing users of the package. The callbacks default to no-ops and are configurable via functional option.

## Steps to Test
Steps for reviewers to follow to test the change.

## Pull Request Checklist
### Testing
- [ ] Your PR passes all CI checks.
- [ ] Tests covering the positive and negative (error paths) are included.
- [ ] Bug fixes contain tests triggering the bug to prevent regressions.

### Code Style and Documentation
- [ ] The change obeys the [Code Documentation and Commenting](https://github.com/lightningnetwork/lnd/blob/master/docs/code_contribution_guidelines.md#CodeDocumentation) guidelines, and lines wrap at 80.
- [ ] Commits follow the [Ideal Git Commit Structure](https://github.com/lightningnetwork/lnd/blob/master/docs/code_contribution_guidelines.md#IdealGitCommitStructure).
- [ ] Any new logging statements use an appropriate subsystem and logging level.
- [ ] Any new lncli commands have appropriate tags in the comments for the rpc in the proto file.
- [ ]  [There is a change description in the release notes](https://github.com/lightningnetwork/lnd/tree/master/docs/release-notes), or `[skip ci]` in the commit message for small changes.

📝 Please see our  [Contribution Guidelines](https://github.com/lightningnetwork/lnd/blob/master/docs/code_contribution_guidelines.md) for further guidance.


coderabbitai[bot]: <!-- This is an auto-generated comment: summarize by coderabbit.ai -->
<!-- This is an auto-generated comment: skip review by coderabbit.ai -->

> [!IMPORTANT]
> ## Auto Review Skipped
> 
> Auto reviews are limited to the following labels: llm-review. Please add one of these labels to enable auto reviews.
> 
> Please check the settings in the CodeRabbit UI or the `.coderabbit.yaml` file in this repository.
> 
> To trigger a single review, invoke the `@coderabbitai review` command.
> 

<!-- end of auto-generated comment: skip review by coderabbit.ai --><!-- tweet_start -->

Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media?

<details>
<summary>Share</summary>

- [X](https://twitter.com/intent/tweet?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A&url=https%3A//coderabbit.ai)
- [Mastodon](https://mastodon.social/share?text=I%20just%20used%20%40coderabbitai%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20the%20proprietary%20code.%20Check%20it%20out%3A%20https%3A%2F%2Fcoderabbit.ai)
- [Reddit](https://www.reddit.com/submit?title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&text=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code.%20Check%20it%20out%3A%20https%3A//coderabbit.ai)
- [LinkedIn](https://www.linkedin.com/sharing/share-offsite/?url=https%3A%2F%2Fcoderabbit.ai&mini=true&title=Great%20tool%20for%20code%20review%20-%20CodeRabbit&summary=I%20just%20used%20CodeRabbit%20for%20my%20code%20review%2C%20and%20it%27s%20fantastic%21%20It%27s%20free%20for%20OSS%20and%20offers%20a%20free%20trial%20for%20proprietary%20code)

</details>

<!-- tweet_end --><!-- tips_start -->

---

<details>
<summary>Tips</summary>

### Chat

There are 3 ways to chat with CodeRabbit:

- Review comments: Directly reply to a review comment made by CodeRabbit. Example:
	- `I pushed a fix in commit <commit_id>.`
	- `Generate unit-tests for this file.`
- Files and specific lines of code (under the "Files changed" tab): Tag `@coderabbitai` in a new review comment at the desired location with your query. Examples:
	- `@coderabbitai generate unit tests for this file.`
	-	`@coderabbitai modularize this function.`
- PR comments: Tag `@coderabbitai` in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
	- `@coderabbitai generate interesting stats about this repository from git and render them as a table.`
	- `@coderabbitai show all the console.log statements in this repository.`
	- `@coderabbitai read src/utils.ts and generate unit tests.`
	- `@coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.`

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

### CodeRabbit Commands (invoked as PR comments)

- `@coderabbitai pause` to pause the reviews on a PR.
- `@coderabbitai resume` to resume the paused reviews.
- `@coderabbitai review` to trigger a review. This is useful when automatic reviews are disabled for the repository.
- `@coderabbitai resolve` resolve all the CodeRabbit review comments.
- `@coderabbitai help` to get help.


Additionally, you can add `@coderabbitai ignore` anywhere in the PR description to prevent this PR from being reviewed.

### CodeRabbit Configration File (`.coderabbit.yaml`)

- You can programmatically configure CodeRabbit by adding a `.coderabbit.yaml` file to the root of your repository.
- The JSON schema for the configuration file is available [here](https://coderabbit.ai/integrations/coderabbit-overrides.v2.json).
- If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: `# yaml-language-server: $schema=https://coderabbit.ai/integrations/coderabbit-overrides.v2.json`

### CodeRabbit Discord Community

Join our [Discord Community](https://discord.com/invite/GsXnASn26c) to get help, request features, and share feedback.

</details>

<!-- tips_end -->

Patch:
diff --git a/batch/interface.go b/batch/interface.go
index cd58a148c..a1690c384 100644
--- a/batch/interface.go
+++ b/batch/interface.go
@@ -48,7 +48,7 @@ func LazyAdd() SchedulerOption {
 // set of Requests, executes them, and returns the error from the operation.
 type Scheduler interface {
 	// Execute schedules a Request for execution with the next available
-	// batch. This method blocks until the underlying closure has been
+	// batch. This method blocks until the the underlying closure has been
 	// run against the database. The resulting error is returned to the
 	// caller.
 	Execute(req *Request) error
diff --git a/cert/tls.go b/cert/tls.go
index 4e5d7c81e..755b8005f 100644
--- a/cert/tls.go
+++ b/cert/tls.go
@@ -57,7 +57,7 @@ func LoadCert(certPath, keyPath string) (tls.Certificate, *x509.Certificate,
 		return tls.Certificate{}, nil, err
 	}
 
-	// Now parse the PEM block of the certificate into its x509 data
+	// Now parse the the PEM block of the certificate into its x509 data
 	// structure so it can be examined in more detail.
 	x509Cert, err := x509.ParseCertificate(certData.Certificate[0])
 	if err != nil {
@@ -82,7 +82,7 @@ func LoadCertFromBytes(certBytes, keyBytes []byte) (tls.Certificate,
 		return tls.Certificate{}, nil, err
 	}
 
-	// Now parse the PEM block of the certificate into its x509 data
+	// Now parse the the PEM block of the certificate into its x509 data
 	// structure so it can be examined in more detail.
 	x509Cert, err := x509.ParseCertificate(certData.Certificate[0])
 	if err != nil {
diff --git a/channeldb/channel.go b/channeldb/channel.go
index 7292fd6b0..1a07ed91d 100644
--- a/channeldb/channel.go
+++ b/channeldb/channel.go
@@ -1169,7 +1169,7 @@ func (c *OpenChannel) fullSync(tx kvdb.RwTx) error {
 		return ErrChanAlreadyExists
 	}
 
-	cid := lnwire.NewChanIDFromOutPoint(c.FundingOutpoint)
+	cid := lnwire.NewChanIDFromOutPoint(&c.FundingOutpoint)
 	if cidBucket.Get(cid[:]) != nil {
 		return ErrChanAlreadyExists
 	}
@@ -1574,7 +1574,7 @@ func (c *OpenChannel) ChanSyncMsg() (*lnwire.ChannelReestablish, error) {
 
 	return &lnwire.ChannelReestablish{
 		ChanID: lnwire.NewChanIDFromOutPoint(
-			c.FundingOutpoint,
+			&c.FundingOutpoint,
 		),
 		NextLocalCommitHeight:  nextLocalCommitHeight,
 		RemoteCommitTailHeight: remoteChainTipHeight,
diff --git a/channeldb/db.go b/channeldb/db.go
index 34d621a68..aff70d462 100644
--- a/channeldb/db.go
+++ b/channeldb/db.go
@@ -704,7 +704,7 @@ func (c *ChannelStateDB) FetchChannelByID(tx kvdb.RTx, id lnwire.ChannelID) (
 				return err
 			}
 
-			chanID := lnwire.NewChanIDFromOutPoint(outPoint)
+			chanID := lnwire.NewChanIDFromOutPoint(&outPoint)
 			if chanID != id {
 				return nil
 			}
diff --git a/cluster/etcd_elector.go b/cluster/etcd_elector.go
index 25b11af25..71057c360 100644
--- a/cluster/etcd_elector.go
+++ b/cluster/etcd_elector.go
@@ -103,7 +103,7 @@ func (e *etcdLeaderElector) Leader(ctx context.Context) (string, error) {
 }
 
 // Campaign will start a new leader election campaign. Campaign will block until
-// the elector context is canceled or the caller is elected as the leader.
+// the elector context is canceled or the the caller is elected as the leader.
 func (e *etcdLeaderElector) Campaign(ctx context.Context) error {
 	return e.election.Campaign(ctx, e.id)
 }
diff --git a/discovery/gossiper.go b/discovery/gossiper.go
index e1884445e..2c353bf6a 100644
--- a/discovery/gossiper.go
+++ b/discovery/gossiper.go
@@ -1748,9 +1748,8 @@ func (d *AuthenticatedGossiper) processChanPolicyUpdate(
 			// update with the peer's alias. We do this after
 			// updateChannel so that the alias isn't persisted to
 			// the database.
-			chanID := lnwire.NewChanIDFromOutPoint(
-				edgeInfo.Info.ChannelPoint,
-			)
+			op := &edgeInfo.Info.ChannelPoint
+			chanID := lnwire.NewChanIDFromOutPoint(op)
 
 			var defaultAlias lnwire.ShortChannelID
 			foundAlias, _ := d.cfg.GetAlias(chanID)
diff --git a/docs/release-notes/release-notes-0.18.0.md b/docs/release-notes/release-notes-0.18.0.md
index ed485af77..2d0fd04c3 100644
--- a/docs/release-notes/release-notes-0.18.0.md
+++ b/docs/release-notes/release-notes-0.18.0.md
@@ -205,6 +205,9 @@
   for blinded path payloads to allow fuzzing before LND fully supports 
   blinded payment relay.
 
+* Allow `healthcheck` package users to provide [custom callbacks](https://github.com/lightningnetwork/lnd/pull/8504)
+  which will execute whenever a healthcheck succeeds/fails.
+
 ### Logging
 * [Add the htlc amount](https://github.com/lightningnetwork/lnd/pull/8156) to
   contract court logs in case of timed-out htlcs in order to easily spot dust
diff --git a/funding/manager.go b/funding/manager.go
index 86e70c17c..5196090b7 100644
--- a/funding/manager.go
+++ b/funding/manager.go
@@ -698,7 +698,7 @@ func (f *Manager) start() error {
 	}
 
 	for _, channel := range allChannels {
-		chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
 
 		// For any channels that were in a pending state when the
 		// daemon was last connected, the Funding Manager will
@@ -1113,7 +1113,7 @@ func (f *Manager) stateStep(channel *channeldb.OpenChannel,
 	channelState channelOpeningState,
 	updateChan chan<- *lnrpc.OpenStatusUpdate) error {
 
-	chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
 	log.Debugf("Channel(%v) with ShortChanID %v has opening state %v",
 		chanID, shortChanID, channelState)
 
@@ -1273,7 +1273,7 @@ func (f *Manager) advancePendingChannelState(
 
 		// Find and close the discoverySignal for this channel such
 		// that ChannelReady messages will be processed.
-		chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
 		discoverySignal, ok := f.localDiscoverySignals.Load(chanID)
 		if ok {
 			close(discoverySignal)
@@ -1339,7 +1339,7 @@ func (f *Manager) advancePendingChannelState(
 	}
 
 	// Success, funding transaction was confirmed.
-	chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
 	log.Debugf("ChannelID(%v) is now fully confirmed! "+
 		"(shortChanID=%v)", chanID, confChannel.shortChanID)
 
@@ -2246,7 +2246,7 @@ func (f *Manager) continueFundingAccept(resCtx *reservationWithCtx,
 	// properly synchronize with the writeHandler goroutine, we add a new
 	// channel to the barriers map which will be closed once the channel is
 	// fully open.
-	channelID := lnwire.NewChanIDFromOutPoint(*outPoint)
+	channelID := lnwire.NewChanIDFromOutPoint(outPoint)
 	log.Debugf("Creating chan barrier for ChanID(%v)", channelID)
 
 	// The next message that advances the funding flow will reference the
@@ -2421,7 +2421,7 @@ func (f *Manager) fundeeProcessFundingCreated(peer lnpeer.Peer,
 	// properly synchronize with the writeHandler goroutine, we add a new
 	// channel to the barriers map which will be closed once the channel is
 	// fully open.
-	channelID := lnwire.NewChanIDFromOutPoint(fundingOut)
+	channelID := lnwire.NewChanIDFromOutPoint(&fundingOut)
 	log.Debugf("Creating chan barrier for ChanID(%v)", channelID)
 
 	fundingSigned := &lnwire.FundingSigned{}
@@ -2582,7 +2582,7 @@ func (f *Manager) funderProcessFundingSigned(peer lnpeer.Peer,
 	// process the channel confirmation fully before we receive a
 	// channel_ready message.
 	fundingPoint := resCtx.reservation.FundingOutpoint()
-	permChanID := lnwire.NewChanIDFromOutPoint(*fundingPoint)
+	permChanID := lnwire.NewChanIDFromOutPoint(fundingPoint)
 	f.localDiscoverySignals.Store(permChanID, make(chan struct{}))
 
 	// We have to store the forwardingPolicy before the reservation context
@@ -2788,7 +2788,7 @@ func (f *Manager) fundingTimeout(c *channeldb.OpenChannel,
 
 		// Create channel identifier and set the channel ID.
 		cid := newChanIdentifier(pendingID)
-		cid.setChanID(lnwire.NewChanIDFromOutPoint(c.FundingOutpoint))
+		cid.setChanID(lnwire.NewChanIDFromOutPoint(&c.FundingOutpoint))
 
 		// TODO(halseth): should this send be made
 		// reliable?
@@ -2953,7 +2953,7 @@ func (f *Manager) waitForFundingConfirmation(
 
 	fundingPoint := completeChan.FundingOutpoint
 	log.Infof("ChannelPoint(%v) is now active: ChannelID(%v)",
-		fundingPoint, lnwire.NewChanIDFromOutPoint(fundingPoint))
+		fundingPoint, lnwire.NewChanIDFromOutPoint(&fundingPoint))
 
 	// With the block height and the transaction index known, we can
 	// construct the compact chanID which is used on the network to unique
@@ -3071,7 +3071,7 @@ func (f *Manager) handleFundingConfirmation(
 	confChannel *confirmedChannel) error {
 
 	fundingPoint := completeChan.FundingOutpoint
-	chanID := lnwire.NewChanIDFromOutPoint(fundingPoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&fundingPoint)
 
 	// TODO(roasbeef): ideally persistent state update for chan above
 	// should be abstracted
@@ -3147,7 +3147,7 @@ func (f *Manager) handleFundingConfirmation(
 func (f *Manager) sendChannelReady(completeChan *channeldb.OpenChannel,
 	channel *lnwallet.LightningChannel) error {
 
-	chanID := lnwire.NewChanIDFromOutPoint(completeChan.FundingOutpoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&completeChan.FundingOutpoint)
 
 	var peerKey [33]byte
 	copy(peerKey[:], completeChan.IdentityPub.SerializeCompressed())
@@ -3374,7 +3374,7 @@ func (f *Manager) addToRouterGraph(completeChan *channeldb.OpenChannel,
 	peerAlias *lnwire.ShortChannelID,
 	ourPolicy *models.ChannelEdgePolicy) error {
 
-	chanID := lnwire.NewChanIDFromOutPoint(completeChan.FundingOutpoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&completeChan.FundingOutpoint)
 
 	fwdMinHTLC, fwdMaxHTLC := f.extractAnnounceParams(completeChan)
 
@@ -3465,7 +3465,7 @@ func (f *Manager) annAfterSixConfs(completeChan *channeldb.OpenChannel,
 		}
 
 		chanID := lnwire.NewChanIDFromOutPoint(
-			completeChan.FundingOutpoint,
+			&completeChan.FundingOutpoint,
 		)
 		pubKey := peer.PubKey()
 		log.Debugf("Sending our NodeAnnouncement for "+
@@ -3530,7 +3530,7 @@ func (f *Manager) annAfterSixConfs(completeChan *channeldb.OpenChannel,
 		}
 
 		fundingPoint := completeChan.FundingOutpoint
-		chanID := lnwire.NewChanIDFromOutPoint(fundingPoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingPoint)
 
 		log.Infof("Announcing ChannelPoint(%v), short_chan_id=%v",
 			&fundingPoint, shortChanID)
@@ -3964,7 +3964,7 @@ func (f *Manager) handleChannelReadyReceived(channel *channeldb.OpenChannel,
 	scid *lnwire.ShortChannelID, pendingChanID [32]byte,
 	updateChan chan<- *lnrpc.OpenStatusUpdate) error {
 
-	chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
 
 	// Since we've sent+received funding locked at this point, we
 	// can clean up the pending musig2 nonce state.
@@ -3981,7 +3981,7 @@ func (f *Manager) handleChannelReadyReceived(channel *channeldb.OpenChannel,
 		// we'll just return, letting the next iteration of the loop
 		// check again.
 		var defaultAlias lnwire.ShortChannelID
-		chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
 		foundAlias, _ := f.cfg.AliasManager.GetPeerAlias(chanID)
 		if foundAlias == defaultAlias {
 			return nil
@@ -4876,7 +4876,7 @@ func (f *Manager) pruneZombieReservations() {
 		log.Warnf(err.Error())
 
 		chanID := lnwire.NewChanIDFromOutPoint(
-			*resCtx.reservation.FundingOutpoint(),
+			resCtx.reservation.FundingOutpoint(),
 		)
 
 		// Create channel identifier and set the channel ID.
diff --git a/healthcheck/healthcheck.go b/healthcheck/healthcheck.go
index e72d65620..e15cbd4cb 100644
--- a/healthcheck/healthcheck.go
+++ b/healthcheck/healthcheck.go
@@ -15,6 +15,8 @@ import (
 	"github.com/lightningnetwork/lnd/ticker"
 )
 
+var noOpCallback = func() {}
+
 // Config contains configuration settings for our monitor.
 type Config struct {
 	// Checks is a set of health checks that assert that lnd has access to
@@ -96,6 +98,19 @@ func (m *Monitor) Stop() error {
 	return nil
 }
 
+// AddCheck adds a new healthcheck to our monitor.
+func (m *Monitor) AddCheck(check *Observation) error {
+
+	m.wg.Add(1)
+	go func(check *Observation) {
+		defer m.wg.Done()
+
+		check.monitor(m.cfg.Shutdown, m.quit)
+	}(check)
+
+	return nil
+}
+
 // CreateCheck is a helper function that takes a function that produces an error
 // and wraps it in a function that returns its result on an error channel.
 // We do not wait group the goroutine running our checkFunc because we expect
@@ -137,13 +152,42 @@ type Observation struct {
 	// Backoff is the amount of time we back off between retries for failed
 	// checks.
 	Backoff time.Duration
+
+	// OnSuccess is a callback which will be executed when the healthcheck
+	// succeeds. This is optional.
+	OnSuccess func()
+
+	// OnFailure is a callback which will be executed when the healthcheck
+	// fails. This is optional.
+	OnFailure func()
+}
+
+// ObservationOption describes the signature of a functional option that can be
+// used to modify the behaviour of an Observation.
+type ObservationOption func(*Observation)
+
+// WithSuccessCallback configures an observation with a callback to be fired
+// whenever the health check succeeds.
+func WithSuccessCallback(callback func()) ObservationOption {
+	return func(o *Observation) {
+		o.OnSuccess = callback
+	}
+}
+
+// WithFailureCallback configures an observation with a callback to be fired
+// whenever the health check reaches its failure threshold.
+func WithFailureCallback(callback func()) ObservationOption {
+	return func(o *Observation) {
+		o.OnFailure = callback
+	}
 }
 
 // NewObservation creates an observation.
-func NewObservation(name string, check func() error, interval,
-	timeout, backoff time.Duration, attempts int) *Observation {
+func NewObservation(name string, check func() error, interval, timeout,
+	backoff time.Duration, attempts int,
+	opts ...ObservationOption) *Observation {
 
-	return &Observation{
+	observation := &Observation{
 		Name:     name,
 		Check:    CreateCheck(check),
 		Interval: ticker.New(interval),
@@ -151,6 +195,22 @@ func NewObservation(name string, check func() error, interval,
 		Timeout:  timeout,
 		Backoff:  backoff,
 	}
+
+	// Apply each option to the observation.
+	for _, opt := range opts {
+		opt(observation)
+	}
+
+	// Ensure that we default to NO-OP callbacks.
+	if observation.OnSuccess == nil {
+		observation.OnSuccess = noOpCallback
+	}
+
+	if observation.OnFailure == nil {
+		observation.OnFailure = noOpCallback
+	}
+
+	return observation
 }
 
 // String returns a string representation of an observation.
@@ -206,6 +266,17 @@ func (o *Observation) retryCheck(quit chan struct{},
 		var err error
 		select {
 		case err = <-o.Check():
+			// If our error is nil, we have passed our health check,
+			// so we'll invoke our success callback if defined and
+			// then exit.
+			if err == nil {
+				log.Debug("invoking success callback")
+
+				// Invoke the success callback.
+				o.OnSuccess()
+
+				return false
+			}
 
 		case <-time.After(o.Timeout):
 			err = fmt.Errorf("health check: %v timed out after: "+
@@ -216,15 +287,14 @@ func (o *Observation) retryCheck(quit chan struct{},
 			return false
 		}
 
-		// If our error is nil, we have passed our health check, so we
-		// can exit.
-		if err == nil {
-			return false
-		}
-
 		// If we have reached our allowed number of attempts, this
-		// check has failed so we request shutdown.
+		// check has failed so we'll fire the on failure callback
+		// and request shutdown.
 		if count == o.Attempts {
+			log.Debug("invoking failure callback")
+
+			o.OnFailure()
+
 			shutdown("Health check: %v failed after %v "+
 				"calls", o, o.Attempts)
 			return true
diff --git a/htlcswitch/interfaces.go b/htlcswitch/interfaces.go
index efaf28fa3..ac3e10bab 100644
--- a/htlcswitch/interfaces.go
+++ b/htlcswitch/interfaces.go
@@ -221,7 +221,7 @@ type ChannelLink interface {
 	IsUnadvertised() bool
 
 	// ChannelPoint returns the channel outpoint for the channel link.
-	ChannelPoint() wire.OutPoint
+	ChannelPoint() *wire.OutPoint
 
 	// ShortChanID returns the short channel ID for the channel link. The
 	// short channel ID encodes the exact location in the main chain that
diff --git a/htlcswitch/link.go b/htlcswitch/link.go
index e80c7650c..0b1a3b160 100644
--- a/htlcswitch/link.go
+++ b/htlcswitch/link.go
@@ -1090,8 +1090,8 @@ func (l *channelLink) htlcManager() {
 	// ActiveLinkEvent. We'll also defer an inactive link notification for
 	// when the link exits to ensure that every active notification is
 	// matched by an inactive one.
-	l.cfg.NotifyActiveLink(l.ChannelPoint())
-	defer l.cfg.NotifyInactiveLinkEvent(l.ChannelPoint())
+	l.cfg.NotifyActiveLink(*l.ChannelPoint())
+	defer l.cfg.NotifyInactiveLinkEvent(*l.ChannelPoint())
 
 	// TODO(roasbeef): need to call wipe chan whenever D/C?
 
@@ -1215,8 +1215,8 @@ func (l *channelLink) htlcManager() {
 	// we can go ahead and send the active channel notification. We'll also
 	// defer the inactive notification for when the link exits to ensure
 	// that every active notification is matched by an inactive one.
-	l.cfg.NotifyActiveChannel(l.ChannelPoint())
-	defer l.cfg.NotifyInactiveChannel(l.ChannelPoint())
+	l.cfg.NotifyActiveChannel(*l.ChannelPoint())
+	defer l.cfg.NotifyInactiveChannel(*l.ChannelPoint())
 
 	// With the channel states synced, we now reset the mailbox to ensure
 	// we start processing all unacked packets in order. This is done here
@@ -1371,7 +1371,7 @@ func (l *channelLink) htlcManager() {
 			// TODO(roasbeef): remove all together
 			go func() {
 				chanPoint := l.channel.ChannelPoint()
-				l.cfg.Peer.WipeChannel(&chanPoint)
+				l.cfg.Peer.WipeChannel(chanPoint)
 			}()
 
 			return
@@ -2558,7 +2558,7 @@ func (l *channelLink) PeerPubKey() [33]byte {
 
 // ChannelPoint returns the channel outpoint for the channel link.
 // NOTE: Part of the ChannelLink interface.
-func (l *channelLink) ChannelPoint() wire.OutPoint {
+func (l *channelLink) ChannelPoint() *wire.OutPoint {
 	return l.channel.ChannelPoint()
 }
 
diff --git a/htlcswitch/mock.go b/htlcswitch/mock.go
index 6770c949f..e995b3ed7 100644
--- a/htlcswitch/mock.go
+++ b/htlcswitch/mock.go
@@ -907,10 +907,7 @@ func (f *mockChannelLink) PeerPubKey() [33]byte {
 	return f.peer.PubKey()
 }
 
-func (f *mockChannelLink) ChannelPoint() wire.OutPoint {
-	return wire.OutPoint{}
-}
-
+func (f *mockChannelLink) ChannelPoint() *wire.OutPoint                 { return &wire.OutPoint{} }
 func (f *mockChannelLink) Stop()                                        {}
 func (f *mockChannelLink) EligibleToForward() bool                      { return f.eligible }
 func (f *mockChannelLink) MayAddOutgoingHtlc(lnwire.MilliSatoshi) error { return nil }
diff --git a/htlcswitch/switch.go b/htlcswitch/switch.go
index b82e410a1..0e2101027 100644
--- a/htlcswitch/switch.go
+++ b/htlcswitch/switch.go
@@ -621,7 +621,7 @@ func (s *Switch) UpdateForwardingPolicies(
 
 	// Update each link in chanPolicies.
 	for targetLink, policy := range chanPolicies {
-		cid := lnwire.NewChanIDFromOutPoint(targetLink)
+		cid := lnwire.NewChanIDFromOutPoint(&targetLink)
 
 		link, ok := s.linkIndex[cid]
 		if !ok {
@@ -1469,7 +1469,7 @@ func (s *Switch) failAddPacket(packet *htlcPacket, failure *LinkError) error {
 
 	log.Error(failure.Error())
 
-	// Create a failure packet for this htlc. The full set of
+	// Create a failure packet for this htlc. The the full set of
 	// information about the htlc failure is included so that they can
 	// be included in link failure notifications.
 	failPkt := &htlcPacket{
@@ -1797,7 +1797,7 @@ out:
 		// relevant link (if it exists) so the channel can be
 		// cooperatively closed (if possible).
 		case req := <-s.chanCloseRequests:
-			chanID := lnwire.NewChanIDFromOutPoint(*req.ChanPoint)
+			chanID := lnwire.NewChanIDFromOutPoint(req.ChanPoint)
 
 			s.indexMtx.RLock()
 			link, ok := s.linkIndex[chanID]
diff --git a/invoices/invoice_expiry_watcher.go b/invoices/invoice_expiry_watcher.go
index 7c5539636..f16a7a18d 100644
--- a/invoices/invoice_expiry_watcher.go
+++ b/invoices/invoice_expiry_watcher.go
@@ -129,7 +129,7 @@ func NewInvoiceExpiryWatcher(clock clock.Clock,
 	}
 }
 
-// Start starts the subscription handler and the main loop. Start() will
+// Start starts the the subscription handler and the main loop. Start() will
 // return with error if InvoiceExpiryWatcher is already started. Start()
 // expects a cancellation function passed that will be use to cancel expired
 // invoices by their payment hash.
diff --git a/kvdb/etcd/stm.go b/kvdb/etcd/stm.go
index 5b3a9a977..94a401f4b 100644
--- a/kvdb/etcd/stm.go
+++ b/kvdb/etcd/stm.go
@@ -1170,7 +1170,7 @@ func (s *stm) Rollback() {
 }
 
 // rollback will reset the read and write sets. If clearReadSet is false we'll
-// only reset the write set.
+// only reset the the write set.
 func (s *stm) rollback(clearReadSet bool) {
 	if clearReadSet {
 		s.rset.clear()
diff --git a/lnrpc/invoicesrpc/addinvoice.go b/lnrpc/invoicesrpc/addinvoice.go
index 3e20ebf62..8b38b76a2 100644
--- a/lnrpc/invoicesrpc/addinvoice.go
+++ b/lnrpc/invoicesrpc/addinvoice.go
@@ -731,7 +731,7 @@ func shouldIncludeChannel(cfg *SelectHopHintsCfg,
 	}
 
 	chanID := lnwire.NewChanIDFromOutPoint(
-		channel.FundingOutpoint,
+		&channel.FundingOutpoint,
 	)
 
 	hopHintInfo := newHopHintInfo(channel, cfg.IsChannelActive(chanID))
diff --git a/lnrpc/signrpc/signer.pb.go b/lnrpc/signrpc/signer.pb.go
index 9b23b7a40..ca79e36df 100644
--- a/lnrpc/signrpc/signer.pb.go
+++ b/lnrpc/signrpc/signer.pb.go
@@ -1231,7 +1231,7 @@ type MuSig2CombineKeysRequest struct {
 	// session. The list will always be sorted lexicographically internally. This
 	// must include the local key which is described by the above key_loc.
 	AllSignerPubkeys [][]byte `protobuf:"bytes,1,rep,name=all_signer_pubkeys,json=allSignerPubkeys,proto3" json:"all_signer_pubkeys,omitempty"`
-	// A series of optional generic tweaks to be applied to the aggregated
+	// A series of optional generic tweaks to be applied to the the aggregated
 	// public key.
 	Tweaks []*TweakDesc `protobuf:"bytes,2,rep,name=tweaks,proto3" json:"tweaks,omitempty"`
 	// An optional taproot specific tweak that must be specified if the MuSig2
@@ -1391,7 +1391,7 @@ type MuSig2SessionRequest struct {
 	// An optional list of all public nonces of other signing participants that
 	// might already be known.
 	OtherSignerPublicNonces [][]byte `protobuf:"bytes,3,rep,name=other_signer_public_nonces,json=otherSignerPublicNonces,proto3" json:"other_signer_public_nonces,omitempty"`
-	// A series of optional generic tweaks to be applied to the aggregated
+	// A series of optional generic tweaks to be applied to the the aggregated
 	// public key.
 	Tweaks []*TweakDesc `protobuf:"bytes,4,rep,name=tweaks,proto3" json:"tweaks,omitempty"`
 	// An optional taproot specific tweak that must be specified if the MuSig2
diff --git a/lnrpc/signrpc/signer.proto b/lnrpc/signrpc/signer.proto
index 28a3295dd..a210f2c71 100644
--- a/lnrpc/signrpc/signer.proto
+++ b/lnrpc/signrpc/signer.proto
@@ -487,7 +487,7 @@ message MuSig2CombineKeysRequest {
     repeated bytes all_signer_pubkeys = 1;
 
     /*
-    A series of optional generic tweaks to be applied to the aggregated
+    A series of optional generic tweaks to be applied to the the aggregated
     public key.
     */
     repeated TweakDesc tweaks = 2;
@@ -551,7 +551,7 @@ message MuSig2SessionRequest {
     repeated bytes other_signer_public_nonces = 3;
 
     /*
-    A series of optional generic tweaks to be applied to the aggregated
+    A series of optional generic tweaks to be applied to the the aggregated
     public key.
     */
     repeated TweakDesc tweaks = 4;
diff --git a/lnrpc/signrpc/signer.swagger.json b/lnrpc/signrpc/signer.swagger.json
index 4a7ffa8d1..2668d6cd2 100644
--- a/lnrpc/signrpc/signer.swagger.json
+++ b/lnrpc/signrpc/signer.swagger.json
@@ -509,7 +509,7 @@
           "items": {
             "$ref": "#/definitions/signrpcTweakDesc"
           },
-          "description": "A series of optional generic tweaks to be applied to the aggregated\npublic key."
+          "description": "A series of optional generic tweaks to be applied to the the aggregated\npublic key."
         },
         "taproot_tweak": {
           "$ref": "#/definitions/signrpcTaprootTweakDesc",
@@ -627,7 +627,7 @@
           "items": {
             "$ref": "#/definitions/signrpcTweakDesc"
           },
-          "description": "A series of optional generic tweaks to be applied to the aggregated\npublic key."
+          "description": "A series of optional generic tweaks to be applied to the the aggregated\npublic key."
         },
         "taproot_tweak": {
           "$ref": "#/definitions/signrpcTaprootTweakDesc",
diff --git a/lnwallet/chainfee/rates.go b/lnwallet/chainfee/rates.go
index 6496b39c0..0bdb8a17a 100644
--- a/lnwallet/chainfee/rates.go
+++ b/lnwallet/chainfee/rates.go
@@ -13,7 +13,7 @@ const (
 	FeePerKwFloor SatPerKWeight = 253
 
 	// AbsoluteFeePerKwFloor is the lowest fee rate in sat/kw of a
-	// transaction that we should ever _create_. This is the equivalent
+	// transaction that we should ever _create_. This is the the equivalent
 	// of 1 sat/byte in sat/kw.
 	AbsoluteFeePerKwFloor SatPerKWeight = 250
 )
diff --git a/lnwallet/chancloser/chancloser.go b/lnwallet/chancloser/chancloser.go
index bc9a1c903..b77e175e6 100644
--- a/lnwallet/chancloser/chancloser.go
+++ b/lnwallet/chancloser/chancloser.go
@@ -268,12 +268,11 @@ func NewChanCloser(cfg ChanCloseCfg, deliveryScript []byte,
 	idealFeePerKw chainfee.SatPerKWeight, negotiationHeight uint32,
 	closeReq *htlcswitch.ChanClose, locallyInitiated bool) *ChanCloser {
 
-	chanPoint := cfg.Channel.ChannelPoint()
-	cid := lnwire.NewChanIDFromOutPoint(chanPoint)
+	cid := lnwire.NewChanIDFromOutPoint(cfg.Channel.ChannelPoint())
 	return &ChanCloser{
 		closeReq:            closeReq,
 		state:               closeIdle,
-		chanPoint:           chanPoint,
+		chanPoint:           *cfg.Channel.ChannelPoint(),
 		cid:                 cid,
 		cfg:                 cfg,
 		negotiationHeight:   negotiationHeight,
diff --git a/lnwallet/chancloser/interface.go b/lnwallet/chancloser/interface.go
index 40b81efb4..4daf5ac34 100644
--- a/lnwallet/chancloser/interface.go
+++ b/lnwallet/chancloser/interface.go
@@ -29,7 +29,7 @@ type CoopFeeEstimator interface {
 // closing process.
 type Channel interface { //nolint:interfacebloat
 	// ChannelPoint returns the channel point of the target channel.
-	ChannelPoint() wire.OutPoint
+	ChannelPoint() *wire.OutPoint
 
 	// MarkCoopBroadcasted persistently marks that the channel close
 	// transaction has been broadcast.
diff --git a/lnwallet/chanfunding/coin_select.go b/lnwallet/chanfunding/coin_select.go
index 4cf50c574..5594d26b1 100644
--- a/lnwallet/chanfunding/coin_select.go
+++ b/lnwallet/chanfunding/coin_select.go
@@ -307,7 +307,7 @@ func CoinSelectSubtractFees(feeRate chainfee.SatPerKWeight, amt,
 	outputAmt := totalSat - requiredFeeNoChange
 	changeAmt := btcutil.Amount(0)
 
-	// If the output is too small after subtracting the fee, the coin
+	// If the the output is too small after subtracting the fee, the coin
 	// selection cannot be performed with an amount this small.
 	if outputAmt < dustLimit {
 		return nil, 0, 0, fmt.Errorf("output amount(%v) after "+
diff --git a/lnwallet/channel.go b/lnwallet/channel.go
index a34384876..5e6af76c8 100644
--- a/lnwallet/channel.go
+++ b/lnwallet/channel.go
@@ -1260,6 +1260,9 @@ type LightningChannel struct {
 
 	isClosed bool
 
+	// ChanPoint is the funding outpoint of this channel.
+	ChanPoint *wire.OutPoint
+
 	// sigPool is a pool of workers that are capable of signing and
 	// validating signatures in parallel. This is utilized as an
 	// optimization to void serially signing or validating the HTLC
@@ -1409,6 +1412,7 @@ func NewLightningChannel(signer input.Signer,
 		commitBuilder:        NewCommitmentBuilder(state),
 		localUpdateLog:       localUpdateLog,
 		remoteUpdateLog:      remoteUpdateLog,
+		ChanPoint:            &state.FundingOutpoint,
 		Capacity:             state.Capacity,
 		taprootNonceProducer: taprootNonceProducer,
 		log:                  build.NewPrefixLog(logPrefix, walletLog),
@@ -3560,7 +3564,7 @@ func (lc *LightningChannel) createCommitDiff(
 	// used on the wire to identify this channel. We'll use this shortly
 	// when recording the exact CommitSig message that we'll be sending
 	// out.
-	chanID := lnwire.NewChanIDFromOutPoint(lc.channelState.FundingOutpoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&lc.channelState.FundingOutpoint)
 
 	var (
 		logUpdates        []channeldb.LogUpdate
@@ -3680,7 +3684,7 @@ func (lc *LightningChannel) createCommitDiff(
 		Commitment: *diskCommit,
 		CommitSig: &lnwire.CommitSig{
 			ChanID: lnwire.NewChanIDFromOutPoint(
-				lc.channelState.FundingOutpoint,
+				&lc.channelState.FundingOutpoint,
 			),
 			CommitSig: commitSig,
 			HtlcSigs:  htlcSigs,
@@ -3698,7 +3702,7 @@ func (lc *LightningChannel) createCommitDiff(
 func (lc *LightningChannel) getUnsignedAckedUpdates() []channeldb.LogUpdate {
 	// First, we need to convert the funding outpoint into the ID that's
 	// used on the wire to identify this channel.
-	chanID := lnwire.NewChanIDFromOutPoint(lc.channelState.FundingOutpoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&lc.channelState.FundingOutpoint)
 
 	// Fetch the last remote update that we have signed for.
 	lastRemoteCommitted := lc.remoteCommitChain.tail().theirMessageIndex
@@ -4543,7 +4547,7 @@ func (lc *LightningChannel) ProcessChanSyncMsg(
 			case err == nil:
 				commitSig := &lnwire.CommitSig{
 					ChanID: lnwire.NewChanIDFromOutPoint(
-						lc.channelState.FundingOutpoint,
+						&lc.channelState.FundingOutpoint,
 					),
 					CommitSig:  newCommit.CommitSig,
 					HtlcSigs:   newCommit.HtlcSigs,
@@ -5571,7 +5575,7 @@ func (lc *LightningChannel) RevokeCurrentCommitment() (*lnwire.RevokeAndAck,
 		len(unsignedAckedUpdates))
 
 	revocationMsg.ChanID = lnwire.NewChanIDFromOutPoint(
-		lc.channelState.FundingOutpoint,
+		&lc.channelState.FundingOutpoint,
 	)
 
 	return revocationMsg, newCommitment.Htlcs, finalHtlcs, nil
@@ -5638,7 +5642,7 @@ func (lc *LightningChannel) ReceiveRevocation(revMsg *lnwire.RevokeAndAck) (
 	localChainTail := lc.localCommitChain.tail().height
 
 	source := lc.ShortChanID()
-	chanID := lnwire.NewChanIDFromOutPoint(lc.channelState.FundingOutpoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&lc.channelState.FundingOutpoint)
 
 	// Determine the set of htlcs that can be forwarded as a result of
 	// having received the revocation. We will simultaneously construct the
@@ -6426,8 +6430,8 @@ func (lc *LightningChannel) ReceiveFailHTLC(htlcIndex uint64, reason []byte,
 // ChannelPoint returns the outpoint of the original funding transaction which
 // created this active channel. This outpoint is used throughout various
 // subsystems to uniquely identify an open channel.
-func (lc *LightningChannel) ChannelPoint() wire.OutPoint {
-	return lc.channelState.FundingOutpoint
+func (lc *LightningChannel) ChannelPoint() *wire.OutPoint {
+	return &lc.channelState.FundingOutpoint
 }
 
 // ShortChanID returns the short channel ID for the channel. The short channel
@@ -8517,7 +8521,7 @@ func (lc *LightningChannel) generateRevocation(height uint64) (*lnwire.RevokeAnd
 
 	revocationMsg.NextRevocationKey = input.ComputeCommitmentPoint(nextCommitSecret[:])
 	revocationMsg.ChanID = lnwire.NewChanIDFromOutPoint(
-		lc.channelState.FundingOutpoint,
+		&lc.channelState.FundingOutpoint,
 	)
 
 	// If this is a taproot channel, then we also need to generate the
diff --git a/lnwire/channel_id.go b/lnwire/channel_id.go
index 1615eb747..0a9e08226 100644
--- a/lnwire/channel_id.go
+++ b/lnwire/channel_id.go
@@ -40,7 +40,7 @@ func (c ChannelID) String() string {
 // usable within the network. In order to convert the OutPoint into a ChannelID,
 // we XOR the lower 2-bytes of the txid within the OutPoint with the big-endian
 // serialization of the Index of the OutPoint, truncated to 2-bytes.
-func NewChanIDFromOutPoint(op wire.OutPoint) ChannelID {
+func NewChanIDFromOutPoint(op *wire.OutPoint) ChannelID {
 	// First we'll copy the txid of the outpoint into our channel ID slice.
 	var cid ChannelID
 	copy(cid[:], op.Hash[:])
@@ -85,7 +85,7 @@ func (c *ChannelID) GenPossibleOutPoints() [MaxFundingTxOutputs]wire.OutPoint {
 // IsChanPoint returns true if the OutPoint passed corresponds to the target
 // ChannelID.
 func (c ChannelID) IsChanPoint(op *wire.OutPoint) bool {
-	candidateCid := NewChanIDFromOutPoint(*op)
+	candidateCid := NewChanIDFromOutPoint(op)
 
 	return candidateCid == c
 }
diff --git a/netann/chan_status_manager.go b/netann/chan_status_manager.go
index f536d7228..7ee543d2a 100644
--- a/netann/chan_status_manager.go
+++ b/netann/chan_status_manager.go
@@ -391,7 +391,7 @@ func (m *ChanStatusManager) processEnableRequest(outpoint wire.OutPoint,
 
 	// Quickly check to see if the requested channel is active within the
 	// htlcswitch and return an error if it isn't.
-	chanID := lnwire.NewChanIDFromOutPoint(outpoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&outpoint)
 	if !m.cfg.IsChannelActive(chanID) {
 		return ErrEnableInactiveChan
 	}
@@ -531,7 +531,7 @@ func (m *ChanStatusManager) markPendingInactiveChannels() {
 		// If our bookkeeping shows the channel as active, sample the
 		// htlcswitch to see if it believes the link is also active. If
 		// so, we will skip marking it as ChanStatusPendingDisabled.
-		chanID := lnwire.NewChanIDFromOutPoint(c.FundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&c.FundingOutpoint)
 		if m.cfg.IsChannelActive(chanID) {
 			continue
 		}
diff --git a/peer/brontide.go b/peer/brontide.go
index 07fb5731e..189fb1660 100644
--- a/peer/brontide.go
+++ b/peer/brontide.go
@@ -834,7 +834,7 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
 				}
 
 				chanID := lnwire.NewChanIDFromOutPoint(
-					dbChan.FundingOutpoint,
+					&dbChan.FundingOutpoint,
 				)
 
 				// Fetch the second commitment point to send in
@@ -870,7 +870,7 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
 			return nil, err
 		}
 
-		chanPoint := dbChan.FundingOutpoint
+		chanPoint := &dbChan.FundingOutpoint
 
 		chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
 
@@ -932,9 +932,7 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
 		// need to fetch its current link-layer forwarding policy from
 		// the database.
 		graph := p.cfg.ChannelGraph
-		info, p1, p2, err := graph.FetchChannelEdgesByOutpoint(
-			&chanPoint,
-		)
+		info, p1, p2, err := graph.FetchChannelEdgesByOutpoint(chanPoint)
 		if err != nil && err != channeldb.ErrEdgeNotFound {
 			return nil, err
 		}
@@ -1022,7 +1020,7 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
 			}
 
 			chanID := lnwire.NewChanIDFromOutPoint(
-				lnChan.State().FundingOutpoint,
+				&lnChan.State().FundingOutpoint,
 			)
 
 			p.activeChanCloses[chanID] = chanCloser
@@ -1044,14 +1042,14 @@ func (p *Brontide) loadActiveChannels(chans []*channeldb.OpenChannel) (
 
 		// Subscribe to the set of on-chain events for this channel.
 		chainEvents, err := p.cfg.ChainArb.SubscribeChannelEvents(
-			chanPoint,
+			*chanPoint,
 		)
 		if err != nil {
 			return nil, err
 		}
 
 		err = p.addLink(
-			&chanPoint, lnChan, forwardingPolicy, chainEvents,
+			chanPoint, lnChan, forwardingPolicy, chainEvents,
 			true, shutdownMsg,
 		)
 		if err != nil {
@@ -1146,7 +1144,7 @@ func (p *Brontide) addLink(chanPoint *wire.OutPoint,
 	// links going by the same channel id. If one is found, we'll shut it
 	// down to ensure that the mailboxes are only ever under the control of
 	// one link.
-	chanID := lnwire.NewChanIDFromOutPoint(*chanPoint)
+	chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
 	p.cfg.Switch.RemoveLink(chanID)
 
 	// With the channel link created, we'll now notify the htlc switch so
@@ -2817,16 +2815,16 @@ func chooseDeliveryScript(upfront,
 		return requested, nil
 	}
 
-	// If an upfront shutdown script was provided, and the user did not
-	// request a custom shutdown script, return the upfront address.
+	// If an upfront shutdown script was provided, and the user did not request
+	// a custom shutdown script, return the upfront address.
 	if len(requested) == 0 {
 		return upfront, nil
 	}
 
 	// If both an upfront shutdown script and a custom close script were
 	// provided, error if the user provided shutdown script does not match
-	// the upfront shutdown script (because closing out to a different
-	// script would violate upfront shutdown).
+	// the upfront shutdown script (because closing out to a different script
+	// would violate upfront shutdown).
 	if !bytes.Equal(upfront, requested) {
 		return nil, chancloser.ErrUpfrontShutdownScriptMismatch
 	}
@@ -2914,7 +2912,7 @@ func (p *Brontide) restartCoopClose(lnChan *lnwallet.LightningChannel) (
 	// This does not need a mutex even though it is in a different
 	// goroutine since this is done before the channelManager goroutine is
 	// created.
-	chanID := lnwire.NewChanIDFromOutPoint(c.FundingOutpoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&c.FundingOutpoint)
 	p.activeChanCloses[chanID] = chanCloser
 
 	// Create the Shutdown message.
@@ -2978,7 +2976,7 @@ func (p *Brontide) createChanCloser(channel *lnwallet.LightningChannel,
 // handleLocalCloseReq kicks-off the workflow to execute a cooperative or
 // forced unilateral closure of the channel initiated by a local subsystem.
 func (p *Brontide) handleLocalCloseReq(req *htlcswitch.ChanClose) {
-	chanID := lnwire.NewChanIDFromOutPoint(*req.ChanPoint)
+	chanID := lnwire.NewChanIDFromOutPoint(req.ChanPoint)
 
 	channel, ok := p.activeChannels.Load(chanID)
 
@@ -3101,7 +3099,7 @@ type linkFailureReport struct {
 func (p *Brontide) handleLinkFailure(failure linkFailureReport) {
 	// Retrieve the channel from the map of active channels. We do this to
 	// have access to it even after WipeChannel remove it from the map.
-	chanID := lnwire.NewChanIDFromOutPoint(failure.chanPoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&failure.chanPoint)
 	lnChan, _ := p.activeChannels.Load(chanID)
 
 	// We begin by wiping the link, which will remove it from the switch,
@@ -3211,7 +3209,7 @@ func (p *Brontide) finalizeChanClosure(chanCloser *chancloser.ChanCloser) {
 
 	// First, we'll clear all indexes related to the channel in question.
 	chanPoint := chanCloser.Channel().ChannelPoint()
-	p.WipeChannel(&chanPoint)
+	p.WipeChannel(chanPoint)
 
 	// Also clear the activeChanCloses map of this channel.
 	cid := lnwire.NewChanIDFromOutPoint(chanPoint)
@@ -3249,7 +3247,7 @@ func (p *Brontide) finalizeChanClosure(chanCloser *chancloser.ChanCloser) {
 	}
 
 	go WaitForChanToClose(chanCloser.NegotiationHeight(), notifier, errChan,
-		&chanPoint, &closingTxid, closingTx.TxOut[0].PkScript, func() {
+		chanPoint, &closingTxid, closingTx.TxOut[0].PkScript, func() {
 			// Respond to the local subsystem which requested the
 			// channel closure.
 			if closeReq != nil {
@@ -3304,7 +3302,7 @@ func WaitForChanToClose(bestHeight uint32, notifier chainntnfs.ChainNotifier,
 // WipeChannel removes the passed channel point from all indexes associated with
 // the peer and the switch.
 func (p *Brontide) WipeChannel(chanPoint *wire.OutPoint) {
-	chanID := lnwire.NewChanIDFromOutPoint(*chanPoint)
+	chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
 
 	p.activeChannels.Delete(chanID)
 
@@ -3883,7 +3881,7 @@ func (p *Brontide) attachChannelEventSubscription() error {
 // updateNextRevocation updates the existing channel's next revocation if it's
 // nil.
 func (p *Brontide) updateNextRevocation(c *channeldb.OpenChannel) error {
-	chanPoint := c.FundingOutpoint
+	chanPoint := &c.FundingOutpoint
 	chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
 
 	// Read the current channel.
@@ -3927,7 +3925,7 @@ func (p *Brontide) updateNextRevocation(c *channeldb.OpenChannel) error {
 // takes a `channeldb.OpenChannel`, creates a `lnwallet.LightningChannel` from
 // it and assembles it with a channel link.
 func (p *Brontide) addActiveChannel(c *lnpeer.NewChannel) error {
-	chanPoint := c.FundingOutpoint
+	chanPoint := &c.FundingOutpoint
 	chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
 
 	// If we've reached this point, there are two possible scenarios.  If
@@ -3962,7 +3960,7 @@ func (p *Brontide) addActiveChannel(c *lnpeer.NewChannel) error {
 
 	// Next, we'll assemble a ChannelLink along with the necessary items it
 	// needs to function.
-	chainEvents, err := p.cfg.ChainArb.SubscribeChannelEvents(chanPoint)
+	chainEvents, err := p.cfg.ChainArb.SubscribeChannelEvents(*chanPoint)
 	if err != nil {
 		return fmt.Errorf("unable to subscribe to chain events: %w",
 			err)
@@ -3978,7 +3976,7 @@ func (p *Brontide) addActiveChannel(c *lnpeer.NewChannel) error {
 
 	// Create the link and add it to the switch.
 	err = p.addLink(
-		&chanPoint, lnChan, initialPolicy, chainEvents,
+		chanPoint, lnChan, initialPolicy, chainEvents,
 		shouldReestablish, fn.None[lnwire.Shutdown](),
 	)
 	if err != nil {
@@ -3994,7 +3992,7 @@ func (p *Brontide) addActiveChannel(c *lnpeer.NewChannel) error {
 // or init the next revocation for it.
 func (p *Brontide) handleNewActiveChannel(req *newChannelMsg) {
 	newChan := req.channel
-	chanPoint := newChan.FundingOutpoint
+	chanPoint := &newChan.FundingOutpoint
 	chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
 
 	// Only update RemoteNextRevocation if the channel is in the
diff --git a/queue/priority_queue.go b/queue/priority_queue.go
index 8f120a767..06485e531 100644
--- a/queue/priority_queue.go
+++ b/queue/priority_queue.go
@@ -29,7 +29,7 @@ func (pq priorityQueue) Swap(i, j int) {
 	pq[i], pq[j] = pq[j], pq[i]
 }
 
-// Push adds a new item the priorityQueue.
+// Push adds a new item the the priorityQueue.
 func (pq *priorityQueue) Push(x interface{}) {
 	item := x.(PriorityQueueItem)
 	*pq = append(*pq, item)
diff --git a/rpcserver.go b/rpcserver.go
index 8c3d6b05c..d55c97257 100644
--- a/rpcserver.go
+++ b/rpcserver.go
@@ -2580,9 +2580,7 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
 			//  * so only need to grab from database
 			peer.WipeChannel(&channel.FundingOutpoint)
 		} else {
-			chanID := lnwire.NewChanIDFromOutPoint(
-				channel.FundingOutpoint,
-			)
+			chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
 			r.server.htlcSwitch.RemoveLink(chanID)
 		}
 
@@ -2636,7 +2634,7 @@ func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
 
 		// If the link is not known by the switch, we cannot gracefully close
 		// the channel.
-		channelID := lnwire.NewChanIDFromOutPoint(*chanPoint)
+		channelID := lnwire.NewChanIDFromOutPoint(chanPoint)
 		if _, err := r.server.htlcSwitch.GetLink(channelID); err != nil {
 			rpcsLog.Debugf("Trying to non-force close offline channel with "+
 				"chan_point=%v", chanPoint)
@@ -2955,7 +2953,7 @@ func (r *rpcServer) GetInfo(_ context.Context,
 
 	var activeChannels uint32
 	for _, channel := range openChannels {
-		chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
 		if r.server.htlcSwitch.HasActiveLink(chanID) {
 			activeChannels++
 		}
@@ -4223,7 +4221,7 @@ func (r *rpcServer) ListChannels(ctx context.Context,
 			peerOnline = true
 		}
 
-		channelID := lnwire.NewChanIDFromOutPoint(chanPoint)
+		channelID := lnwire.NewChanIDFromOutPoint(&chanPoint)
 		var linkActive bool
 		if link, err := r.server.htlcSwitch.GetLink(channelID); err == nil {
 			// A channel is only considered active if it is known
@@ -4315,7 +4313,7 @@ func createRPCOpenChannel(r *rpcServer, dbChannel *channeldb.OpenChannel,
 	nodePub := dbChannel.IdentityPub
 	nodeID := hex.EncodeToString(nodePub.SerializeCompressed())
 	chanPoint := dbChannel.FundingOutpoint
-	chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&chanPoint)
 
 	// As this is required for display purposes, we'll calculate
 	// the weight of the commitment transaction. We also add on the
diff --git a/sample-lnd.conf b/sample-lnd.conf
index dd538b07a..abc0ea80f 100644
--- a/sample-lnd.conf
+++ b/sample-lnd.conf
@@ -1205,7 +1205,7 @@
 ; `Payment_In_FLIGHT` will be sent for compatibility concerns.
 ; routerrpc.usestatusinitiated=false
 
-; Defines the maximum duration that the probing fee estimation is allowed to
+; Defines the the maximum duration that the probing fee estimation is allowed to
 ; take.
 ; routerrpc.fee-estimation-timeout=1m
 
diff --git a/server.go b/server.go
index a089a2238..32dbc9cf0 100644
--- a/server.go
+++ b/server.go
@@ -1164,7 +1164,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
 		FeeEstimator: cc.FeeEstimator,
 		ChainIO:      cc.ChainIO,
 		MarkLinkInactive: func(chanPoint wire.OutPoint) error {
-			chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
+			chanID := lnwire.NewChanIDFromOutPoint(&chanPoint)
 			s.htlcSwitch.RemoveLink(chanID)
 			return nil
 		},
@@ -1421,7 +1421,7 @@ func newServer(cfg *Config, listenAddrs []net.Addr,
 			return s.chainArb.WatchNewChannel(channel)
 		},
 		ReportShortChanID: func(chanPoint wire.OutPoint) error {
-			cid := lnwire.NewChanIDFromOutPoint(chanPoint)
+			cid := lnwire.NewChanIDFromOutPoint(&chanPoint)
 			return s.htlcSwitch.UpdateShortChanID(cid)
 		},
 		RequiredRemoteChanReserve: func(chanAmt,
@@ -4633,7 +4633,7 @@ func (s *server) applyChannelUpdate(update *lnwire.ChannelUpdate,
 		defaultAlias lnwire.ShortChannelID
 	)
 
-	chanID := lnwire.NewChanIDFromOutPoint(*op)
+	chanID := lnwire.NewChanIDFromOutPoint(op)
 
 	// Fetch the peer's alias from the lnwire.ChannelID so it can be used
 	// in the ChannelUpdate if it hasn't been announced yet.
diff --git a/sweep/sweeper.go b/sweep/sweeper.go
index ebdce7d1b..49e9e0994 100644
--- a/sweep/sweeper.go
+++ b/sweep/sweeper.go
@@ -292,7 +292,7 @@ type UtxoSweeperConfig struct {
 	// sweeps, how many blocks to wait before retrying to sweep.
 	NextAttemptDeltaFunc func(int) int32
 
-	// MaxFeeRate is the maximum fee rate allowed within the
+	// MaxFeeRate is the the maximum fee rate allowed within the
 	// UtxoSweeper.
 	MaxFeeRate chainfee.SatPerVByte
 
@@ -794,7 +794,7 @@ func (s *UtxoSweeper) createInputClusters() []inputCluster {
 	// if the locktime is equal.
 	lockTimeClusters, nonLockTimeInputs := s.clusterByLockTime(inputs)
 
-	// Cluster the remaining inputs by sweep fee rate.
+	// Cluster the the remaining inputs by sweep fee rate.
 	feeClusters := s.clusterBySweepFeeRate(nonLockTimeInputs)
 
 	// Since the inputs that we clustered by fee rate don't commit to a
@@ -1481,7 +1481,7 @@ func DefaultNextAttemptDeltaFunc(attempts int) int32 {
 	return 1 + rand.Int31n(1<<uint(attempts-1))
 }
 
-// ListSweeps returns a list of the sweeps recorded by the sweep store.
+// ListSweeps returns a list of the the sweeps recorded by the sweep store.
 func (s *UtxoSweeper) ListSweeps() ([]chainhash.Hash, error) {
 	return s.cfg.Store.ListSweeps()
 }
diff --git a/watchtower/wtclient/manager.go b/watchtower/wtclient/manager.go
index 01a9fa01e..f1cae979f 100644
--- a/watchtower/wtclient/manager.go
+++ b/watchtower/wtclient/manager.go
@@ -780,7 +780,7 @@ func (m *Manager) handleChannelCloses(chanSub subscribe.Subscription) {
 			}
 
 			chanID := lnwire.NewChanIDFromOutPoint(
-				event.CloseSummary.ChanPoint,
+				&event.CloseSummary.ChanPoint,
 			)
 
 			log.Debugf("Received ClosedChannelEvent for "+
diff --git a/watchtower/wtserver/server.go b/watchtower/wtserver/server.go
index 01234f9d0..a88d8db0e 100644
--- a/watchtower/wtserver/server.go
+++ b/watchtower/wtserver/server.go
@@ -33,7 +33,7 @@ type Config struct {
 	// storing state updates.
 	DB DB
 
-	// NodeKeyECDH is the ECDH capable wrapper of the key to be used in
+	// NodeKeyECDH is the the ECDH capable wrapper of the key to be used in
 	// accepting new brontide connections.
 	NodeKeyECDH keychain.SingleKeyECDH
 


Test patch:
diff --git a/channeldb/db_test.go b/channeldb/db_test.go
index a954f2828..62e720407 100644
--- a/channeldb/db_test.go
+++ b/channeldb/db_test.go
@@ -140,7 +140,7 @@ func TestFetchClosedChannelForID(t *testing.T) {
 		state.FundingOutpoint.Index = i
 
 		// We calculate the ChannelID and use it to fetch the summary.
-		cid := lnwire.NewChanIDFromOutPoint(state.FundingOutpoint)
+		cid := lnwire.NewChanIDFromOutPoint(&state.FundingOutpoint)
 		fetchedSummary, err := cdb.FetchClosedChannelForID(cid)
 		if err != nil {
 			t.Fatalf("unable to fetch close summary: %v", err)
@@ -158,7 +158,7 @@ func TestFetchClosedChannelForID(t *testing.T) {
 	// As a final test we make sure that we get ErrClosedChannelNotFound
 	// for a ChannelID we didn't add to the DB.
 	state.FundingOutpoint.Index++
-	cid := lnwire.NewChanIDFromOutPoint(state.FundingOutpoint)
+	cid := lnwire.NewChanIDFromOutPoint(&state.FundingOutpoint)
 	_, err = cdb.FetchClosedChannelForID(cid)
 	if err != ErrClosedChannelNotFound {
 		t.Fatalf("expected ErrClosedChannelNotFound, instead got: %v", err)
@@ -240,7 +240,7 @@ func TestFetchChannel(t *testing.T) {
 	require.Equal(t, channelState, dbChannel)
 
 	// Next, attempt to fetch the channel by its channel ID.
-	chanID := lnwire.NewChanIDFromOutPoint(channelState.FundingOutpoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&channelState.FundingOutpoint)
 	dbChannel, err = cdb.FetchChannelByID(nil, chanID)
 	require.NoError(t, err, "unable to fetch channel")
 
@@ -259,7 +259,7 @@ func TestFetchChannel(t *testing.T) {
 	_, err = cdb.FetchChannel(nil, channelState2.FundingOutpoint)
 	require.ErrorIs(t, err, ErrChannelNotFound)
 
-	chanID2 := lnwire.NewChanIDFromOutPoint(channelState2.FundingOutpoint)
+	chanID2 := lnwire.NewChanIDFromOutPoint(&channelState2.FundingOutpoint)
 	_, err = cdb.FetchChannelByID(nil, chanID2)
 	require.ErrorIs(t, err, ErrChannelNotFound)
 }
diff --git a/channeldb/forwarding_package_test.go b/channeldb/forwarding_package_test.go
index d796c6d51..1aabe7614 100644
--- a/channeldb/forwarding_package_test.go
+++ b/channeldb/forwarding_package_test.go
@@ -141,7 +141,7 @@ func checkPkgFilterEncodeDecode(t *testing.T, i uint16, f *channeldb.PkgFilter)
 }
 
 var (
-	chanID = lnwire.NewChanIDFromOutPoint(wire.OutPoint{})
+	chanID = lnwire.NewChanIDFromOutPoint(&wire.OutPoint{})
 
 	adds = []channeldb.LogUpdate{
 		{
diff --git a/contractcourt/breach_arbitrator_test.go b/contractcourt/breach_arbitrator_test.go
index fdc1239b4..29f33881a 100644
--- a/contractcourt/breach_arbitrator_test.go
+++ b/contractcourt/breach_arbitrator_test.go
@@ -1010,13 +1010,13 @@ func initBreachedState(t *testing.T) (*BreachArbitrator,
 func TestBreachHandoffSuccess(t *testing.T) {
 	brar, alice, _, bobClose, contractBreaches := initBreachedState(t)
 
-	chanPoint := alice.ChannelPoint()
+	chanPoint := alice.ChanPoint
 
 	// Signal a spend of the funding transaction and wait for the close
 	// observer to exit.
 	processACK := make(chan error)
 	breach := &ContractBreachEvent{
-		ChanPoint: chanPoint,
+		ChanPoint: *chanPoint,
 		ProcessACK: func(brarErr error) {
 			processACK <- brarErr
 		},
@@ -1044,13 +1044,13 @@ func TestBreachHandoffSuccess(t *testing.T) {
 	// After exiting, the breach arbiter should have persisted the
 	// retribution information and the channel should be shown as pending
 	// force closed.
-	assertArbiterBreach(t, brar, &chanPoint)
+	assertArbiterBreach(t, brar, chanPoint)
 
 	// Send another breach event. Since the handoff for this channel was
 	// already ACKed, the breach arbiter should immediately ACK and ignore
 	// this event.
 	breach = &ContractBreachEvent{
-		ChanPoint: chanPoint,
+		ChanPoint: *chanPoint,
 		ProcessACK: func(brarErr error) {
 			processACK <- brarErr
 		},
@@ -1077,7 +1077,7 @@ func TestBreachHandoffSuccess(t *testing.T) {
 	}
 
 	// State should not have changed.
-	assertArbiterBreach(t, brar, &chanPoint)
+	assertArbiterBreach(t, brar, chanPoint)
 }
 
 // TestBreachHandoffFail tests that a channel's close observer properly
@@ -1096,10 +1096,10 @@ func TestBreachHandoffFail(t *testing.T) {
 
 	// Signal the notifier to dispatch spend notifications of the funding
 	// transaction using the transaction from bob's closing summary.
-	chanPoint := alice.ChannelPoint()
+	chanPoint := alice.ChanPoint
 	processACK := make(chan error)
 	breach := &ContractBreachEvent{
-		ChanPoint: chanPoint,
+		ChanPoint: *chanPoint,
 		ProcessACK: func(brarErr error) {
 			processACK <- brarErr
 		},
@@ -1127,7 +1127,7 @@ func TestBreachHandoffFail(t *testing.T) {
 	// Since the handoff failed, the breach arbiter should not show the
 	// channel as breached, and the channel should also not have been marked
 	// pending closed.
-	assertNoArbiterBreach(t, brar, &chanPoint)
+	assertNoArbiterBreach(t, brar, chanPoint)
 	assertNotPendingClosed(t, alice)
 
 	brar, err := createTestArbiter(
@@ -1138,7 +1138,7 @@ func TestBreachHandoffFail(t *testing.T) {
 	// Signal a spend of the funding transaction and wait for the close
 	// observer to exit. This time we are allowing the handoff to succeed.
 	breach = &ContractBreachEvent{
-		ChanPoint: chanPoint,
+		ChanPoint: *chanPoint,
 		ProcessACK: func(brarErr error) {
 			processACK <- brarErr
 		},
@@ -1166,7 +1166,7 @@ func TestBreachHandoffFail(t *testing.T) {
 	// Check that the breach was properly recorded in the breach arbiter,
 	// and that the close observer marked the channel as pending closed
 	// before exiting.
-	assertArbiterBreach(t, brar, &chanPoint)
+	assertArbiterBreach(t, brar, chanPoint)
 }
 
 // TestBreachCreateJusticeTx tests that we create three different variants of
@@ -1560,7 +1560,7 @@ func testBreachSpends(t *testing.T, test breachTest) {
 	var (
 		height       = bobClose.ChanSnapshot.CommitHeight
 		forceCloseTx = bobClose.CloseTx
-		chanPoint    = alice.ChannelPoint()
+		chanPoint    = alice.ChanPoint
 		publTx       = make(chan *wire.MsgTx)
 		publErr      error
 		publMtx      sync.Mutex
@@ -1590,7 +1590,7 @@ func testBreachSpends(t *testing.T, test breachTest) {
 
 	processACK := make(chan error)
 	breach := &ContractBreachEvent{
-		ChanPoint: chanPoint,
+		ChanPoint: *chanPoint,
 		ProcessACK: func(brarErr error) {
 			processACK <- brarErr
 		},
@@ -1630,7 +1630,7 @@ func testBreachSpends(t *testing.T, test breachTest) {
 	// After exiting, the breach arbiter should have persisted the
 	// retribution information and the channel should be shown as pending
 	// force closed.
-	assertArbiterBreach(t, brar, &chanPoint)
+	assertArbiterBreach(t, brar, chanPoint)
 
 	// Assert that the database sees the channel as pending close, otherwise
 	// the breach arbiter won't be able to fully close it.
@@ -1669,7 +1669,7 @@ func testBreachSpends(t *testing.T, test breachTest) {
 	htlcOutpoint := retribution.HtlcRetributions[0].OutPoint
 
 	spendTxs, err := getSpendTransactions(
-		brar.cfg.Signer, &chanPoint, retribution,
+		brar.cfg.Signer, chanPoint, retribution,
 	)
 	require.NoError(t, err)
 
@@ -1764,7 +1764,7 @@ func testBreachSpends(t *testing.T, test breachTest) {
 	}
 
 	// Assert that the channel is fully resolved.
-	assertBrarCleanup(t, brar, &chanPoint, alice.State().Db)
+	assertBrarCleanup(t, brar, alice.ChanPoint, alice.State().Db)
 }
 
 // TestBreachDelayedJusticeConfirmation tests that the breach arbiter will
@@ -1777,7 +1777,7 @@ func TestBreachDelayedJusticeConfirmation(t *testing.T) {
 		height       = bobClose.ChanSnapshot.CommitHeight
 		blockHeight  = int32(10)
 		forceCloseTx = bobClose.CloseTx
-		chanPoint    = alice.ChannelPoint()
+		chanPoint    = alice.ChanPoint
 		publTx       = make(chan *wire.MsgTx)
 	)
 
@@ -1799,7 +1799,7 @@ func TestBreachDelayedJusticeConfirmation(t *testing.T) {
 
 	processACK := make(chan error, 1)
 	breach := &ContractBreachEvent{
-		ChanPoint: chanPoint,
+		ChanPoint: *chanPoint,
 		ProcessACK: func(brarErr error) {
 			processACK <- brarErr
 		},
@@ -1840,7 +1840,7 @@ func TestBreachDelayedJusticeConfirmation(t *testing.T) {
 	// After exiting, the breach arbiter should have persisted the
 	// retribution information and the channel should be shown as pending
 	// force closed.
-	assertArbiterBreach(t, brar, &chanPoint)
+	assertArbiterBreach(t, brar, chanPoint)
 
 	// Assert that the database sees the channel as pending close, otherwise
 	// the breach arbiter won't be able to fully close it.
@@ -1965,7 +1965,7 @@ func TestBreachDelayedJusticeConfirmation(t *testing.T) {
 	}
 
 	// Assert that the channel is fully resolved.
-	assertBrarCleanup(t, brar, &chanPoint, alice.State().Db)
+	assertBrarCleanup(t, brar, alice.ChanPoint, alice.State().Db)
 }
 
 // findInputIndex returns the index of the input that spends from the given
@@ -2081,12 +2081,12 @@ func assertPendingClosed(t *testing.T, c *lnwallet.LightningChannel) {
 	require.NoError(t, err, "unable to load pending closed channels")
 
 	for _, chanSummary := range closedChans {
-		if chanSummary.ChanPoint == c.ChannelPoint() {
+		if chanSummary.ChanPoint == *c.ChanPoint {
 			return
 		}
 	}
 
-	t.Fatalf("channel %v was not marked pending closed", c.ChannelPoint())
+	t.Fatalf("channel %v was not marked pending closed", c.ChanPoint)
 }
 
 // assertNotPendingClosed checks that the channel has not been marked pending
@@ -2098,9 +2098,9 @@ func assertNotPendingClosed(t *testing.T, c *lnwallet.LightningChannel) {
 	require.NoError(t, err, "unable to load pending closed channels")
 
 	for _, chanSummary := range closedChans {
-		if chanSummary.ChanPoint == c.ChannelPoint() {
+		if chanSummary.ChanPoint == *c.ChanPoint {
 			t.Fatalf("channel %v was marked pending closed",
-				c.ChannelPoint())
+				c.ChanPoint)
 		}
 	}
 }
diff --git a/funding/manager_test.go b/funding/manager_test.go
index db61c3000..6e1f22216 100644
--- a/funding/manager_test.go
+++ b/funding/manager_test.go
@@ -3365,7 +3365,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) {
 		t, alice, bob, func(node *testNode, msg *newChannelMsg) bool {
 			aliceDB := alice.fundingMgr.cfg.ChannelDB
 			chanID := lnwire.NewChanIDFromOutPoint(
-				msg.channel.FundingOutpoint,
+				&msg.channel.FundingOutpoint,
 			)
 
 			if node == alice {
diff --git a/healthcheck/healthcheck_test.go b/healthcheck/healthcheck_test.go
index b198e60a5..cb1a5952c 100644
--- a/healthcheck/healthcheck_test.go
+++ b/healthcheck/healthcheck_test.go
@@ -55,11 +55,13 @@ func TestMonitor(t *testing.T) {
 	cfg := &Config{
 		Checks: []*Observation{
 			{
-				Check:    mock.call,
-				Interval: intervalTicker,
-				Attempts: 2,
-				Backoff:  0,
-				Timeout:  time.Hour,
+				Check:     mock.call,
+				Interval:  intervalTicker,
+				Attempts:  2,
+				Backoff:   0,
+				Timeout:   time.Hour,
+				OnSuccess: noOpCallback,
+				OnFailure: noOpCallback,
 			},
 		},
 		Shutdown: func(string, ...interface{}) {
@@ -202,10 +204,12 @@ func TestRetryCheck(t *testing.T) {
 			// function. We set a zero back off so that the test
 			// will not wait.
 			observation := &Observation{
-				Check:    mock.call,
-				Attempts: test.attempts,
-				Timeout:  test.timeout,
-				Backoff:  0,
+				Check:     mock.call,
+				Attempts:  test.attempts,
+				Timeout:   test.timeout,
+				Backoff:   0,
+				OnSuccess: noOpCallback,
+				OnFailure: noOpCallback,
 			}
 			quit := make(chan struct{})
 
@@ -238,3 +242,187 @@ func TestRetryCheck(t *testing.T) {
 		})
 	}
 }
+
+// TestCallbacks verifies that we fire the OnSuccess/OnFailure callbacks
+// as expected.
+//
+// - When the health check succeeds, the OnSuccess callback should fire.
+// - When the failure threshold is reached, the OnFailure callback should fire.
+func TestCallbacks(t *testing.T) {
+	intervalTicker := ticker.NewForce(time.Hour)
+
+	mock := newMockCheck(t)
+	failureThreshold := 3
+
+	successChan := make(chan struct{})
+	failChan := make(chan struct{})
+	shutdown := make(chan struct{})
+
+	// Create our config for monitoring. We will use a 0 back off so that
+	// out test does not need to wait.
+	observation := &Observation{
+		Check:    mock.call,
+		Interval: intervalTicker,
+		Attempts: failureThreshold,
+		Backoff:  0,
+		Timeout:  time.Hour,
+		OnSuccess: func() {
+			select {
+			case successChan <- struct{}{}:
+			case <-time.After(timeout):
+				t.Fatal("unable to fire onSuccess callback")
+			}
+		},
+		OnFailure: func() {
+			close(failChan)
+		},
+	}
+
+	cfg := &Config{
+		Checks: []*Observation{observation},
+		Shutdown: func(string, ...interface{}) {
+			shutdown <- struct{}{}
+		},
+	}
+	monitor := NewMonitor(cfg)
+	require.NoError(t, monitor.Start(), "could not start monitor")
+
+	// Tick is a helper we will use to tick our interval.
+	tick := func() {
+		select {
+		case intervalTicker.Force <- testTime:
+		case <-time.After(timeout):
+			t.Fatal("could not tick timer")
+		}
+	}
+
+	// We expect that the onSuccess callback is fired after each successful
+	// check.
+	for i := 0; i < failureThreshold; i++ {
+		tick()
+		mock.sendError(nil)
+
+		// We expect that the onSuccess callback will have fired.
+		select {
+		case <-successChan:
+		case <-time.After(timeout):
+			t.Fatal("expected success callback")
+		}
+
+	}
+
+	// Kick off another health check iteration. The monitor's internal
+	// retry mechanism will re-attempt the check until it has reached
+	// the configured maximum # of attempts.
+	//
+	// This mocks our check function failing the maximum # of times
+	// consecutively that it is allowed.
+	tick()
+	for i := 1; i <= failureThreshold; i++ {
+		mock.sendError(errNonNil)
+
+		// Verify that the onFailure callback does not fire unless
+		// the failure threshold (maximum # of attempts) is reached.
+		if i < failureThreshold {
+			select {
+			case <-failChan:
+				t.Fatal("unexpected onFailure callback")
+			default:
+			}
+		}
+	}
+
+	// After reaching the failure threshold for this health check,
+	// we expect that the onFailure callback will have fired.
+	select {
+	case <-failChan:
+	case <-time.After(timeout):
+		t.Fatal("expected onFailure callback")
+	}
+
+	// Since we have failed within our allowed number of retries, we now
+	// expect a call to our shutdown function.
+	select {
+	case <-shutdown:
+	case <-time.After(timeout):
+		t.Fatal("expected shutdown")
+	}
+	require.NoError(t, monitor.Stop(), "could not stop monitor")
+}
+
+// TestDynamicChecks verifies that we actually kick off health check routines
+// for observations that are added after starting the monitor.
+func TestDynamicChecks(t *testing.T) {
+	intervalTicker := ticker.NewForce(time.Hour)
+
+	mock := newMockCheck(t)
+
+	successChan := make(chan struct{})
+	shutdown := make(chan struct{})
+
+	// Don't configure any health checks for this monitor.
+	// We'd like to verify that we can add checks after startup.
+	cfg := &Config{
+		Checks: []*Observation{},
+		Shutdown: func(string, ...interface{}) {
+			shutdown <- struct{}{}
+		},
+	}
+	monitor := NewMonitor(cfg)
+	require.NoError(t, monitor.Start(), "could not start monitor")
+
+	// Tick is a helper we will use to tick our interval.
+	tick := func() {
+		select {
+		case intervalTicker.Force <- testTime:
+		case <-time.After(timeout):
+			t.Fatal("could not tick timer")
+		}
+	}
+
+	observation := &Observation{
+		Check:    mock.call,
+		Interval: intervalTicker,
+		Attempts: 2,
+		Backoff:  0,
+		Timeout:  time.Hour,
+		OnSuccess: func() {
+			select {
+			case successChan <- struct{}{}:
+			case <-time.After(timeout):
+				t.Fatal("unable to fire onSuccess callback")
+			}
+		},
+		OnFailure: noOpCallback,
+	}
+
+	// Add the check after having started the monitor.
+	err := monitor.AddCheck(observation)
+	require.NoError(t, err, "could not add new observation")
+
+	// This should initiate the check we dynamically added above.
+	tick()
+
+	// Verify that we can fire the OnSuccess callback.
+	mock.sendError(errNonNil)
+	mock.sendError(nil)
+	select {
+	case <-successChan:
+	case <-time.After(timeout):
+		t.Fatal("expected success callback")
+	}
+
+	// Verify that we correctly shutdown if the added health check fails.
+	tick()
+	mock.sendError(errNonNil)
+	mock.sendError(errNonNil)
+
+	// Since we have failed within our allowed number of retries, we now
+	// expect a call to our shutdown function.
+	select {
+	case <-shutdown:
+	case <-time.After(timeout):
+		t.Fatal("expected shutdown")
+	}
+	require.NoError(t, monitor.Stop(), "could not stop monitor")
+}
diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go
index 44836cf65..fdd2a0d6a 100644
--- a/htlcswitch/link_test.go
+++ b/htlcswitch/link_test.go
@@ -1497,7 +1497,7 @@ func TestChannelLinkMultiHopUnknownNextHop(t *testing.T) {
 	// back the payment to Alice since he is unaware of Carol when the
 	// payment comes across.
 	bobChanID := lnwire.NewChanIDFromOutPoint(
-		channels.bobToCarol.ChannelPoint(),
+		&channels.bobToCarol.State().FundingOutpoint,
 	)
 	n.bobServer.htlcSwitch.RemoveLink(bobChanID)
 
@@ -3762,8 +3762,7 @@ func TestChannelRetransmission(t *testing.T) {
 			t.Fatalf("unable to create channel: %v", err)
 		}
 
-		chanPoint := channels.aliceToBob.ChannelPoint()
-		chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
+		chanID := lnwire.NewChanIDFromOutPoint(channels.aliceToBob.ChannelPoint())
 		serverErr := make(chan error, 4)
 
 		aliceInterceptor := createInterceptorFunc("[alice] <-- [bob]",
diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go
index 0c98fa4fe..c566118d6 100644
--- a/htlcswitch/test_utils.go
+++ b/htlcswitch/test_utils.go
@@ -73,7 +73,7 @@ func genID() (lnwire.ChannelID, lnwire.ShortChannelID) {
 	hash1, _ := chainhash.NewHash(bytes.Repeat(scratch[:], 4))
 
 	chanPoint1 := wire.NewOutPoint(hash1, uint32(id))
-	chanID1 := lnwire.NewChanIDFromOutPoint(*chanPoint1)
+	chanID1 := lnwire.NewChanIDFromOutPoint(chanPoint1)
 	aliceChanID := lnwire.NewShortChanIDFromInt(id)
 
 	return chanID1, aliceChanID
diff --git a/lnrpc/invoicesrpc/addinvoice_test.go b/lnrpc/invoicesrpc/addinvoice_test.go
index a384fd959..1b15921d0 100644
--- a/lnrpc/invoicesrpc/addinvoice_test.go
+++ b/lnrpc/invoicesrpc/addinvoice_test.go
@@ -120,7 +120,7 @@ var shouldIncludeChannelTestCases = []struct {
 		fundingOutpoint := wire.OutPoint{
 			Index: 0,
 		}
-		chanID := lnwire.NewChanIDFromOutPoint(fundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingOutpoint)
 		h.Mock.On(
 			"IsChannelActive", chanID,
 		).Once().Return(true)
@@ -137,7 +137,7 @@ var shouldIncludeChannelTestCases = []struct {
 		fundingOutpoint := wire.OutPoint{
 			Index: 0,
 		}
-		chanID := lnwire.NewChanIDFromOutPoint(fundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingOutpoint)
 		h.Mock.On(
 			"IsChannelActive", chanID,
 		).Once().Return(false)
@@ -154,7 +154,7 @@ var shouldIncludeChannelTestCases = []struct {
 		fundingOutpoint := wire.OutPoint{
 			Index: 0,
 		}
-		chanID := lnwire.NewChanIDFromOutPoint(fundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingOutpoint)
 
 		h.Mock.On(
 			"IsChannelActive", chanID,
@@ -178,7 +178,7 @@ var shouldIncludeChannelTestCases = []struct {
 		fundingOutpoint := wire.OutPoint{
 			Index: 0,
 		}
-		chanID := lnwire.NewChanIDFromOutPoint(fundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingOutpoint)
 
 		h.Mock.On(
 			"IsChannelActive", chanID,
@@ -213,7 +213,7 @@ var shouldIncludeChannelTestCases = []struct {
 		fundingOutpoint := wire.OutPoint{
 			Index: 0,
 		}
-		chanID := lnwire.NewChanIDFromOutPoint(fundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingOutpoint)
 
 		h.Mock.On(
 			"IsChannelActive", chanID,
@@ -251,7 +251,7 @@ var shouldIncludeChannelTestCases = []struct {
 		fundingOutpoint := wire.OutPoint{
 			Index: 0,
 		}
-		chanID := lnwire.NewChanIDFromOutPoint(fundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingOutpoint)
 
 		h.Mock.On(
 			"IsChannelActive", chanID,
@@ -289,7 +289,7 @@ var shouldIncludeChannelTestCases = []struct {
 		fundingOutpoint := wire.OutPoint{
 			Index: 1,
 		}
-		chanID := lnwire.NewChanIDFromOutPoint(fundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingOutpoint)
 
 		h.Mock.On(
 			"IsChannelActive", chanID,
@@ -340,7 +340,7 @@ var shouldIncludeChannelTestCases = []struct {
 		fundingOutpoint := wire.OutPoint{
 			Index: 1,
 		}
-		chanID := lnwire.NewChanIDFromOutPoint(fundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingOutpoint)
 
 		h.Mock.On(
 			"IsChannelActive", chanID,
@@ -385,7 +385,7 @@ var shouldIncludeChannelTestCases = []struct {
 		fundingOutpoint := wire.OutPoint{
 			Index: 1,
 		}
-		chanID := lnwire.NewChanIDFromOutPoint(fundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingOutpoint)
 
 		h.Mock.On(
 			"IsChannelActive", chanID,
@@ -538,7 +538,7 @@ var populateHopHintsTestCases = []struct {
 		"hop hints allowed",
 	setupMock: func(h *hopHintsConfigMock) {
 		fundingOutpoint := wire.OutPoint{Index: 9}
-		chanID := lnwire.NewChanIDFromOutPoint(fundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingOutpoint)
 		allChannels := []*channeldb.OpenChannel{
 			{
 				FundingOutpoint: fundingOutpoint,
@@ -584,7 +584,7 @@ var populateHopHintsTestCases = []struct {
 	name: "populate hop hints stops when we reached the targeted bandwidth",
 	setupMock: func(h *hopHintsConfigMock) {
 		fundingOutpoint := wire.OutPoint{Index: 9}
-		chanID := lnwire.NewChanIDFromOutPoint(fundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingOutpoint)
 		remoteBalance := lnwire.MilliSatoshi(10_000_000)
 		allChannels := []*channeldb.OpenChannel{
 			{
@@ -635,7 +635,7 @@ var populateHopHintsTestCases = []struct {
 		"remote balance frist",
 	setupMock: func(h *hopHintsConfigMock) {
 		fundingOutpoint := wire.OutPoint{Index: 9}
-		chanID := lnwire.NewChanIDFromOutPoint(fundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&fundingOutpoint)
 		remoteBalance := lnwire.MilliSatoshi(10_000_000)
 		allChannels := []*channeldb.OpenChannel{
 			// Because the channels with higher remote balance have
@@ -829,11 +829,11 @@ func setupMockTwoChannels(h *hopHintsConfigMock) (lnwire.ChannelID,
 	lnwire.ChannelID) {
 
 	fundingOutpoint1 := wire.OutPoint{Index: 9}
-	chanID1 := lnwire.NewChanIDFromOutPoint(fundingOutpoint1)
+	chanID1 := lnwire.NewChanIDFromOutPoint(&fundingOutpoint1)
 	remoteBalance1 := lnwire.MilliSatoshi(10_000_000)
 
 	fundingOutpoint2 := wire.OutPoint{Index: 2}
-	chanID2 := lnwire.NewChanIDFromOutPoint(fundingOutpoint2)
+	chanID2 := lnwire.NewChanIDFromOutPoint(&fundingOutpoint2)
 	remoteBalance2 := lnwire.MilliSatoshi(1_000_000)
 
 	allChannels := []*channeldb.OpenChannel{
diff --git a/lnwallet/chancloser/chancloser_test.go b/lnwallet/chancloser/chancloser_test.go
index 1956f0d2b..8111ef657 100644
--- a/lnwallet/chancloser/chancloser_test.go
+++ b/lnwallet/chancloser/chancloser_test.go
@@ -146,8 +146,8 @@ type mockChannel struct {
 	remoteKey keychain.KeyDescriptor
 }
 
-func (m *mockChannel) ChannelPoint() wire.OutPoint {
-	return m.chanPoint
+func (m *mockChannel) ChannelPoint() *wire.OutPoint {
+	return &m.chanPoint
 }
 
 func (m *mockChannel) MarkCoopBroadcasted(*wire.MsgTx, bool) error {
diff --git a/lnwallet/channel_test.go b/lnwallet/channel_test.go
index aa747bc42..6717b9209 100644
--- a/lnwallet/channel_test.go
+++ b/lnwallet/channel_test.go
@@ -3052,7 +3052,7 @@ func TestChanSyncOweCommitment(t *testing.T) {
 	}
 
 	chanID := lnwire.NewChanIDFromOutPoint(
-		aliceChannel.channelState.FundingOutpoint,
+		&aliceChannel.channelState.FundingOutpoint,
 	)
 
 	// With the HTLC's applied to both update logs, we'll initiate a state
@@ -3419,7 +3419,7 @@ func testChanSyncOweRevocation(t *testing.T, chanType channeldb.ChannelType) {
 	require.NoError(t, err, "unable to create test channels")
 
 	chanID := lnwire.NewChanIDFromOutPoint(
-		aliceChannel.channelState.FundingOutpoint,
+		&aliceChannel.channelState.FundingOutpoint,
 	)
 
 	// We'll start the test with Bob extending a single HTLC to Alice, and
@@ -4682,7 +4682,7 @@ func TestChanSyncUnableToSync(t *testing.T) {
 	// state.
 	badChanSync := &lnwire.ChannelReestablish{
 		ChanID: lnwire.NewChanIDFromOutPoint(
-			aliceChannel.channelState.FundingOutpoint,
+			&aliceChannel.channelState.FundingOutpoint,
 		),
 		NextLocalCommitHeight:  1000,
 		RemoteCommitTailHeight: 9000,
diff --git a/lnwallet/transactions_test.go b/lnwallet/transactions_test.go
index ab0ef7328..550586a4c 100644
--- a/lnwallet/transactions_test.go
+++ b/lnwallet/transactions_test.go
@@ -269,7 +269,7 @@ func addTestHtlcs(t *testing.T, remote, local *LightningChannel,
 		hash160map[hash160] = preimage
 
 		// Add htlc to the channel.
-		chanID := lnwire.NewChanIDFromOutPoint(remote.ChannelPoint())
+		chanID := lnwire.NewChanIDFromOutPoint(remote.ChanPoint)
 
 		msg := &lnwire.UpdateAddHTLC{
 			Amount:      htlc.amount,
diff --git a/lnwire/channel_id_test.go b/lnwire/channel_id_test.go
index a2aee4083..49f7b904b 100644
--- a/lnwire/channel_id_test.go
+++ b/lnwire/channel_id_test.go
@@ -17,7 +17,7 @@ func TestChannelIDOutPointConversion(t *testing.T) {
 
 		// With the output index mutated, we'll convert it into a
 		// ChannelID.
-		cid := NewChanIDFromOutPoint(testChanPoint)
+		cid := NewChanIDFromOutPoint(&testChanPoint)
 
 		// Once the channel point has been converted to a channelID, it
 		// should recognize its original outpoint.
@@ -48,7 +48,7 @@ func TestGenPossibleOutPoints(t *testing.T) {
 	// We'll first convert out test outpoint into a ChannelID.
 	testChanPoint := *outpoint1
 	testChanPoint.Index = 24
-	chanID := NewChanIDFromOutPoint(testChanPoint)
+	chanID := NewChanIDFromOutPoint(&testChanPoint)
 
 	// With the chan ID created, we'll generate all possible root outpoints
 	// given this channel ID.
diff --git a/netann/chan_status_manager_test.go b/netann/chan_status_manager_test.go
index 1e64a53f8..cb871ba01 100644
--- a/netann/chan_status_manager_test.go
+++ b/netann/chan_status_manager_test.go
@@ -391,7 +391,7 @@ func (h *testHarness) markActive(channels []*channeldb.OpenChannel) {
 	h.t.Helper()
 
 	for _, channel := range channels {
-		chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
 		h.htlcSwitch.SetStatus(chanID, true)
 	}
 }
@@ -402,7 +402,7 @@ func (h *testHarness) markInactive(channels []*channeldb.OpenChannel) {
 	h.t.Helper()
 
 	for _, channel := range channels {
-		chanID := lnwire.NewChanIDFromOutPoint(channel.FundingOutpoint)
+		chanID := lnwire.NewChanIDFromOutPoint(&channel.FundingOutpoint)
 		h.htlcSwitch.SetStatus(chanID, false)
 	}
 }
diff --git a/peer/brontide_test.go b/peer/brontide_test.go
index 46c1bec4d..c88aeed96 100644
--- a/peer/brontide_test.go
+++ b/peer/brontide_test.go
@@ -53,8 +53,7 @@ func TestPeerChannelClosureShutdownResponseLinkRemoved(t *testing.T) {
 	)
 	require.NoError(t, err, "unable to create test channels")
 
-	chanPoint := bobChan.ChannelPoint()
-	chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
+	chanID := lnwire.NewChanIDFromOutPoint(bobChan.ChannelPoint())
 
 	dummyDeliveryScript := genScript(t, p2wshAddress)
 
@@ -101,8 +100,7 @@ func TestPeerChannelClosureAcceptFeeResponder(t *testing.T) {
 	)
 	require.NoError(t, err, "unable to create test channels")
 
-	chanPoint := bobChan.ChannelPoint()
-	chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
+	chanID := lnwire.NewChanIDFromOutPoint(bobChan.ChannelPoint())
 
 	mockLink := newMockUpdateHandler(chanID)
 	mockSwitch.links = append(mockSwitch.links, mockLink)
@@ -206,8 +204,7 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) {
 	)
 	require.NoError(t, err, "unable to create test channels")
 
-	chanPoint := bobChan.ChannelPoint()
-	chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
+	chanID := lnwire.NewChanIDFromOutPoint(bobChan.ChannelPoint())
 	mockLink := newMockUpdateHandler(chanID)
 	mockSwitch.links = append(mockSwitch.links, mockLink)
 
@@ -218,7 +215,7 @@ func TestPeerChannelClosureAcceptFeeInitiator(t *testing.T) {
 	errChan := make(chan error, 1)
 	closeCommand := &htlcswitch.ChanClose{
 		CloseType:      contractcourt.CloseRegular,
-		ChanPoint:      &chanPoint,
+		ChanPoint:      bobChan.ChannelPoint(),
 		Updates:        updateChan,
 		TargetFeePerKw: 12500,
 		Err:            errChan,
@@ -330,8 +327,7 @@ func TestPeerChannelClosureFeeNegotiationsResponder(t *testing.T) {
 	)
 	require.NoError(t, err, "unable to create test channels")
 
-	chanPoint := bobChan.ChannelPoint()
-	chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
+	chanID := lnwire.NewChanIDFromOutPoint(bobChan.ChannelPoint())
 
 	mockLink := newMockUpdateHandler(chanID)
 	mockSwitch.links = append(mockSwitch.links, mockLink)
@@ -517,8 +513,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) {
 	)
 	require.NoError(t, err, "unable to create test channels")
 
-	chanPoint := bobChan.ChannelPoint()
-	chanID := lnwire.NewChanIDFromOutPoint(chanPoint)
+	chanID := lnwire.NewChanIDFromOutPoint(bobChan.ChannelPoint())
 	mockLink := newMockUpdateHandler(chanID)
 	mockSwitch.links = append(mockSwitch.links, mockLink)
 
@@ -527,7 +522,7 @@ func TestPeerChannelClosureFeeNegotiationsInitiator(t *testing.T) {
 	errChan := make(chan error, 1)
 	closeCommand := &htlcswitch.ChanClose{
 		CloseType:      contractcourt.CloseRegular,
-		ChanPoint:      &chanPoint,
+		ChanPoint:      bobChan.ChannelPoint(),
 		Updates:        updateChan,
 		TargetFeePerKw: 12500,
 		Err:            errChan,
@@ -859,7 +854,7 @@ func TestCustomShutdownScript(t *testing.T) {
 			errChan := make(chan error, 1)
 			closeCommand := htlcswitch.ChanClose{
 				CloseType:      contractcourt.CloseRegular,
-				ChanPoint:      &chanPoint,
+				ChanPoint:      chanPoint,
 				Updates:        updateChan,
 				TargetFeePerKw: 12500,
 				DeliveryScript: test.userCloseScript,
@@ -1218,7 +1213,7 @@ func TestUpdateNextRevocation(t *testing.T) {
 	// Test an error is returned when the chanID's corresponding channel is
 	// nil.
 	testChannel.FundingOutpoint = wire.OutPoint{Index: 1}
-	chanID := lnwire.NewChanIDFromOutPoint(testChannel.FundingOutpoint)
+	chanID := lnwire.NewChanIDFromOutPoint(&testChannel.FundingOutpoint)
 	alicePeer.activeChannels.Store(chanID, nil)
 
 	err = alicePeer.updateNextRevocation(testChannel)