From 5f7a62913f871323feff8a0d4bef1b2827e5c642 Mon Sep 17 00:00:00 2001 From: Conner Fromknecht Date: Tue, 13 Mar 2018 21:15:20 -0700 Subject: [PATCH] chainregistry: generalize bitcoind logic to handle litecoind --- chainregistry.go | 95 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 74 insertions(+), 21 deletions(-) diff --git a/chainregistry.go b/chainregistry.go index 38969ec0..c5947653 100644 --- a/chainregistry.go +++ b/chainregistry.go @@ -22,23 +22,46 @@ import ( "github.com/lightningnetwork/lnd/keychain" "github.com/lightningnetwork/lnd/lnwallet" "github.com/lightningnetwork/lnd/lnwallet/btcwallet" + "github.com/lightningnetwork/lnd/lnwire" "github.com/lightningnetwork/lnd/routing/chainview" "github.com/roasbeef/btcd/chaincfg/chainhash" "github.com/roasbeef/btcd/rpcclient" + "github.com/roasbeef/btcutil" "github.com/roasbeef/btcwallet/chain" "github.com/roasbeef/btcwallet/walletdb" ) -// defaultChannelConstraints is the default set of channel constraints that are -// meant to be used when initially funding a channel. +const ( + defaultBitcoinMinHTLCMSat = lnwire.MilliSatoshi(1000) + defaultBitcoinBaseFeeMSat = lnwire.MilliSatoshi(1000) + defaultBitcoinFeeRate = lnwire.MilliSatoshi(1) + defaultBitcoinTimeLockDelta = 144 + defaultBitcoinStaticFeeRate = lnwallet.SatPerVByte(50) + + defaultLitecoinMinHTLCMSat = lnwire.MilliSatoshi(1000) + defaultLitecoinBaseFeeMSat = lnwire.MilliSatoshi(1000) + defaultLitecoinFeeRate = lnwire.MilliSatoshi(1) + defaultLitecoinTimeLockDelta = 576 + defaultLitecoinStaticFeeRate = lnwallet.SatPerVByte(200) + defaultLitecoinMinRelayFee = btcutil.Amount(1000) +) + +// defaultBtcChannelConstraints is the default set of channel constraints that are +// meant to be used when initially funding a Bitcoin channel. // -// TODO(roasbeef): have one for both chains // TODO(halseth): make configurable at startup? -var defaultChannelConstraints = channeldb.ChannelConstraints{ +var defaultBtcChannelConstraints = channeldb.ChannelConstraints{ DustLimit: lnwallet.DefaultDustLimit(), MaxAcceptedHtlcs: lnwallet.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: defaultLitecoinMinRelayFee, + MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2, +} + // chainCode is an enum-like structure for keeping track of the chains // currently supported within lnd. type chainCode uint32 @@ -111,7 +134,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, TimeLockDelta: cfg.Bitcoin.TimeLockDelta, } cc.feeEstimator = lnwallet.StaticFeeEstimator{ - FeeRate: 50, + FeeRate: defaultBitcoinStaticFeeRate, } case litecoinChain: cc.routingPolicy = htlcswitch.ForwardingPolicy{ @@ -121,7 +144,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, TimeLockDelta: cfg.Litecoin.TimeLockDelta, } cc.feeEstimator = lnwallet.StaticFeeEstimator{ - FeeRate: 100, + FeeRate: defaultLitecoinStaticFeeRate, } default: return nil, nil, fmt.Errorf("Default routing policy for "+ @@ -223,17 +246,24 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, // database. walletConfig.ChainSource = chain.NewNeutrinoClient(svc) cleanUp = func() { - defer nodeDatabase.Close() + nodeDatabase.Close() + } + case "bitcoind", "litecoind": + var bitcoindMode *bitcoindConfig + switch { + case cfg.Bitcoin.Active: + bitcoindMode = cfg.BitcoindMode + case cfg.Litecoin.Active: + bitcoindMode = cfg.LitecoindMode } - case "bitcoind": // 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(cfg.BitcoindMode.RPCHost, ":") { - bitcoindHost = cfg.BitcoindMode.RPCHost + 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 @@ -245,13 +275,13 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, } rpcPort -= 2 bitcoindHost = fmt.Sprintf("%v:%d", - cfg.BitcoindMode.RPCHost, rpcPort) - if cfg.Bitcoin.RegTest { + bitcoindMode.RPCHost, rpcPort) + if cfg.Bitcoin.Active && cfg.Bitcoin.RegTest { conn, err := net.Dial("tcp", bitcoindHost) if err != nil || conn == nil { rpcPort = 18443 bitcoindHost = fmt.Sprintf("%v:%d", - cfg.BitcoindMode.RPCHost, + bitcoindMode.RPCHost, rpcPort) } else { conn.Close() @@ -259,8 +289,8 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, } } - bitcoindUser := cfg.BitcoindMode.RPCUser - bitcoindPass := cfg.BitcoindMode.RPCPass + bitcoindUser := bitcoindMode.RPCUser + bitcoindPass := bitcoindMode.RPCPass rpcConfig := &rpcclient.ConnConfig{ Host: bitcoindHost, User: bitcoindUser, @@ -271,7 +301,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, HTTPPostMode: true, } cc.chainNotifier, err = bitcoindnotify.New(rpcConfig, - cfg.BitcoindMode.ZMQPath, *activeNetParams.Params) + bitcoindMode.ZMQPath, *activeNetParams.Params) if err != nil { return nil, nil, err } @@ -279,7 +309,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, // Next, we'll create an instance of the bitcoind chain view to // be used within the routing layer. cc.chainView, err = chainview.NewBitcoindFilteredChainView( - *rpcConfig, cfg.BitcoindMode.ZMQPath, + *rpcConfig, bitcoindMode.ZMQPath, *activeNetParams.Params) if err != nil { srvrLog.Errorf("unable to create chain view: %v", err) @@ -290,7 +320,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, // used by the wallet for notifications, calls, etc. bitcoindConn, err = chain.NewBitcoindClient( activeNetParams.Params, bitcoindHost, bitcoindUser, - bitcoindPass, cfg.BitcoindMode.ZMQPath, + bitcoindPass, bitcoindMode.ZMQPath, time.Millisecond*100) if err != nil { return nil, nil, err @@ -300,7 +330,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, // If we're not in regtest mode, then we'll attempt to use a // proper fee estimator for testnet. - if !cfg.Bitcoin.RegTest { + if cfg.Bitcoin.Active && !cfg.Bitcoin.RegTest { ltndLog.Infof("Initializing bitcoind backed fee estimator") // Finally, we'll re-initialize the fee estimator, as @@ -317,8 +347,25 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, if err := cc.feeEstimator.Start(); err != nil { return nil, nil, err } + } else if cfg.Litecoin.Active { + ltndLog.Infof("Initializing litecoind backed fee estimator") + + // 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 := lnwallet.SatPerVByte(25) + cc.feeEstimator, err = lnwallet.NewBitcoindFeeEstimator( + *rpcConfig, fallBackFeeRate, + ) + if err != nil { + return nil, nil, err + } + if err := cc.feeEstimator.Start(); err != nil { + return nil, nil, err + } } - case "btcd": + 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 @@ -437,6 +484,12 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, cc.signer = wc cc.chainIO = wc + // Select the default channel constraints for the primary chain. + channelConstraints := defaultBtcChannelConstraints + if registeredChains.PrimaryChain() == litecoinChain { + channelConstraints = defaultLtcChannelConstraints + } + keyRing := keychain.NewBtcWalletKeyRing( wc.InternalWallet(), activeNetParams.CoinType, ) @@ -451,7 +504,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, FeeEstimator: cc.feeEstimator, SecretKeyRing: keyRing, ChainIO: cc.chainIO, - DefaultConstraints: defaultChannelConstraints, + DefaultConstraints: channelConstraints, NetParams: *activeNetParams.Params, } wallet, err := lnwallet.NewLightningWallet(walletCfg)