From bebe258e2db5e2eecee65ecac11c155f3f0bad79 Mon Sep 17 00:00:00 2001 From: Eugene Date: Tue, 6 Oct 2020 11:56:10 -0700 Subject: [PATCH] chainregistry+lnd: moving chainregistry+chainparams to new package --- chainreg/chainregistry.go | 712 ++++++++++++++++++ chainreg/log.go | 24 + chainregistry.go | 721 ------------------- cmd/lncli/cmd_build_route.go | 4 +- config.go | 24 +- fundingmanager.go | 6 +- fundingmanager_test.go | 4 +- lnd.go | 2 +- lntest/itest/lnd_forward_interceptor_test.go | 3 +- lntest/itest/lnd_mpp_test.go | 3 +- lntest/itest/lnd_multi-hop-payments_test.go | 5 +- lntest/itest/lnd_test.go | 21 +- nursery_store_test.go | 7 +- server.go | 7 +- subrpcserver_config.go | 3 +- 15 files changed, 783 insertions(+), 763 deletions(-) create mode 100644 chainreg/log.go delete mode 100644 chainregistry.go diff --git a/chainreg/chainregistry.go b/chainreg/chainregistry.go index 9a8786615..4acc898bf 100644 --- a/chainreg/chainregistry.go +++ b/chainreg/chainregistry.go @@ -1,12 +1,37 @@ package chainreg import ( + "encoding/hex" + "errors" + "fmt" + "io/ioutil" + "net" + "os" + "strconv" + "strings" + "sync" "time" + "github.com/btcsuite/btcd/chaincfg/chainhash" + "github.com/btcsuite/btcd/rpcclient" + "github.com/btcsuite/btcutil" + "github.com/btcsuite/btcwallet/chain" "github.com/btcsuite/btcwallet/wallet" "github.com/lightninglabs/neutrino" + "github.com/lightningnetwork/lnd/chainntnfs" + "github.com/lightningnetwork/lnd/chainntnfs/bitcoindnotify" + "github.com/lightningnetwork/lnd/chainntnfs/btcdnotify" + "github.com/lightningnetwork/lnd/chainntnfs/neutrinonotify" "github.com/lightningnetwork/lnd/channeldb" + "github.com/lightningnetwork/lnd/htlcswitch" + "github.com/lightningnetwork/lnd/input" + "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lncfg" + "github.com/lightningnetwork/lnd/lnwallet" + "github.com/lightningnetwork/lnd/lnwallet/btcwallet" + "github.com/lightningnetwork/lnd/lnwallet/chainfee" + "github.com/lightningnetwork/lnd/lnwire" + "github.com/lightningnetwork/lnd/routing/chainview" ) // Config houses necessary fields that a chainControl instance needs to @@ -76,3 +101,690 @@ type Config struct { // optional. FeeURL string } + +const ( + // DefaultBitcoinMinHTLCInMSat is the default smallest value htlc this + // node will accept. This value is proposed in the channel open sequence + // and cannot be changed during the life of the channel. It is 1 msat by + // default to allow maximum flexibility in deciding what size payments + // to forward. + // + // All forwarded payments are subjected to the min htlc constraint of + // the routing policy of the outgoing channel. This implicitly controls + // the minimum htlc value on the incoming channel too. + DefaultBitcoinMinHTLCInMSat = lnwire.MilliSatoshi(1) + + // DefaultBitcoinMinHTLCOutMSat is the default minimum htlc value that + // we require for sending out htlcs. Our channel peer may have a lower + // min htlc channel parameter, but we - by default - don't forward + // anything under the value defined here. + DefaultBitcoinMinHTLCOutMSat = lnwire.MilliSatoshi(1000) + + // DefaultBitcoinBaseFeeMSat is the default forwarding base fee. + DefaultBitcoinBaseFeeMSat = lnwire.MilliSatoshi(1000) + + // DefaultBitcoinFeeRate is the default forwarding fee rate. + DefaultBitcoinFeeRate = lnwire.MilliSatoshi(1) + + // DefaultBitcoinTimeLockDelta is the default forwarding time lock + // delta. + DefaultBitcoinTimeLockDelta = 40 + + DefaultLitecoinMinHTLCInMSat = lnwire.MilliSatoshi(1) + DefaultLitecoinMinHTLCOutMSat = lnwire.MilliSatoshi(1000) + DefaultLitecoinBaseFeeMSat = lnwire.MilliSatoshi(1000) + DefaultLitecoinFeeRate = lnwire.MilliSatoshi(1) + DefaultLitecoinTimeLockDelta = 576 + DefaultLitecoinDustLimit = btcutil.Amount(54600) + + // DefaultBitcoinStaticFeePerKW is the fee rate of 50 sat/vbyte + // expressed in sat/kw. + DefaultBitcoinStaticFeePerKW = chainfee.SatPerKWeight(12500) + + // DefaultBitcoinStaticMinRelayFeeRate is the min relay fee used for + // static estimators. + DefaultBitcoinStaticMinRelayFeeRate = chainfee.FeePerKwFloor + + // DefaultLitecoinStaticFeePerKW is the fee rate of 200 sat/vbyte + // expressed in sat/kw. + DefaultLitecoinStaticFeePerKW = chainfee.SatPerKWeight(50000) + + // BtcToLtcConversionRate is a fixed ratio used in order to scale up + // payments when running on the Litecoin chain. + BtcToLtcConversionRate = 60 +) + +// DefaultBtcChannelConstraints is the default set of channel constraints that are +// meant to be used when initially funding a Bitcoin channel. +// +// TODO(halseth): make configurable at startup? +var DefaultBtcChannelConstraints = channeldb.ChannelConstraints{ + DustLimit: lnwallet.DefaultDustLimit(), + MaxAcceptedHtlcs: input.MaxHTLCNumber / 2, +} + +// DefaultLtcChannelConstraints is the default set of channel constraints that are +// meant to be used when initially funding a Litecoin channel. +var DefaultLtcChannelConstraints = channeldb.ChannelConstraints{ + DustLimit: DefaultLitecoinDustLimit, + MaxAcceptedHtlcs: input.MaxHTLCNumber / 2, +} + +// ChainControl couples the three primary interfaces lnd utilizes for a +// particular chain together. A single ChainControl instance will exist for all +// the chains lnd is currently active on. +type ChainControl struct { + // ChainIO represents an abstraction over a source that can query the blockchain. + ChainIO lnwallet.BlockChainIO + + // FeeEstimator is used to estimate an optimal fee for transactions important to us. + FeeEstimator chainfee.Estimator + + // Signer is used to provide signatures over things like transactions. + Signer input.Signer + + // KeyRing represents a set of keys that we have the private keys to. + KeyRing keychain.SecretKeyRing + + // Wc is an abstraction over some basic wallet commands. This base set of commands + // will be provided to the Wallet *LightningWallet raw pointer below. + Wc lnwallet.WalletController + + // MsgSigner is used to sign arbitrary messages. + MsgSigner lnwallet.MessageSigner + + // ChainNotifier is used to receive blockchain events that we are interested in. + ChainNotifier chainntnfs.ChainNotifier + + // ChainView is used in the router for maintaining an up-to-date graph. + ChainView chainview.FilteredChainView + + // Wallet is our LightningWallet that also contains the abstract Wc above. This wallet + // handles all of the lightning operations. + Wallet *lnwallet.LightningWallet + + // RoutingPolicy is the routing policy we have decided to use. + RoutingPolicy htlcswitch.ForwardingPolicy + + // MinHtlcIn is the minimum HTLC we will accept. + MinHtlcIn lnwire.MilliSatoshi +} + +// NewChainControl attempts to create a ChainControl instance according +// to the parameters in the passed configuration. Currently three +// branches of ChainControl instances exist: one backed by a running btcd +// 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 +// neutrino light client instance, `neutrinoCS` must be non-nil. +func NewChainControl(cfg *Config) (*ChainControl, error) { + + // 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. + homeChainConfig := cfg.Bitcoin + if cfg.PrimaryChain() == LitecoinChain { + homeChainConfig = cfg.Litecoin + } + log.Infof("Primary chain is set to: %v", + cfg.PrimaryChain()) + + cc := &ChainControl{} + + switch cfg.PrimaryChain() { + case BitcoinChain: + cc.RoutingPolicy = htlcswitch.ForwardingPolicy{ + MinHTLCOut: cfg.Bitcoin.MinHTLCOut, + BaseFee: cfg.Bitcoin.BaseFee, + FeeRate: cfg.Bitcoin.FeeRate, + TimeLockDelta: cfg.Bitcoin.TimeLockDelta, + } + cc.MinHtlcIn = cfg.Bitcoin.MinHTLCIn + cc.FeeEstimator = chainfee.NewStaticEstimator( + DefaultBitcoinStaticFeePerKW, + DefaultBitcoinStaticMinRelayFeeRate, + ) + case LitecoinChain: + cc.RoutingPolicy = htlcswitch.ForwardingPolicy{ + MinHTLCOut: cfg.Litecoin.MinHTLCOut, + BaseFee: cfg.Litecoin.BaseFee, + FeeRate: cfg.Litecoin.FeeRate, + TimeLockDelta: cfg.Litecoin.TimeLockDelta, + } + cc.MinHtlcIn = cfg.Litecoin.MinHTLCIn + cc.FeeEstimator = chainfee.NewStaticEstimator( + DefaultLitecoinStaticFeePerKW, 0, + ) + default: + return nil, fmt.Errorf("default routing policy for chain %v is "+ + "unknown", cfg.PrimaryChain()) + } + + walletConfig := &btcwallet.Config{ + PrivatePass: cfg.PrivateWalletPw, + PublicPass: cfg.PublicWalletPw, + Birthday: cfg.Birthday, + RecoveryWindow: cfg.RecoveryWindow, + DataDir: homeChainConfig.ChainDir, + NetParams: cfg.ActiveNetParams.Params, + CoinType: cfg.ActiveNetParams.CoinType, + Wallet: cfg.Wallet, + } + + var err error + + heightHintCacheConfig := chainntnfs.CacheConfig{ + QueryDisable: cfg.HeightHintCacheQueryDisable, + } + if cfg.HeightHintCacheQueryDisable { + log.Infof("Height Hint Cache Queries disabled") + } + + // Initialize the height hint cache within the chain directory. + hintCache, err := chainntnfs.NewHeightHintCache( + heightHintCacheConfig, cfg.LocalChanDB, + ) + if err != nil { + return nil, fmt.Errorf("unable to initialize height hint "+ + "cache: %v", err) + } + + // If spv mode is active, then we'll be using a distinct set of + // chainControl interfaces that interface directly with the p2p network + // of the selected chain. + switch homeChainConfig.Node { + case "neutrino": + // We'll create ChainNotifier and FilteredChainView instances, + // along with the wallet's ChainSource, which are all backed by + // the neutrino light client. + cc.ChainNotifier = neutrinonotify.New( + cfg.NeutrinoCS, hintCache, hintCache, + ) + cc.ChainView, err = chainview.NewCfFilteredChainView(cfg.NeutrinoCS) + if err != nil { + return nil, err + } + + // Map the deprecated neutrino feeurl flag to the general fee + // url. + if cfg.NeutrinoMode.FeeURL != "" { + if cfg.FeeURL != "" { + return nil, errors.New("feeurl and " + + "neutrino.feeurl are mutually exclusive") + } + + cfg.FeeURL = cfg.NeutrinoMode.FeeURL + } + + walletConfig.ChainSource = chain.NewNeutrinoClient( + cfg.ActiveNetParams.Params, cfg.NeutrinoCS, + ) + + case "bitcoind", "litecoind": + var bitcoindMode *lncfg.Bitcoind + switch { + case cfg.Bitcoin.Active: + bitcoindMode = cfg.BitcoindMode + case cfg.Litecoin.Active: + bitcoindMode = cfg.LitecoindMode + } + // Otherwise, we'll be speaking directly via RPC and ZMQ to a + // bitcoind node. If the specified host for the btcd/ltcd RPC + // server already has a port specified, then we use that + // directly. Otherwise, we assume the default port according to + // the selected chain parameters. + var bitcoindHost string + if strings.Contains(bitcoindMode.RPCHost, ":") { + bitcoindHost = bitcoindMode.RPCHost + } else { + // The RPC ports specified in chainparams.go assume + // btcd, which picks a different port so that btcwallet + // can use the same RPC port as bitcoind. We convert + // this back to the btcwallet/bitcoind port. + rpcPort, err := strconv.Atoi(cfg.ActiveNetParams.RPCPort) + if err != nil { + return nil, err + } + rpcPort -= 2 + bitcoindHost = fmt.Sprintf("%v:%d", + bitcoindMode.RPCHost, rpcPort) + if (cfg.Bitcoin.Active && cfg.Bitcoin.RegTest) || + (cfg.Litecoin.Active && cfg.Litecoin.RegTest) { + conn, err := net.Dial("tcp", bitcoindHost) + if err != nil || conn == nil { + if cfg.Bitcoin.Active && cfg.Bitcoin.RegTest { + rpcPort = 18443 + } else if cfg.Litecoin.Active && cfg.Litecoin.RegTest { + rpcPort = 19443 + } + bitcoindHost = fmt.Sprintf("%v:%d", + bitcoindMode.RPCHost, + rpcPort) + } else { + conn.Close() + } + } + } + + // Establish the connection to bitcoind and create the clients + // required for our relevant subsystems. + bitcoindConn, err := chain.NewBitcoindConn( + cfg.ActiveNetParams.Params, bitcoindHost, + bitcoindMode.RPCUser, bitcoindMode.RPCPass, + bitcoindMode.ZMQPubRawBlock, bitcoindMode.ZMQPubRawTx, + 5*time.Second, + ) + if err != nil { + return nil, err + } + + if err := bitcoindConn.Start(); err != nil { + return nil, fmt.Errorf("unable to connect to bitcoind: "+ + "%v", err) + } + + cc.ChainNotifier = bitcoindnotify.New( + bitcoindConn, cfg.ActiveNetParams.Params, hintCache, hintCache, + ) + cc.ChainView = chainview.NewBitcoindFilteredChainView(bitcoindConn) + walletConfig.ChainSource = bitcoindConn.NewBitcoindClient() + + // If we're not in regtest mode, then we'll attempt to use a + // proper fee estimator for testnet. + rpcConfig := &rpcclient.ConnConfig{ + Host: bitcoindHost, + User: bitcoindMode.RPCUser, + Pass: bitcoindMode.RPCPass, + DisableConnectOnNew: true, + DisableAutoReconnect: false, + DisableTLS: true, + HTTPPostMode: true, + } + if cfg.Bitcoin.Active && !cfg.Bitcoin.RegTest { + log.Infof("Initializing bitcoind backed fee estimator in "+ + "%s mode", bitcoindMode.EstimateMode) + + // Finally, we'll re-initialize the fee estimator, as + // if we're using bitcoind as a backend, then we can + // use live fee estimates, rather than a statically + // coded value. + fallBackFeeRate := chainfee.SatPerKVByte(25 * 1000) + cc.FeeEstimator, err = chainfee.NewBitcoindEstimator( + *rpcConfig, bitcoindMode.EstimateMode, + fallBackFeeRate.FeePerKWeight(), + ) + if err != nil { + return nil, err + } + } else if cfg.Litecoin.Active && !cfg.Litecoin.RegTest { + log.Infof("Initializing litecoind backed fee estimator in "+ + "%s mode", bitcoindMode.EstimateMode) + + // Finally, we'll re-initialize the fee estimator, as + // if we're using litecoind as a backend, then we can + // use live fee estimates, rather than a statically + // coded value. + fallBackFeeRate := chainfee.SatPerKVByte(25 * 1000) + cc.FeeEstimator, err = chainfee.NewBitcoindEstimator( + *rpcConfig, bitcoindMode.EstimateMode, + fallBackFeeRate.FeePerKWeight(), + ) + if err != nil { + return nil, err + } + } + case "btcd", "ltcd": + // Otherwise, we'll be speaking directly via RPC to a node. + // + // So first we'll load btcd/ltcd's TLS cert for the RPC + // connection. If a raw cert was specified in the config, then + // we'll set that directly. Otherwise, we attempt to read the + // cert from the path specified in the config. + var btcdMode *lncfg.Btcd + switch { + case cfg.Bitcoin.Active: + btcdMode = cfg.BtcdMode + case cfg.Litecoin.Active: + btcdMode = cfg.LtcdMode + } + var rpcCert []byte + if btcdMode.RawRPCCert != "" { + rpcCert, err = hex.DecodeString(btcdMode.RawRPCCert) + if err != nil { + return nil, err + } + } else { + certFile, err := os.Open(btcdMode.RPCCert) + if err != nil { + return nil, err + } + rpcCert, err = ioutil.ReadAll(certFile) + if err != nil { + return nil, err + } + if err := certFile.Close(); err != nil { + return nil, err + } + } + + // If the specified host for the btcd/ltcd RPC server already + // has a port specified, then we use that directly. Otherwise, + // we assume the default port according to the selected chain + // parameters. + var btcdHost string + if strings.Contains(btcdMode.RPCHost, ":") { + btcdHost = btcdMode.RPCHost + } else { + btcdHost = fmt.Sprintf("%v:%v", btcdMode.RPCHost, + cfg.ActiveNetParams.RPCPort) + } + + btcdUser := btcdMode.RPCUser + btcdPass := btcdMode.RPCPass + rpcConfig := &rpcclient.ConnConfig{ + Host: btcdHost, + Endpoint: "ws", + User: btcdUser, + Pass: btcdPass, + Certificates: rpcCert, + DisableTLS: false, + DisableConnectOnNew: true, + DisableAutoReconnect: false, + } + cc.ChainNotifier, err = btcdnotify.New( + rpcConfig, cfg.ActiveNetParams.Params, hintCache, hintCache, + ) + if err != nil { + return nil, err + } + + // Finally, we'll create an instance of the default chain view to be + // used within the routing layer. + cc.ChainView, err = chainview.NewBtcdFilteredChainView(*rpcConfig) + if err != nil { + log.Errorf("unable to create chain view: %v", err) + return nil, err + } + + // Create a special websockets rpc client for btcd which will be used + // by the wallet for notifications, calls, etc. + chainRPC, err := chain.NewRPCClient(cfg.ActiveNetParams.Params, btcdHost, + btcdUser, btcdPass, rpcCert, false, 20) + if err != nil { + return nil, err + } + + walletConfig.ChainSource = chainRPC + + // If we're not in simnet or regtest mode, then we'll attempt + // to use a proper fee estimator for testnet. + if !cfg.Bitcoin.SimNet && !cfg.Litecoin.SimNet && + !cfg.Bitcoin.RegTest && !cfg.Litecoin.RegTest { + + log.Info("Initializing btcd backed fee estimator") + + // Finally, we'll re-initialize the fee estimator, as + // if we're using btcd as a backend, then we can use + // live fee estimates, rather than a statically coded + // value. + fallBackFeeRate := chainfee.SatPerKVByte(25 * 1000) + cc.FeeEstimator, err = chainfee.NewBtcdEstimator( + *rpcConfig, fallBackFeeRate.FeePerKWeight(), + ) + if err != nil { + return nil, err + } + } + default: + return nil, fmt.Errorf("unknown node type: %s", + homeChainConfig.Node) + } + + // Override default fee estimator if an external service is specified. + if cfg.FeeURL != "" { + // Do not cache fees on regtest to make it easier to execute + // manual or automated test cases. + cacheFees := !cfg.Bitcoin.RegTest + + log.Infof("Using external fee estimator %v: cached=%v", + cfg.FeeURL, cacheFees) + + cc.FeeEstimator = chainfee.NewWebAPIEstimator( + chainfee.SparseConfFeeSource{ + URL: cfg.FeeURL, + }, + !cacheFees, + ) + } + + // Start fee estimator. + if err := cc.FeeEstimator.Start(); err != nil { + return nil, err + } + + wc, err := btcwallet.New(*walletConfig) + if err != nil { + fmt.Printf("unable to create wallet controller: %v\n", err) + return nil, err + } + + cc.MsgSigner = wc + cc.Signer = wc + cc.ChainIO = wc + cc.Wc = wc + + // Select the default channel constraints for the primary chain. + channelConstraints := DefaultBtcChannelConstraints + if cfg.PrimaryChain() == LitecoinChain { + channelConstraints = DefaultLtcChannelConstraints + } + + keyRing := keychain.NewBtcWalletKeyRing( + wc.InternalWallet(), cfg.ActiveNetParams.CoinType, + ) + cc.KeyRing = keyRing + + // Create, and start the lnwallet, which handles the core payment + // channel logic, and exposes control via proxy state machines. + walletCfg := lnwallet.Config{ + Database: cfg.RemoteChanDB, + Notifier: cc.ChainNotifier, + WalletController: wc, + Signer: cc.Signer, + FeeEstimator: cc.FeeEstimator, + SecretKeyRing: keyRing, + ChainIO: cc.ChainIO, + DefaultConstraints: channelConstraints, + NetParams: *cfg.ActiveNetParams.Params, + } + lnWallet, err := lnwallet.NewLightningWallet(walletCfg) + if err != nil { + fmt.Printf("unable to create wallet: %v\n", err) + return nil, err + } + if err := lnWallet.Startup(); err != nil { + fmt.Printf("unable to start wallet: %v\n", err) + return nil, err + } + + log.Info("LightningWallet opened") + + cc.Wallet = lnWallet + + return cc, nil +} + +var ( + // BitcoinTestnetGenesis is the genesis hash of Bitcoin's testnet + // chain. + BitcoinTestnetGenesis = chainhash.Hash([chainhash.HashSize]byte{ + 0x43, 0x49, 0x7f, 0xd7, 0xf8, 0x26, 0x95, 0x71, + 0x08, 0xf4, 0xa3, 0x0f, 0xd9, 0xce, 0xc3, 0xae, + 0xba, 0x79, 0x97, 0x20, 0x84, 0xe9, 0x0e, 0xad, + 0x01, 0xea, 0x33, 0x09, 0x00, 0x00, 0x00, 0x00, + }) + + // BitcoinMainnetGenesis is the genesis hash of Bitcoin's main chain. + BitcoinMainnetGenesis = chainhash.Hash([chainhash.HashSize]byte{ + 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, + 0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f, + 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c, + 0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, + }) + + // LitecoinTestnetGenesis is the genesis hash of Litecoin's testnet4 + // chain. + LitecoinTestnetGenesis = chainhash.Hash([chainhash.HashSize]byte{ + 0xa0, 0x29, 0x3e, 0x4e, 0xeb, 0x3d, 0xa6, 0xe6, + 0xf5, 0x6f, 0x81, 0xed, 0x59, 0x5f, 0x57, 0x88, + 0x0d, 0x1a, 0x21, 0x56, 0x9e, 0x13, 0xee, 0xfd, + 0xd9, 0x51, 0x28, 0x4b, 0x5a, 0x62, 0x66, 0x49, + }) + + // LitecoinMainnetGenesis is the genesis hash of Litecoin's main chain. + LitecoinMainnetGenesis = chainhash.Hash([chainhash.HashSize]byte{ + 0xe2, 0xbf, 0x04, 0x7e, 0x7e, 0x5a, 0x19, 0x1a, + 0xa4, 0xef, 0x34, 0xd3, 0x14, 0x97, 0x9d, 0xc9, + 0x98, 0x6e, 0x0f, 0x19, 0x25, 0x1e, 0xda, 0xba, + 0x59, 0x40, 0xfd, 0x1f, 0xe3, 0x65, 0xa7, 0x12, + }) + + // chainMap is a simple index that maps a chain's genesis hash to the + // ChainCode enum for that chain. + chainMap = map[chainhash.Hash]ChainCode{ + BitcoinTestnetGenesis: BitcoinChain, + LitecoinTestnetGenesis: LitecoinChain, + + BitcoinMainnetGenesis: BitcoinChain, + LitecoinMainnetGenesis: LitecoinChain, + } + + // ChainDNSSeeds is a map of a chain's hash to the set of DNS seeds + // that will be use to bootstrap peers upon first startup. + // + // The first item in the array is the primary host we'll use to attempt + // the SRV lookup we require. If we're unable to receive a response + // over UDP, then we'll fall back to manual TCP resolution. The second + // item in the array is a special A record that we'll query in order to + // receive the IP address of the current authoritative DNS server for + // the network seed. + // + // TODO(roasbeef): extend and collapse these and chainparams.go into + // struct like chaincfg.Params + ChainDNSSeeds = map[chainhash.Hash][][2]string{ + BitcoinMainnetGenesis: { + { + "nodes.lightning.directory", + "soa.nodes.lightning.directory", + }, + { + "lseed.bitcoinstats.com", + }, + }, + + BitcoinTestnetGenesis: { + { + "test.nodes.lightning.directory", + "soa.nodes.lightning.directory", + }, + }, + + LitecoinMainnetGenesis: { + { + "ltc.nodes.lightning.directory", + "soa.nodes.lightning.directory", + }, + }, + } +) + +// ChainRegistry keeps track of the current chains +type ChainRegistry struct { + sync.RWMutex + + activeChains map[ChainCode]*ChainControl + netParams map[ChainCode]*BitcoinNetParams + + primaryChain ChainCode +} + +// NewChainRegistry creates a new ChainRegistry. +func NewChainRegistry() *ChainRegistry { + return &ChainRegistry{ + activeChains: make(map[ChainCode]*ChainControl), + netParams: make(map[ChainCode]*BitcoinNetParams), + } +} + +// RegisterChain assigns an active ChainControl instance to a target chain +// identified by its ChainCode. +func (c *ChainRegistry) RegisterChain(newChain ChainCode, + cc *ChainControl) { + + c.Lock() + c.activeChains[newChain] = cc + c.Unlock() +} + +// LookupChain attempts to lookup an active ChainControl instance for the +// target chain. +func (c *ChainRegistry) LookupChain(targetChain ChainCode) ( + *ChainControl, bool) { + + c.RLock() + cc, ok := c.activeChains[targetChain] + c.RUnlock() + return cc, ok +} + +// LookupChainByHash attempts to look up an active ChainControl which +// corresponds to the passed genesis hash. +func (c *ChainRegistry) LookupChainByHash(chainHash chainhash.Hash) (*ChainControl, bool) { + c.RLock() + defer c.RUnlock() + + targetChain, ok := chainMap[chainHash] + if !ok { + return nil, ok + } + + cc, ok := c.activeChains[targetChain] + return cc, ok +} + +// RegisterPrimaryChain sets a target chain as the "home chain" for lnd. +func (c *ChainRegistry) RegisterPrimaryChain(cc ChainCode) { + c.Lock() + defer c.Unlock() + + c.primaryChain = cc +} + +// PrimaryChain returns the primary chain for this running lnd instance. The +// primary chain is considered the "home base" while the other registered +// chains are treated as secondary chains. +func (c *ChainRegistry) PrimaryChain() ChainCode { + c.RLock() + defer c.RUnlock() + + return c.primaryChain +} + +// ActiveChains returns a slice containing the active chains. +func (c *ChainRegistry) ActiveChains() []ChainCode { + c.RLock() + defer c.RUnlock() + + chains := make([]ChainCode, 0, len(c.activeChains)) + for activeChain := range c.activeChains { + chains = append(chains, activeChain) + } + + return chains +} + +// NumActiveChains returns the total number of active chains. +func (c *ChainRegistry) NumActiveChains() uint32 { + c.RLock() + defer c.RUnlock() + + return uint32(len(c.activeChains)) +} diff --git a/chainreg/log.go b/chainreg/log.go new file mode 100644 index 000000000..94bbb5543 --- /dev/null +++ b/chainreg/log.go @@ -0,0 +1,24 @@ +package chainreg + +import ( + "github.com/btcsuite/btclog" + "github.com/lightningnetwork/lnd/build" +) + +// log is a logger that is initialized with the btclog.Disabled logger. +var log btclog.Logger + +// The default amount of logging is none. +func init() { + UseLogger(build.NewSubLogger("CHRE", nil)) +} + +// DisableLog disables all logging output. +func DisableLog() { + UseLogger(btclog.Disabled) +} + +// UseLogger uses a specified Logger to output package logging info. +func UseLogger(logger btclog.Logger) { + log = logger +} diff --git a/chainregistry.go b/chainregistry.go deleted file mode 100644 index 6d0ce2cbb..000000000 --- a/chainregistry.go +++ /dev/null @@ -1,721 +0,0 @@ -package lnd - -import ( - "encoding/hex" - "errors" - "fmt" - "io/ioutil" - "net" - "os" - "strconv" - "strings" - "sync" - "time" - - "github.com/btcsuite/btcd/chaincfg/chainhash" - "github.com/btcsuite/btcd/rpcclient" - "github.com/btcsuite/btcutil" - "github.com/btcsuite/btcwallet/chain" - "github.com/lightningnetwork/lnd/chainntnfs" - "github.com/lightningnetwork/lnd/chainntnfs/bitcoindnotify" - "github.com/lightningnetwork/lnd/chainntnfs/btcdnotify" - "github.com/lightningnetwork/lnd/chainntnfs/neutrinonotify" - "github.com/lightningnetwork/lnd/chainreg" - "github.com/lightningnetwork/lnd/channeldb" - "github.com/lightningnetwork/lnd/htlcswitch" - "github.com/lightningnetwork/lnd/input" - "github.com/lightningnetwork/lnd/keychain" - "github.com/lightningnetwork/lnd/lncfg" - "github.com/lightningnetwork/lnd/lnwallet" - "github.com/lightningnetwork/lnd/lnwallet/btcwallet" - "github.com/lightningnetwork/lnd/lnwallet/chainfee" - "github.com/lightningnetwork/lnd/lnwire" - "github.com/lightningnetwork/lnd/routing/chainview" -) - -const ( - // DefaultBitcoinMinHTLCMSat is the default smallest value htlc this - // node will accept. This value is proposed in the channel open sequence - // and cannot be changed during the life of the channel. It is 1 msat by - // default to allow maximum flexibility in deciding what size payments - // to forward. - // - // All forwarded payments are subjected to the min htlc constraint of - // the routing policy of the outgoing channel. This implicitly controls - // the minimum htlc value on the incoming channel too. - DefaultBitcoinMinHTLCInMSat = lnwire.MilliSatoshi(1) - - // DefaultBitcoinMinHTLCOutMSat is the default minimum htlc value that - // we require for sending out htlcs. Our channel peer may have a lower - // min htlc channel parameter, but we - by default - don't forward - // anything under the value defined here. - DefaultBitcoinMinHTLCOutMSat = lnwire.MilliSatoshi(1000) - - // DefaultBitcoinBaseFeeMSat is the default forwarding base fee. - DefaultBitcoinBaseFeeMSat = lnwire.MilliSatoshi(1000) - - // DefaultBitcoinFeeRate is the default forwarding fee rate. - DefaultBitcoinFeeRate = lnwire.MilliSatoshi(1) - - // DefaultBitcoinTimeLockDelta is the default forwarding time lock - // delta. - DefaultBitcoinTimeLockDelta = 40 - - DefaultLitecoinMinHTLCInMSat = lnwire.MilliSatoshi(1) - DefaultLitecoinMinHTLCOutMSat = lnwire.MilliSatoshi(1000) - DefaultLitecoinBaseFeeMSat = lnwire.MilliSatoshi(1000) - DefaultLitecoinFeeRate = lnwire.MilliSatoshi(1) - DefaultLitecoinTimeLockDelta = 576 - DefaultLitecoinDustLimit = btcutil.Amount(54600) - - // DefaultBitcoinStaticFeePerKW is the fee rate of 50 sat/vbyte - // expressed in sat/kw. - DefaultBitcoinStaticFeePerKW = chainfee.SatPerKWeight(12500) - - // DefaultBitcoinStaticMinRelayFeeRate is the min relay fee used for - // static estimators. - DefaultBitcoinStaticMinRelayFeeRate = chainfee.FeePerKwFloor - - // DefaultLitecoinStaticFeePerKW is the fee rate of 200 sat/vbyte - // expressed in sat/kw. - DefaultLitecoinStaticFeePerKW = chainfee.SatPerKWeight(50000) - - // BtcToLtcConversionRate is a fixed ratio used in order to scale up - // payments when running on the Litecoin chain. - BtcToLtcConversionRate = 60 -) - -// DefaultBtcChannelConstraints is the default set of channel constraints that are -// meant to be used when initially funding a Bitcoin channel. -// -// TODO(halseth): make configurable at startup? -var DefaultBtcChannelConstraints = channeldb.ChannelConstraints{ - DustLimit: lnwallet.DefaultDustLimit(), - MaxAcceptedHtlcs: input.MaxHTLCNumber / 2, -} - -// DefaultLtcChannelConstraints is the default set of channel constraints that are -// meant to be used when initially funding a Litecoin channel. -var DefaultLtcChannelConstraints = channeldb.ChannelConstraints{ - DustLimit: DefaultLitecoinDustLimit, - MaxAcceptedHtlcs: input.MaxHTLCNumber / 2, -} - -// ChainControl couples the three primary interfaces lnd utilizes for a -// particular chain together. A single ChainControl instance will exist for all -// the chains lnd is currently active on. -type ChainControl struct { - // ChainIO represents an abstraction over a source that can query the blockchain. - ChainIO lnwallet.BlockChainIO - - // FeeEstimator is used to estimate an optimal fee for transactions important to us. - FeeEstimator chainfee.Estimator - - // Signer is used to provide signatures over things like transactions. - Signer input.Signer - - // KeyRing represents a set of keys that we have the private keys to. - KeyRing keychain.SecretKeyRing - - // Wc is an abstraction over some basic wallet commands. This base set of commands - // will be provided to the Wallet *LightningWallet raw pointer below. - Wc lnwallet.WalletController - - // MsgSigner is used to sign arbitrary messages. - MsgSigner lnwallet.MessageSigner - - // ChainNotifier is used to receive blockchain events that we are interested in. - ChainNotifier chainntnfs.ChainNotifier - - // ChainView is used in the router for maintaining an up-to-date graph. - ChainView chainview.FilteredChainView - - // Wallet is our LightningWallet that also contains the abstract Wc above. This wallet - // handles all of the lightning operations. - Wallet *lnwallet.LightningWallet - - // RoutingPolicy is the routing policy we have decided to use. - RoutingPolicy htlcswitch.ForwardingPolicy - - // MinHtlcIn is the minimum HTLC we will accept. - MinHtlcIn lnwire.MilliSatoshi -} - -// NewChainControl attempts to create a ChainControl instance according -// to the parameters in the passed configuration. Currently three -// branches of ChainControl instances exist: one backed by a running btcd -// 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 -// neutrino light client instance, `neutrinoCS` must be non-nil. -func NewChainControl(cfg *chainreg.Config) (*ChainControl, error) { - - // 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. - homeChainConfig := cfg.Bitcoin - if cfg.PrimaryChain() == chainreg.LitecoinChain { - homeChainConfig = cfg.Litecoin - } - ltndLog.Infof("Primary chain is set to: %v", - cfg.PrimaryChain()) - - cc := &ChainControl{} - - switch cfg.PrimaryChain() { - case chainreg.BitcoinChain: - cc.RoutingPolicy = htlcswitch.ForwardingPolicy{ - MinHTLCOut: cfg.Bitcoin.MinHTLCOut, - BaseFee: cfg.Bitcoin.BaseFee, - FeeRate: cfg.Bitcoin.FeeRate, - TimeLockDelta: cfg.Bitcoin.TimeLockDelta, - } - cc.MinHtlcIn = cfg.Bitcoin.MinHTLCIn - cc.FeeEstimator = chainfee.NewStaticEstimator( - DefaultBitcoinStaticFeePerKW, - DefaultBitcoinStaticMinRelayFeeRate, - ) - case chainreg.LitecoinChain: - cc.RoutingPolicy = htlcswitch.ForwardingPolicy{ - MinHTLCOut: cfg.Litecoin.MinHTLCOut, - BaseFee: cfg.Litecoin.BaseFee, - FeeRate: cfg.Litecoin.FeeRate, - TimeLockDelta: cfg.Litecoin.TimeLockDelta, - } - cc.MinHtlcIn = cfg.Litecoin.MinHTLCIn - cc.FeeEstimator = chainfee.NewStaticEstimator( - DefaultLitecoinStaticFeePerKW, 0, - ) - default: - return nil, fmt.Errorf("default routing policy for chain %v is "+ - "unknown", cfg.PrimaryChain()) - } - - walletConfig := &btcwallet.Config{ - PrivatePass: cfg.PrivateWalletPw, - PublicPass: cfg.PublicWalletPw, - Birthday: cfg.Birthday, - RecoveryWindow: cfg.RecoveryWindow, - DataDir: homeChainConfig.ChainDir, - NetParams: cfg.ActiveNetParams.Params, - CoinType: cfg.ActiveNetParams.CoinType, - Wallet: cfg.Wallet, - } - - var err error - - heightHintCacheConfig := chainntnfs.CacheConfig{ - QueryDisable: cfg.HeightHintCacheQueryDisable, - } - if cfg.HeightHintCacheQueryDisable { - ltndLog.Infof("Height Hint Cache Queries disabled") - } - - // Initialize the height hint cache within the chain directory. - hintCache, err := chainntnfs.NewHeightHintCache( - heightHintCacheConfig, cfg.LocalChanDB, - ) - if err != nil { - return nil, fmt.Errorf("unable to initialize height hint "+ - "cache: %v", err) - } - - // If spv mode is active, then we'll be using a distinct set of - // chainControl interfaces that interface directly with the p2p network - // of the selected chain. - switch homeChainConfig.Node { - case "neutrino": - // We'll create ChainNotifier and FilteredChainView instances, - // along with the wallet's ChainSource, which are all backed by - // the neutrino light client. - cc.ChainNotifier = neutrinonotify.New( - cfg.NeutrinoCS, hintCache, hintCache, - ) - cc.ChainView, err = chainview.NewCfFilteredChainView(cfg.NeutrinoCS) - if err != nil { - return nil, err - } - - // Map the deprecated neutrino feeurl flag to the general fee - // url. - if cfg.NeutrinoMode.FeeURL != "" { - if cfg.FeeURL != "" { - return nil, errors.New("feeurl and " + - "neutrino.feeurl are mutually exclusive") - } - - cfg.FeeURL = cfg.NeutrinoMode.FeeURL - } - - walletConfig.ChainSource = chain.NewNeutrinoClient( - cfg.ActiveNetParams.Params, cfg.NeutrinoCS, - ) - - case "bitcoind", "litecoind": - var bitcoindMode *lncfg.Bitcoind - switch { - case cfg.Bitcoin.Active: - bitcoindMode = cfg.BitcoindMode - case cfg.Litecoin.Active: - bitcoindMode = cfg.LitecoindMode - } - // Otherwise, we'll be speaking directly via RPC and ZMQ to a - // bitcoind node. If the specified host for the btcd/ltcd RPC - // server already has a port specified, then we use that - // directly. Otherwise, we assume the default port according to - // the selected chain parameters. - var bitcoindHost string - if strings.Contains(bitcoindMode.RPCHost, ":") { - bitcoindHost = bitcoindMode.RPCHost - } else { - // The RPC ports specified in chainparams.go assume - // btcd, which picks a different port so that btcwallet - // can use the same RPC port as bitcoind. We convert - // this back to the btcwallet/bitcoind port. - rpcPort, err := strconv.Atoi(cfg.ActiveNetParams.RPCPort) - if err != nil { - return nil, err - } - rpcPort -= 2 - bitcoindHost = fmt.Sprintf("%v:%d", - bitcoindMode.RPCHost, rpcPort) - if (cfg.Bitcoin.Active && cfg.Bitcoin.RegTest) || - (cfg.Litecoin.Active && cfg.Litecoin.RegTest) { - conn, err := net.Dial("tcp", bitcoindHost) - if err != nil || conn == nil { - if cfg.Bitcoin.Active && cfg.Bitcoin.RegTest { - rpcPort = 18443 - } else if cfg.Litecoin.Active && cfg.Litecoin.RegTest { - rpcPort = 19443 - } - bitcoindHost = fmt.Sprintf("%v:%d", - bitcoindMode.RPCHost, - rpcPort) - } else { - conn.Close() - } - } - } - - // Establish the connection to bitcoind and create the clients - // required for our relevant subsystems. - bitcoindConn, err := chain.NewBitcoindConn( - cfg.ActiveNetParams.Params, bitcoindHost, - bitcoindMode.RPCUser, bitcoindMode.RPCPass, - bitcoindMode.ZMQPubRawBlock, bitcoindMode.ZMQPubRawTx, - 5*time.Second, - ) - if err != nil { - return nil, err - } - - if err := bitcoindConn.Start(); err != nil { - return nil, fmt.Errorf("unable to connect to bitcoind: "+ - "%v", err) - } - - cc.ChainNotifier = bitcoindnotify.New( - bitcoindConn, cfg.ActiveNetParams.Params, hintCache, hintCache, - ) - cc.ChainView = chainview.NewBitcoindFilteredChainView(bitcoindConn) - walletConfig.ChainSource = bitcoindConn.NewBitcoindClient() - - // If we're not in regtest mode, then we'll attempt to use a - // proper fee estimator for testnet. - rpcConfig := &rpcclient.ConnConfig{ - Host: bitcoindHost, - User: bitcoindMode.RPCUser, - Pass: bitcoindMode.RPCPass, - DisableConnectOnNew: true, - DisableAutoReconnect: false, - DisableTLS: true, - HTTPPostMode: true, - } - if cfg.Bitcoin.Active && !cfg.Bitcoin.RegTest { - ltndLog.Infof("Initializing bitcoind backed fee estimator in "+ - "%s mode", bitcoindMode.EstimateMode) - - // Finally, we'll re-initialize the fee estimator, as - // if we're using bitcoind as a backend, then we can - // use live fee estimates, rather than a statically - // coded value. - fallBackFeeRate := chainfee.SatPerKVByte(25 * 1000) - cc.FeeEstimator, err = chainfee.NewBitcoindEstimator( - *rpcConfig, bitcoindMode.EstimateMode, - fallBackFeeRate.FeePerKWeight(), - ) - if err != nil { - return nil, err - } - } else if cfg.Litecoin.Active && !cfg.Litecoin.RegTest { - ltndLog.Infof("Initializing litecoind backed fee estimator in "+ - "%s mode", bitcoindMode.EstimateMode) - - // Finally, we'll re-initialize the fee estimator, as - // if we're using litecoind as a backend, then we can - // use live fee estimates, rather than a statically - // coded value. - fallBackFeeRate := chainfee.SatPerKVByte(25 * 1000) - cc.FeeEstimator, err = chainfee.NewBitcoindEstimator( - *rpcConfig, bitcoindMode.EstimateMode, - fallBackFeeRate.FeePerKWeight(), - ) - if err != nil { - return nil, err - } - } - case "btcd", "ltcd": - // Otherwise, we'll be speaking directly via RPC to a node. - // - // So first we'll load btcd/ltcd's TLS cert for the RPC - // connection. If a raw cert was specified in the config, then - // we'll set that directly. Otherwise, we attempt to read the - // cert from the path specified in the config. - var btcdMode *lncfg.Btcd - switch { - case cfg.Bitcoin.Active: - btcdMode = cfg.BtcdMode - case cfg.Litecoin.Active: - btcdMode = cfg.LtcdMode - } - var rpcCert []byte - if btcdMode.RawRPCCert != "" { - rpcCert, err = hex.DecodeString(btcdMode.RawRPCCert) - if err != nil { - return nil, err - } - } else { - certFile, err := os.Open(btcdMode.RPCCert) - if err != nil { - return nil, err - } - rpcCert, err = ioutil.ReadAll(certFile) - if err != nil { - return nil, err - } - if err := certFile.Close(); err != nil { - return nil, err - } - } - - // If the specified host for the btcd/ltcd RPC server already - // has a port specified, then we use that directly. Otherwise, - // we assume the default port according to the selected chain - // parameters. - var btcdHost string - if strings.Contains(btcdMode.RPCHost, ":") { - btcdHost = btcdMode.RPCHost - } else { - btcdHost = fmt.Sprintf("%v:%v", btcdMode.RPCHost, - cfg.ActiveNetParams.RPCPort) - } - - btcdUser := btcdMode.RPCUser - btcdPass := btcdMode.RPCPass - rpcConfig := &rpcclient.ConnConfig{ - Host: btcdHost, - Endpoint: "ws", - User: btcdUser, - Pass: btcdPass, - Certificates: rpcCert, - DisableTLS: false, - DisableConnectOnNew: true, - DisableAutoReconnect: false, - } - cc.ChainNotifier, err = btcdnotify.New( - rpcConfig, cfg.ActiveNetParams.Params, hintCache, hintCache, - ) - if err != nil { - return nil, err - } - - // Finally, we'll create an instance of the default chain view to be - // used within the routing layer. - cc.ChainView, err = chainview.NewBtcdFilteredChainView(*rpcConfig) - if err != nil { - srvrLog.Errorf("unable to create chain view: %v", err) - return nil, err - } - - // Create a special websockets rpc client for btcd which will be used - // by the wallet for notifications, calls, etc. - chainRPC, err := chain.NewRPCClient(cfg.ActiveNetParams.Params, btcdHost, - btcdUser, btcdPass, rpcCert, false, 20) - if err != nil { - return nil, err - } - - walletConfig.ChainSource = chainRPC - - // If we're not in simnet or regtest mode, then we'll attempt - // to use a proper fee estimator for testnet. - if !cfg.Bitcoin.SimNet && !cfg.Litecoin.SimNet && - !cfg.Bitcoin.RegTest && !cfg.Litecoin.RegTest { - - ltndLog.Infof("Initializing btcd backed fee estimator") - - // Finally, we'll re-initialize the fee estimator, as - // if we're using btcd as a backend, then we can use - // live fee estimates, rather than a statically coded - // value. - fallBackFeeRate := chainfee.SatPerKVByte(25 * 1000) - cc.FeeEstimator, err = chainfee.NewBtcdEstimator( - *rpcConfig, fallBackFeeRate.FeePerKWeight(), - ) - if err != nil { - return nil, err - } - } - default: - return nil, fmt.Errorf("unknown node type: %s", - homeChainConfig.Node) - } - - // Override default fee estimator if an external service is specified. - if cfg.FeeURL != "" { - // Do not cache fees on regtest to make it easier to execute - // manual or automated test cases. - cacheFees := !cfg.Bitcoin.RegTest - - ltndLog.Infof("Using external fee estimator %v: cached=%v", - cfg.FeeURL, cacheFees) - - cc.FeeEstimator = chainfee.NewWebAPIEstimator( - chainfee.SparseConfFeeSource{ - URL: cfg.FeeURL, - }, - !cacheFees, - ) - } - - // Start fee estimator. - if err := cc.FeeEstimator.Start(); err != nil { - return nil, err - } - - wc, err := btcwallet.New(*walletConfig) - if err != nil { - fmt.Printf("unable to create wallet controller: %v\n", err) - return nil, err - } - - cc.MsgSigner = wc - cc.Signer = wc - cc.ChainIO = wc - cc.Wc = wc - - // Select the default channel constraints for the primary chain. - channelConstraints := DefaultBtcChannelConstraints - if cfg.PrimaryChain() == chainreg.LitecoinChain { - channelConstraints = DefaultLtcChannelConstraints - } - - keyRing := keychain.NewBtcWalletKeyRing( - wc.InternalWallet(), cfg.ActiveNetParams.CoinType, - ) - cc.KeyRing = keyRing - - // Create, and start the lnwallet, which handles the core payment - // channel logic, and exposes control via proxy state machines. - walletCfg := lnwallet.Config{ - Database: cfg.RemoteChanDB, - Notifier: cc.ChainNotifier, - WalletController: wc, - Signer: cc.Signer, - FeeEstimator: cc.FeeEstimator, - SecretKeyRing: keyRing, - ChainIO: cc.ChainIO, - DefaultConstraints: channelConstraints, - NetParams: *cfg.ActiveNetParams.Params, - } - lnWallet, err := lnwallet.NewLightningWallet(walletCfg) - if err != nil { - fmt.Printf("unable to create wallet: %v\n", err) - return nil, err - } - if err := lnWallet.Startup(); err != nil { - fmt.Printf("unable to start wallet: %v\n", err) - return nil, err - } - - ltndLog.Info("LightningWallet opened") - - cc.Wallet = lnWallet - - return cc, nil -} - -var ( - // BitcoinTestnetGenesis is the genesis hash of Bitcoin's testnet - // chain. - BitcoinTestnetGenesis = chainhash.Hash([chainhash.HashSize]byte{ - 0x43, 0x49, 0x7f, 0xd7, 0xf8, 0x26, 0x95, 0x71, - 0x08, 0xf4, 0xa3, 0x0f, 0xd9, 0xce, 0xc3, 0xae, - 0xba, 0x79, 0x97, 0x20, 0x84, 0xe9, 0x0e, 0xad, - 0x01, 0xea, 0x33, 0x09, 0x00, 0x00, 0x00, 0x00, - }) - - // BitcoinMainnetGenesis is the genesis hash of Bitcoin's main chain. - BitcoinMainnetGenesis = chainhash.Hash([chainhash.HashSize]byte{ - 0x6f, 0xe2, 0x8c, 0x0a, 0xb6, 0xf1, 0xb3, 0x72, - 0xc1, 0xa6, 0xa2, 0x46, 0xae, 0x63, 0xf7, 0x4f, - 0x93, 0x1e, 0x83, 0x65, 0xe1, 0x5a, 0x08, 0x9c, - 0x68, 0xd6, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00, - }) - - // LitecoinTestnetGenesis is the genesis hash of Litecoin's testnet4 - // chain. - LitecoinTestnetGenesis = chainhash.Hash([chainhash.HashSize]byte{ - 0xa0, 0x29, 0x3e, 0x4e, 0xeb, 0x3d, 0xa6, 0xe6, - 0xf5, 0x6f, 0x81, 0xed, 0x59, 0x5f, 0x57, 0x88, - 0x0d, 0x1a, 0x21, 0x56, 0x9e, 0x13, 0xee, 0xfd, - 0xd9, 0x51, 0x28, 0x4b, 0x5a, 0x62, 0x66, 0x49, - }) - - // LitecoinMainnetGenesis is the genesis hash of Litecoin's main chain. - LitecoinMainnetGenesis = chainhash.Hash([chainhash.HashSize]byte{ - 0xe2, 0xbf, 0x04, 0x7e, 0x7e, 0x5a, 0x19, 0x1a, - 0xa4, 0xef, 0x34, 0xd3, 0x14, 0x97, 0x9d, 0xc9, - 0x98, 0x6e, 0x0f, 0x19, 0x25, 0x1e, 0xda, 0xba, - 0x59, 0x40, 0xfd, 0x1f, 0xe3, 0x65, 0xa7, 0x12, - }) - - // chainMap is a simple index that maps a chain's genesis hash to the - // ChainCode enum for that chain. - chainMap = map[chainhash.Hash]chainreg.ChainCode{ - BitcoinTestnetGenesis: chainreg.BitcoinChain, - LitecoinTestnetGenesis: chainreg.LitecoinChain, - - BitcoinMainnetGenesis: chainreg.BitcoinChain, - LitecoinMainnetGenesis: chainreg.LitecoinChain, - } - - // ChainDNSSeeds is a map of a chain's hash to the set of DNS seeds - // that will be use to bootstrap peers upon first startup. - // - // The first item in the array is the primary host we'll use to attempt - // the SRV lookup we require. If we're unable to receive a response - // over UDP, then we'll fall back to manual TCP resolution. The second - // item in the array is a special A record that we'll query in order to - // receive the IP address of the current authoritative DNS server for - // the network seed. - // - // TODO(roasbeef): extend and collapse these and chainparams.go into - // struct like chaincfg.Params - ChainDNSSeeds = map[chainhash.Hash][][2]string{ - BitcoinMainnetGenesis: { - { - "nodes.lightning.directory", - "soa.nodes.lightning.directory", - }, - { - "lseed.bitcoinstats.com", - }, - }, - - BitcoinTestnetGenesis: { - { - "test.nodes.lightning.directory", - "soa.nodes.lightning.directory", - }, - }, - - LitecoinMainnetGenesis: { - { - "ltc.nodes.lightning.directory", - "soa.nodes.lightning.directory", - }, - }, - } -) - -// ChainRegistry keeps track of the current chains -type ChainRegistry struct { - sync.RWMutex - - activeChains map[chainreg.ChainCode]*ChainControl - netParams map[chainreg.ChainCode]*chainreg.BitcoinNetParams - - primaryChain chainreg.ChainCode -} - -// NewChainRegistry creates a new ChainRegistry. -func NewChainRegistry() *ChainRegistry { - return &ChainRegistry{ - activeChains: make(map[chainreg.ChainCode]*ChainControl), - netParams: make(map[chainreg.ChainCode]*chainreg.BitcoinNetParams), - } -} - -// RegisterChain assigns an active ChainControl instance to a target chain -// identified by its ChainCode. -func (c *ChainRegistry) RegisterChain(newChain chainreg.ChainCode, - cc *ChainControl) { - - c.Lock() - c.activeChains[newChain] = cc - c.Unlock() -} - -// LookupChain attempts to lookup an active ChainControl instance for the -// target chain. -func (c *ChainRegistry) LookupChain(targetChain chainreg.ChainCode) ( - *ChainControl, bool) { - - c.RLock() - cc, ok := c.activeChains[targetChain] - c.RUnlock() - return cc, ok -} - -// LookupChainByHash attempts to look up an active ChainControl which -// corresponds to the passed genesis hash. -func (c *ChainRegistry) LookupChainByHash(chainHash chainhash.Hash) (*ChainControl, bool) { - c.RLock() - defer c.RUnlock() - - targetChain, ok := chainMap[chainHash] - if !ok { - return nil, ok - } - - cc, ok := c.activeChains[targetChain] - return cc, ok -} - -// RegisterPrimaryChain sets a target chain as the "home chain" for lnd. -func (c *ChainRegistry) RegisterPrimaryChain(cc chainreg.ChainCode) { - c.Lock() - defer c.Unlock() - - c.primaryChain = cc -} - -// PrimaryChain returns the primary chain for this running lnd instance. The -// primary chain is considered the "home base" while the other registered -// chains are treated as secondary chains. -func (c *ChainRegistry) PrimaryChain() chainreg.ChainCode { - c.RLock() - defer c.RUnlock() - - return c.primaryChain -} - -// ActiveChains returns a slice containing the active chains. -func (c *ChainRegistry) ActiveChains() []chainreg.ChainCode { - c.RLock() - defer c.RUnlock() - - chains := make([]chainreg.ChainCode, 0, len(c.activeChains)) - for activeChain := range c.activeChains { - chains = append(chains, activeChain) - } - - return chains -} - -// NumActiveChains returns the total number of active chains. -func (c *ChainRegistry) NumActiveChains() uint32 { - c.RLock() - defer c.RUnlock() - - return uint32(len(c.activeChains)) -} diff --git a/cmd/lncli/cmd_build_route.go b/cmd/lncli/cmd_build_route.go index 81c5bfb04..1d5eeb7b7 100644 --- a/cmd/lncli/cmd_build_route.go +++ b/cmd/lncli/cmd_build_route.go @@ -6,7 +6,7 @@ import ( "fmt" "strings" - "github.com/lightningnetwork/lnd" + "github.com/lightningnetwork/lnd/chainreg" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/routing/route" "github.com/urfave/cli" @@ -27,7 +27,7 @@ var buildRouteCommand = cli.Command{ Name: "final_cltv_delta", Usage: "number of blocks the last hop has to reveal " + "the preimage", - Value: lnd.DefaultBitcoinTimeLockDelta, + Value: chainreg.DefaultBitcoinTimeLockDelta, }, cli.StringFlag{ Name: "hops", diff --git a/config.go b/config.go index b85ea41cf..6095e5284 100644 --- a/config.go +++ b/config.go @@ -312,7 +312,7 @@ type Config struct { // registeredChains keeps track of all chains that have been registered // with the daemon. - registeredChains *ChainRegistry + registeredChains *chainreg.ChainRegistry // networkDir is the path to the directory of the currently active // network. This path will hold the files related to each different @@ -339,11 +339,11 @@ func DefaultConfig() Config { MaxLogFileSize: defaultMaxLogFileSize, AcceptorTimeout: defaultAcceptorTimeout, Bitcoin: &lncfg.Chain{ - MinHTLCIn: DefaultBitcoinMinHTLCInMSat, - MinHTLCOut: DefaultBitcoinMinHTLCOutMSat, - BaseFee: DefaultBitcoinBaseFeeMSat, - FeeRate: DefaultBitcoinFeeRate, - TimeLockDelta: DefaultBitcoinTimeLockDelta, + MinHTLCIn: chainreg.DefaultBitcoinMinHTLCInMSat, + MinHTLCOut: chainreg.DefaultBitcoinMinHTLCOutMSat, + BaseFee: chainreg.DefaultBitcoinBaseFeeMSat, + FeeRate: chainreg.DefaultBitcoinFeeRate, + TimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta, Node: "btcd", }, BtcdMode: &lncfg.Btcd{ @@ -357,11 +357,11 @@ func DefaultConfig() Config { EstimateMode: defaultBitcoindEstimateMode, }, Litecoin: &lncfg.Chain{ - MinHTLCIn: DefaultLitecoinMinHTLCInMSat, - MinHTLCOut: DefaultLitecoinMinHTLCOutMSat, - BaseFee: DefaultLitecoinBaseFeeMSat, - FeeRate: DefaultLitecoinFeeRate, - TimeLockDelta: DefaultLitecoinTimeLockDelta, + MinHTLCIn: chainreg.DefaultLitecoinMinHTLCInMSat, + MinHTLCOut: chainreg.DefaultLitecoinMinHTLCOutMSat, + BaseFee: chainreg.DefaultLitecoinBaseFeeMSat, + FeeRate: chainreg.DefaultLitecoinFeeRate, + TimeLockDelta: chainreg.DefaultLitecoinTimeLockDelta, Node: "ltcd", }, LtcdMode: &lncfg.Btcd{ @@ -452,7 +452,7 @@ func DefaultConfig() Config { MaxChannelFeeAllocation: htlcswitch.DefaultMaxLinkFeeAllocation, LogWriter: build.NewRotatingLogWriter(), DB: lncfg.DefaultDB(), - registeredChains: NewChainRegistry(), + registeredChains: chainreg.NewChainRegistry(), ActiveNetParams: chainreg.BitcoinTestNetParams, } } diff --git a/fundingmanager.go b/fundingmanager.go index c20f04c2f..43e3c29d3 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -76,7 +76,7 @@ const ( // maxLtcFundingAmount is a soft-limit of the maximum channel size // currently accepted on the Litecoin chain within the Lightning // Protocol. - maxLtcFundingAmount = MaxBtcFundingAmount * BtcToLtcConversionRate + maxLtcFundingAmount = MaxBtcFundingAmount * chainreg.BtcToLtcConversionRate ) var ( @@ -358,7 +358,7 @@ type fundingConfig struct { // RegisteredChains keeps track of all chains that have been registered // with the daemon. - RegisteredChains *ChainRegistry + RegisteredChains *chainreg.ChainRegistry } // fundingManager acts as an orchestrator/bridge between the wallet's @@ -3064,7 +3064,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { case chainreg.BitcoinChain: ourDustLimit = lnwallet.DefaultDustLimit() case chainreg.LitecoinChain: - ourDustLimit = DefaultLitecoinDustLimit + ourDustLimit = chainreg.DefaultLitecoinDustLimit } fndgLog.Infof("Initiating fundingRequest(local_amt=%v "+ diff --git a/fundingmanager_test.go b/fundingmanager_test.go index 831078669..c08d1d8f0 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -271,7 +271,7 @@ func createTestWallet(cdb *channeldb.DB, netParams *chaincfg.Params, ChainIO: bio, FeeEstimator: estimator, NetParams: *netParams, - DefaultConstraints: DefaultBtcChannelConstraints, + DefaultConstraints: chainreg.DefaultBtcChannelConstraints, }) if err != nil { return nil, err @@ -437,7 +437,7 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, NotifyOpenChannelEvent: evt.NotifyOpenChannelEvent, OpenChannelPredicate: chainedAcceptor, NotifyPendingOpenChannelEvent: evt.NotifyPendingOpenChannelEvent, - RegisteredChains: NewChainRegistry(), + RegisteredChains: chainreg.NewChainRegistry(), } for _, op := range options { diff --git a/lnd.go b/lnd.go index a05336016..47bb34891 100644 --- a/lnd.go +++ b/lnd.go @@ -472,7 +472,7 @@ func Main(cfg *Config, lisCfg ListenerCfg, shutdownChan <-chan struct{}) error { FeeURL: cfg.FeeURL, } - activeChainControl, err := NewChainControl(chainControlCfg) + activeChainControl, err := chainreg.NewChainControl(chainControlCfg) if err != nil { err := fmt.Errorf("unable to create chain control: %v", err) ltndLog.Error(err) diff --git a/lntest/itest/lnd_forward_interceptor_test.go b/lntest/itest/lnd_forward_interceptor_test.go index 6c54756f8..108263c54 100644 --- a/lntest/itest/lnd_forward_interceptor_test.go +++ b/lntest/itest/lnd_forward_interceptor_test.go @@ -10,6 +10,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd" + "github.com/lightningnetwork/lnd/chainreg" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lntest" @@ -402,7 +403,7 @@ func (c *interceptorTestContext) buildRoute(ctx context.Context, amtMsat int64, req := &routerrpc.BuildRouteRequest{ AmtMsat: amtMsat, - FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta, + FinalCltvDelta: chainreg.DefaultBitcoinTimeLockDelta, HopPubkeys: rpcHops, } diff --git a/lntest/itest/lnd_mpp_test.go b/lntest/itest/lnd_mpp_test.go index e213d9818..5a5e8ece2 100644 --- a/lntest/itest/lnd_mpp_test.go +++ b/lntest/itest/lnd_mpp_test.go @@ -9,6 +9,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd" + "github.com/lightningnetwork/lnd/chainreg" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lntest" @@ -91,7 +92,7 @@ func testSendToRouteMultiPath(net *lntest.NetworkHarness, t *harnessTest) { req := &routerrpc.BuildRouteRequest{ AmtMsat: int64(amt * 1000), - FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta, + FinalCltvDelta: chainreg.DefaultBitcoinTimeLockDelta, HopPubkeys: rpcHops, } diff --git a/lntest/itest/lnd_multi-hop-payments_test.go b/lntest/itest/lnd_multi-hop-payments_test.go index ed8f25d80..afacc4812 100644 --- a/lntest/itest/lnd_multi-hop-payments_test.go +++ b/lntest/itest/lnd_multi-hop-payments_test.go @@ -7,6 +7,7 @@ import ( "github.com/btcsuite/btcd/wire" "github.com/btcsuite/btcutil" "github.com/lightningnetwork/lnd" + "github.com/lightningnetwork/lnd/chainreg" "github.com/lightningnetwork/lnd/lnrpc" "github.com/lightningnetwork/lnd/lnrpc/routerrpc" "github.com/lightningnetwork/lnd/lntest" @@ -173,7 +174,7 @@ func testMultiHopPayments(net *lntest.NetworkHarness, t *harnessTest) { const aliceFeeRatePPM = 100000 updateChannelPolicy( t, net.Alice, chanPointAlice, aliceBaseFeeSat*1000, - aliceFeeRatePPM, lnd.DefaultBitcoinTimeLockDelta, maxHtlc, + aliceFeeRatePPM, chainreg.DefaultBitcoinTimeLockDelta, maxHtlc, carol, ) @@ -181,7 +182,7 @@ func testMultiHopPayments(net *lntest.NetworkHarness, t *harnessTest) { const daveFeeRatePPM = 150000 updateChannelPolicy( t, dave, chanPointDave, daveBaseFeeSat*1000, daveFeeRatePPM, - lnd.DefaultBitcoinTimeLockDelta, maxHtlc, carol, + chainreg.DefaultBitcoinTimeLockDelta, maxHtlc, carol, ) // Before we start sending payments, subscribe to htlc events for each diff --git a/lntest/itest/lnd_test.go b/lntest/itest/lnd_test.go index 7f60c405b..cdccb404d 100644 --- a/lntest/itest/lnd_test.go +++ b/lntest/itest/lnd_test.go @@ -31,6 +31,7 @@ import ( "github.com/davecgh/go-spew/spew" "github.com/go-errors/errors" "github.com/lightningnetwork/lnd" + "github.com/lightningnetwork/lnd/chainreg" "github.com/lightningnetwork/lnd/channeldb" "github.com/lightningnetwork/lnd/input" "github.com/lightningnetwork/lnd/labels" @@ -1856,7 +1857,7 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) { const ( defaultFeeBase = 1000 defaultFeeRate = 1 - defaultTimeLockDelta = lnd.DefaultBitcoinTimeLockDelta + defaultTimeLockDelta = chainreg.DefaultBitcoinTimeLockDelta defaultMinHtlc = 1000 ) defaultMaxHtlc := calculateMaxHtlc(lnd.MaxBtcFundingAmount) @@ -3152,7 +3153,7 @@ func testChannelUnsettledBalance(net *lntest.NetworkHarness, t *harnessTest) { Dest: carolPubKey, Amt: int64(payAmt), PaymentHash: makeFakePayHash(t), - FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta, + FinalCltvDelta: chainreg.DefaultBitcoinTimeLockDelta, TimeoutSeconds: 60, FeeLimitMsat: noFeeLimitMsat, }) @@ -3449,7 +3450,7 @@ func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest, // TODO(roasbeef): should check default value in config here // instead, or make delay a param - defaultCLTV := uint32(lnd.DefaultBitcoinTimeLockDelta) + defaultCLTV := uint32(chainreg.DefaultBitcoinTimeLockDelta) // We must let Alice have an open channel before she can send a node // announcement, so we open a channel with Carol, @@ -3507,7 +3508,7 @@ func channelForceClosureTest(net *lntest.NetworkHarness, t *harnessTest, Dest: carolPubKey, Amt: int64(paymentAmt), PaymentHash: makeFakePayHash(t), - FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta, + FinalCltvDelta: chainreg.DefaultBitcoinTimeLockDelta, TimeoutSeconds: 60, FeeLimitMsat: noFeeLimitMsat, }, @@ -5790,7 +5791,7 @@ func testMultiHopSendToRoute(net *lntest.NetworkHarness, t *harnessTest) { routesReq := &lnrpc.QueryRoutesRequest{ PubKey: carol.PubKeyStr, Amt: paymentAmt, - FinalCltvDelta: lnd.DefaultBitcoinTimeLockDelta, + FinalCltvDelta: chainreg.DefaultBitcoinTimeLockDelta, } ctxt, _ = context.WithTimeout(ctxb, defaultTimeout) routes, err := net.Alice.QueryRoutes(ctxt, routesReq) @@ -7956,7 +7957,7 @@ func testGarbageCollectLinkNodes(net *lntest.NetworkHarness, t *harnessTest) { // We'll need to mine some blocks in order to mark the channel fully // closed. - _, err = net.Miner.Node.Generate(lnd.DefaultBitcoinTimeLockDelta - defaultCSV) + _, err = net.Miner.Node.Generate(chainreg.DefaultBitcoinTimeLockDelta - defaultCSV) if err != nil { t.Fatalf("unable to generate blocks: %v", err) } @@ -12596,7 +12597,7 @@ func testRouteFeeCutoff(net *lntest.NetworkHarness, t *harnessTest) { // Alice -> Carol -> Dave baseFee := int64(10000) feeRate := int64(5) - timeLockDelta := uint32(lnd.DefaultBitcoinTimeLockDelta) + timeLockDelta := uint32(chainreg.DefaultBitcoinTimeLockDelta) maxHtlc := calculateMaxHtlc(chanAmt) expectedPolicy := &lnrpc.RoutingPolicy{ @@ -12857,9 +12858,9 @@ func testSendUpdateDisableChannel(net *lntest.NetworkHarness, t *harnessTest) { // We should expect to see a channel update with the default routing // policy, except that it should indicate the channel is disabled. expectedPolicy := &lnrpc.RoutingPolicy{ - FeeBaseMsat: int64(lnd.DefaultBitcoinBaseFeeMSat), - FeeRateMilliMsat: int64(lnd.DefaultBitcoinFeeRate), - TimeLockDelta: lnd.DefaultBitcoinTimeLockDelta, + FeeBaseMsat: int64(chainreg.DefaultBitcoinBaseFeeMSat), + FeeRateMilliMsat: int64(chainreg.DefaultBitcoinFeeRate), + TimeLockDelta: chainreg.DefaultBitcoinTimeLockDelta, MinHtlc: 1000, // default value MaxHtlcMsat: calculateMaxHtlc(chanAmt), Disabled: true, diff --git a/nursery_store_test.go b/nursery_store_test.go index a5a0c18d9..052b23043 100644 --- a/nursery_store_test.go +++ b/nursery_store_test.go @@ -7,6 +7,7 @@ import ( "testing" "github.com/btcsuite/btcd/wire" + "github.com/lightningnetwork/lnd/chainreg" "github.com/lightningnetwork/lnd/channeldb" ) @@ -54,7 +55,7 @@ func TestNurseryStoreInit(t *testing.T) { } defer cleanUp() - ns, err := newNurseryStore(&BitcoinTestnetGenesis, cdb) + ns, err := newNurseryStore(&chainreg.BitcoinTestnetGenesis, cdb) if err != nil { t.Fatalf("unable to open nursery store: %v", err) } @@ -74,7 +75,7 @@ func TestNurseryStoreIncubate(t *testing.T) { } defer cleanUp() - ns, err := newNurseryStore(&BitcoinTestnetGenesis, cdb) + ns, err := newNurseryStore(&chainreg.BitcoinTestnetGenesis, cdb) if err != nil { t.Fatalf("unable to open nursery store: %v", err) } @@ -315,7 +316,7 @@ func TestNurseryStoreGraduate(t *testing.T) { } defer cleanUp() - ns, err := newNurseryStore(&BitcoinTestnetGenesis, cdb) + ns, err := newNurseryStore(&chainreg.BitcoinTestnetGenesis, cdb) if err != nil { t.Fatalf("unable to open nursery store: %v", err) } diff --git a/server.go b/server.go index 7a37379cb..a687c9936 100644 --- a/server.go +++ b/server.go @@ -67,7 +67,6 @@ import ( "github.com/lightningnetwork/lnd/tor" "github.com/lightningnetwork/lnd/walletunlocker" "github.com/lightningnetwork/lnd/watchtower/wtclient" - "github.com/lightningnetwork/lnd/watchtower/wtdb" "github.com/lightningnetwork/lnd/watchtower/wtpolicy" "github.com/lightningnetwork/lnd/watchtower/wtserver" ) @@ -204,7 +203,7 @@ type server struct { // intended to replace it. scheduledPeerConnection map[string]func() - cc *ChainControl + cc *chainreg.ChainControl fundingMgr *fundingManager @@ -339,7 +338,7 @@ func noiseDial(idKey keychain.SingleKeyECDH, // passed listener address. func newServer(cfg *Config, listenAddrs []net.Addr, localChanDB, remoteChanDB *channeldb.DB, - towerClientDB *wtdb.ClientDB, cc *ChainControl, + towerClientDB wtclient.DB, cc *chainreg.ChainControl, nodeKeyDesc *keychain.KeyDescriptor, chansToRestore walletunlocker.ChannelsToRecover, chanPredicate chanacceptor.ChannelAcceptor, @@ -1853,7 +1852,7 @@ func initNetworkBootstrappers(s *server) ([]discovery.NetworkPeerBootstrapper, e // If this isn't simnet mode, then one of our additional bootstrapping // sources will be the set of running DNS seeds. if !s.cfg.Bitcoin.SimNet || !s.cfg.Litecoin.SimNet { - dnsSeeds, ok := ChainDNSSeeds[*s.cfg.ActiveNetParams.GenesisHash] + dnsSeeds, ok := chainreg.ChainDNSSeeds[*s.cfg.ActiveNetParams.GenesisHash] // If we have a set of DNS seeds for this chain, then we'll add // it as an additional bootstrapping source. diff --git a/subrpcserver_config.go b/subrpcserver_config.go index 8e9c19218..aa1a9ce01 100644 --- a/subrpcserver_config.go +++ b/subrpcserver_config.go @@ -82,7 +82,8 @@ type subRPCServerConfigs struct { // // NOTE: This MUST be called before any callers are permitted to execute the // FetchConfig method. -func (s *subRPCServerConfigs) PopulateDependencies(cfg *Config, cc *ChainControl, +func (s *subRPCServerConfigs) PopulateDependencies(cfg *Config, + cc *chainreg.ChainControl, networkDir string, macService *macaroons.Service, atpl *autopilot.Manager, invoiceRegistry *invoices.InvoiceRegistry,