Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
98 changes: 52 additions & 46 deletions chainreg/chainregistry.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package chainreg

import (
"encoding/hex"
"encoding/json"
"errors"
"fmt"
"io"
Expand Down Expand Up @@ -452,52 +451,43 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) {
return nil, nil, err
}

// Fetch all active zmq notifications from the bitcoind client.
resp, err := chainConn.RawRequest("getzmqnotifications", nil)
// Fetch all active ZMQ notifications from bitcoind.
zmq, err := chainConn.GetZmqNotifications()
if err != nil {
return nil, nil, err
}

zmq := []struct {
Type string `json:"type"`
Address string `json:"address"`
}{}

if err = json.Unmarshal([]byte(resp), &zmq); err != nil {
return nil, nil, err
}

pubRawBlockActive := false
pubRawTxActive := false

for i := range zmq {
if zmq[i].Type == "pubrawblock" {
url, err := url.Parse(zmq[i].Address)
if err != nil {
return nil, nil, err
}
if url.Port() != zmqPubRawBlockURL.Port() {
log.Warnf(
"unable to subscribe to zmq block events on "+
"%s (bitcoind is running on %s)",
if zmq[i].Address.Port() !=
zmqPubRawBlockURL.Port() {

log.Warnf("zmq block port "+
"mismatch: lnd is "+
"using %s but "+
"bitcoind reports %s "+
"- ensure the port "+
"is correct",
zmqPubRawBlockURL.Host,
url.Host,
)
zmq[i].Address.Host)
}
pubRawBlockActive = true
}
if zmq[i].Type == "pubrawtx" {
url, err := url.Parse(zmq[i].Address)
if err != nil {
return nil, nil, err
}
if url.Port() != zmqPubRawTxURL.Port() {
log.Warnf(
"unable to subscribe to zmq tx events on "+
"%s (bitcoind is running on %s)",
if zmq[i].Address.Port() !=
zmqPubRawTxURL.Port() {

log.Warnf("zmq tx port "+
"mismatch: lnd is "+
"using %s but "+
"bitcoind reports %s "+
"- ensure the port "+
"is correct",
zmqPubRawTxURL.Host,
url.Host,
)
zmq[i].Address.Host)
}
pubRawTxActive = true
}
Expand Down Expand Up @@ -535,7 +525,7 @@ func NewPartialChainControl(cfg *Config) (*PartialChainControl, func(), error) {
// Make sure the bitcoind chain backend maintains a
// healthy connection to the network by checking the
// number of outbound peers.
return checkOutboundPeers(chainConn)
return checkOutboundPeersBitcoind(chainConn)
}

case "btcd":
Expand Down Expand Up @@ -802,30 +792,22 @@ func NewChainControl(walletConfig lnwallet.Config,
// getblockchaininfo.
func getBitcoindHealthCheckCmd(client *rpcclient.Client) (string, int64, error) {
// Query bitcoind to get our current version.
resp, err := client.RawRequest("getnetworkinfo", nil)
info, err := client.GetNetworkInfo()
if err != nil {
return "", 0, err
}

// Parse the response to retrieve bitcoind's version.
info := struct {
Version int64 `json:"version"`
}{}
if err := json.Unmarshal(resp, &info); err != nil {
return "", 0, err
}

// Bitcoind returns a single value representing the semantic version:
// 1000000 * CLIENT_VERSION_MAJOR + 10000 * CLIENT_VERSION_MINOR
// + 100 * CLIENT_VERSION_REVISION + 1 * CLIENT_VERSION_BUILD
//
// The uptime call was added in version 0.15.0, so we return it for
// any version value >= 150000, as per the above calculation.
if info.Version >= 150000 {
return "uptime", info.Version, nil
return "uptime", int64(info.Version), nil
}

return "getblockchaininfo", info.Version, nil
return "getblockchaininfo", int64(info.Version), nil
}

var (
Expand Down Expand Up @@ -909,6 +891,24 @@ var (
}
)

// checkOutboundPeersBitcoind checks the number of outbound peers connected to
// a bitcoind backend. If the number of outbound peers is below 6, a warning is
// logged. This function is intended to ensure that the chain backend maintains
// a healthy connection to the network.
//
// This helper is bitcoind-specific because btcd does not currently implement
// getnetworkinfo.
func checkOutboundPeersBitcoind(client *rpcclient.Client) error {
info, err := client.GetNetworkInfo()
if err != nil {
return err
}

logOutboundPeerCount(int(info.ConnectionsOut))

return nil
}

// checkOutboundPeers checks the number of outbound peers connected to the
// provided RPC client. If the number of outbound peers is below 6, a warning
// is logged. This function is intended to ensure that the chain backend
Expand All @@ -926,13 +926,19 @@ func checkOutboundPeers(client *rpcclient.Client) error {
}
}

logOutboundPeerCount(outboundPeers)

return nil
}

// logOutboundPeerCount logs a warning when the number of outbound peers is
// below the minimum threshold.
func logOutboundPeerCount(outboundPeers int) {
if outboundPeers < DefaultMinOutboundPeers {
log.Warnf("The chain backend has an insufficient number "+
"of connected outbound peers (%d connected, expected "+
"minimum is %d) which can be a security issue. "+
"Connect to more trusted nodes manually if necessary.",
outboundPeers, DefaultMinOutboundPeers)
}

return nil
}
5 changes: 5 additions & 0 deletions docs/release-notes/release-notes-0.21.0.md
Original file line number Diff line number Diff line change
Expand Up @@ -70,6 +70,11 @@
the chain watch filter on restart. This was a pre-existing bug since
private taproot channels were first introduced.

* Bitcoind outbound peer health checks [now use](https://github.com/lightningnetwork/lnd/pull/10686)
`getnetworkinfo.connections_out` instead of `getpeerinfo`. The same PR also
[clarifies](https://github.com/lightningnetwork/lnd/issues/10568) the ZMQ
port-mismatch warnings so they no longer suggest that the connection failed.

# New Features

- [Basic Support](https://github.com/lightningnetwork/lnd/pull/9868) for onion
Expand Down
Loading