chainregistry+lnd: moving chainregistry+chainparams to new package
This commit is contained in:
parent
46ef212de4
commit
bebe258e2d
@ -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))
|
||||
}
|
||||
|
24
chainreg/log.go
Normal file
24
chainreg/log.go
Normal file
@ -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
|
||||
}
|
721
chainregistry.go
721
chainregistry.go
@ -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))
|
||||
}
|
@ -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",
|
||||
|
24
config.go
24
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,
|
||||
}
|
||||
}
|
||||
|
@ -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 "+
|
||||
|
@ -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 {
|
||||
|
2
lnd.go
2
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)
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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,
|
||||
|
@ -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)
|
||||
}
|
||||
|
@ -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.
|
||||
|
@ -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,
|
||||
|
Loading…
Reference in New Issue
Block a user