Merge pull request #4286 from guggero/remove-global-cfg
multi: remove global cfg variable
This commit is contained in:
commit
c2516d9352
@ -28,6 +28,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||||
@ -160,7 +161,7 @@ type chainControl struct {
|
|||||||
// full-node, another backed by a running bitcoind full-node, and the other
|
// full-node, another backed by a running bitcoind full-node, and the other
|
||||||
// backed by a running neutrino light client instance. When running with a
|
// backed by a running neutrino light client instance. When running with a
|
||||||
// neutrino light client instance, `neutrinoCS` must be non-nil.
|
// neutrino light client instance, `neutrinoCS` must be non-nil.
|
||||||
func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
func newChainControlFromConfig(cfg *Config, chanDB *channeldb.DB,
|
||||||
privateWalletPw, publicWalletPw []byte, birthday time.Time,
|
privateWalletPw, publicWalletPw []byte, birthday time.Time,
|
||||||
recoveryWindow uint32, wallet *wallet.Wallet,
|
recoveryWindow uint32, wallet *wallet.Wallet,
|
||||||
neutrinoCS *neutrino.ChainService) (*chainControl, error) {
|
neutrinoCS *neutrino.ChainService) (*chainControl, error) {
|
||||||
@ -168,15 +169,15 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
|||||||
// Set the RPC config from the "home" chain. Multi-chain isn't yet
|
// Set the RPC config from the "home" chain. Multi-chain isn't yet
|
||||||
// active, so we'll restrict usage to a particular chain for now.
|
// active, so we'll restrict usage to a particular chain for now.
|
||||||
homeChainConfig := cfg.Bitcoin
|
homeChainConfig := cfg.Bitcoin
|
||||||
if registeredChains.PrimaryChain() == litecoinChain {
|
if cfg.registeredChains.PrimaryChain() == litecoinChain {
|
||||||
homeChainConfig = cfg.Litecoin
|
homeChainConfig = cfg.Litecoin
|
||||||
}
|
}
|
||||||
ltndLog.Infof("Primary chain is set to: %v",
|
ltndLog.Infof("Primary chain is set to: %v",
|
||||||
registeredChains.PrimaryChain())
|
cfg.registeredChains.PrimaryChain())
|
||||||
|
|
||||||
cc := &chainControl{}
|
cc := &chainControl{}
|
||||||
|
|
||||||
switch registeredChains.PrimaryChain() {
|
switch cfg.registeredChains.PrimaryChain() {
|
||||||
case bitcoinChain:
|
case bitcoinChain:
|
||||||
cc.routingPolicy = htlcswitch.ForwardingPolicy{
|
cc.routingPolicy = htlcswitch.ForwardingPolicy{
|
||||||
MinHTLCOut: cfg.Bitcoin.MinHTLCOut,
|
MinHTLCOut: cfg.Bitcoin.MinHTLCOut,
|
||||||
@ -202,7 +203,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
|||||||
)
|
)
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("default routing policy for chain %v is "+
|
return nil, fmt.Errorf("default routing policy for chain %v is "+
|
||||||
"unknown", registeredChains.PrimaryChain())
|
"unknown", cfg.registeredChains.PrimaryChain())
|
||||||
}
|
}
|
||||||
|
|
||||||
walletConfig := &btcwallet.Config{
|
walletConfig := &btcwallet.Config{
|
||||||
@ -263,7 +264,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
|||||||
)
|
)
|
||||||
|
|
||||||
case "bitcoind", "litecoind":
|
case "bitcoind", "litecoind":
|
||||||
var bitcoindMode *bitcoindConfig
|
var bitcoindMode *lncfg.Bitcoind
|
||||||
switch {
|
switch {
|
||||||
case cfg.Bitcoin.Active:
|
case cfg.Bitcoin.Active:
|
||||||
bitcoindMode = cfg.BitcoindMode
|
bitcoindMode = cfg.BitcoindMode
|
||||||
@ -388,7 +389,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
|||||||
// connection. If a raw cert was specified in the config, then
|
// connection. If a raw cert was specified in the config, then
|
||||||
// we'll set that directly. Otherwise, we attempt to read the
|
// we'll set that directly. Otherwise, we attempt to read the
|
||||||
// cert from the path specified in the config.
|
// cert from the path specified in the config.
|
||||||
var btcdMode *btcdConfig
|
var btcdMode *lncfg.Btcd
|
||||||
switch {
|
switch {
|
||||||
case cfg.Bitcoin.Active:
|
case cfg.Bitcoin.Active:
|
||||||
btcdMode = cfg.BtcdMode
|
btcdMode = cfg.BtcdMode
|
||||||
@ -504,7 +505,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
|||||||
|
|
||||||
// Select the default channel constraints for the primary chain.
|
// Select the default channel constraints for the primary chain.
|
||||||
channelConstraints := defaultBtcChannelConstraints
|
channelConstraints := defaultBtcChannelConstraints
|
||||||
if registeredChains.PrimaryChain() == litecoinChain {
|
if cfg.registeredChains.PrimaryChain() == litecoinChain {
|
||||||
channelConstraints = defaultLtcChannelConstraints
|
channelConstraints = defaultLtcChannelConstraints
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -718,7 +719,9 @@ func (c *chainRegistry) NumActiveChains() uint32 {
|
|||||||
|
|
||||||
// initNeutrinoBackend inits a new instance of the neutrino light client
|
// initNeutrinoBackend inits a new instance of the neutrino light client
|
||||||
// backend given a target chain directory to store the chain state.
|
// backend given a target chain directory to store the chain state.
|
||||||
func initNeutrinoBackend(chainDir string) (*neutrino.ChainService, func(), error) {
|
func initNeutrinoBackend(cfg *Config, chainDir string) (*neutrino.ChainService,
|
||||||
|
func(), error) {
|
||||||
|
|
||||||
// First we'll open the database file for neutrino, creating the
|
// First we'll open the database file for neutrino, creating the
|
||||||
// database if needed. We append the normalized network name here to
|
// database if needed. We append the normalized network name here to
|
||||||
// match the behavior of btcwallet.
|
// match the behavior of btcwallet.
|
||||||
|
@ -4,17 +4,32 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
flags "github.com/jessevdk/go-flags"
|
"github.com/jessevdk/go-flags"
|
||||||
"github.com/lightningnetwork/lnd"
|
"github.com/lightningnetwork/lnd"
|
||||||
|
"github.com/lightningnetwork/lnd/signal"
|
||||||
)
|
)
|
||||||
|
|
||||||
func main() {
|
func main() {
|
||||||
|
// Load the configuration, and parse any command line options. This
|
||||||
|
// function will also set up logging properly.
|
||||||
|
loadedConfig, err := lnd.LoadConfig()
|
||||||
|
if err != nil {
|
||||||
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Hook interceptor for os signals.
|
||||||
|
signal.Intercept()
|
||||||
|
|
||||||
// Call the "real" main in a nested manner so the defers will properly
|
// Call the "real" main in a nested manner so the defers will properly
|
||||||
// be executed in the case of a graceful shutdown.
|
// be executed in the case of a graceful shutdown.
|
||||||
if err := lnd.Main(lnd.ListenerCfg{}); err != nil {
|
err = lnd.Main(
|
||||||
|
loadedConfig, lnd.ListenerCfg{}, signal.ShutdownChannel(),
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp {
|
if e, ok := err.(*flags.Error); ok && e.Type == flags.ErrHelp {
|
||||||
} else {
|
} else {
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
}
|
}
|
||||||
os.Exit(1)
|
os.Exit(1)
|
||||||
}
|
}
|
||||||
|
387
config.go
387
config.go
@ -1,6 +1,6 @@
|
|||||||
// Copyright (c) 2013-2017 The btcsuite developers
|
// Copyright (c) 2013-2017 The btcsuite developers
|
||||||
// Copyright (c) 2015-2016 The Decred developers
|
// Copyright (c) 2015-2016 The Decred developers
|
||||||
// Copyright (C) 2015-2017 The Lightning Network Developers
|
// Copyright (C) 2015-2020 The Lightning Network Developers
|
||||||
|
|
||||||
package lnd
|
package lnd
|
||||||
|
|
||||||
@ -30,13 +30,11 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/lncfg"
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/signrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
|
||||||
"github.com/lightningnetwork/lnd/routing"
|
"github.com/lightningnetwork/lnd/routing"
|
||||||
"github.com/lightningnetwork/lnd/tor"
|
"github.com/lightningnetwork/lnd/tor"
|
||||||
)
|
)
|
||||||
|
|
||||||
const (
|
const (
|
||||||
defaultConfigFilename = "lnd.conf"
|
|
||||||
defaultDataDirname = "data"
|
defaultDataDirname = "data"
|
||||||
defaultChainSubDirname = "chain"
|
defaultChainSubDirname = "chain"
|
||||||
defaultGraphSubDirname = "graph"
|
defaultGraphSubDirname = "graph"
|
||||||
@ -54,10 +52,6 @@ const (
|
|||||||
defaultPeerPort = 9735
|
defaultPeerPort = 9735
|
||||||
defaultRPCHost = "localhost"
|
defaultRPCHost = "localhost"
|
||||||
|
|
||||||
// DefaultMaxPendingChannels is the default maximum number of incoming
|
|
||||||
// pending channels permitted per peer.
|
|
||||||
DefaultMaxPendingChannels = 1
|
|
||||||
|
|
||||||
defaultNoSeedBackup = false
|
defaultNoSeedBackup = false
|
||||||
defaultPaymentsExpirationGracePeriod = time.Duration(0)
|
defaultPaymentsExpirationGracePeriod = time.Duration(0)
|
||||||
defaultTrickleDelay = 90 * 1000
|
defaultTrickleDelay = 90 * 1000
|
||||||
@ -76,51 +70,6 @@ const (
|
|||||||
defaultTorV2PrivateKeyFilename = "v2_onion_private_key"
|
defaultTorV2PrivateKeyFilename = "v2_onion_private_key"
|
||||||
defaultTorV3PrivateKeyFilename = "v3_onion_private_key"
|
defaultTorV3PrivateKeyFilename = "v3_onion_private_key"
|
||||||
|
|
||||||
// DefaultIncomingBroadcastDelta defines the number of blocks before the
|
|
||||||
// expiry of an incoming htlc at which we force close the channel. We
|
|
||||||
// only go to chain if we also have the preimage to actually pull in the
|
|
||||||
// htlc. BOLT #2 suggests 7 blocks. We use a few more for extra safety.
|
|
||||||
// Within this window we need to get our sweep or 2nd level success tx
|
|
||||||
// confirmed, because after that the remote party is also able to claim
|
|
||||||
// the htlc using the timeout path.
|
|
||||||
DefaultIncomingBroadcastDelta = 10
|
|
||||||
|
|
||||||
// defaultFinalCltvRejectDelta defines the number of blocks before the
|
|
||||||
// expiry of an incoming exit hop htlc at which we cancel it back
|
|
||||||
// immediately. It is an extra safety measure over the final cltv
|
|
||||||
// requirement as it is defined in the invoice. It ensures that we
|
|
||||||
// cancel back htlcs that, when held on to, may cause us to force close
|
|
||||||
// the channel because we enter the incoming broadcast window. Bolt #11
|
|
||||||
// suggests 9 blocks here. We use a few more for additional safety.
|
|
||||||
//
|
|
||||||
// There is still a small gap that remains between receiving the
|
|
||||||
// RevokeAndAck and canceling back. If a new block arrives within that
|
|
||||||
// window, we may still force close the channel. There is currently no
|
|
||||||
// way to reject an UpdateAddHtlc of which we already know that it will
|
|
||||||
// push us in the broadcast window.
|
|
||||||
defaultFinalCltvRejectDelta = DefaultIncomingBroadcastDelta + 3
|
|
||||||
|
|
||||||
// DefaultOutgoingBroadcastDelta defines the number of blocks before the
|
|
||||||
// expiry of an outgoing htlc at which we force close the channel. We
|
|
||||||
// are not in a hurry to force close, because there is nothing to claim
|
|
||||||
// for us. We do need to time the htlc out, because there may be an
|
|
||||||
// incoming htlc that will time out too (albeit later). Bolt #2 suggests
|
|
||||||
// a value of -1 here, but we allow one block less to prevent potential
|
|
||||||
// confusion around the negative value. It means we force close the
|
|
||||||
// channel at exactly the htlc expiry height.
|
|
||||||
DefaultOutgoingBroadcastDelta = 0
|
|
||||||
|
|
||||||
// defaultOutgoingCltvRejectDelta defines the number of blocks before
|
|
||||||
// the expiry of an outgoing htlc at which we don't want to offer it to
|
|
||||||
// the next peer anymore. If that happens, we cancel back the incoming
|
|
||||||
// htlc. This is to prevent the situation where we have an outstanding
|
|
||||||
// htlc that brings or will soon bring us inside the outgoing broadcast
|
|
||||||
// window and trigger us to force close the channel. Bolt #2 suggests a
|
|
||||||
// value of 0. We pad it a bit, to prevent a slow round trip to the next
|
|
||||||
// peer and a block arriving during that round trip to trigger force
|
|
||||||
// closure.
|
|
||||||
defaultOutgoingCltvRejectDelta = DefaultOutgoingBroadcastDelta + 3
|
|
||||||
|
|
||||||
// minTimeLockDelta is the minimum timelock we require for incoming
|
// minTimeLockDelta is the minimum timelock we require for incoming
|
||||||
// HTLCs on our channels.
|
// HTLCs on our channels.
|
||||||
minTimeLockDelta = 4
|
minTimeLockDelta = 4
|
||||||
@ -134,15 +83,25 @@ const (
|
|||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
defaultLndDir = btcutil.AppDataDir("lnd", false)
|
// DefaultLndDir is the default directory where lnd tries to find its
|
||||||
defaultConfigFile = filepath.Join(defaultLndDir, defaultConfigFilename)
|
// configuration file and store its data. This is a directory in the
|
||||||
defaultDataDir = filepath.Join(defaultLndDir, defaultDataDirname)
|
// user's application data, for example:
|
||||||
defaultLogDir = filepath.Join(defaultLndDir, defaultLogDirname)
|
// C:\Users\<username>\AppData\Local\Lnd on Windows
|
||||||
|
// ~/.lnd on Linux
|
||||||
|
// ~/Library/Application Support/Lnd on MacOS
|
||||||
|
DefaultLndDir = btcutil.AppDataDir("lnd", false)
|
||||||
|
|
||||||
|
// DefaultConfigFile is the default full path of lnd's configuration
|
||||||
|
// file.
|
||||||
|
DefaultConfigFile = filepath.Join(DefaultLndDir, lncfg.DefaultConfigFilename)
|
||||||
|
|
||||||
|
defaultDataDir = filepath.Join(DefaultLndDir, defaultDataDirname)
|
||||||
|
defaultLogDir = filepath.Join(DefaultLndDir, defaultLogDirname)
|
||||||
|
|
||||||
defaultTowerDir = filepath.Join(defaultDataDir, defaultTowerSubDirname)
|
defaultTowerDir = filepath.Join(defaultDataDir, defaultTowerSubDirname)
|
||||||
|
|
||||||
defaultTLSCertPath = filepath.Join(defaultLndDir, defaultTLSCertFilename)
|
defaultTLSCertPath = filepath.Join(DefaultLndDir, defaultTLSCertFilename)
|
||||||
defaultTLSKeyPath = filepath.Join(defaultLndDir, defaultTLSKeyFilename)
|
defaultTLSKeyPath = filepath.Join(DefaultLndDir, defaultTLSKeyFilename)
|
||||||
|
|
||||||
defaultBtcdDir = btcutil.AppDataDir("btcd", false)
|
defaultBtcdDir = btcutil.AppDataDir("btcd", false)
|
||||||
defaultBtcdRPCCertFile = filepath.Join(defaultBtcdDir, "rpc.cert")
|
defaultBtcdRPCCertFile = filepath.Join(defaultBtcdDir, "rpc.cert")
|
||||||
@ -163,86 +122,11 @@ var (
|
|||||||
bitcoindEstimateModes = [2]string{"ECONOMICAL", defaultBitcoindEstimateMode}
|
bitcoindEstimateModes = [2]string{"ECONOMICAL", defaultBitcoindEstimateMode}
|
||||||
)
|
)
|
||||||
|
|
||||||
type chainConfig struct {
|
// Config defines the configuration options for lnd.
|
||||||
Active bool `long:"active" description:"If the chain should be active or not."`
|
|
||||||
ChainDir string `long:"chaindir" description:"The directory to store the chain's data within."`
|
|
||||||
|
|
||||||
Node string `long:"node" description:"The blockchain interface to use." choice:"btcd" choice:"bitcoind" choice:"neutrino" choice:"ltcd" choice:"litecoind"`
|
|
||||||
|
|
||||||
MainNet bool `long:"mainnet" description:"Use the main network"`
|
|
||||||
TestNet3 bool `long:"testnet" description:"Use the test network"`
|
|
||||||
SimNet bool `long:"simnet" description:"Use the simulation test network"`
|
|
||||||
RegTest bool `long:"regtest" description:"Use the regression test network"`
|
|
||||||
|
|
||||||
DefaultNumChanConfs int `long:"defaultchanconfs" description:"The default number of confirmations a channel must have before it's considered open. If this is not set, we will scale the value according to the channel size."`
|
|
||||||
DefaultRemoteDelay int `long:"defaultremotedelay" description:"The default number of blocks we will require our channel counterparty to wait before accessing its funds in case of unilateral close. If this is not set, we will scale the value according to the channel size."`
|
|
||||||
MinHTLCIn lnwire.MilliSatoshi `long:"minhtlc" description:"The smallest HTLC we are willing to accept on our channels, in millisatoshi"`
|
|
||||||
MinHTLCOut lnwire.MilliSatoshi `long:"minhtlcout" description:"The smallest HTLC we are willing to send out on our channels, in millisatoshi"`
|
|
||||||
BaseFee lnwire.MilliSatoshi `long:"basefee" description:"The base fee in millisatoshi we will charge for forwarding payments on our channels"`
|
|
||||||
FeeRate lnwire.MilliSatoshi `long:"feerate" description:"The fee rate used when forwarding payments on our channels. The total fee charged is basefee + (amount * feerate / 1000000), where amount is the forwarded amount."`
|
|
||||||
TimeLockDelta uint32 `long:"timelockdelta" description:"The CLTV delta we will subtract from a forwarded HTLC's timelock value"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type neutrinoConfig struct {
|
|
||||||
AddPeers []string `short:"a" long:"addpeer" description:"Add a peer to connect with at startup"`
|
|
||||||
ConnectPeers []string `long:"connect" description:"Connect only to the specified peers at startup"`
|
|
||||||
MaxPeers int `long:"maxpeers" description:"Max number of inbound and outbound peers"`
|
|
||||||
BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"`
|
|
||||||
BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."`
|
|
||||||
FeeURL string `long:"feeurl" description:"Optional URL for fee estimation. If a URL is not specified, static fees will be used for estimation."`
|
|
||||||
AssertFilterHeader string `long:"assertfilterheader" description:"Optional filter header in height:hash format to assert the state of neutrino's filter header chain on startup. If the assertion does not hold, then the filter header chain will be re-synced from the genesis block."`
|
|
||||||
}
|
|
||||||
|
|
||||||
type btcdConfig struct {
|
|
||||||
Dir string `long:"dir" description:"The base directory that contains the node's data, logs, configuration file, etc."`
|
|
||||||
RPCHost string `long:"rpchost" description:"The daemon's rpc listening address. If a port is omitted, then the default port for the selected chain parameters will be used."`
|
|
||||||
RPCUser string `long:"rpcuser" description:"Username for RPC connections"`
|
|
||||||
RPCPass string `long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
|
|
||||||
RPCCert string `long:"rpccert" description:"File containing the daemon's certificate file"`
|
|
||||||
RawRPCCert string `long:"rawrpccert" description:"The raw bytes of the daemon's PEM-encoded certificate chain which will be used to authenticate the RPC connection."`
|
|
||||||
}
|
|
||||||
|
|
||||||
type bitcoindConfig struct {
|
|
||||||
Dir string `long:"dir" description:"The base directory that contains the node's data, logs, configuration file, etc."`
|
|
||||||
RPCHost string `long:"rpchost" description:"The daemon's rpc listening address. If a port is omitted, then the default port for the selected chain parameters will be used."`
|
|
||||||
RPCUser string `long:"rpcuser" description:"Username for RPC connections"`
|
|
||||||
RPCPass string `long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
|
|
||||||
ZMQPubRawBlock string `long:"zmqpubrawblock" description:"The address listening for ZMQ connections to deliver raw block notifications"`
|
|
||||||
ZMQPubRawTx string `long:"zmqpubrawtx" description:"The address listening for ZMQ connections to deliver raw transaction notifications"`
|
|
||||||
EstimateMode string `long:"estimatemode" description:"The fee estimate mode. Must be either ECONOMICAL or CONSERVATIVE."`
|
|
||||||
}
|
|
||||||
|
|
||||||
type autoPilotConfig struct {
|
|
||||||
Active bool `long:"active" description:"If the autopilot agent should be active or not."`
|
|
||||||
Heuristic map[string]float64 `long:"heuristic" description:"Heuristic to activate, and the weight to give it during scoring."`
|
|
||||||
MaxChannels int `long:"maxchannels" description:"The maximum number of channels that should be created"`
|
|
||||||
Allocation float64 `long:"allocation" description:"The percentage of total funds that should be committed to automatic channel establishment"`
|
|
||||||
MinChannelSize int64 `long:"minchansize" description:"The smallest channel that the autopilot agent should create"`
|
|
||||||
MaxChannelSize int64 `long:"maxchansize" description:"The largest channel that the autopilot agent should create"`
|
|
||||||
Private bool `long:"private" description:"Whether the channels created by the autopilot agent should be private or not. Private channels won't be announced to the network."`
|
|
||||||
MinConfs int32 `long:"minconfs" description:"The minimum number of confirmations each of your inputs in funding transactions created by the autopilot agent must have."`
|
|
||||||
ConfTarget uint32 `long:"conftarget" description:"The confirmation target (in blocks) for channels opened by autopilot."`
|
|
||||||
}
|
|
||||||
|
|
||||||
type torConfig struct {
|
|
||||||
Active bool `long:"active" description:"Allow outbound and inbound connections to be routed through Tor"`
|
|
||||||
SOCKS string `long:"socks" description:"The host:port that Tor's exposed SOCKS5 proxy is listening on"`
|
|
||||||
DNS string `long:"dns" description:"The DNS server as host:port that Tor will use for SRV queries - NOTE must have TCP resolution enabled"`
|
|
||||||
StreamIsolation bool `long:"streamisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."`
|
|
||||||
Control string `long:"control" description:"The host:port that Tor is listening on for Tor control connections"`
|
|
||||||
TargetIPAddress string `long:"targetipaddress" description:"IP address that Tor should use as the target of the hidden service"`
|
|
||||||
Password string `long:"password" description:"The password used to arrive at the HashedControlPassword for the control port. If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one."`
|
|
||||||
V2 bool `long:"v2" description:"Automatically set up a v2 onion service to listen for inbound connections"`
|
|
||||||
V3 bool `long:"v3" description:"Automatically set up a v3 onion service to listen for inbound connections"`
|
|
||||||
PrivateKeyPath string `long:"privatekeypath" description:"The path to the private key of the onion service being created"`
|
|
||||||
WatchtowerKeyPath string `long:"watchtowerkeypath" description:"The path to the private key of the watchtower onion service being created"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// config defines the configuration options for lnd.
|
|
||||||
//
|
//
|
||||||
// See loadConfig for further details regarding the configuration
|
// See LoadConfig for further details regarding the configuration
|
||||||
// loading+parsing process.
|
// loading+parsing process.
|
||||||
type config struct {
|
type Config struct {
|
||||||
ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"`
|
ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"`
|
||||||
|
|
||||||
LndDir string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."`
|
LndDir string `long:"lnddir" description:"The base directory that contains lnd's data, logs, configuration file, etc."`
|
||||||
@ -294,18 +178,18 @@ type config struct {
|
|||||||
MaxPendingChannels int `long:"maxpendingchannels" description:"The maximum number of incoming pending channels permitted per peer."`
|
MaxPendingChannels int `long:"maxpendingchannels" description:"The maximum number of incoming pending channels permitted per peer."`
|
||||||
BackupFilePath string `long:"backupfilepath" description:"The target location of the channel backup file"`
|
BackupFilePath string `long:"backupfilepath" description:"The target location of the channel backup file"`
|
||||||
|
|
||||||
Bitcoin *chainConfig `group:"Bitcoin" namespace:"bitcoin"`
|
Bitcoin *lncfg.Chain `group:"Bitcoin" namespace:"bitcoin"`
|
||||||
BtcdMode *btcdConfig `group:"btcd" namespace:"btcd"`
|
BtcdMode *lncfg.Btcd `group:"btcd" namespace:"btcd"`
|
||||||
BitcoindMode *bitcoindConfig `group:"bitcoind" namespace:"bitcoind"`
|
BitcoindMode *lncfg.Bitcoind `group:"bitcoind" namespace:"bitcoind"`
|
||||||
NeutrinoMode *neutrinoConfig `group:"neutrino" namespace:"neutrino"`
|
NeutrinoMode *lncfg.Neutrino `group:"neutrino" namespace:"neutrino"`
|
||||||
|
|
||||||
Litecoin *chainConfig `group:"Litecoin" namespace:"litecoin"`
|
Litecoin *lncfg.Chain `group:"Litecoin" namespace:"litecoin"`
|
||||||
LtcdMode *btcdConfig `group:"ltcd" namespace:"ltcd"`
|
LtcdMode *lncfg.Btcd `group:"ltcd" namespace:"ltcd"`
|
||||||
LitecoindMode *bitcoindConfig `group:"litecoind" namespace:"litecoind"`
|
LitecoindMode *lncfg.Bitcoind `group:"litecoind" namespace:"litecoind"`
|
||||||
|
|
||||||
Autopilot *autoPilotConfig `group:"Autopilot" namespace:"autopilot"`
|
Autopilot *lncfg.AutoPilot `group:"Autopilot" namespace:"autopilot"`
|
||||||
|
|
||||||
Tor *torConfig `group:"Tor" namespace:"tor"`
|
Tor *lncfg.Tor `group:"Tor" namespace:"tor"`
|
||||||
|
|
||||||
SubRPCServers *subRPCServerConfigs `group:"subrpc"`
|
SubRPCServers *subRPCServerConfigs `group:"subrpc"`
|
||||||
|
|
||||||
@ -363,20 +247,22 @@ type config struct {
|
|||||||
ProtocolOptions *lncfg.ProtocolOptions `group:"protocol" namespace:"protocol"`
|
ProtocolOptions *lncfg.ProtocolOptions `group:"protocol" namespace:"protocol"`
|
||||||
|
|
||||||
AllowCircularRoute bool `long:"allow-circular-route" description:"If true, our node will allow htlc forwards that arrive and depart on the same channel."`
|
AllowCircularRoute bool `long:"allow-circular-route" description:"If true, our node will allow htlc forwards that arrive and depart on the same channel."`
|
||||||
|
|
||||||
|
// registeredChains keeps track of all chains that have been registered
|
||||||
|
// with the daemon.
|
||||||
|
registeredChains *chainRegistry
|
||||||
|
|
||||||
|
// networkDir is the path to the directory of the currently active
|
||||||
|
// network. This path will hold the files related to each different
|
||||||
|
// network.
|
||||||
|
networkDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
// loadConfig initializes and parses the config using a config file and command
|
// DefaultConfig returns all default values for the Config struct.
|
||||||
// line options.
|
func DefaultConfig() Config {
|
||||||
//
|
return Config{
|
||||||
// The configuration proceeds as follows:
|
LndDir: DefaultLndDir,
|
||||||
// 1) Start with a default config with sane settings
|
ConfigFile: DefaultConfigFile,
|
||||||
// 2) Pre-parse the command line to check for an alternative config file
|
|
||||||
// 3) Load configuration file overwriting defaults with any specified options
|
|
||||||
// 4) Parse CLI options and overwrite/add any specified options
|
|
||||||
func loadConfig() (*config, error) {
|
|
||||||
defaultCfg := config{
|
|
||||||
LndDir: defaultLndDir,
|
|
||||||
ConfigFile: defaultConfigFile,
|
|
||||||
DataDir: defaultDataDir,
|
DataDir: defaultDataDir,
|
||||||
DebugLevel: defaultLogLevel,
|
DebugLevel: defaultLogLevel,
|
||||||
TLSCertPath: defaultTLSCertPath,
|
TLSCertPath: defaultTLSCertPath,
|
||||||
@ -385,7 +271,7 @@ func loadConfig() (*config, error) {
|
|||||||
MaxLogFiles: defaultMaxLogFiles,
|
MaxLogFiles: defaultMaxLogFiles,
|
||||||
MaxLogFileSize: defaultMaxLogFileSize,
|
MaxLogFileSize: defaultMaxLogFileSize,
|
||||||
AcceptorTimeout: defaultAcceptorTimeout,
|
AcceptorTimeout: defaultAcceptorTimeout,
|
||||||
Bitcoin: &chainConfig{
|
Bitcoin: &lncfg.Chain{
|
||||||
MinHTLCIn: defaultBitcoinMinHTLCInMSat,
|
MinHTLCIn: defaultBitcoinMinHTLCInMSat,
|
||||||
MinHTLCOut: defaultBitcoinMinHTLCOutMSat,
|
MinHTLCOut: defaultBitcoinMinHTLCOutMSat,
|
||||||
BaseFee: DefaultBitcoinBaseFeeMSat,
|
BaseFee: DefaultBitcoinBaseFeeMSat,
|
||||||
@ -393,17 +279,17 @@ func loadConfig() (*config, error) {
|
|||||||
TimeLockDelta: DefaultBitcoinTimeLockDelta,
|
TimeLockDelta: DefaultBitcoinTimeLockDelta,
|
||||||
Node: "btcd",
|
Node: "btcd",
|
||||||
},
|
},
|
||||||
BtcdMode: &btcdConfig{
|
BtcdMode: &lncfg.Btcd{
|
||||||
Dir: defaultBtcdDir,
|
Dir: defaultBtcdDir,
|
||||||
RPCHost: defaultRPCHost,
|
RPCHost: defaultRPCHost,
|
||||||
RPCCert: defaultBtcdRPCCertFile,
|
RPCCert: defaultBtcdRPCCertFile,
|
||||||
},
|
},
|
||||||
BitcoindMode: &bitcoindConfig{
|
BitcoindMode: &lncfg.Bitcoind{
|
||||||
Dir: defaultBitcoindDir,
|
Dir: defaultBitcoindDir,
|
||||||
RPCHost: defaultRPCHost,
|
RPCHost: defaultRPCHost,
|
||||||
EstimateMode: defaultBitcoindEstimateMode,
|
EstimateMode: defaultBitcoindEstimateMode,
|
||||||
},
|
},
|
||||||
Litecoin: &chainConfig{
|
Litecoin: &lncfg.Chain{
|
||||||
MinHTLCIn: defaultLitecoinMinHTLCInMSat,
|
MinHTLCIn: defaultLitecoinMinHTLCInMSat,
|
||||||
MinHTLCOut: defaultLitecoinMinHTLCOutMSat,
|
MinHTLCOut: defaultLitecoinMinHTLCOutMSat,
|
||||||
BaseFee: defaultLitecoinBaseFeeMSat,
|
BaseFee: defaultLitecoinBaseFeeMSat,
|
||||||
@ -411,18 +297,18 @@ func loadConfig() (*config, error) {
|
|||||||
TimeLockDelta: defaultLitecoinTimeLockDelta,
|
TimeLockDelta: defaultLitecoinTimeLockDelta,
|
||||||
Node: "ltcd",
|
Node: "ltcd",
|
||||||
},
|
},
|
||||||
LtcdMode: &btcdConfig{
|
LtcdMode: &lncfg.Btcd{
|
||||||
Dir: defaultLtcdDir,
|
Dir: defaultLtcdDir,
|
||||||
RPCHost: defaultRPCHost,
|
RPCHost: defaultRPCHost,
|
||||||
RPCCert: defaultLtcdRPCCertFile,
|
RPCCert: defaultLtcdRPCCertFile,
|
||||||
},
|
},
|
||||||
LitecoindMode: &bitcoindConfig{
|
LitecoindMode: &lncfg.Bitcoind{
|
||||||
Dir: defaultLitecoindDir,
|
Dir: defaultLitecoindDir,
|
||||||
RPCHost: defaultRPCHost,
|
RPCHost: defaultRPCHost,
|
||||||
EstimateMode: defaultBitcoindEstimateMode,
|
EstimateMode: defaultBitcoindEstimateMode,
|
||||||
},
|
},
|
||||||
UnsafeDisconnect: true,
|
UnsafeDisconnect: true,
|
||||||
MaxPendingChannels: DefaultMaxPendingChannels,
|
MaxPendingChannels: lncfg.DefaultMaxPendingChannels,
|
||||||
NoSeedBackup: defaultNoSeedBackup,
|
NoSeedBackup: defaultNoSeedBackup,
|
||||||
MinBackoff: defaultMinBackoff,
|
MinBackoff: defaultMinBackoff,
|
||||||
MaxBackoff: defaultMaxBackoff,
|
MaxBackoff: defaultMaxBackoff,
|
||||||
@ -430,7 +316,7 @@ func loadConfig() (*config, error) {
|
|||||||
SignRPC: &signrpc.Config{},
|
SignRPC: &signrpc.Config{},
|
||||||
RouterRPC: routerrpc.DefaultConfig(),
|
RouterRPC: routerrpc.DefaultConfig(),
|
||||||
},
|
},
|
||||||
Autopilot: &autoPilotConfig{
|
Autopilot: &lncfg.AutoPilot{
|
||||||
MaxChannels: 5,
|
MaxChannels: 5,
|
||||||
Allocation: 0.6,
|
Allocation: 0.6,
|
||||||
MinChannelSize: int64(minChanFundingSize),
|
MinChannelSize: int64(minChanFundingSize),
|
||||||
@ -451,7 +337,7 @@ func loadConfig() (*config, error) {
|
|||||||
MinChanSize: int64(minChanFundingSize),
|
MinChanSize: int64(minChanFundingSize),
|
||||||
NumGraphSyncPeers: defaultMinPeers,
|
NumGraphSyncPeers: defaultMinPeers,
|
||||||
HistoricalSyncInterval: discovery.DefaultHistoricalSyncInterval,
|
HistoricalSyncInterval: discovery.DefaultHistoricalSyncInterval,
|
||||||
Tor: &torConfig{
|
Tor: &lncfg.Tor{
|
||||||
SOCKS: defaultTorSOCKS,
|
SOCKS: defaultTorSOCKS,
|
||||||
DNS: defaultTorDNS,
|
DNS: defaultTorDNS,
|
||||||
Control: defaultTorControl,
|
Control: defaultTorControl,
|
||||||
@ -472,11 +358,22 @@ func loadConfig() (*config, error) {
|
|||||||
},
|
},
|
||||||
MaxOutgoingCltvExpiry: htlcswitch.DefaultMaxOutgoingCltvExpiry,
|
MaxOutgoingCltvExpiry: htlcswitch.DefaultMaxOutgoingCltvExpiry,
|
||||||
MaxChannelFeeAllocation: htlcswitch.DefaultMaxLinkFeeAllocation,
|
MaxChannelFeeAllocation: htlcswitch.DefaultMaxLinkFeeAllocation,
|
||||||
|
registeredChains: newChainRegistry(),
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// LoadConfig initializes and parses the config using a config file and command
|
||||||
|
// line options.
|
||||||
|
//
|
||||||
|
// The configuration proceeds as follows:
|
||||||
|
// 1) Start with a default config with sane settings
|
||||||
|
// 2) Pre-parse the command line to check for an alternative config file
|
||||||
|
// 3) Load configuration file overwriting defaults with any specified options
|
||||||
|
// 4) Parse CLI options and overwrite/add any specified options
|
||||||
|
func LoadConfig() (*Config, error) {
|
||||||
// Pre-parse the command line options to pick up an alternative config
|
// Pre-parse the command line options to pick up an alternative config
|
||||||
// file.
|
// file.
|
||||||
preCfg := defaultCfg
|
preCfg := DefaultConfig()
|
||||||
if _, err := flags.Parse(&preCfg); err != nil {
|
if _, err := flags.Parse(&preCfg); err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -495,12 +392,12 @@ func loadConfig() (*config, error) {
|
|||||||
// use the default config file path. However, if the user has modified
|
// use the default config file path. However, if the user has modified
|
||||||
// their lnddir, then we should assume they intend to use the config
|
// their lnddir, then we should assume they intend to use the config
|
||||||
// file within it.
|
// file within it.
|
||||||
configFileDir := cleanAndExpandPath(preCfg.LndDir)
|
configFileDir := CleanAndExpandPath(preCfg.LndDir)
|
||||||
configFilePath := cleanAndExpandPath(preCfg.ConfigFile)
|
configFilePath := CleanAndExpandPath(preCfg.ConfigFile)
|
||||||
if configFileDir != defaultLndDir {
|
if configFileDir != DefaultLndDir {
|
||||||
if configFilePath == defaultConfigFile {
|
if configFilePath == DefaultConfigFile {
|
||||||
configFilePath = filepath.Join(
|
configFilePath = filepath.Join(
|
||||||
configFileDir, defaultConfigFilename,
|
configFileDir, lncfg.DefaultConfigFilename,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -525,10 +422,30 @@ func loadConfig() (*config, error) {
|
|||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure everything we just loaded makes sense.
|
||||||
|
cleanCfg, err := ValidateConfig(cfg, usageMessage)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Warn about missing config file only after all other configuration is
|
||||||
|
// done. This prevents the warning on help messages and invalid
|
||||||
|
// options. Note this should go directly before the return.
|
||||||
|
if configFileError != nil {
|
||||||
|
ltndLog.Warnf("%v", configFileError)
|
||||||
|
}
|
||||||
|
|
||||||
|
return cleanCfg, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// ValidateConfig check the given configuration to be sane. This makes sure no
|
||||||
|
// illegal values or combination of values are set. All file system paths are
|
||||||
|
// normalized. The cleaned up config is returned on success.
|
||||||
|
func ValidateConfig(cfg Config, usageMessage string) (*Config, error) {
|
||||||
// If the provided lnd directory is not the default, we'll modify the
|
// If the provided lnd directory is not the default, we'll modify the
|
||||||
// path to all of the files and directories that will live within it.
|
// path to all of the files and directories that will live within it.
|
||||||
lndDir := cleanAndExpandPath(cfg.LndDir)
|
lndDir := CleanAndExpandPath(cfg.LndDir)
|
||||||
if lndDir != defaultLndDir {
|
if lndDir != DefaultLndDir {
|
||||||
cfg.DataDir = filepath.Join(lndDir, defaultDataDirname)
|
cfg.DataDir = filepath.Join(lndDir, defaultDataDirname)
|
||||||
cfg.TLSCertPath = filepath.Join(lndDir, defaultTLSCertFilename)
|
cfg.TLSCertPath = filepath.Join(lndDir, defaultTLSCertFilename)
|
||||||
cfg.TLSKeyPath = filepath.Join(lndDir, defaultTLSKeyFilename)
|
cfg.TLSKeyPath = filepath.Join(lndDir, defaultTLSKeyFilename)
|
||||||
@ -558,64 +475,64 @@ func loadConfig() (*config, error) {
|
|||||||
|
|
||||||
str := "%s: Failed to create lnd directory: %v"
|
str := "%s: Failed to create lnd directory: %v"
|
||||||
err := fmt.Errorf(str, funcName, err)
|
err := fmt.Errorf(str, funcName, err)
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// As soon as we're done parsing configuration options, ensure all paths
|
// As soon as we're done parsing configuration options, ensure all paths
|
||||||
// to directories and files are cleaned and expanded before attempting
|
// to directories and files are cleaned and expanded before attempting
|
||||||
// to use them later on.
|
// to use them later on.
|
||||||
cfg.DataDir = cleanAndExpandPath(cfg.DataDir)
|
cfg.DataDir = CleanAndExpandPath(cfg.DataDir)
|
||||||
cfg.TLSCertPath = cleanAndExpandPath(cfg.TLSCertPath)
|
cfg.TLSCertPath = CleanAndExpandPath(cfg.TLSCertPath)
|
||||||
cfg.TLSKeyPath = cleanAndExpandPath(cfg.TLSKeyPath)
|
cfg.TLSKeyPath = CleanAndExpandPath(cfg.TLSKeyPath)
|
||||||
cfg.AdminMacPath = cleanAndExpandPath(cfg.AdminMacPath)
|
cfg.AdminMacPath = CleanAndExpandPath(cfg.AdminMacPath)
|
||||||
cfg.ReadMacPath = cleanAndExpandPath(cfg.ReadMacPath)
|
cfg.ReadMacPath = CleanAndExpandPath(cfg.ReadMacPath)
|
||||||
cfg.InvoiceMacPath = cleanAndExpandPath(cfg.InvoiceMacPath)
|
cfg.InvoiceMacPath = CleanAndExpandPath(cfg.InvoiceMacPath)
|
||||||
cfg.LogDir = cleanAndExpandPath(cfg.LogDir)
|
cfg.LogDir = CleanAndExpandPath(cfg.LogDir)
|
||||||
cfg.BtcdMode.Dir = cleanAndExpandPath(cfg.BtcdMode.Dir)
|
cfg.BtcdMode.Dir = CleanAndExpandPath(cfg.BtcdMode.Dir)
|
||||||
cfg.LtcdMode.Dir = cleanAndExpandPath(cfg.LtcdMode.Dir)
|
cfg.LtcdMode.Dir = CleanAndExpandPath(cfg.LtcdMode.Dir)
|
||||||
cfg.BitcoindMode.Dir = cleanAndExpandPath(cfg.BitcoindMode.Dir)
|
cfg.BitcoindMode.Dir = CleanAndExpandPath(cfg.BitcoindMode.Dir)
|
||||||
cfg.LitecoindMode.Dir = cleanAndExpandPath(cfg.LitecoindMode.Dir)
|
cfg.LitecoindMode.Dir = CleanAndExpandPath(cfg.LitecoindMode.Dir)
|
||||||
cfg.Tor.PrivateKeyPath = cleanAndExpandPath(cfg.Tor.PrivateKeyPath)
|
cfg.Tor.PrivateKeyPath = CleanAndExpandPath(cfg.Tor.PrivateKeyPath)
|
||||||
cfg.Tor.WatchtowerKeyPath = cleanAndExpandPath(cfg.Tor.WatchtowerKeyPath)
|
cfg.Tor.WatchtowerKeyPath = CleanAndExpandPath(cfg.Tor.WatchtowerKeyPath)
|
||||||
cfg.Watchtower.TowerDir = cleanAndExpandPath(cfg.Watchtower.TowerDir)
|
cfg.Watchtower.TowerDir = CleanAndExpandPath(cfg.Watchtower.TowerDir)
|
||||||
|
|
||||||
// Ensure that the user didn't attempt to specify negative values for
|
// Ensure that the user didn't attempt to specify negative values for
|
||||||
// any of the autopilot params.
|
// any of the autopilot params.
|
||||||
if cfg.Autopilot.MaxChannels < 0 {
|
if cfg.Autopilot.MaxChannels < 0 {
|
||||||
str := "%s: autopilot.maxchannels must be non-negative"
|
str := "%s: autopilot.maxchannels must be non-negative"
|
||||||
err := fmt.Errorf(str, funcName)
|
err := fmt.Errorf(str, funcName)
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if cfg.Autopilot.Allocation < 0 {
|
if cfg.Autopilot.Allocation < 0 {
|
||||||
str := "%s: autopilot.allocation must be non-negative"
|
str := "%s: autopilot.allocation must be non-negative"
|
||||||
err := fmt.Errorf(str, funcName)
|
err := fmt.Errorf(str, funcName)
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if cfg.Autopilot.MinChannelSize < 0 {
|
if cfg.Autopilot.MinChannelSize < 0 {
|
||||||
str := "%s: autopilot.minchansize must be non-negative"
|
str := "%s: autopilot.minchansize must be non-negative"
|
||||||
err := fmt.Errorf(str, funcName)
|
err := fmt.Errorf(str, funcName)
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if cfg.Autopilot.MaxChannelSize < 0 {
|
if cfg.Autopilot.MaxChannelSize < 0 {
|
||||||
str := "%s: autopilot.maxchansize must be non-negative"
|
str := "%s: autopilot.maxchansize must be non-negative"
|
||||||
err := fmt.Errorf(str, funcName)
|
err := fmt.Errorf(str, funcName)
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if cfg.Autopilot.MinConfs < 0 {
|
if cfg.Autopilot.MinConfs < 0 {
|
||||||
str := "%s: autopilot.minconfs must be non-negative"
|
str := "%s: autopilot.minconfs must be non-negative"
|
||||||
err := fmt.Errorf(str, funcName)
|
err := fmt.Errorf(str, funcName)
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if cfg.Autopilot.ConfTarget < 1 {
|
if cfg.Autopilot.ConfTarget < 1 {
|
||||||
str := "%s: autopilot.conftarget must be positive"
|
str := "%s: autopilot.conftarget must be positive"
|
||||||
err := fmt.Errorf(str, funcName)
|
err := fmt.Errorf(str, funcName)
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -829,7 +746,7 @@ func loadConfig() (*config, error) {
|
|||||||
|
|
||||||
// Finally we'll register the litecoin chain as our current
|
// Finally we'll register the litecoin chain as our current
|
||||||
// primary chain.
|
// primary chain.
|
||||||
registeredChains.RegisterPrimaryChain(litecoinChain)
|
cfg.registeredChains.RegisterPrimaryChain(litecoinChain)
|
||||||
MaxFundingAmount = maxLtcFundingAmount
|
MaxFundingAmount = maxLtcFundingAmount
|
||||||
MaxPaymentMSat = maxLtcPaymentMSat
|
MaxPaymentMSat = maxLtcPaymentMSat
|
||||||
|
|
||||||
@ -916,7 +833,7 @@ func loadConfig() (*config, error) {
|
|||||||
|
|
||||||
// Finally we'll register the bitcoin chain as our current
|
// Finally we'll register the bitcoin chain as our current
|
||||||
// primary chain.
|
// primary chain.
|
||||||
registeredChains.RegisterPrimaryChain(bitcoinChain)
|
cfg.registeredChains.RegisterPrimaryChain(bitcoinChain)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ensure that the user didn't attempt to specify negative values for
|
// Ensure that the user didn't attempt to specify negative values for
|
||||||
@ -924,25 +841,25 @@ func loadConfig() (*config, error) {
|
|||||||
if cfg.Autopilot.MaxChannels < 0 {
|
if cfg.Autopilot.MaxChannels < 0 {
|
||||||
str := "%s: autopilot.maxchannels must be non-negative"
|
str := "%s: autopilot.maxchannels must be non-negative"
|
||||||
err := fmt.Errorf(str, funcName)
|
err := fmt.Errorf(str, funcName)
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if cfg.Autopilot.Allocation < 0 {
|
if cfg.Autopilot.Allocation < 0 {
|
||||||
str := "%s: autopilot.allocation must be non-negative"
|
str := "%s: autopilot.allocation must be non-negative"
|
||||||
err := fmt.Errorf(str, funcName)
|
err := fmt.Errorf(str, funcName)
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if cfg.Autopilot.MinChannelSize < 0 {
|
if cfg.Autopilot.MinChannelSize < 0 {
|
||||||
str := "%s: autopilot.minchansize must be non-negative"
|
str := "%s: autopilot.minchansize must be non-negative"
|
||||||
err := fmt.Errorf(str, funcName)
|
err := fmt.Errorf(str, funcName)
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
if cfg.Autopilot.MaxChannelSize < 0 {
|
if cfg.Autopilot.MaxChannelSize < 0 {
|
||||||
str := "%s: autopilot.maxchansize must be non-negative"
|
str := "%s: autopilot.maxchansize must be non-negative"
|
||||||
err := fmt.Errorf(str, funcName)
|
err := fmt.Errorf(str, funcName)
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -961,17 +878,17 @@ func loadConfig() (*config, error) {
|
|||||||
if err != nil || profilePort < 1024 || profilePort > 65535 {
|
if err != nil || profilePort < 1024 || profilePort > 65535 {
|
||||||
str := "%s: The profile port must be between 1024 and 65535"
|
str := "%s: The profile port must be between 1024 and 65535"
|
||||||
err := fmt.Errorf(str, funcName)
|
err := fmt.Errorf(str, funcName)
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
fmt.Fprintln(os.Stderr, usageMessage)
|
_, _ = fmt.Fprintln(os.Stderr, usageMessage)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// We'll now construct the network directory which will be where we
|
// We'll now construct the network directory which will be where we
|
||||||
// store all the data specific to this chain/network.
|
// store all the data specific to this chain/network.
|
||||||
networkDir = filepath.Join(
|
cfg.networkDir = filepath.Join(
|
||||||
cfg.DataDir, defaultChainSubDirname,
|
cfg.DataDir, defaultChainSubDirname,
|
||||||
registeredChains.PrimaryChain().String(),
|
cfg.registeredChains.PrimaryChain().String(),
|
||||||
normalizeNetwork(activeNetParams.Name),
|
normalizeNetwork(activeNetParams.Name),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -980,17 +897,17 @@ func loadConfig() (*config, error) {
|
|||||||
// the path for the macaroons to be generated.
|
// the path for the macaroons to be generated.
|
||||||
if cfg.AdminMacPath == "" {
|
if cfg.AdminMacPath == "" {
|
||||||
cfg.AdminMacPath = filepath.Join(
|
cfg.AdminMacPath = filepath.Join(
|
||||||
networkDir, defaultAdminMacFilename,
|
cfg.networkDir, defaultAdminMacFilename,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if cfg.ReadMacPath == "" {
|
if cfg.ReadMacPath == "" {
|
||||||
cfg.ReadMacPath = filepath.Join(
|
cfg.ReadMacPath = filepath.Join(
|
||||||
networkDir, defaultReadMacFilename,
|
cfg.networkDir, defaultReadMacFilename,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
if cfg.InvoiceMacPath == "" {
|
if cfg.InvoiceMacPath == "" {
|
||||||
cfg.InvoiceMacPath = filepath.Join(
|
cfg.InvoiceMacPath = filepath.Join(
|
||||||
networkDir, defaultInvoiceMacFilename,
|
cfg.networkDir, defaultInvoiceMacFilename,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -998,41 +915,41 @@ func loadConfig() (*config, error) {
|
|||||||
// we'll update the file location to match our set network directory.
|
// we'll update the file location to match our set network directory.
|
||||||
if cfg.BackupFilePath == "" {
|
if cfg.BackupFilePath == "" {
|
||||||
cfg.BackupFilePath = filepath.Join(
|
cfg.BackupFilePath = filepath.Join(
|
||||||
networkDir, chanbackup.DefaultBackupFileName,
|
cfg.networkDir, chanbackup.DefaultBackupFileName,
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Append the network type to the log directory so it is "namespaced"
|
// Append the network type to the log directory so it is "namespaced"
|
||||||
// per network in the same fashion as the data directory.
|
// per network in the same fashion as the data directory.
|
||||||
cfg.LogDir = filepath.Join(cfg.LogDir,
|
cfg.LogDir = filepath.Join(cfg.LogDir,
|
||||||
registeredChains.PrimaryChain().String(),
|
cfg.registeredChains.PrimaryChain().String(),
|
||||||
normalizeNetwork(activeNetParams.Name))
|
normalizeNetwork(activeNetParams.Name))
|
||||||
|
|
||||||
// Special show command to list supported subsystems and exit.
|
// Special show command to list supported subsystems and exit.
|
||||||
if cfg.DebugLevel == "show" {
|
if cfg.DebugLevel == "show" {
|
||||||
fmt.Println("Supported subsystems",
|
fmt.Println("Supported subsystems",
|
||||||
logWriter.SupportedSubsystems())
|
RootLogWriter.SupportedSubsystems())
|
||||||
os.Exit(0)
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize logging at the default logging level.
|
// Initialize logging at the default logging level.
|
||||||
err = logWriter.InitLogRotator(
|
err = RootLogWriter.InitLogRotator(
|
||||||
filepath.Join(cfg.LogDir, defaultLogFilename),
|
filepath.Join(cfg.LogDir, defaultLogFilename),
|
||||||
cfg.MaxLogFileSize, cfg.MaxLogFiles,
|
cfg.MaxLogFileSize, cfg.MaxLogFiles,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
str := "%s: log rotation setup failed: %v"
|
str := "%s: log rotation setup failed: %v"
|
||||||
err = fmt.Errorf(str, funcName, err.Error())
|
err = fmt.Errorf(str, funcName, err.Error())
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
// Parse, validate, and set debug log level(s).
|
// Parse, validate, and set debug log level(s).
|
||||||
err = build.ParseAndSetDebugLevels(cfg.DebugLevel, logWriter)
|
err = build.ParseAndSetDebugLevels(cfg.DebugLevel, RootLogWriter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = fmt.Errorf("%s: %v", funcName, err.Error())
|
err = fmt.Errorf("%s: %v", funcName, err.Error())
|
||||||
fmt.Fprintln(os.Stderr, err)
|
_, _ = fmt.Fprintln(os.Stderr, err)
|
||||||
fmt.Fprintln(os.Stderr, usageMessage)
|
_, _ = fmt.Fprintln(os.Stderr, usageMessage)
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1169,20 +1086,14 @@ func loadConfig() (*config, error) {
|
|||||||
return nil, fmt.Errorf("unable to parse node color: %v", err)
|
return nil, fmt.Errorf("unable to parse node color: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Warn about missing config file only after all other configuration is
|
// All good, return the sanitized result.
|
||||||
// done. This prevents the warning on help messages and invalid
|
return &cfg, err
|
||||||
// options. Note this should go directly before the return.
|
|
||||||
if configFileError != nil {
|
|
||||||
ltndLog.Warnf("%v", configFileError)
|
|
||||||
}
|
|
||||||
|
|
||||||
return &cfg, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// cleanAndExpandPath expands environment variables and leading ~ in the
|
// CleanAndExpandPath expands environment variables and leading ~ in the
|
||||||
// passed path, cleans the result, and returns it.
|
// passed path, cleans the result, and returns it.
|
||||||
// This function is taken from https://github.com/btcsuite/btcd
|
// This function is taken from https://github.com/btcsuite/btcd
|
||||||
func cleanAndExpandPath(path string) string {
|
func CleanAndExpandPath(path string) string {
|
||||||
if path == "" {
|
if path == "" {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
@ -1190,9 +1101,9 @@ func cleanAndExpandPath(path string) string {
|
|||||||
// Expand initial ~ to OS specific home directory.
|
// Expand initial ~ to OS specific home directory.
|
||||||
if strings.HasPrefix(path, "~") {
|
if strings.HasPrefix(path, "~") {
|
||||||
var homeDir string
|
var homeDir string
|
||||||
user, err := user.Current()
|
u, err := user.Current()
|
||||||
if err == nil {
|
if err == nil {
|
||||||
homeDir = user.HomeDir
|
homeDir = u.HomeDir
|
||||||
} else {
|
} else {
|
||||||
homeDir = os.Getenv("HOME")
|
homeDir = os.Getenv("HOME")
|
||||||
}
|
}
|
||||||
@ -1205,15 +1116,15 @@ func cleanAndExpandPath(path string) string {
|
|||||||
return filepath.Clean(os.ExpandEnv(path))
|
return filepath.Clean(os.ExpandEnv(path))
|
||||||
}
|
}
|
||||||
|
|
||||||
func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
func parseRPCParams(cConfig *lncfg.Chain, nodeConfig interface{}, net chainCode,
|
||||||
funcName string) error {
|
funcName string) error { // nolint:unparam
|
||||||
|
|
||||||
// First, we'll check our node config to make sure the RPC parameters
|
// First, we'll check our node config to make sure the RPC parameters
|
||||||
// were set correctly. We'll also determine the path to the conf file
|
// were set correctly. We'll also determine the path to the conf file
|
||||||
// depending on the backend node.
|
// depending on the backend node.
|
||||||
var daemonName, confDir, confFile string
|
var daemonName, confDir, confFile string
|
||||||
switch conf := nodeConfig.(type) {
|
switch conf := nodeConfig.(type) {
|
||||||
case *btcdConfig:
|
case *lncfg.Btcd:
|
||||||
// If both RPCUser and RPCPass are set, we assume those
|
// If both RPCUser and RPCPass are set, we assume those
|
||||||
// credentials are good to use.
|
// credentials are good to use.
|
||||||
if conf.RPCUser != "" && conf.RPCPass != "" {
|
if conf.RPCUser != "" && conf.RPCPass != "" {
|
||||||
@ -1239,7 +1150,7 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
|||||||
"%[1]v.rpcuser, %[1]v.rpcpass", daemonName)
|
"%[1]v.rpcuser, %[1]v.rpcpass", daemonName)
|
||||||
}
|
}
|
||||||
|
|
||||||
case *bitcoindConfig:
|
case *lncfg.Bitcoind:
|
||||||
// Ensure that if the ZMQ options are set, that they are not
|
// Ensure that if the ZMQ options are set, that they are not
|
||||||
// equal.
|
// equal.
|
||||||
if conf.ZMQPubRawBlock != "" && conf.ZMQPubRawTx != "" {
|
if conf.ZMQPubRawBlock != "" && conf.ZMQPubRawTx != "" {
|
||||||
@ -1305,7 +1216,7 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
|||||||
confFile = filepath.Join(confDir, fmt.Sprintf("%v.conf", confFile))
|
confFile = filepath.Join(confDir, fmt.Sprintf("%v.conf", confFile))
|
||||||
switch cConfig.Node {
|
switch cConfig.Node {
|
||||||
case "btcd", "ltcd":
|
case "btcd", "ltcd":
|
||||||
nConf := nodeConfig.(*btcdConfig)
|
nConf := nodeConfig.(*lncfg.Btcd)
|
||||||
rpcUser, rpcPass, err := extractBtcdRPCParams(confFile)
|
rpcUser, rpcPass, err := extractBtcdRPCParams(confFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("unable to extract RPC credentials:"+
|
return fmt.Errorf("unable to extract RPC credentials:"+
|
||||||
@ -1314,7 +1225,7 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
|||||||
}
|
}
|
||||||
nConf.RPCUser, nConf.RPCPass = rpcUser, rpcPass
|
nConf.RPCUser, nConf.RPCPass = rpcUser, rpcPass
|
||||||
case "bitcoind", "litecoind":
|
case "bitcoind", "litecoind":
|
||||||
nConf := nodeConfig.(*bitcoindConfig)
|
nConf := nodeConfig.(*lncfg.Bitcoind)
|
||||||
rpcUser, rpcPass, zmqBlockHost, zmqTxHost, err :=
|
rpcUser, rpcPass, zmqBlockHost, zmqTxHost, err :=
|
||||||
extractBitcoindRPCParams(confFile)
|
extractBitcoindRPCParams(confFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1340,7 +1251,7 @@ func extractBtcdRPCParams(btcdConfigPath string) (string, string, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", err
|
return "", "", err
|
||||||
}
|
}
|
||||||
defer btcdConfigFile.Close()
|
defer func() { _ = btcdConfigFile.Close() }()
|
||||||
|
|
||||||
// With the file open extract the contents of the configuration file so
|
// With the file open extract the contents of the configuration file so
|
||||||
// we can attempt to locate the RPC credentials.
|
// we can attempt to locate the RPC credentials.
|
||||||
@ -1381,14 +1292,16 @@ func extractBtcdRPCParams(btcdConfigPath string) (string, string, error) {
|
|||||||
// location of bitcoind's bitcoin.conf on the target system. The routine looks
|
// location of bitcoind's bitcoin.conf on the target system. The routine looks
|
||||||
// for a cookie first, optionally following the datadir configuration option in
|
// for a cookie first, optionally following the datadir configuration option in
|
||||||
// the bitcoin.conf. If it doesn't find one, it looks for rpcuser/rpcpassword.
|
// the bitcoin.conf. If it doesn't find one, it looks for rpcuser/rpcpassword.
|
||||||
func extractBitcoindRPCParams(bitcoindConfigPath string) (string, string, string, string, error) {
|
func extractBitcoindRPCParams(bitcoindConfigPath string) (string, string, string,
|
||||||
|
string, error) {
|
||||||
|
|
||||||
// First, we'll open up the bitcoind configuration file found at the
|
// First, we'll open up the bitcoind configuration file found at the
|
||||||
// target destination.
|
// target destination.
|
||||||
bitcoindConfigFile, err := os.Open(bitcoindConfigPath)
|
bitcoindConfigFile, err := os.Open(bitcoindConfigPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", "", "", "", err
|
return "", "", "", "", err
|
||||||
}
|
}
|
||||||
defer bitcoindConfigFile.Close()
|
defer func() { _ = bitcoindConfigFile.Close() }()
|
||||||
|
|
||||||
// With the file open extract the contents of the configuration file so
|
// With the file open extract the contents of the configuration file so
|
||||||
// we can attempt to locate the RPC credentials.
|
// we can attempt to locate the RPC credentials.
|
||||||
|
@ -369,6 +369,14 @@ type fundingConfig struct {
|
|||||||
// NotifyPendingOpenChannelEvent informs the ChannelNotifier when channels
|
// NotifyPendingOpenChannelEvent informs the ChannelNotifier when channels
|
||||||
// enter a pending state.
|
// enter a pending state.
|
||||||
NotifyPendingOpenChannelEvent func(wire.OutPoint, *channeldb.OpenChannel)
|
NotifyPendingOpenChannelEvent func(wire.OutPoint, *channeldb.OpenChannel)
|
||||||
|
|
||||||
|
// EnableUpfrontShutdown specifies whether the upfront shutdown script
|
||||||
|
// is enabled.
|
||||||
|
EnableUpfrontShutdown bool
|
||||||
|
|
||||||
|
// RegisteredChains keeps track of all chains that have been registered
|
||||||
|
// with the daemon.
|
||||||
|
RegisteredChains *chainRegistry
|
||||||
}
|
}
|
||||||
|
|
||||||
// fundingManager acts as an orchestrator/bridge between the wallet's
|
// fundingManager acts as an orchestrator/bridge between the wallet's
|
||||||
@ -1322,7 +1330,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) {
|
|||||||
// A nil address is set in place of user input, because this channel open
|
// A nil address is set in place of user input, because this channel open
|
||||||
// was not initiated by the user.
|
// was not initiated by the user.
|
||||||
shutdown, err := getUpfrontShutdownScript(
|
shutdown, err := getUpfrontShutdownScript(
|
||||||
fmsg.peer, nil,
|
f.cfg.EnableUpfrontShutdown, fmsg.peer, nil,
|
||||||
func() (lnwire.DeliveryAddress, error) {
|
func() (lnwire.DeliveryAddress, error) {
|
||||||
addr, err := f.cfg.Wallet.NewAddress(lnwallet.WitnessPubKey, false)
|
addr, err := f.cfg.Wallet.NewAddress(lnwallet.WitnessPubKey, false)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -2981,7 +2989,8 @@ func (f *fundingManager) initFundingWorkflow(peer lnpeer.Peer, req *openChanReq)
|
|||||||
// our peer does support the feature, we will return the user provided script
|
// our peer does support the feature, we will return the user provided script
|
||||||
// if non-zero, or a freshly generated script if our node is configured to set
|
// if non-zero, or a freshly generated script if our node is configured to set
|
||||||
// upfront shutdown scripts automatically.
|
// upfront shutdown scripts automatically.
|
||||||
func getUpfrontShutdownScript(peer lnpeer.Peer, script lnwire.DeliveryAddress,
|
func getUpfrontShutdownScript(enableUpfrontShutdown bool, peer lnpeer.Peer,
|
||||||
|
script lnwire.DeliveryAddress,
|
||||||
getScript func() (lnwire.DeliveryAddress, error)) (lnwire.DeliveryAddress,
|
getScript func() (lnwire.DeliveryAddress, error)) (lnwire.DeliveryAddress,
|
||||||
error) {
|
error) {
|
||||||
|
|
||||||
@ -3010,7 +3019,7 @@ func getUpfrontShutdownScript(peer lnpeer.Peer, script lnwire.DeliveryAddress,
|
|||||||
|
|
||||||
// If we do not have setting of upfront shutdown script enabled, return
|
// If we do not have setting of upfront shutdown script enabled, return
|
||||||
// an empty script.
|
// an empty script.
|
||||||
if !cfg.EnableUpfrontShutdown {
|
if !enableUpfrontShutdown {
|
||||||
return nil, nil
|
return nil, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -3030,7 +3039,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
|||||||
|
|
||||||
// We'll determine our dust limit depending on which chain is active.
|
// We'll determine our dust limit depending on which chain is active.
|
||||||
var ourDustLimit btcutil.Amount
|
var ourDustLimit btcutil.Amount
|
||||||
switch registeredChains.PrimaryChain() {
|
switch f.cfg.RegisteredChains.PrimaryChain() {
|
||||||
case bitcoinChain:
|
case bitcoinChain:
|
||||||
ourDustLimit = lnwallet.DefaultDustLimit()
|
ourDustLimit = lnwallet.DefaultDustLimit()
|
||||||
case litecoinChain:
|
case litecoinChain:
|
||||||
@ -3084,7 +3093,8 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) {
|
|||||||
// address from the wallet if our node is configured to set shutdown
|
// address from the wallet if our node is configured to set shutdown
|
||||||
// address by default).
|
// address by default).
|
||||||
shutdown, err := getUpfrontShutdownScript(
|
shutdown, err := getUpfrontShutdownScript(
|
||||||
msg.peer, msg.openChanReq.shutdownScript,
|
f.cfg.EnableUpfrontShutdown, msg.peer,
|
||||||
|
msg.openChanReq.shutdownScript,
|
||||||
func() (lnwire.DeliveryAddress, error) {
|
func() (lnwire.DeliveryAddress, error) {
|
||||||
addr, err := f.cfg.Wallet.NewAddress(
|
addr, err := f.cfg.Wallet.NewAddress(
|
||||||
lnwallet.WitnessPubKey, false,
|
lnwallet.WitnessPubKey, false,
|
||||||
|
@ -21,6 +21,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
|
|
||||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||||
"github.com/lightningnetwork/lnd/chanacceptor"
|
"github.com/lightningnetwork/lnd/chanacceptor"
|
||||||
@ -417,10 +418,11 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey,
|
|||||||
},
|
},
|
||||||
ZombieSweeperInterval: 1 * time.Hour,
|
ZombieSweeperInterval: 1 * time.Hour,
|
||||||
ReservationTimeout: 1 * time.Nanosecond,
|
ReservationTimeout: 1 * time.Nanosecond,
|
||||||
MaxPendingChannels: DefaultMaxPendingChannels,
|
MaxPendingChannels: lncfg.DefaultMaxPendingChannels,
|
||||||
NotifyOpenChannelEvent: evt.NotifyOpenChannelEvent,
|
NotifyOpenChannelEvent: evt.NotifyOpenChannelEvent,
|
||||||
OpenChannelPredicate: chainedAcceptor,
|
OpenChannelPredicate: chainedAcceptor,
|
||||||
NotifyPendingOpenChannelEvent: evt.NotifyPendingOpenChannelEvent,
|
NotifyPendingOpenChannelEvent: evt.NotifyPendingOpenChannelEvent,
|
||||||
|
RegisteredChains: newChainRegistry(),
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, op := range options {
|
for _, op := range options {
|
||||||
@ -3087,11 +3089,9 @@ func TestGetUpfrontShutdownScript(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the command line option in config as needed.
|
|
||||||
cfg = &config{EnableUpfrontShutdown: test.localEnabled}
|
|
||||||
|
|
||||||
addr, err := getUpfrontShutdownScript(
|
addr, err := getUpfrontShutdownScript(
|
||||||
&mockPeer, test.upfrontScript, test.getScript,
|
test.localEnabled, &mockPeer, test.upfrontScript,
|
||||||
|
test.getScript,
|
||||||
)
|
)
|
||||||
if err != test.expectedErr {
|
if err != test.expectedErr {
|
||||||
t.Fatalf("got: %v, expected error: %v", err, test.expectedErr)
|
t.Fatalf("got: %v, expected error: %v", err, test.expectedErr)
|
||||||
|
14
lncfg/autopilot.go
Normal file
14
lncfg/autopilot.go
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
package lncfg
|
||||||
|
|
||||||
|
// AutoPilot holds the configuration options for the daemon's autopilot.
|
||||||
|
type AutoPilot struct {
|
||||||
|
Active bool `long:"active" description:"If the autopilot agent should be active or not."`
|
||||||
|
Heuristic map[string]float64 `long:"heuristic" description:"Heuristic to activate, and the weight to give it during scoring."`
|
||||||
|
MaxChannels int `long:"maxchannels" description:"The maximum number of channels that should be created"`
|
||||||
|
Allocation float64 `long:"allocation" description:"The percentage of total funds that should be committed to automatic channel establishment"`
|
||||||
|
MinChannelSize int64 `long:"minchansize" description:"The smallest channel that the autopilot agent should create"`
|
||||||
|
MaxChannelSize int64 `long:"maxchansize" description:"The largest channel that the autopilot agent should create"`
|
||||||
|
Private bool `long:"private" description:"Whether the channels created by the autopilot agent should be private or not. Private channels won't be announced to the network."`
|
||||||
|
MinConfs int32 `long:"minconfs" description:"The minimum number of confirmations each of your inputs in funding transactions created by the autopilot agent must have."`
|
||||||
|
ConfTarget uint32 `long:"conftarget" description:"The confirmation target (in blocks) for channels opened by autopilot."`
|
||||||
|
}
|
13
lncfg/bitcoind.go
Normal file
13
lncfg/bitcoind.go
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
package lncfg
|
||||||
|
|
||||||
|
// Bitcoind holds the configuration options for the daemon's connection to
|
||||||
|
// bitcoind.
|
||||||
|
type Bitcoind struct {
|
||||||
|
Dir string `long:"dir" description:"The base directory that contains the node's data, logs, configuration file, etc."`
|
||||||
|
RPCHost string `long:"rpchost" description:"The daemon's rpc listening address. If a port is omitted, then the default port for the selected chain parameters will be used."`
|
||||||
|
RPCUser string `long:"rpcuser" description:"Username for RPC connections"`
|
||||||
|
RPCPass string `long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
|
||||||
|
ZMQPubRawBlock string `long:"zmqpubrawblock" description:"The address listening for ZMQ connections to deliver raw block notifications"`
|
||||||
|
ZMQPubRawTx string `long:"zmqpubrawtx" description:"The address listening for ZMQ connections to deliver raw transaction notifications"`
|
||||||
|
EstimateMode string `long:"estimatemode" description:"The fee estimate mode. Must be either ECONOMICAL or CONSERVATIVE."`
|
||||||
|
}
|
11
lncfg/btcd.go
Normal file
11
lncfg/btcd.go
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
package lncfg
|
||||||
|
|
||||||
|
// Btcd holds the configuration options for the daemon's connection to btcd.
|
||||||
|
type Btcd struct {
|
||||||
|
Dir string `long:"dir" description:"The base directory that contains the node's data, logs, configuration file, etc."`
|
||||||
|
RPCHost string `long:"rpchost" description:"The daemon's rpc listening address. If a port is omitted, then the default port for the selected chain parameters will be used."`
|
||||||
|
RPCUser string `long:"rpcuser" description:"Username for RPC connections"`
|
||||||
|
RPCPass string `long:"rpcpass" default-mask:"-" description:"Password for RPC connections"`
|
||||||
|
RPCCert string `long:"rpccert" description:"File containing the daemon's certificate file"`
|
||||||
|
RawRPCCert string `long:"rawrpccert" description:"The raw bytes of the daemon's PEM-encoded certificate chain which will be used to authenticate the RPC connection."`
|
||||||
|
}
|
24
lncfg/chain.go
Normal file
24
lncfg/chain.go
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
package lncfg
|
||||||
|
|
||||||
|
import "github.com/lightningnetwork/lnd/lnwire"
|
||||||
|
|
||||||
|
// Chain holds the configuration options for the daemon's chain settings.
|
||||||
|
type Chain struct {
|
||||||
|
Active bool `long:"active" description:"If the chain should be active or not."`
|
||||||
|
ChainDir string `long:"chaindir" description:"The directory to store the chain's data within."`
|
||||||
|
|
||||||
|
Node string `long:"node" description:"The blockchain interface to use." choice:"btcd" choice:"bitcoind" choice:"neutrino" choice:"ltcd" choice:"litecoind"`
|
||||||
|
|
||||||
|
MainNet bool `long:"mainnet" description:"Use the main network"`
|
||||||
|
TestNet3 bool `long:"testnet" description:"Use the test network"`
|
||||||
|
SimNet bool `long:"simnet" description:"Use the simulation test network"`
|
||||||
|
RegTest bool `long:"regtest" description:"Use the regression test network"`
|
||||||
|
|
||||||
|
DefaultNumChanConfs int `long:"defaultchanconfs" description:"The default number of confirmations a channel must have before it's considered open. If this is not set, we will scale the value according to the channel size."`
|
||||||
|
DefaultRemoteDelay int `long:"defaultremotedelay" description:"The default number of blocks we will require our channel counterparty to wait before accessing its funds in case of unilateral close. If this is not set, we will scale the value according to the channel size."`
|
||||||
|
MinHTLCIn lnwire.MilliSatoshi `long:"minhtlc" description:"The smallest HTLC we are willing to accept on our channels, in millisatoshi"`
|
||||||
|
MinHTLCOut lnwire.MilliSatoshi `long:"minhtlcout" description:"The smallest HTLC we are willing to send out on our channels, in millisatoshi"`
|
||||||
|
BaseFee lnwire.MilliSatoshi `long:"basefee" description:"The base fee in millisatoshi we will charge for forwarding payments on our channels"`
|
||||||
|
FeeRate lnwire.MilliSatoshi `long:"feerate" description:"The fee rate used when forwarding payments on our channels. The total fee charged is basefee + (amount * feerate / 1000000), where amount is the forwarded amount."`
|
||||||
|
TimeLockDelta uint32 `long:"timelockdelta" description:"The CLTV delta we will subtract from a forwarded HTLC's timelock value"`
|
||||||
|
}
|
89
lncfg/config.go
Normal file
89
lncfg/config.go
Normal file
@ -0,0 +1,89 @@
|
|||||||
|
package lncfg
|
||||||
|
|
||||||
|
import (
|
||||||
|
"os"
|
||||||
|
"os/user"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
// DefaultConfigFilename is the default configuration file name lnd
|
||||||
|
// tries to load.
|
||||||
|
DefaultConfigFilename = "lnd.conf"
|
||||||
|
|
||||||
|
// DefaultMaxPendingChannels is the default maximum number of incoming
|
||||||
|
// pending channels permitted per peer.
|
||||||
|
DefaultMaxPendingChannels = 1
|
||||||
|
|
||||||
|
// DefaultIncomingBroadcastDelta defines the number of blocks before the
|
||||||
|
// expiry of an incoming htlc at which we force close the channel. We
|
||||||
|
// only go to chain if we also have the preimage to actually pull in the
|
||||||
|
// htlc. BOLT #2 suggests 7 blocks. We use a few more for extra safety.
|
||||||
|
// Within this window we need to get our sweep or 2nd level success tx
|
||||||
|
// confirmed, because after that the remote party is also able to claim
|
||||||
|
// the htlc using the timeout path.
|
||||||
|
DefaultIncomingBroadcastDelta = 10
|
||||||
|
|
||||||
|
// DefaultFinalCltvRejectDelta defines the number of blocks before the
|
||||||
|
// expiry of an incoming exit hop htlc at which we cancel it back
|
||||||
|
// immediately. It is an extra safety measure over the final cltv
|
||||||
|
// requirement as it is defined in the invoice. It ensures that we
|
||||||
|
// cancel back htlcs that, when held on to, may cause us to force close
|
||||||
|
// the channel because we enter the incoming broadcast window. Bolt #11
|
||||||
|
// suggests 9 blocks here. We use a few more for additional safety.
|
||||||
|
//
|
||||||
|
// There is still a small gap that remains between receiving the
|
||||||
|
// RevokeAndAck and canceling back. If a new block arrives within that
|
||||||
|
// window, we may still force close the channel. There is currently no
|
||||||
|
// way to reject an UpdateAddHtlc of which we already know that it will
|
||||||
|
// push us in the broadcast window.
|
||||||
|
DefaultFinalCltvRejectDelta = DefaultIncomingBroadcastDelta + 3
|
||||||
|
|
||||||
|
// DefaultOutgoingBroadcastDelta defines the number of blocks before the
|
||||||
|
// expiry of an outgoing htlc at which we force close the channel. We
|
||||||
|
// are not in a hurry to force close, because there is nothing to claim
|
||||||
|
// for us. We do need to time the htlc out, because there may be an
|
||||||
|
// incoming htlc that will time out too (albeit later). Bolt #2 suggests
|
||||||
|
// a value of -1 here, but we allow one block less to prevent potential
|
||||||
|
// confusion around the negative value. It means we force close the
|
||||||
|
// channel at exactly the htlc expiry height.
|
||||||
|
DefaultOutgoingBroadcastDelta = 0
|
||||||
|
|
||||||
|
// DefaultOutgoingCltvRejectDelta defines the number of blocks before
|
||||||
|
// the expiry of an outgoing htlc at which we don't want to offer it to
|
||||||
|
// the next peer anymore. If that happens, we cancel back the incoming
|
||||||
|
// htlc. This is to prevent the situation where we have an outstanding
|
||||||
|
// htlc that brings or will soon bring us inside the outgoing broadcast
|
||||||
|
// window and trigger us to force close the channel. Bolt #2 suggests a
|
||||||
|
// value of 0. We pad it a bit, to prevent a slow round trip to the next
|
||||||
|
// peer and a block arriving during that round trip to trigger force
|
||||||
|
// closure.
|
||||||
|
DefaultOutgoingCltvRejectDelta = DefaultOutgoingBroadcastDelta + 3
|
||||||
|
)
|
||||||
|
|
||||||
|
// CleanAndExpandPath expands environment variables and leading ~ in the
|
||||||
|
// passed path, cleans the result, and returns it.
|
||||||
|
// This function is taken from https://github.com/btcsuite/btcd
|
||||||
|
func CleanAndExpandPath(path string) string {
|
||||||
|
if path == "" {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
|
// Expand initial ~ to OS specific home directory.
|
||||||
|
if strings.HasPrefix(path, "~") {
|
||||||
|
var homeDir string
|
||||||
|
u, err := user.Current()
|
||||||
|
if err == nil {
|
||||||
|
homeDir = u.HomeDir
|
||||||
|
} else {
|
||||||
|
homeDir = os.Getenv("HOME")
|
||||||
|
}
|
||||||
|
|
||||||
|
path = strings.Replace(path, "~", homeDir, 1)
|
||||||
|
}
|
||||||
|
|
||||||
|
// NOTE: The os.ExpandEnv doesn't work with Windows-style %VARIABLE%,
|
||||||
|
// but the variables can still be expanded via POSIX-style $VARIABLE.
|
||||||
|
return filepath.Clean(os.ExpandEnv(path))
|
||||||
|
}
|
15
lncfg/neutrino.go
Normal file
15
lncfg/neutrino.go
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
package lncfg
|
||||||
|
|
||||||
|
import "time"
|
||||||
|
|
||||||
|
// Neutrino holds the configuration options for the daemon's connection to
|
||||||
|
// neutrino.
|
||||||
|
type Neutrino struct {
|
||||||
|
AddPeers []string `short:"a" long:"addpeer" description:"Add a peer to connect with at startup"`
|
||||||
|
ConnectPeers []string `long:"connect" description:"Connect only to the specified peers at startup"`
|
||||||
|
MaxPeers int `long:"maxpeers" description:"Max number of inbound and outbound peers"`
|
||||||
|
BanDuration time.Duration `long:"banduration" description:"How long to ban misbehaving peers. Valid time units are {s, m, h}. Minimum 1 second"`
|
||||||
|
BanThreshold uint32 `long:"banthreshold" description:"Maximum allowed ban score before disconnecting and banning misbehaving peers."`
|
||||||
|
FeeURL string `long:"feeurl" description:"Optional URL for fee estimation. If a URL is not specified, static fees will be used for estimation."`
|
||||||
|
AssertFilterHeader string `long:"assertfilterheader" description:"Optional filter header in height:hash format to assert the state of neutrino's filter header chain on startup. If the assertion does not hold, then the filter header chain will be re-synced from the genesis block."`
|
||||||
|
}
|
16
lncfg/tor.go
Normal file
16
lncfg/tor.go
Normal file
@ -0,0 +1,16 @@
|
|||||||
|
package lncfg
|
||||||
|
|
||||||
|
// Tor holds the configuration options for the daemon's connection to tor.
|
||||||
|
type Tor struct {
|
||||||
|
Active bool `long:"active" description:"Allow outbound and inbound connections to be routed through Tor"`
|
||||||
|
SOCKS string `long:"socks" description:"The host:port that Tor's exposed SOCKS5 proxy is listening on"`
|
||||||
|
DNS string `long:"dns" description:"The DNS server as host:port that Tor will use for SRV queries - NOTE must have TCP resolution enabled"`
|
||||||
|
StreamIsolation bool `long:"streamisolation" description:"Enable Tor stream isolation by randomizing user credentials for each connection."`
|
||||||
|
Control string `long:"control" description:"The host:port that Tor is listening on for Tor control connections"`
|
||||||
|
TargetIPAddress string `long:"targetipaddress" description:"IP address that Tor should use as the target of the hidden service"`
|
||||||
|
Password string `long:"password" description:"The password used to arrive at the HashedControlPassword for the control port. If provided, the HASHEDPASSWORD authentication method will be used instead of the SAFECOOKIE one."`
|
||||||
|
V2 bool `long:"v2" description:"Automatically set up a v2 onion service to listen for inbound connections"`
|
||||||
|
V3 bool `long:"v3" description:"Automatically set up a v3 onion service to listen for inbound connections"`
|
||||||
|
PrivateKeyPath string `long:"privatekeypath" description:"The path to the private key of the onion service being created"`
|
||||||
|
WatchtowerKeyPath string `long:"watchtowerkeypath" description:"The path to the private key of the watchtower onion service being created"`
|
||||||
|
}
|
148
lnd.go
148
lnd.go
@ -51,22 +51,12 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/watchtower/wtdb"
|
"github.com/lightningnetwork/lnd/watchtower/wtdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
cfg *config
|
|
||||||
registeredChains = newChainRegistry()
|
|
||||||
|
|
||||||
// networkDir is the path to the directory of the currently active
|
|
||||||
// network. This path will hold the files related to each different
|
|
||||||
// network.
|
|
||||||
networkDir string
|
|
||||||
)
|
|
||||||
|
|
||||||
// WalletUnlockerAuthOptions returns a list of DialOptions that can be used to
|
// WalletUnlockerAuthOptions returns a list of DialOptions that can be used to
|
||||||
// authenticate with the wallet unlocker service.
|
// authenticate with the wallet unlocker service.
|
||||||
//
|
//
|
||||||
// NOTE: This should only be called after the WalletUnlocker listener has
|
// NOTE: This should only be called after the WalletUnlocker listener has
|
||||||
// signaled it is ready.
|
// signaled it is ready.
|
||||||
func WalletUnlockerAuthOptions() ([]grpc.DialOption, error) {
|
func WalletUnlockerAuthOptions(cfg *Config) ([]grpc.DialOption, error) {
|
||||||
creds, err := credentials.NewClientTLSFromFile(cfg.TLSCertPath, "")
|
creds, err := credentials.NewClientTLSFromFile(cfg.TLSCertPath, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to read TLS cert: %v", err)
|
return nil, fmt.Errorf("unable to read TLS cert: %v", err)
|
||||||
@ -85,7 +75,7 @@ func WalletUnlockerAuthOptions() ([]grpc.DialOption, error) {
|
|||||||
//
|
//
|
||||||
// NOTE: This should only be called after the RPCListener has signaled it is
|
// NOTE: This should only be called after the RPCListener has signaled it is
|
||||||
// ready.
|
// ready.
|
||||||
func AdminAuthOptions() ([]grpc.DialOption, error) {
|
func AdminAuthOptions(cfg *Config) ([]grpc.DialOption, error) {
|
||||||
creds, err := credentials.NewClientTLSFromFile(cfg.TLSCertPath, "")
|
creds, err := credentials.NewClientTLSFromFile(cfg.TLSCertPath, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("unable to read TLS cert: %v", err)
|
return nil, fmt.Errorf("unable to read TLS cert: %v", err)
|
||||||
@ -119,6 +109,45 @@ func AdminAuthOptions() ([]grpc.DialOption, error) {
|
|||||||
return opts, nil
|
return opts, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GrpcRegistrar is an interface that must be satisfied by an external subserver
|
||||||
|
// that wants to be able to register its own gRPC server onto lnd's main
|
||||||
|
// grpc.Server instance.
|
||||||
|
type GrpcRegistrar interface {
|
||||||
|
// RegisterGrpcSubserver is called for each net.Listener on which lnd
|
||||||
|
// creates a grpc.Server instance. External subservers implementing this
|
||||||
|
// method can then register their own gRPC server structs to the main
|
||||||
|
// server instance.
|
||||||
|
RegisterGrpcSubserver(*grpc.Server) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// RestRegistrar is an interface that must be satisfied by an external subserver
|
||||||
|
// that wants to be able to register its own REST mux onto lnd's main
|
||||||
|
// proxy.ServeMux instance.
|
||||||
|
type RestRegistrar interface {
|
||||||
|
// RegisterRestSubserver is called after lnd creates the main
|
||||||
|
// proxy.ServeMux instance. External subservers implementing this method
|
||||||
|
// can then register their own REST proxy stubs to the main server
|
||||||
|
// instance.
|
||||||
|
RegisterRestSubserver(context.Context, *proxy.ServeMux, string,
|
||||||
|
[]grpc.DialOption) error
|
||||||
|
}
|
||||||
|
|
||||||
|
// RPCSubserverConfig is a struct that can be used to register an external
|
||||||
|
// subserver with the custom permissions that map to the gRPC server that is
|
||||||
|
// going to be registered with the GrpcRegistrar.
|
||||||
|
type RPCSubserverConfig struct {
|
||||||
|
// Registrar is a callback that is invoked for each net.Listener on
|
||||||
|
// which lnd creates a grpc.Server instance.
|
||||||
|
Registrar GrpcRegistrar
|
||||||
|
|
||||||
|
// Permissions is the permissions required for the external subserver.
|
||||||
|
// It is a map between the full HTTP URI of each RPC and its required
|
||||||
|
// macaroon permissions. If multiple action/entity tuples are specified
|
||||||
|
// per URI, they are all required. See rpcserver.go for a list of valid
|
||||||
|
// action and entity values.
|
||||||
|
Permissions map[string][]bakery.Op
|
||||||
|
}
|
||||||
|
|
||||||
// ListenerWithSignal is a net.Listener that has an additional Ready channel that
|
// ListenerWithSignal is a net.Listener that has an additional Ready channel that
|
||||||
// will be closed when a server starts listening.
|
// will be closed when a server starts listening.
|
||||||
type ListenerWithSignal struct {
|
type ListenerWithSignal struct {
|
||||||
@ -126,6 +155,14 @@ type ListenerWithSignal struct {
|
|||||||
|
|
||||||
// Ready will be closed by the server listening on Listener.
|
// Ready will be closed by the server listening on Listener.
|
||||||
Ready chan struct{}
|
Ready chan struct{}
|
||||||
|
|
||||||
|
// ExternalRPCSubserverCfg is optional and specifies the registration
|
||||||
|
// callback and permissions to register external gRPC subservers.
|
||||||
|
ExternalRPCSubserverCfg *RPCSubserverConfig
|
||||||
|
|
||||||
|
// ExternalRestRegistrar is optional and specifies the registration
|
||||||
|
// callback to register external REST subservers.
|
||||||
|
ExternalRestRegistrar RestRegistrar
|
||||||
}
|
}
|
||||||
|
|
||||||
// ListenerCfg is a wrapper around custom listeners that can be passed to lnd
|
// ListenerCfg is a wrapper around custom listeners that can be passed to lnd
|
||||||
@ -147,23 +184,14 @@ type ListenerCfg struct {
|
|||||||
// listeners.
|
// listeners.
|
||||||
type rpcListeners func() ([]*ListenerWithSignal, func(), error)
|
type rpcListeners func() ([]*ListenerWithSignal, func(), error)
|
||||||
|
|
||||||
// Main is the true entry point for lnd. This function is required since defers
|
// Main is the true entry point for lnd. It accepts a fully populated and
|
||||||
// created in the top-level scope of a main method aren't executed if os.Exit()
|
// validated main configuration struct and an optional listener config struct.
|
||||||
// is called.
|
// This function starts all main system components then blocks until a signal
|
||||||
func Main(lisCfg ListenerCfg) error {
|
// is received on the shutdownChan at which point everything is shut down again.
|
||||||
// Hook interceptor for os signals.
|
func Main(cfg *Config, lisCfg ListenerCfg, shutdownChan <-chan struct{}) error {
|
||||||
signal.Intercept()
|
|
||||||
|
|
||||||
// Load the configuration, and parse any command line options. This
|
|
||||||
// function will also set up logging properly.
|
|
||||||
loadedConfig, err := loadConfig()
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
cfg = loadedConfig
|
|
||||||
defer func() {
|
defer func() {
|
||||||
ltndLog.Info("Shutdown complete")
|
ltndLog.Info("Shutdown complete")
|
||||||
err := logWriter.Close()
|
err := RootLogWriter.Close()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ltndLog.Errorf("Could not close log rotator: %v", err)
|
ltndLog.Errorf("Could not close log rotator: %v", err)
|
||||||
}
|
}
|
||||||
@ -190,7 +218,7 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
ltndLog.Infof("Active chain: %v (network=%v)",
|
ltndLog.Infof("Active chain: %v (network=%v)",
|
||||||
strings.Title(registeredChains.PrimaryChain().String()),
|
strings.Title(cfg.registeredChains.PrimaryChain().String()),
|
||||||
network,
|
network,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -256,10 +284,7 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
ctx, cancel := context.WithCancel(ctx)
|
ctx, cancel := context.WithCancel(ctx)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
tlsCfg, restCreds, restProxyDest, err := getTLSConfig(
|
tlsCfg, restCreds, restProxyDest, err := getTLSConfig(cfg)
|
||||||
cfg.TLSCertPath, cfg.TLSKeyPath, cfg.TLSExtraIPs,
|
|
||||||
cfg.TLSExtraDomains, cfg.RPCListeners,
|
|
||||||
)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("unable to load TLS credentials: %v", err)
|
err := fmt.Errorf("unable to load TLS credentials: %v", err)
|
||||||
ltndLog.Error(err)
|
ltndLog.Error(err)
|
||||||
@ -285,13 +310,13 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
// light client instance, if enabled, in order to allow it to sync
|
// light client instance, if enabled, in order to allow it to sync
|
||||||
// while the rest of the daemon continues startup.
|
// while the rest of the daemon continues startup.
|
||||||
mainChain := cfg.Bitcoin
|
mainChain := cfg.Bitcoin
|
||||||
if registeredChains.PrimaryChain() == litecoinChain {
|
if cfg.registeredChains.PrimaryChain() == litecoinChain {
|
||||||
mainChain = cfg.Litecoin
|
mainChain = cfg.Litecoin
|
||||||
}
|
}
|
||||||
var neutrinoCS *neutrino.ChainService
|
var neutrinoCS *neutrino.ChainService
|
||||||
if mainChain.Node == "neutrino" {
|
if mainChain.Node == "neutrino" {
|
||||||
neutrinoBackend, neutrinoCleanUp, err := initNeutrinoBackend(
|
neutrinoBackend, neutrinoCleanUp, err := initNeutrinoBackend(
|
||||||
mainChain.ChainDir,
|
cfg, mainChain.ChainDir,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("unable to initialize neutrino "+
|
err := fmt.Errorf("unable to initialize neutrino "+
|
||||||
@ -365,7 +390,7 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
// for wallet encryption.
|
// for wallet encryption.
|
||||||
if !cfg.NoSeedBackup {
|
if !cfg.NoSeedBackup {
|
||||||
params, err := waitForWalletPassword(
|
params, err := waitForWalletPassword(
|
||||||
cfg.RESTListeners, serverOpts, restDialOpts,
|
cfg, cfg.RESTListeners, serverOpts, restDialOpts,
|
||||||
restProxyDest, tlsCfg, walletUnlockerListeners,
|
restProxyDest, tlsCfg, walletUnlockerListeners,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -390,7 +415,7 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
if !cfg.NoMacaroons {
|
if !cfg.NoMacaroons {
|
||||||
// Create the macaroon authentication/authorization service.
|
// Create the macaroon authentication/authorization service.
|
||||||
macaroonService, err = macaroons.NewService(
|
macaroonService, err = macaroons.NewService(
|
||||||
networkDir, macaroons.IPLockChecker,
|
cfg.networkDir, macaroons.IPLockChecker,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err := fmt.Errorf("unable to set up macaroon "+
|
err := fmt.Errorf("unable to set up macaroon "+
|
||||||
@ -442,8 +467,8 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
// Finally before we start the server, we'll register the "holy
|
// Finally before we start the server, we'll register the "holy
|
||||||
// trinity" of interface for our current "home chain" with the active
|
// trinity" of interface for our current "home chain" with the active
|
||||||
// chainRegistry interface.
|
// chainRegistry interface.
|
||||||
primaryChain := registeredChains.PrimaryChain()
|
primaryChain := cfg.registeredChains.PrimaryChain()
|
||||||
registeredChains.RegisterChain(primaryChain, activeChainControl)
|
cfg.registeredChains.RegisterChain(primaryChain, activeChainControl)
|
||||||
|
|
||||||
// TODO(roasbeef): add rotation
|
// TODO(roasbeef): add rotation
|
||||||
idPrivKey, err := activeChainControl.wallet.DerivePrivKey(keychain.KeyDescriptor{
|
idPrivKey, err := activeChainControl.wallet.DerivePrivKey(keychain.KeyDescriptor{
|
||||||
@ -507,7 +532,7 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
// Segment the watchtower directory by chain and network.
|
// Segment the watchtower directory by chain and network.
|
||||||
towerDBDir := filepath.Join(
|
towerDBDir := filepath.Join(
|
||||||
cfg.Watchtower.TowerDir,
|
cfg.Watchtower.TowerDir,
|
||||||
registeredChains.PrimaryChain().String(),
|
cfg.registeredChains.PrimaryChain().String(),
|
||||||
normalizeNetwork(activeNetParams.Name),
|
normalizeNetwork(activeNetParams.Name),
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -586,7 +611,7 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
// Set up the core server which will listen for incoming peer
|
// Set up the core server which will listen for incoming peer
|
||||||
// connections.
|
// connections.
|
||||||
server, err := newServer(
|
server, err := newServer(
|
||||||
cfg.Listeners, chanDB, towerClientDB, activeChainControl,
|
cfg, cfg.Listeners, chanDB, towerClientDB, activeChainControl,
|
||||||
idPrivKey, walletInitParams.ChansToRestore, chainedAcceptor,
|
idPrivKey, walletInitParams.ChansToRestore, chainedAcceptor,
|
||||||
torController,
|
torController,
|
||||||
)
|
)
|
||||||
@ -636,7 +661,7 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
// Initialize, and register our implementation of the gRPC interface
|
// Initialize, and register our implementation of the gRPC interface
|
||||||
// exported by the rpcServer.
|
// exported by the rpcServer.
|
||||||
rpcServer, err := newRPCServer(
|
rpcServer, err := newRPCServer(
|
||||||
server, macaroonService, cfg.SubRPCServers, serverOpts,
|
cfg, server, macaroonService, cfg.SubRPCServers, serverOpts,
|
||||||
restDialOpts, restProxyDest, atplManager, server.invoices,
|
restDialOpts, restProxyDest, atplManager, server.invoices,
|
||||||
tower, tlsCfg, rpcListeners, chainedAcceptor,
|
tower, tlsCfg, rpcListeners, chainedAcceptor,
|
||||||
)
|
)
|
||||||
@ -734,22 +759,21 @@ func Main(lisCfg ListenerCfg) error {
|
|||||||
|
|
||||||
// Wait for shutdown signal from either a graceful server stop or from
|
// Wait for shutdown signal from either a graceful server stop or from
|
||||||
// the interrupt handler.
|
// the interrupt handler.
|
||||||
<-signal.ShutdownChannel()
|
<-shutdownChan
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// getTLSConfig returns a TLS configuration for the gRPC server and credentials
|
// getTLSConfig returns a TLS configuration for the gRPC server and credentials
|
||||||
// and a proxy destination for the REST reverse proxy.
|
// and a proxy destination for the REST reverse proxy.
|
||||||
func getTLSConfig(tlsCertPath string, tlsKeyPath string, tlsExtraIPs,
|
func getTLSConfig(cfg *Config) (*tls.Config, *credentials.TransportCredentials,
|
||||||
tlsExtraDomains []string, rpcListeners []net.Addr) (*tls.Config,
|
string, error) {
|
||||||
*credentials.TransportCredentials, string, error) {
|
|
||||||
|
|
||||||
// Ensure we create TLS key and certificate if they don't exist.
|
// Ensure we create TLS key and certificate if they don't exist.
|
||||||
if !fileExists(tlsCertPath) && !fileExists(tlsKeyPath) {
|
if !fileExists(cfg.TLSCertPath) && !fileExists(cfg.TLSKeyPath) {
|
||||||
rpcsLog.Infof("Generating TLS certificates...")
|
rpcsLog.Infof("Generating TLS certificates...")
|
||||||
err := cert.GenCertPair(
|
err := cert.GenCertPair(
|
||||||
"lnd autogenerated cert", tlsCertPath, tlsKeyPath,
|
"lnd autogenerated cert", cfg.TLSCertPath,
|
||||||
tlsExtraIPs, tlsExtraDomains,
|
cfg.TLSKeyPath, cfg.TLSExtraIPs, cfg.TLSExtraDomains,
|
||||||
cert.DefaultAutogenValidity,
|
cert.DefaultAutogenValidity,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -758,7 +782,9 @@ func getTLSConfig(tlsCertPath string, tlsKeyPath string, tlsExtraIPs,
|
|||||||
rpcsLog.Infof("Done generating TLS certificates")
|
rpcsLog.Infof("Done generating TLS certificates")
|
||||||
}
|
}
|
||||||
|
|
||||||
certData, parsedCert, err := cert.LoadCert(tlsCertPath, tlsKeyPath)
|
certData, parsedCert, err := cert.LoadCert(
|
||||||
|
cfg.TLSCertPath, cfg.TLSKeyPath,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, "", err
|
return nil, nil, "", err
|
||||||
}
|
}
|
||||||
@ -770,7 +796,7 @@ func getTLSConfig(tlsCertPath string, tlsKeyPath string, tlsExtraIPs,
|
|||||||
refresh := false
|
refresh := false
|
||||||
if cfg.TLSAutoRefresh {
|
if cfg.TLSAutoRefresh {
|
||||||
refresh, err = cert.IsOutdated(
|
refresh, err = cert.IsOutdated(
|
||||||
parsedCert, tlsExtraIPs, tlsExtraDomains,
|
parsedCert, cfg.TLSExtraIPs, cfg.TLSExtraDomains,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, "", err
|
return nil, nil, "", err
|
||||||
@ -783,20 +809,20 @@ func getTLSConfig(tlsCertPath string, tlsKeyPath string, tlsExtraIPs,
|
|||||||
ltndLog.Info("TLS certificate is expired or outdated, " +
|
ltndLog.Info("TLS certificate is expired or outdated, " +
|
||||||
"generating a new one")
|
"generating a new one")
|
||||||
|
|
||||||
err := os.Remove(tlsCertPath)
|
err := os.Remove(cfg.TLSCertPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, "", err
|
return nil, nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
err = os.Remove(tlsKeyPath)
|
err = os.Remove(cfg.TLSKeyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, "", err
|
return nil, nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
rpcsLog.Infof("Renewing TLS certificates...")
|
rpcsLog.Infof("Renewing TLS certificates...")
|
||||||
err = cert.GenCertPair(
|
err = cert.GenCertPair(
|
||||||
"lnd autogenerated cert", tlsCertPath, tlsKeyPath,
|
"lnd autogenerated cert", cfg.TLSCertPath,
|
||||||
tlsExtraIPs, tlsExtraDomains,
|
cfg.TLSKeyPath, cfg.TLSExtraIPs, cfg.TLSExtraDomains,
|
||||||
cert.DefaultAutogenValidity,
|
cert.DefaultAutogenValidity,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -805,19 +831,21 @@ func getTLSConfig(tlsCertPath string, tlsKeyPath string, tlsExtraIPs,
|
|||||||
rpcsLog.Infof("Done renewing TLS certificates")
|
rpcsLog.Infof("Done renewing TLS certificates")
|
||||||
|
|
||||||
// Reload the certificate data.
|
// Reload the certificate data.
|
||||||
certData, _, err = cert.LoadCert(tlsCertPath, tlsKeyPath)
|
certData, _, err = cert.LoadCert(
|
||||||
|
cfg.TLSCertPath, cfg.TLSKeyPath,
|
||||||
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, "", err
|
return nil, nil, "", err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
tlsCfg := cert.TLSConfFromCert(certData)
|
tlsCfg := cert.TLSConfFromCert(certData)
|
||||||
restCreds, err := credentials.NewClientTLSFromFile(tlsCertPath, "")
|
restCreds, err := credentials.NewClientTLSFromFile(cfg.TLSCertPath, "")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, "", err
|
return nil, nil, "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
restProxyDest := rpcListeners[0].String()
|
restProxyDest := cfg.RPCListeners[0].String()
|
||||||
switch {
|
switch {
|
||||||
case strings.Contains(restProxyDest, "0.0.0.0"):
|
case strings.Contains(restProxyDest, "0.0.0.0"):
|
||||||
restProxyDest = strings.Replace(
|
restProxyDest = strings.Replace(
|
||||||
@ -934,7 +962,7 @@ type WalletUnlockParams struct {
|
|||||||
// waitForWalletPassword will spin up gRPC and REST endpoints for the
|
// waitForWalletPassword will spin up gRPC and REST endpoints for the
|
||||||
// WalletUnlocker server, and block until a password is provided by
|
// WalletUnlocker server, and block until a password is provided by
|
||||||
// the user to this RPC server.
|
// the user to this RPC server.
|
||||||
func waitForWalletPassword(restEndpoints []net.Addr,
|
func waitForWalletPassword(cfg *Config, restEndpoints []net.Addr,
|
||||||
serverOpts []grpc.ServerOption, restDialOpts []grpc.DialOption,
|
serverOpts []grpc.ServerOption, restDialOpts []grpc.DialOption,
|
||||||
restProxyDest string, tlsConf *tls.Config,
|
restProxyDest string, tlsConf *tls.Config,
|
||||||
getListeners rpcListeners) (*WalletUnlockParams, error) {
|
getListeners rpcListeners) (*WalletUnlockParams, error) {
|
||||||
@ -953,7 +981,7 @@ func waitForWalletPassword(restEndpoints []net.Addr,
|
|||||||
defer grpcServer.GracefulStop()
|
defer grpcServer.GracefulStop()
|
||||||
|
|
||||||
chainConfig := cfg.Bitcoin
|
chainConfig := cfg.Bitcoin
|
||||||
if registeredChains.PrimaryChain() == litecoinChain {
|
if cfg.registeredChains.PrimaryChain() == litecoinChain {
|
||||||
chainConfig = cfg.Litecoin
|
chainConfig = cfg.Litecoin
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -962,7 +990,7 @@ func waitForWalletPassword(restEndpoints []net.Addr,
|
|||||||
// deleted within it and recreated when successfully changing the
|
// deleted within it and recreated when successfully changing the
|
||||||
// wallet's password.
|
// wallet's password.
|
||||||
macaroonFiles := []string{
|
macaroonFiles := []string{
|
||||||
filepath.Join(networkDir, macaroons.DBFilename),
|
filepath.Join(cfg.networkDir, macaroons.DBFilename),
|
||||||
cfg.AdminMacPath, cfg.ReadMacPath, cfg.InvoiceMacPath,
|
cfg.AdminMacPath, cfg.ReadMacPath, cfg.InvoiceMacPath,
|
||||||
}
|
}
|
||||||
pwService := walletunlocker.New(
|
pwService := walletunlocker.New(
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd"
|
"github.com/lightningnetwork/lnd"
|
||||||
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
@ -136,7 +137,7 @@ func testMultiHopHtlcLocalChainClaim(net *lntest.NetworkHarness, t *harnessTest,
|
|||||||
// We'll now mine enough blocks so Carol decides that she needs to go
|
// We'll now mine enough blocks so Carol decides that she needs to go
|
||||||
// on-chain to claim the HTLC as Bob has been inactive.
|
// on-chain to claim the HTLC as Bob has been inactive.
|
||||||
numBlocks := padCLTV(uint32(invoiceReq.CltvExpiry -
|
numBlocks := padCLTV(uint32(invoiceReq.CltvExpiry -
|
||||||
lnd.DefaultIncomingBroadcastDelta))
|
lncfg.DefaultIncomingBroadcastDelta))
|
||||||
|
|
||||||
if _, err := net.Miner.Node.Generate(numBlocks); err != nil {
|
if _, err := net.Miner.Node.Generate(numBlocks); err != nil {
|
||||||
t.Fatalf("unable to generate blocks")
|
t.Fatalf("unable to generate blocks")
|
||||||
|
@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd"
|
"github.com/lightningnetwork/lnd"
|
||||||
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
"github.com/lightningnetwork/lnd/lntest/wait"
|
"github.com/lightningnetwork/lnd/lntest/wait"
|
||||||
@ -101,7 +102,7 @@ func testMultiHopHtlcLocalTimeout(net *lntest.NetworkHarness, t *harnessTest,
|
|||||||
// timeout. With the default outgoing broadcast delta of zero, this will
|
// timeout. With the default outgoing broadcast delta of zero, this will
|
||||||
// be the same height as the htlc expiry height.
|
// be the same height as the htlc expiry height.
|
||||||
numBlocks := padCLTV(
|
numBlocks := padCLTV(
|
||||||
uint32(finalCltvDelta - lnd.DefaultOutgoingBroadcastDelta),
|
uint32(finalCltvDelta - lncfg.DefaultOutgoingBroadcastDelta),
|
||||||
)
|
)
|
||||||
if _, err := net.Miner.Node.Generate(numBlocks); err != nil {
|
if _, err := net.Miner.Node.Generate(numBlocks); err != nil {
|
||||||
t.Fatalf("unable to generate blocks: %v", err)
|
t.Fatalf("unable to generate blocks: %v", err)
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd"
|
"github.com/lightningnetwork/lnd"
|
||||||
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
@ -118,7 +119,7 @@ func testMultiHopReceiverChainClaim(net *lntest.NetworkHarness, t *harnessTest,
|
|||||||
// chain in order to sweep her HTLC since the value is high enough.
|
// chain in order to sweep her HTLC since the value is high enough.
|
||||||
// TODO(roasbeef): modify once go to chain policy changes
|
// TODO(roasbeef): modify once go to chain policy changes
|
||||||
numBlocks := padCLTV(uint32(
|
numBlocks := padCLTV(uint32(
|
||||||
invoiceReq.CltvExpiry - lnd.DefaultIncomingBroadcastDelta,
|
invoiceReq.CltvExpiry - lncfg.DefaultIncomingBroadcastDelta,
|
||||||
))
|
))
|
||||||
if _, err := net.Miner.Node.Generate(numBlocks); err != nil {
|
if _, err := net.Miner.Node.Generate(numBlocks); err != nil {
|
||||||
t.Fatalf("unable to generate blocks")
|
t.Fatalf("unable to generate blocks")
|
||||||
|
@ -10,6 +10,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/davecgh/go-spew/spew"
|
"github.com/davecgh/go-spew/spew"
|
||||||
"github.com/lightningnetwork/lnd"
|
"github.com/lightningnetwork/lnd"
|
||||||
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||||
"github.com/lightningnetwork/lnd/lntest"
|
"github.com/lightningnetwork/lnd/lntest"
|
||||||
@ -148,7 +149,7 @@ func testMultiHopHtlcRemoteChainClaim(net *lntest.NetworkHarness, t *harnessTest
|
|||||||
// We'll now mine enough blocks so Carol decides that she needs to go
|
// We'll now mine enough blocks so Carol decides that she needs to go
|
||||||
// on-chain to claim the HTLC as Bob has been inactive.
|
// on-chain to claim the HTLC as Bob has been inactive.
|
||||||
numBlocks := padCLTV(uint32(invoiceReq.CltvExpiry-
|
numBlocks := padCLTV(uint32(invoiceReq.CltvExpiry-
|
||||||
lnd.DefaultIncomingBroadcastDelta) - defaultCSV)
|
lncfg.DefaultIncomingBroadcastDelta) - defaultCSV)
|
||||||
|
|
||||||
if _, err := net.Miner.Node.Generate(numBlocks); err != nil {
|
if _, err := net.Miner.Node.Generate(numBlocks); err != nil {
|
||||||
t.Fatalf("unable to generate blocks")
|
t.Fatalf("unable to generate blocks")
|
||||||
|
@ -34,6 +34,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/chanbackup"
|
"github.com/lightningnetwork/lnd/chanbackup"
|
||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/invoicesrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
"github.com/lightningnetwork/lnd/lnrpc/routerrpc"
|
||||||
@ -6695,7 +6696,7 @@ func testBasicChannelCreationAndUpdates(net *lntest.NetworkHarness, t *harnessTe
|
|||||||
func testMaxPendingChannels(net *lntest.NetworkHarness, t *harnessTest) {
|
func testMaxPendingChannels(net *lntest.NetworkHarness, t *harnessTest) {
|
||||||
ctxb := context.Background()
|
ctxb := context.Background()
|
||||||
|
|
||||||
maxPendingChannels := lnd.DefaultMaxPendingChannels + 1
|
maxPendingChannels := lncfg.DefaultMaxPendingChannels + 1
|
||||||
amount := lnd.MaxBtcFundingAmount
|
amount := lnd.MaxBtcFundingAmount
|
||||||
|
|
||||||
// Create a new node (Carol) with greater number of max pending
|
// Create a new node (Carol) with greater number of max pending
|
||||||
|
26
log.go
26
log.go
@ -46,21 +46,23 @@ import (
|
|||||||
//
|
//
|
||||||
// Loggers can not be used before the log rotator has been initialized with a
|
// Loggers can not be used before the log rotator has been initialized with a
|
||||||
// log file. This must be performed early during application startup by
|
// log file. This must be performed early during application startup by
|
||||||
// calling logWriter.InitLogRotator.
|
// calling RootLogWriter.InitLogRotator.
|
||||||
var (
|
var (
|
||||||
logWriter = build.NewRotatingLogWriter()
|
// RootLogWriter is the main parent log writer all sub loggers should be
|
||||||
|
// appended to.
|
||||||
|
RootLogWriter = build.NewRotatingLogWriter()
|
||||||
|
|
||||||
// Loggers that need to be accessible from the lnd package can be placed
|
// Loggers that need to be accessible from the lnd package can be placed
|
||||||
// here. Loggers that are only used in sub modules can be added directly
|
// here. Loggers that are only used in sub modules can be added directly
|
||||||
// by using the addSubLogger method.
|
// by using the addSubLogger method.
|
||||||
ltndLog = build.NewSubLogger("LTND", logWriter.GenSubLogger)
|
ltndLog = build.NewSubLogger("LTND", RootLogWriter.GenSubLogger)
|
||||||
peerLog = build.NewSubLogger("PEER", logWriter.GenSubLogger)
|
peerLog = build.NewSubLogger("PEER", RootLogWriter.GenSubLogger)
|
||||||
rpcsLog = build.NewSubLogger("RPCS", logWriter.GenSubLogger)
|
rpcsLog = build.NewSubLogger("RPCS", RootLogWriter.GenSubLogger)
|
||||||
srvrLog = build.NewSubLogger("SRVR", logWriter.GenSubLogger)
|
srvrLog = build.NewSubLogger("SRVR", RootLogWriter.GenSubLogger)
|
||||||
fndgLog = build.NewSubLogger("FNDG", logWriter.GenSubLogger)
|
fndgLog = build.NewSubLogger("FNDG", RootLogWriter.GenSubLogger)
|
||||||
utxnLog = build.NewSubLogger("UTXN", logWriter.GenSubLogger)
|
utxnLog = build.NewSubLogger("UTXN", RootLogWriter.GenSubLogger)
|
||||||
brarLog = build.NewSubLogger("BRAR", logWriter.GenSubLogger)
|
brarLog = build.NewSubLogger("BRAR", RootLogWriter.GenSubLogger)
|
||||||
atplLog = build.NewSubLogger("ATPL", logWriter.GenSubLogger)
|
atplLog = build.NewSubLogger("ATPL", RootLogWriter.GenSubLogger)
|
||||||
)
|
)
|
||||||
|
|
||||||
// Initialize package-global logger variables.
|
// Initialize package-global logger variables.
|
||||||
@ -110,7 +112,7 @@ func init() {
|
|||||||
func addSubLogger(subsystem string, useLoggers ...func(btclog.Logger)) {
|
func addSubLogger(subsystem string, useLoggers ...func(btclog.Logger)) {
|
||||||
// Create and register just a single logger to prevent them from
|
// Create and register just a single logger to prevent them from
|
||||||
// overwriting each other internally.
|
// overwriting each other internally.
|
||||||
logger := build.NewSubLogger(subsystem, logWriter.GenSubLogger)
|
logger := build.NewSubLogger(subsystem, RootLogWriter.GenSubLogger)
|
||||||
setSubLogger(subsystem, logger, useLoggers...)
|
setSubLogger(subsystem, logger, useLoggers...)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -119,7 +121,7 @@ func addSubLogger(subsystem string, useLoggers ...func(btclog.Logger)) {
|
|||||||
func setSubLogger(subsystem string, logger btclog.Logger,
|
func setSubLogger(subsystem string, logger btclog.Logger,
|
||||||
useLoggers ...func(btclog.Logger)) {
|
useLoggers ...func(btclog.Logger)) {
|
||||||
|
|
||||||
logWriter.RegisterSubLogger(subsystem, logger)
|
RootLogWriter.RegisterSubLogger(subsystem, logger)
|
||||||
for _, useLogger := range useLoggers {
|
for _, useLogger := range useLoggers {
|
||||||
useLogger(logger)
|
useLogger(logger)
|
||||||
}
|
}
|
||||||
|
14
peer.go
14
peer.go
@ -114,6 +114,8 @@ type peer struct {
|
|||||||
started int32
|
started int32
|
||||||
disconnect int32
|
disconnect int32
|
||||||
|
|
||||||
|
cfg *Config
|
||||||
|
|
||||||
// The following fields are only meant to be used *atomically*
|
// The following fields are only meant to be used *atomically*
|
||||||
bytesReceived uint64
|
bytesReceived uint64
|
||||||
bytesSent uint64
|
bytesSent uint64
|
||||||
@ -263,7 +265,7 @@ var _ lnpeer.Peer = (*peer)(nil)
|
|||||||
// pointer to the main server. It takes an error buffer which may contain errors
|
// pointer to the main server. It takes an error buffer which may contain errors
|
||||||
// from a previous connection with the peer if we have been connected to them
|
// from a previous connection with the peer if we have been connected to them
|
||||||
// before.
|
// before.
|
||||||
func newPeer(conn net.Conn, connReq *connmgr.ConnReq, server *server,
|
func newPeer(cfg *Config, conn net.Conn, connReq *connmgr.ConnReq, server *server,
|
||||||
addr *lnwire.NetAddress, inbound bool,
|
addr *lnwire.NetAddress, inbound bool,
|
||||||
features, legacyFeatures *lnwire.FeatureVector,
|
features, legacyFeatures *lnwire.FeatureVector,
|
||||||
chanActiveTimeout time.Duration,
|
chanActiveTimeout time.Duration,
|
||||||
@ -277,6 +279,8 @@ func newPeer(conn net.Conn, connReq *connmgr.ConnReq, server *server,
|
|||||||
conn: conn,
|
conn: conn,
|
||||||
addr: addr,
|
addr: addr,
|
||||||
|
|
||||||
|
cfg: cfg,
|
||||||
|
|
||||||
activeSignal: make(chan struct{}),
|
activeSignal: make(chan struct{}),
|
||||||
|
|
||||||
inbound: inbound,
|
inbound: inbound,
|
||||||
@ -651,7 +655,7 @@ func (p *peer) addLink(chanPoint *wire.OutPoint,
|
|||||||
DecodeHopIterators: p.server.sphinx.DecodeHopIterators,
|
DecodeHopIterators: p.server.sphinx.DecodeHopIterators,
|
||||||
ExtractErrorEncrypter: p.server.sphinx.ExtractErrorEncrypter,
|
ExtractErrorEncrypter: p.server.sphinx.ExtractErrorEncrypter,
|
||||||
FetchLastChannelUpdate: p.server.fetchLastChanUpdate(),
|
FetchLastChannelUpdate: p.server.fetchLastChanUpdate(),
|
||||||
HodlMask: cfg.Hodl.Mask(),
|
HodlMask: p.cfg.Hodl.Mask(),
|
||||||
Registry: p.server.invoices,
|
Registry: p.server.invoices,
|
||||||
Switch: p.server.htlcSwitch,
|
Switch: p.server.htlcSwitch,
|
||||||
Circuits: p.server.htlcSwitch.CircuitModifier(),
|
Circuits: p.server.htlcSwitch.CircuitModifier(),
|
||||||
@ -671,13 +675,13 @@ func (p *peer) addLink(chanPoint *wire.OutPoint,
|
|||||||
FwdPkgGCTicker: ticker.New(time.Minute),
|
FwdPkgGCTicker: ticker.New(time.Minute),
|
||||||
PendingCommitTicker: ticker.New(time.Minute),
|
PendingCommitTicker: ticker.New(time.Minute),
|
||||||
BatchSize: 10,
|
BatchSize: 10,
|
||||||
UnsafeReplay: cfg.UnsafeReplay,
|
UnsafeReplay: p.cfg.UnsafeReplay,
|
||||||
MinFeeUpdateTimeout: htlcswitch.DefaultMinLinkFeeUpdateTimeout,
|
MinFeeUpdateTimeout: htlcswitch.DefaultMinLinkFeeUpdateTimeout,
|
||||||
MaxFeeUpdateTimeout: htlcswitch.DefaultMaxLinkFeeUpdateTimeout,
|
MaxFeeUpdateTimeout: htlcswitch.DefaultMaxLinkFeeUpdateTimeout,
|
||||||
OutgoingCltvRejectDelta: p.outgoingCltvRejectDelta,
|
OutgoingCltvRejectDelta: p.outgoingCltvRejectDelta,
|
||||||
TowerClient: p.server.towerClient,
|
TowerClient: p.server.towerClient,
|
||||||
MaxOutgoingCltvExpiry: cfg.MaxOutgoingCltvExpiry,
|
MaxOutgoingCltvExpiry: p.cfg.MaxOutgoingCltvExpiry,
|
||||||
MaxFeeAllocation: cfg.MaxChannelFeeAllocation,
|
MaxFeeAllocation: p.cfg.MaxChannelFeeAllocation,
|
||||||
NotifyActiveLink: p.server.channelNotifier.NotifyActiveLinkEvent,
|
NotifyActiveLink: p.server.channelNotifier.NotifyActiveLinkEvent,
|
||||||
NotifyActiveChannel: p.server.channelNotifier.NotifyActiveChannelEvent,
|
NotifyActiveChannel: p.server.channelNotifier.NotifyActiveChannelEvent,
|
||||||
NotifyInactiveChannel: p.server.channelNotifier.NotifyInactiveChannelEvent,
|
NotifyInactiveChannel: p.server.channelNotifier.NotifyInactiveChannelEvent,
|
||||||
|
7
pilot.go
7
pilot.go
@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/btcsuite/btcd/wire"
|
"github.com/btcsuite/btcd/wire"
|
||||||
"github.com/btcsuite/btcutil"
|
"github.com/btcsuite/btcutil"
|
||||||
"github.com/lightningnetwork/lnd/autopilot"
|
"github.com/lightningnetwork/lnd/autopilot"
|
||||||
|
"github.com/lightningnetwork/lnd/lncfg"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/tor"
|
"github.com/lightningnetwork/lnd/tor"
|
||||||
)
|
)
|
||||||
@ -17,7 +18,7 @@ import (
|
|||||||
// configuration is sane. Currently it checks that the heuristic configuration
|
// configuration is sane. Currently it checks that the heuristic configuration
|
||||||
// makes sense. In case the config is valid, it will return a list of
|
// makes sense. In case the config is valid, it will return a list of
|
||||||
// WeightedHeuristics that can be combined for use with the autopilot agent.
|
// WeightedHeuristics that can be combined for use with the autopilot agent.
|
||||||
func validateAtplCfg(cfg *autoPilotConfig) ([]*autopilot.WeightedHeuristic,
|
func validateAtplCfg(cfg *lncfg.AutoPilot) ([]*autopilot.WeightedHeuristic,
|
||||||
error) {
|
error) {
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -138,8 +139,8 @@ var _ autopilot.ChannelController = (*chanController)(nil)
|
|||||||
// Agent instance based on the passed configuration structs. The agent and all
|
// Agent instance based on the passed configuration structs. The agent and all
|
||||||
// interfaces needed to drive it won't be launched before the Manager's
|
// interfaces needed to drive it won't be launched before the Manager's
|
||||||
// StartAgent method is called.
|
// StartAgent method is called.
|
||||||
func initAutoPilot(svr *server, cfg *autoPilotConfig, chainCfg *chainConfig) (
|
func initAutoPilot(svr *server, cfg *lncfg.AutoPilot,
|
||||||
*autopilot.ManagerCfg, error) {
|
chainCfg *lncfg.Chain) (*autopilot.ManagerCfg, error) {
|
||||||
|
|
||||||
atplLog.Infof("Instantiating autopilot with active=%v, "+
|
atplLog.Infof("Instantiating autopilot with active=%v, "+
|
||||||
"max_channels=%d, allocation=%f, min_chan_size=%d, "+
|
"max_channels=%d, allocation=%f, min_chan_size=%d, "+
|
||||||
|
131
rpcserver.go
131
rpcserver.go
@ -461,6 +461,8 @@ type rpcServer struct {
|
|||||||
|
|
||||||
server *server
|
server *server
|
||||||
|
|
||||||
|
cfg *Config
|
||||||
|
|
||||||
// subServers are a set of sub-RPC servers that use the same gRPC and
|
// subServers are a set of sub-RPC servers that use the same gRPC and
|
||||||
// listening sockets as the main RPC server, but which maintain their
|
// listening sockets as the main RPC server, but which maintain their
|
||||||
// own independent service. This allows us to expose a set of
|
// own independent service. This allows us to expose a set of
|
||||||
@ -521,7 +523,7 @@ var _ lnrpc.LightningServer = (*rpcServer)(nil)
|
|||||||
// of the sub-servers that it maintains. The set of serverOpts should be the
|
// of the sub-servers that it maintains. The set of serverOpts should be the
|
||||||
// base level options passed to the grPC server. This typically includes things
|
// base level options passed to the grPC server. This typically includes things
|
||||||
// like requiring TLS, etc.
|
// like requiring TLS, etc.
|
||||||
func newRPCServer(s *server, macService *macaroons.Service,
|
func newRPCServer(cfg *Config, s *server, macService *macaroons.Service,
|
||||||
subServerCgs *subRPCServerConfigs, serverOpts []grpc.ServerOption,
|
subServerCgs *subRPCServerConfigs, serverOpts []grpc.ServerOption,
|
||||||
restDialOpts []grpc.DialOption, restProxyDest string,
|
restDialOpts []grpc.DialOption, restProxyDest string,
|
||||||
atpl *autopilot.Manager, invoiceRegistry *invoices.InvoiceRegistry,
|
atpl *autopilot.Manager, invoiceRegistry *invoices.InvoiceRegistry,
|
||||||
@ -585,7 +587,7 @@ func newRPCServer(s *server, macService *macaroons.Service,
|
|||||||
// the dependencies they need are properly populated within each sub
|
// the dependencies they need are properly populated within each sub
|
||||||
// server configuration struct.
|
// server configuration struct.
|
||||||
err = subServerCgs.PopulateDependencies(
|
err = subServerCgs.PopulateDependencies(
|
||||||
s.cc, networkDir, macService, atpl, invoiceRegistry,
|
cfg, s.cc, cfg.networkDir, macService, atpl, invoiceRegistry,
|
||||||
s.htlcSwitch, activeNetParams.Params, s.chanRouter,
|
s.htlcSwitch, activeNetParams.Params, s.chanRouter,
|
||||||
routerBackend, s.nodeSigner, s.chanDB, s.sweeper, tower,
|
routerBackend, s.nodeSigner, s.chanDB, s.sweeper, tower,
|
||||||
s.towerClient, cfg.net.ResolveTCPAddr, genInvoiceFeatures,
|
s.towerClient, cfg.net.ResolveTCPAddr, genInvoiceFeatures,
|
||||||
@ -629,6 +631,32 @@ func newRPCServer(s *server, macService *macaroons.Service,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the listeners and server options to use for this rpc server.
|
||||||
|
listeners, cleanup, err := getListeners()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// External subserver possibly need to register their own permissions.
|
||||||
|
for _, lis := range listeners {
|
||||||
|
extSubserver := lis.ExternalRPCSubserverCfg
|
||||||
|
if extSubserver != nil {
|
||||||
|
for method, ops := range extSubserver.Permissions {
|
||||||
|
// For each new method:ops combo, we also ensure
|
||||||
|
// that non of the sub-servers try to override
|
||||||
|
// each other.
|
||||||
|
if _, ok := permissions[method]; ok {
|
||||||
|
return nil, fmt.Errorf("detected "+
|
||||||
|
"duplicate macaroon "+
|
||||||
|
"constraints for path: %v",
|
||||||
|
method)
|
||||||
|
}
|
||||||
|
|
||||||
|
permissions[method] = ops
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// If macaroons aren't disabled (a non-nil service), then we'll set up
|
// If macaroons aren't disabled (a non-nil service), then we'll set up
|
||||||
// our set of interceptors which will allow us to handle the macaroon
|
// our set of interceptors which will allow us to handle the macaroon
|
||||||
// authentication in a single location.
|
// authentication in a single location.
|
||||||
@ -660,12 +688,6 @@ func newRPCServer(s *server, macService *macaroons.Service,
|
|||||||
strmInterceptors, errorLogStreamServerInterceptor(rpcsLog),
|
strmInterceptors, errorLogStreamServerInterceptor(rpcsLog),
|
||||||
)
|
)
|
||||||
|
|
||||||
// Get the listeners and server options to use for this rpc server.
|
|
||||||
listeners, cleanup, err := getListeners()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// If any interceptors have been set up, add them to the server options.
|
// If any interceptors have been set up, add them to the server options.
|
||||||
if len(unaryInterceptors) != 0 && len(strmInterceptors) != 0 {
|
if len(unaryInterceptors) != 0 && len(strmInterceptors) != 0 {
|
||||||
chainedUnary := grpc_middleware.WithUnaryServerChain(
|
chainedUnary := grpc_middleware.WithUnaryServerChain(
|
||||||
@ -681,6 +703,7 @@ func newRPCServer(s *server, macService *macaroons.Service,
|
|||||||
// gRPC server, and register the main lnrpc server along side.
|
// gRPC server, and register the main lnrpc server along side.
|
||||||
grpcServer := grpc.NewServer(serverOpts...)
|
grpcServer := grpc.NewServer(serverOpts...)
|
||||||
rootRPCServer := &rpcServer{
|
rootRPCServer := &rpcServer{
|
||||||
|
cfg: cfg,
|
||||||
restDialOpts: restDialOpts,
|
restDialOpts: restDialOpts,
|
||||||
listeners: listeners,
|
listeners: listeners,
|
||||||
listenerCleanUp: []func(){cleanup},
|
listenerCleanUp: []func(){cleanup},
|
||||||
@ -737,16 +760,36 @@ func (r *rpcServer) Start() error {
|
|||||||
go func(lis *ListenerWithSignal) {
|
go func(lis *ListenerWithSignal) {
|
||||||
rpcsLog.Infof("RPC server listening on %s", lis.Addr())
|
rpcsLog.Infof("RPC server listening on %s", lis.Addr())
|
||||||
|
|
||||||
|
// Before actually listening on the gRPC listener, give
|
||||||
|
// external subservers the chance to register to our
|
||||||
|
// gRPC server. Those external subservers (think GrUB)
|
||||||
|
// are responsible for starting/stopping on their own,
|
||||||
|
// we just let them register their services to the same
|
||||||
|
// server instance so all of them can be exposed on the
|
||||||
|
// same port/listener.
|
||||||
|
extSubCfg := lis.ExternalRPCSubserverCfg
|
||||||
|
if extSubCfg != nil && extSubCfg.Registrar != nil {
|
||||||
|
registerer := extSubCfg.Registrar
|
||||||
|
err := registerer.RegisterGrpcSubserver(
|
||||||
|
r.grpcServer,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
rpcsLog.Errorf("error registering "+
|
||||||
|
"external gRPC subserver: %v",
|
||||||
|
err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Close the ready chan to indicate we are listening.
|
// Close the ready chan to indicate we are listening.
|
||||||
close(lis.Ready)
|
close(lis.Ready)
|
||||||
r.grpcServer.Serve(lis)
|
_ = r.grpcServer.Serve(lis)
|
||||||
}(lis)
|
}(lis)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If Prometheus monitoring is enabled, start the Prometheus exporter.
|
// If Prometheus monitoring is enabled, start the Prometheus exporter.
|
||||||
if cfg.Prometheus.Enabled() {
|
if r.cfg.Prometheus.Enabled() {
|
||||||
err := monitoring.ExportPrometheusMetrics(
|
err := monitoring.ExportPrometheusMetrics(
|
||||||
r.grpcServer, cfg.Prometheus,
|
r.grpcServer, r.cfg.Prometheus,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@ -771,32 +814,50 @@ func (r *rpcServer) Start() error {
|
|||||||
//
|
//
|
||||||
// TODO(roasbeef): eventually also allow the sub-servers to themselves
|
// TODO(roasbeef): eventually also allow the sub-servers to themselves
|
||||||
// have a REST proxy.
|
// have a REST proxy.
|
||||||
mux := proxy.NewServeMux(customMarshalerOption)
|
restMux := proxy.NewServeMux(customMarshalerOption)
|
||||||
|
restCtx, restCancel := context.WithCancel(context.Background())
|
||||||
|
r.listenerCleanUp = append(r.listenerCleanUp, restCancel)
|
||||||
|
|
||||||
err := lnrpc.RegisterLightningHandlerFromEndpoint(
|
err := lnrpc.RegisterLightningHandlerFromEndpoint(
|
||||||
context.Background(), mux, r.restProxyDest,
|
restCtx, restMux, r.restProxyDest, r.restDialOpts,
|
||||||
r.restDialOpts,
|
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
for _, restEndpoint := range cfg.RESTListeners {
|
|
||||||
|
// Before listening on any of the interfaces, we also want to give the
|
||||||
|
// external subservers a chance to register their own REST proxy stub
|
||||||
|
// with our mux instance.
|
||||||
|
for _, lis := range r.listeners {
|
||||||
|
if lis.ExternalRestRegistrar != nil {
|
||||||
|
err := lis.ExternalRestRegistrar.RegisterRestSubserver(
|
||||||
|
restCtx, restMux, r.restProxyDest,
|
||||||
|
r.restDialOpts,
|
||||||
|
)
|
||||||
|
if err != nil {
|
||||||
|
rpcsLog.Errorf("error registering "+
|
||||||
|
"external REST subserver: %v", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Now spin up a network listener for each requested port and start a
|
||||||
|
// goroutine that serves REST with the created mux there.
|
||||||
|
for _, restEndpoint := range r.cfg.RESTListeners {
|
||||||
lis, err := lncfg.TLSListenOnAddress(restEndpoint, r.tlsCfg)
|
lis, err := lncfg.TLSListenOnAddress(restEndpoint, r.tlsCfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ltndLog.Errorf(
|
ltndLog.Errorf("gRPC proxy unable to listen on %s",
|
||||||
"gRPC proxy unable to listen on %s",
|
restEndpoint)
|
||||||
restEndpoint,
|
|
||||||
)
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
r.listenerCleanUp = append(r.listenerCleanUp, func() {
|
r.listenerCleanUp = append(r.listenerCleanUp, func() {
|
||||||
lis.Close()
|
_ = lis.Close()
|
||||||
})
|
})
|
||||||
|
|
||||||
go func() {
|
go func() {
|
||||||
rpcsLog.Infof("gRPC proxy started at %s", lis.Addr())
|
rpcsLog.Infof("gRPC proxy started at %s", lis.Addr())
|
||||||
http.Serve(lis, mux)
|
_ = http.Serve(lis, restMux)
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1363,7 +1424,7 @@ func (r *rpcServer) ConnectPeer(ctx context.Context,
|
|||||||
return nil, fmt.Errorf("cannot make connection to self")
|
return nil, fmt.Errorf("cannot make connection to self")
|
||||||
}
|
}
|
||||||
|
|
||||||
addr, err := parseAddr(in.Addr.Host)
|
addr, err := parseAddr(in.Addr.Host, r.cfg.net)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -1420,7 +1481,7 @@ func (r *rpcServer) DisconnectPeer(ctx context.Context,
|
|||||||
// In order to avoid erroneously disconnecting from a peer that we have
|
// In order to avoid erroneously disconnecting from a peer that we have
|
||||||
// an active channel with, if we have any channels active with this
|
// an active channel with, if we have any channels active with this
|
||||||
// peer, then we'll disallow disconnecting from them.
|
// peer, then we'll disallow disconnecting from them.
|
||||||
if len(nodeChannels) > 0 && !cfg.UnsafeDisconnect {
|
if len(nodeChannels) > 0 && !r.cfg.UnsafeDisconnect {
|
||||||
return nil, fmt.Errorf("cannot disconnect from peer(%x), "+
|
return nil, fmt.Errorf("cannot disconnect from peer(%x), "+
|
||||||
"all active channels with the peer need to be closed "+
|
"all active channels with the peer need to be closed "+
|
||||||
"first", pubKeyBytes)
|
"first", pubKeyBytes)
|
||||||
@ -2347,8 +2408,8 @@ func (r *rpcServer) GetInfo(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
network := normalizeNetwork(activeNetParams.Name)
|
network := normalizeNetwork(activeNetParams.Name)
|
||||||
activeChains := make([]*lnrpc.Chain, registeredChains.NumActiveChains())
|
activeChains := make([]*lnrpc.Chain, r.cfg.registeredChains.NumActiveChains())
|
||||||
for i, chain := range registeredChains.ActiveChains() {
|
for i, chain := range r.cfg.registeredChains.ActiveChains() {
|
||||||
activeChains[i] = &lnrpc.Chain{
|
activeChains[i] = &lnrpc.Chain{
|
||||||
Chain: chain.String(),
|
Chain: chain.String(),
|
||||||
Network: network,
|
Network: network,
|
||||||
@ -3756,7 +3817,7 @@ func (r *rpcServer) extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPayme
|
|||||||
|
|
||||||
// Take the CLTV limit from the request if set, otherwise use the max.
|
// Take the CLTV limit from the request if set, otherwise use the max.
|
||||||
cltvLimit, err := routerrpc.ValidateCLTVLimit(
|
cltvLimit, err := routerrpc.ValidateCLTVLimit(
|
||||||
rpcPayReq.CltvLimit, cfg.MaxOutgoingCltvExpiry,
|
rpcPayReq.CltvLimit, r.cfg.MaxOutgoingCltvExpiry,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return payIntent, err
|
return payIntent, err
|
||||||
@ -3885,7 +3946,7 @@ func (r *rpcServer) extractPaymentIntent(rpcPayReq *rpcPaymentRequest) (rpcPayme
|
|||||||
// use when creating an invoice. We do not assume the default of
|
// use when creating an invoice. We do not assume the default of
|
||||||
// 9 blocks that is defined in BOLT-11, because this is never
|
// 9 blocks that is defined in BOLT-11, because this is never
|
||||||
// enough for other lnd nodes.
|
// enough for other lnd nodes.
|
||||||
payIntent.cltvDelta = uint16(cfg.Bitcoin.TimeLockDelta)
|
payIntent.cltvDelta = uint16(r.cfg.Bitcoin.TimeLockDelta)
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the user is manually specifying payment details, then the payment
|
// If the user is manually specifying payment details, then the payment
|
||||||
@ -4307,9 +4368,9 @@ func (r *rpcServer) sendPaymentSync(ctx context.Context,
|
|||||||
func (r *rpcServer) AddInvoice(ctx context.Context,
|
func (r *rpcServer) AddInvoice(ctx context.Context,
|
||||||
invoice *lnrpc.Invoice) (*lnrpc.AddInvoiceResponse, error) {
|
invoice *lnrpc.Invoice) (*lnrpc.AddInvoiceResponse, error) {
|
||||||
|
|
||||||
defaultDelta := cfg.Bitcoin.TimeLockDelta
|
defaultDelta := r.cfg.Bitcoin.TimeLockDelta
|
||||||
if registeredChains.PrimaryChain() == litecoinChain {
|
if r.cfg.registeredChains.PrimaryChain() == litecoinChain {
|
||||||
defaultDelta = cfg.Litecoin.TimeLockDelta
|
defaultDelta = r.cfg.Litecoin.TimeLockDelta
|
||||||
}
|
}
|
||||||
|
|
||||||
addInvoiceCfg := &invoicesrpc.AddInvoiceConfig{
|
addInvoiceCfg := &invoicesrpc.AddInvoiceConfig{
|
||||||
@ -5221,7 +5282,7 @@ func (r *rpcServer) DebugLevel(ctx context.Context,
|
|||||||
if req.Show {
|
if req.Show {
|
||||||
return &lnrpc.DebugLevelResponse{
|
return &lnrpc.DebugLevelResponse{
|
||||||
SubSystems: strings.Join(
|
SubSystems: strings.Join(
|
||||||
logWriter.SupportedSubsystems(), " ",
|
RootLogWriter.SupportedSubsystems(), " ",
|
||||||
),
|
),
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
@ -5230,7 +5291,7 @@ func (r *rpcServer) DebugLevel(ctx context.Context,
|
|||||||
|
|
||||||
// Otherwise, we'll attempt to set the logging level using the
|
// Otherwise, we'll attempt to set the logging level using the
|
||||||
// specified level spec.
|
// specified level spec.
|
||||||
err := build.ParseAndSetDebugLevels(req.LevelSpec, logWriter)
|
err := build.ParseAndSetDebugLevels(req.LevelSpec, RootLogWriter)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
@ -6013,14 +6074,14 @@ func (r *rpcServer) ChannelAcceptor(stream lnrpc.Lightning_ChannelAcceptorServer
|
|||||||
}
|
}
|
||||||
|
|
||||||
// timeout is the time after which ChannelAcceptRequests expire.
|
// timeout is the time after which ChannelAcceptRequests expire.
|
||||||
timeout := time.After(cfg.AcceptorTimeout)
|
timeout := time.After(r.cfg.AcceptorTimeout)
|
||||||
|
|
||||||
// Send the request to the newRequests channel.
|
// Send the request to the newRequests channel.
|
||||||
select {
|
select {
|
||||||
case newRequests <- newRequest:
|
case newRequests <- newRequest:
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
rpcsLog.Errorf("RPCAcceptor returned false - reached timeout of %d",
|
rpcsLog.Errorf("RPCAcceptor returned false - reached timeout of %d",
|
||||||
cfg.AcceptorTimeout)
|
r.cfg.AcceptorTimeout)
|
||||||
return false
|
return false
|
||||||
case <-quit:
|
case <-quit:
|
||||||
return false
|
return false
|
||||||
@ -6035,7 +6096,7 @@ func (r *rpcServer) ChannelAcceptor(stream lnrpc.Lightning_ChannelAcceptorServer
|
|||||||
return resp
|
return resp
|
||||||
case <-timeout:
|
case <-timeout:
|
||||||
rpcsLog.Errorf("RPCAcceptor returned false - reached timeout of %d",
|
rpcsLog.Errorf("RPCAcceptor returned false - reached timeout of %d",
|
||||||
cfg.AcceptorTimeout)
|
r.cfg.AcceptorTimeout)
|
||||||
return false
|
return false
|
||||||
case <-quit:
|
case <-quit:
|
||||||
return false
|
return false
|
||||||
|
80
server.go
80
server.go
@ -133,6 +133,8 @@ type server struct {
|
|||||||
start sync.Once
|
start sync.Once
|
||||||
stop sync.Once
|
stop sync.Once
|
||||||
|
|
||||||
|
cfg *Config
|
||||||
|
|
||||||
// identityPriv is the private key used to authenticate any incoming
|
// identityPriv is the private key used to authenticate any incoming
|
||||||
// connections.
|
// connections.
|
||||||
identityPriv *btcec.PrivateKey
|
identityPriv *btcec.PrivateKey
|
||||||
@ -272,7 +274,7 @@ type server struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// parseAddr parses an address from its string format to a net.Addr.
|
// parseAddr parses an address from its string format to a net.Addr.
|
||||||
func parseAddr(address string) (net.Addr, error) {
|
func parseAddr(address string, netCfg tor.Net) (net.Addr, error) {
|
||||||
var (
|
var (
|
||||||
host string
|
host string
|
||||||
port int
|
port int
|
||||||
@ -304,21 +306,23 @@ func parseAddr(address string) (net.Addr, error) {
|
|||||||
// addresses over Tor in order to prevent leaking your real IP
|
// addresses over Tor in order to prevent leaking your real IP
|
||||||
// address.
|
// address.
|
||||||
hostPort := net.JoinHostPort(host, strconv.Itoa(port))
|
hostPort := net.JoinHostPort(host, strconv.Itoa(port))
|
||||||
return cfg.net.ResolveTCPAddr("tcp", hostPort)
|
return netCfg.ResolveTCPAddr("tcp", hostPort)
|
||||||
}
|
}
|
||||||
|
|
||||||
// noiseDial is a factory function which creates a connmgr compliant dialing
|
// noiseDial is a factory function which creates a connmgr compliant dialing
|
||||||
// function by returning a closure which includes the server's identity key.
|
// function by returning a closure which includes the server's identity key.
|
||||||
func noiseDial(idPriv *btcec.PrivateKey) func(net.Addr) (net.Conn, error) {
|
func noiseDial(idPriv *btcec.PrivateKey,
|
||||||
|
netCfg tor.Net) func(net.Addr) (net.Conn, error) {
|
||||||
|
|
||||||
return func(a net.Addr) (net.Conn, error) {
|
return func(a net.Addr) (net.Conn, error) {
|
||||||
lnAddr := a.(*lnwire.NetAddress)
|
lnAddr := a.(*lnwire.NetAddress)
|
||||||
return brontide.Dial(idPriv, lnAddr, cfg.net.Dial)
|
return brontide.Dial(idPriv, lnAddr, netCfg.Dial)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// newServer creates a new instance of the server which is to listen using the
|
// newServer creates a new instance of the server which is to listen using the
|
||||||
// passed listener address.
|
// passed listener address.
|
||||||
func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
|
func newServer(cfg *Config, listenAddrs []net.Addr, chanDB *channeldb.DB,
|
||||||
towerClientDB *wtdb.ClientDB, cc *chainControl,
|
towerClientDB *wtdb.ClientDB, cc *chainControl,
|
||||||
privKey *btcec.PrivateKey,
|
privKey *btcec.PrivateKey,
|
||||||
chansToRestore walletunlocker.ChannelsToRecover,
|
chansToRestore walletunlocker.ChannelsToRecover,
|
||||||
@ -399,13 +403,14 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
|
|||||||
}
|
}
|
||||||
|
|
||||||
registryConfig := invoices.RegistryConfig{
|
registryConfig := invoices.RegistryConfig{
|
||||||
FinalCltvRejectDelta: defaultFinalCltvRejectDelta,
|
FinalCltvRejectDelta: lncfg.DefaultFinalCltvRejectDelta,
|
||||||
HtlcHoldDuration: invoices.DefaultHtlcHoldDuration,
|
HtlcHoldDuration: invoices.DefaultHtlcHoldDuration,
|
||||||
Clock: clock.NewDefaultClock(),
|
Clock: clock.NewDefaultClock(),
|
||||||
AcceptKeySend: cfg.AcceptKeySend,
|
AcceptKeySend: cfg.AcceptKeySend,
|
||||||
}
|
}
|
||||||
|
|
||||||
s := &server{
|
s := &server{
|
||||||
|
cfg: cfg,
|
||||||
chanDB: chanDB,
|
chanDB: chanDB,
|
||||||
cc: cc,
|
cc: cc,
|
||||||
sigPool: lnwallet.NewSigPool(cfg.Workers.Sig, cc.signer),
|
sigPool: lnwallet.NewSigPool(cfg.Workers.Sig, cc.signer),
|
||||||
@ -867,8 +872,8 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
|
|||||||
|
|
||||||
s.chainArb = contractcourt.NewChainArbitrator(contractcourt.ChainArbitratorConfig{
|
s.chainArb = contractcourt.NewChainArbitrator(contractcourt.ChainArbitratorConfig{
|
||||||
ChainHash: *activeNetParams.GenesisHash,
|
ChainHash: *activeNetParams.GenesisHash,
|
||||||
IncomingBroadcastDelta: DefaultIncomingBroadcastDelta,
|
IncomingBroadcastDelta: lncfg.DefaultIncomingBroadcastDelta,
|
||||||
OutgoingBroadcastDelta: DefaultOutgoingBroadcastDelta,
|
OutgoingBroadcastDelta: lncfg.DefaultOutgoingBroadcastDelta,
|
||||||
NewSweepAddr: newSweepPkScriptGen(cc.wallet),
|
NewSweepAddr: newSweepPkScriptGen(cc.wallet),
|
||||||
PublishTx: cc.wallet.PublishTransaction,
|
PublishTx: cc.wallet.PublishTransaction,
|
||||||
DeliverResolutionMsg: func(msgs ...contractcourt.ResolutionMsg) error {
|
DeliverResolutionMsg: func(msgs ...contractcourt.ResolutionMsg) error {
|
||||||
@ -959,7 +964,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
|
|||||||
|
|
||||||
// Select the configuration and furnding parameters for Bitcoin or
|
// Select the configuration and furnding parameters for Bitcoin or
|
||||||
// Litecoin, depending on the primary registered chain.
|
// Litecoin, depending on the primary registered chain.
|
||||||
primaryChain := registeredChains.PrimaryChain()
|
primaryChain := cfg.registeredChains.PrimaryChain()
|
||||||
chainCfg := cfg.Bitcoin
|
chainCfg := cfg.Bitcoin
|
||||||
minRemoteDelay := minBtcRemoteDelay
|
minRemoteDelay := minBtcRemoteDelay
|
||||||
maxRemoteDelay := maxBtcRemoteDelay
|
maxRemoteDelay := maxBtcRemoteDelay
|
||||||
@ -1144,6 +1149,8 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
|
|||||||
NotifyOpenChannelEvent: s.channelNotifier.NotifyOpenChannelEvent,
|
NotifyOpenChannelEvent: s.channelNotifier.NotifyOpenChannelEvent,
|
||||||
OpenChannelPredicate: chanPredicate,
|
OpenChannelPredicate: chanPredicate,
|
||||||
NotifyPendingOpenChannelEvent: s.channelNotifier.NotifyPendingOpenChannelEvent,
|
NotifyPendingOpenChannelEvent: s.channelNotifier.NotifyPendingOpenChannelEvent,
|
||||||
|
EnableUpfrontShutdown: cfg.EnableUpfrontShutdown,
|
||||||
|
RegisteredChains: cfg.registeredChains,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
@ -1220,7 +1227,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB,
|
|||||||
OnAccept: s.InboundPeerConnected,
|
OnAccept: s.InboundPeerConnected,
|
||||||
RetryDuration: time.Second * 5,
|
RetryDuration: time.Second * 5,
|
||||||
TargetOutbound: 100,
|
TargetOutbound: 100,
|
||||||
Dial: noiseDial(s.identityPriv),
|
Dial: noiseDial(s.identityPriv, s.cfg.net),
|
||||||
OnConnection: s.OutboundPeerConnected,
|
OnConnection: s.OutboundPeerConnected,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1402,8 +1409,9 @@ func (s *server) Start() error {
|
|||||||
// configure the set of active bootstrappers, and launch a
|
// configure the set of active bootstrappers, and launch a
|
||||||
// dedicated goroutine to maintain a set of persistent
|
// dedicated goroutine to maintain a set of persistent
|
||||||
// connections.
|
// connections.
|
||||||
if !cfg.NoNetBootstrap && !(cfg.Bitcoin.SimNet || cfg.Litecoin.SimNet) &&
|
if !s.cfg.NoNetBootstrap &&
|
||||||
!(cfg.Bitcoin.RegTest || cfg.Litecoin.RegTest) {
|
!(s.cfg.Bitcoin.SimNet || s.cfg.Litecoin.SimNet) &&
|
||||||
|
!(s.cfg.Bitcoin.RegTest || s.cfg.Litecoin.RegTest) {
|
||||||
|
|
||||||
bootstrappers, err := initNetworkBootstrappers(s)
|
bootstrappers, err := initNetworkBootstrappers(s)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -1546,7 +1554,7 @@ func (s *server) watchExternalIP() {
|
|||||||
// Keep track of the external IPs set by the user to avoid replacing
|
// Keep track of the external IPs set by the user to avoid replacing
|
||||||
// them when detecting a new IP.
|
// them when detecting a new IP.
|
||||||
ipsSetByUser := make(map[string]struct{})
|
ipsSetByUser := make(map[string]struct{})
|
||||||
for _, ip := range cfg.ExternalIPs {
|
for _, ip := range s.cfg.ExternalIPs {
|
||||||
ipsSetByUser[ip.String()] = struct{}{}
|
ipsSetByUser[ip.String()] = struct{}{}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1690,7 +1698,7 @@ func initNetworkBootstrappers(s *server) ([]discovery.NetworkPeerBootstrapper, e
|
|||||||
|
|
||||||
// If this isn't simnet mode, then one of our additional bootstrapping
|
// If this isn't simnet mode, then one of our additional bootstrapping
|
||||||
// sources will be the set of running DNS seeds.
|
// sources will be the set of running DNS seeds.
|
||||||
if !cfg.Bitcoin.SimNet || !cfg.Litecoin.SimNet {
|
if !s.cfg.Bitcoin.SimNet || !s.cfg.Litecoin.SimNet {
|
||||||
dnsSeeds, ok := chainDNSSeeds[*activeNetParams.GenesisHash]
|
dnsSeeds, ok := chainDNSSeeds[*activeNetParams.GenesisHash]
|
||||||
|
|
||||||
// If we have a set of DNS seeds for this chain, then we'll add
|
// If we have a set of DNS seeds for this chain, then we'll add
|
||||||
@ -1700,7 +1708,7 @@ func initNetworkBootstrappers(s *server) ([]discovery.NetworkPeerBootstrapper, e
|
|||||||
"seeds: %v", dnsSeeds)
|
"seeds: %v", dnsSeeds)
|
||||||
|
|
||||||
dnsBootStrapper := discovery.NewDNSSeedBootstrapper(
|
dnsBootStrapper := discovery.NewDNSSeedBootstrapper(
|
||||||
dnsSeeds, cfg.net,
|
dnsSeeds, s.cfg.net,
|
||||||
)
|
)
|
||||||
bootStrappers = append(bootStrappers, dnsBootStrapper)
|
bootStrappers = append(bootStrappers, dnsBootStrapper)
|
||||||
}
|
}
|
||||||
@ -1972,13 +1980,13 @@ func (s *server) createNewHiddenService() error {
|
|||||||
onionCfg := tor.AddOnionConfig{
|
onionCfg := tor.AddOnionConfig{
|
||||||
VirtualPort: defaultPeerPort,
|
VirtualPort: defaultPeerPort,
|
||||||
TargetPorts: listenPorts,
|
TargetPorts: listenPorts,
|
||||||
Store: tor.NewOnionFile(cfg.Tor.PrivateKeyPath, 0600),
|
Store: tor.NewOnionFile(s.cfg.Tor.PrivateKeyPath, 0600),
|
||||||
}
|
}
|
||||||
|
|
||||||
switch {
|
switch {
|
||||||
case cfg.Tor.V2:
|
case s.cfg.Tor.V2:
|
||||||
onionCfg.Type = tor.V2
|
onionCfg.Type = tor.V2
|
||||||
case cfg.Tor.V3:
|
case s.cfg.Tor.V3:
|
||||||
onionCfg.Type = tor.V3
|
onionCfg.Type = tor.V3
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2131,7 +2139,7 @@ func (s *server) establishPersistentConnections() error {
|
|||||||
// We'll only attempt to connect to Tor addresses if Tor
|
// We'll only attempt to connect to Tor addresses if Tor
|
||||||
// outbound support is enabled.
|
// outbound support is enabled.
|
||||||
case *tor.OnionAddr:
|
case *tor.OnionAddr:
|
||||||
if cfg.Tor.Active {
|
if s.cfg.Tor.Active {
|
||||||
addrSet[addr.String()] = addr
|
addrSet[addr.String()] = addr
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2149,7 +2157,7 @@ func (s *server) establishPersistentConnections() error {
|
|||||||
// We'll only attempt to connect to Tor
|
// We'll only attempt to connect to Tor
|
||||||
// addresses if Tor outbound support is enabled.
|
// addresses if Tor outbound support is enabled.
|
||||||
case *tor.OnionAddr:
|
case *tor.OnionAddr:
|
||||||
if cfg.Tor.Active {
|
if s.cfg.Tor.Active {
|
||||||
addrSet[lnAddress.String()] = lnAddress
|
addrSet[lnAddress.String()] = lnAddress
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2193,7 +2201,7 @@ func (s *server) establishPersistentConnections() error {
|
|||||||
// been requested as perm by the user.
|
// been requested as perm by the user.
|
||||||
s.persistentPeers[pubStr] = false
|
s.persistentPeers[pubStr] = false
|
||||||
if _, ok := s.persistentPeersBackoff[pubStr]; !ok {
|
if _, ok := s.persistentPeersBackoff[pubStr]; !ok {
|
||||||
s.persistentPeersBackoff[pubStr] = cfg.MinBackoff
|
s.persistentPeersBackoff[pubStr] = s.cfg.MinBackoff
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, address := range nodeAddr.addresses {
|
for _, address := range nodeAddr.addresses {
|
||||||
@ -2226,7 +2234,7 @@ func (s *server) establishPersistentConnections() error {
|
|||||||
// nodes are able to disperse the costs of connecting to
|
// nodes are able to disperse the costs of connecting to
|
||||||
// all peers at once.
|
// all peers at once.
|
||||||
if numOutboundConns < numInstantInitReconnect ||
|
if numOutboundConns < numInstantInitReconnect ||
|
||||||
!cfg.StaggerInitialReconnect {
|
!s.cfg.StaggerInitialReconnect {
|
||||||
|
|
||||||
go s.connMgr.Connect(connReq)
|
go s.connMgr.Connect(connReq)
|
||||||
} else {
|
} else {
|
||||||
@ -2435,14 +2443,14 @@ func (s *server) nextPeerBackoff(pubStr string,
|
|||||||
backoff, ok := s.persistentPeersBackoff[pubStr]
|
backoff, ok := s.persistentPeersBackoff[pubStr]
|
||||||
if !ok {
|
if !ok {
|
||||||
// If an existing backoff was unknown, use the default.
|
// If an existing backoff was unknown, use the default.
|
||||||
return cfg.MinBackoff
|
return s.cfg.MinBackoff
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the peer failed to start properly, we'll just use the previous
|
// If the peer failed to start properly, we'll just use the previous
|
||||||
// backoff to compute the subsequent randomized exponential backoff
|
// backoff to compute the subsequent randomized exponential backoff
|
||||||
// duration. This will roughly double on average.
|
// duration. This will roughly double on average.
|
||||||
if startTime.IsZero() {
|
if startTime.IsZero() {
|
||||||
return computeNextBackoff(backoff)
|
return computeNextBackoff(backoff, s.cfg.MaxBackoff)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The peer succeeded in starting. If the connection didn't last long
|
// The peer succeeded in starting. If the connection didn't last long
|
||||||
@ -2450,7 +2458,7 @@ func (s *server) nextPeerBackoff(pubStr string,
|
|||||||
// with this peer.
|
// with this peer.
|
||||||
connDuration := time.Since(startTime)
|
connDuration := time.Since(startTime)
|
||||||
if connDuration < defaultStableConnDuration {
|
if connDuration < defaultStableConnDuration {
|
||||||
return computeNextBackoff(backoff)
|
return computeNextBackoff(backoff, s.cfg.MaxBackoff)
|
||||||
}
|
}
|
||||||
|
|
||||||
// The peer succeed in starting and this was stable peer, so we'll
|
// The peer succeed in starting and this was stable peer, so we'll
|
||||||
@ -2458,8 +2466,8 @@ func (s *server) nextPeerBackoff(pubStr string,
|
|||||||
// applying randomized exponential backoff. We'll only apply this in the
|
// applying randomized exponential backoff. We'll only apply this in the
|
||||||
// case that:
|
// case that:
|
||||||
// reb(curBackoff) - connDuration > cfg.MinBackoff
|
// reb(curBackoff) - connDuration > cfg.MinBackoff
|
||||||
relaxedBackoff := computeNextBackoff(backoff) - connDuration
|
relaxedBackoff := computeNextBackoff(backoff, s.cfg.MaxBackoff) - connDuration
|
||||||
if relaxedBackoff > cfg.MinBackoff {
|
if relaxedBackoff > s.cfg.MinBackoff {
|
||||||
return relaxedBackoff
|
return relaxedBackoff
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2467,7 +2475,7 @@ func (s *server) nextPeerBackoff(pubStr string,
|
|||||||
// the stable connection lasted much longer than our previous backoff.
|
// the stable connection lasted much longer than our previous backoff.
|
||||||
// To reward such good behavior, we'll reconnect after the default
|
// To reward such good behavior, we'll reconnect after the default
|
||||||
// timeout.
|
// timeout.
|
||||||
return cfg.MinBackoff
|
return s.cfg.MinBackoff
|
||||||
}
|
}
|
||||||
|
|
||||||
// shouldDropConnection determines if our local connection to a remote peer
|
// shouldDropConnection determines if our local connection to a remote peer
|
||||||
@ -2780,9 +2788,9 @@ func (s *server) peerConnected(conn net.Conn, connReq *connmgr.ConnReq,
|
|||||||
// htlcs, an extra block is added to prevent the channel from being
|
// htlcs, an extra block is added to prevent the channel from being
|
||||||
// closed when the htlc is outstanding and a new block comes in.
|
// closed when the htlc is outstanding and a new block comes in.
|
||||||
p, err := newPeer(
|
p, err := newPeer(
|
||||||
conn, connReq, s, peerAddr, inbound, initFeatures,
|
s.cfg, conn, connReq, s, peerAddr, inbound, initFeatures,
|
||||||
legacyFeatures, cfg.ChanEnableTimeout,
|
legacyFeatures, s.cfg.ChanEnableTimeout,
|
||||||
defaultOutgoingCltvRejectDelta, errBuffer,
|
lncfg.DefaultOutgoingCltvRejectDelta, errBuffer,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
srvrLog.Errorf("unable to create peer %v", err)
|
srvrLog.Errorf("unable to create peer %v", err)
|
||||||
@ -3224,7 +3232,7 @@ func (s *server) ConnectToPeer(addr *lnwire.NetAddress, perm bool) error {
|
|||||||
// zero.
|
// zero.
|
||||||
s.persistentPeers[targetPub] = true
|
s.persistentPeers[targetPub] = true
|
||||||
if _, ok := s.persistentPeersBackoff[targetPub]; !ok {
|
if _, ok := s.persistentPeersBackoff[targetPub]; !ok {
|
||||||
s.persistentPeersBackoff[targetPub] = cfg.MinBackoff
|
s.persistentPeersBackoff[targetPub] = s.cfg.MinBackoff
|
||||||
}
|
}
|
||||||
s.persistentConnReqs[targetPub] = append(
|
s.persistentConnReqs[targetPub] = append(
|
||||||
s.persistentConnReqs[targetPub], connReq,
|
s.persistentConnReqs[targetPub], connReq,
|
||||||
@ -3256,7 +3264,7 @@ func (s *server) ConnectToPeer(addr *lnwire.NetAddress, perm bool) error {
|
|||||||
// notify the caller if the connection attempt has failed. Otherwise, it will be
|
// notify the caller if the connection attempt has failed. Otherwise, it will be
|
||||||
// closed.
|
// closed.
|
||||||
func (s *server) connectToPeer(addr *lnwire.NetAddress, errChan chan<- error) {
|
func (s *server) connectToPeer(addr *lnwire.NetAddress, errChan chan<- error) {
|
||||||
conn, err := brontide.Dial(s.identityPriv, addr, cfg.net.Dial)
|
conn, err := brontide.Dial(s.identityPriv, addr, s.cfg.net.Dial)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
srvrLog.Errorf("Unable to connect to %v: %v", addr, err)
|
srvrLog.Errorf("Unable to connect to %v: %v", addr, err)
|
||||||
select {
|
select {
|
||||||
@ -3407,11 +3415,11 @@ func parseHexColor(colorStr string) (color.RGBA, error) {
|
|||||||
// backoff using the value of the exiting backoff. The returned duration is
|
// backoff using the value of the exiting backoff. The returned duration is
|
||||||
// randomized in either direction by 1/20 to prevent tight loops from
|
// randomized in either direction by 1/20 to prevent tight loops from
|
||||||
// stabilizing.
|
// stabilizing.
|
||||||
func computeNextBackoff(currBackoff time.Duration) time.Duration {
|
func computeNextBackoff(currBackoff, maxBackoff time.Duration) time.Duration {
|
||||||
// Double the current backoff, truncating if it exceeds our maximum.
|
// Double the current backoff, truncating if it exceeds our maximum.
|
||||||
nextBackoff := 2 * currBackoff
|
nextBackoff := 2 * currBackoff
|
||||||
if nextBackoff > cfg.MaxBackoff {
|
if nextBackoff > maxBackoff {
|
||||||
nextBackoff = cfg.MaxBackoff
|
nextBackoff = maxBackoff
|
||||||
}
|
}
|
||||||
|
|
||||||
// Using 1/10 of our duration as a margin, compute a random offset to
|
// Using 1/10 of our duration as a margin, compute a random offset to
|
||||||
|
@ -114,7 +114,12 @@ func TestTLSAutoRegeneration(t *testing.T) {
|
|||||||
|
|
||||||
// Now let's run getTLSConfig. If it works properly, it should delete
|
// Now let's run getTLSConfig. If it works properly, it should delete
|
||||||
// the cert and create a new one.
|
// the cert and create a new one.
|
||||||
_, _, _, err = getTLSConfig(certPath, keyPath, nil, nil, rpcListeners)
|
cfg := &Config{
|
||||||
|
TLSCertPath: certPath,
|
||||||
|
TLSKeyPath: keyPath,
|
||||||
|
RPCListeners: rpcListeners,
|
||||||
|
}
|
||||||
|
_, _, _, err = getTLSConfig(cfg)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("couldn't retrieve TLS config")
|
t.Fatalf("couldn't retrieve TLS config")
|
||||||
}
|
}
|
||||||
|
@ -81,7 +81,7 @@ type subRPCServerConfigs struct {
|
|||||||
//
|
//
|
||||||
// NOTE: This MUST be called before any callers are permitted to execute the
|
// NOTE: This MUST be called before any callers are permitted to execute the
|
||||||
// FetchConfig method.
|
// FetchConfig method.
|
||||||
func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
|
func (s *subRPCServerConfigs) PopulateDependencies(cfg *Config, cc *chainControl,
|
||||||
networkDir string, macService *macaroons.Service,
|
networkDir string, macService *macaroons.Service,
|
||||||
atpl *autopilot.Manager,
|
atpl *autopilot.Manager,
|
||||||
invoiceRegistry *invoices.InvoiceRegistry,
|
invoiceRegistry *invoices.InvoiceRegistry,
|
||||||
@ -205,7 +205,7 @@ func (s *subRPCServerConfigs) PopulateDependencies(cc *chainControl,
|
|||||||
reflect.ValueOf(nodeSigner),
|
reflect.ValueOf(nodeSigner),
|
||||||
)
|
)
|
||||||
defaultDelta := cfg.Bitcoin.TimeLockDelta
|
defaultDelta := cfg.Bitcoin.TimeLockDelta
|
||||||
if registeredChains.PrimaryChain() == litecoinChain {
|
if cfg.registeredChains.PrimaryChain() == litecoinChain {
|
||||||
defaultDelta = cfg.Litecoin.TimeLockDelta
|
defaultDelta = cfg.Litecoin.TimeLockDelta
|
||||||
}
|
}
|
||||||
subCfgValue.FieldByName("DefaultCLTVExpiry").Set(
|
subCfgValue.FieldByName("DefaultCLTVExpiry").Set(
|
||||||
|
Loading…
Reference in New Issue
Block a user