Merge pull request #838 from cfromknecht/litecoind-backend
Litecoind Backend
This commit is contained in:
commit
695b09e32b
@ -22,23 +22,46 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/keychain"
|
"github.com/lightningnetwork/lnd/keychain"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet"
|
"github.com/lightningnetwork/lnd/lnwallet"
|
||||||
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
||||||
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
"github.com/lightningnetwork/lnd/routing/chainview"
|
"github.com/lightningnetwork/lnd/routing/chainview"
|
||||||
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
"github.com/roasbeef/btcd/chaincfg/chainhash"
|
||||||
"github.com/roasbeef/btcd/rpcclient"
|
"github.com/roasbeef/btcd/rpcclient"
|
||||||
|
"github.com/roasbeef/btcutil"
|
||||||
"github.com/roasbeef/btcwallet/chain"
|
"github.com/roasbeef/btcwallet/chain"
|
||||||
"github.com/roasbeef/btcwallet/walletdb"
|
"github.com/roasbeef/btcwallet/walletdb"
|
||||||
)
|
)
|
||||||
|
|
||||||
// defaultChannelConstraints is the default set of channel constraints that are
|
const (
|
||||||
// meant to be used when initially funding a channel.
|
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?
|
// TODO(halseth): make configurable at startup?
|
||||||
var defaultChannelConstraints = channeldb.ChannelConstraints{
|
var defaultBtcChannelConstraints = channeldb.ChannelConstraints{
|
||||||
DustLimit: lnwallet.DefaultDustLimit(),
|
DustLimit: lnwallet.DefaultDustLimit(),
|
||||||
MaxAcceptedHtlcs: lnwallet.MaxHTLCNumber / 2,
|
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
|
// chainCode is an enum-like structure for keeping track of the chains
|
||||||
// currently supported within lnd.
|
// currently supported within lnd.
|
||||||
type chainCode uint32
|
type chainCode uint32
|
||||||
@ -111,7 +134,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
|||||||
TimeLockDelta: cfg.Bitcoin.TimeLockDelta,
|
TimeLockDelta: cfg.Bitcoin.TimeLockDelta,
|
||||||
}
|
}
|
||||||
cc.feeEstimator = lnwallet.StaticFeeEstimator{
|
cc.feeEstimator = lnwallet.StaticFeeEstimator{
|
||||||
FeeRate: 50,
|
FeeRate: defaultBitcoinStaticFeeRate,
|
||||||
}
|
}
|
||||||
case litecoinChain:
|
case litecoinChain:
|
||||||
cc.routingPolicy = htlcswitch.ForwardingPolicy{
|
cc.routingPolicy = htlcswitch.ForwardingPolicy{
|
||||||
@ -121,7 +144,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
|||||||
TimeLockDelta: cfg.Litecoin.TimeLockDelta,
|
TimeLockDelta: cfg.Litecoin.TimeLockDelta,
|
||||||
}
|
}
|
||||||
cc.feeEstimator = lnwallet.StaticFeeEstimator{
|
cc.feeEstimator = lnwallet.StaticFeeEstimator{
|
||||||
FeeRate: 100,
|
FeeRate: defaultLitecoinStaticFeeRate,
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
return nil, nil, fmt.Errorf("Default routing policy for "+
|
return nil, nil, fmt.Errorf("Default routing policy for "+
|
||||||
@ -223,17 +246,24 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
|||||||
// database.
|
// database.
|
||||||
walletConfig.ChainSource = chain.NewNeutrinoClient(svc)
|
walletConfig.ChainSource = chain.NewNeutrinoClient(svc)
|
||||||
cleanUp = func() {
|
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
|
// Otherwise, we'll be speaking directly via RPC and ZMQ to a
|
||||||
// bitcoind node. If the specified host for the btcd/ltcd RPC
|
// bitcoind node. If the specified host for the btcd/ltcd RPC
|
||||||
// server already has a port specified, then we use that
|
// server already has a port specified, then we use that
|
||||||
// directly. Otherwise, we assume the default port according to
|
// directly. Otherwise, we assume the default port according to
|
||||||
// the selected chain parameters.
|
// the selected chain parameters.
|
||||||
var bitcoindHost string
|
var bitcoindHost string
|
||||||
if strings.Contains(cfg.BitcoindMode.RPCHost, ":") {
|
if strings.Contains(bitcoindMode.RPCHost, ":") {
|
||||||
bitcoindHost = cfg.BitcoindMode.RPCHost
|
bitcoindHost = bitcoindMode.RPCHost
|
||||||
} else {
|
} else {
|
||||||
// The RPC ports specified in chainparams.go assume
|
// The RPC ports specified in chainparams.go assume
|
||||||
// btcd, which picks a different port so that btcwallet
|
// btcd, which picks a different port so that btcwallet
|
||||||
@ -245,13 +275,13 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
|||||||
}
|
}
|
||||||
rpcPort -= 2
|
rpcPort -= 2
|
||||||
bitcoindHost = fmt.Sprintf("%v:%d",
|
bitcoindHost = fmt.Sprintf("%v:%d",
|
||||||
cfg.BitcoindMode.RPCHost, rpcPort)
|
bitcoindMode.RPCHost, rpcPort)
|
||||||
if cfg.Bitcoin.RegTest {
|
if cfg.Bitcoin.Active && cfg.Bitcoin.RegTest {
|
||||||
conn, err := net.Dial("tcp", bitcoindHost)
|
conn, err := net.Dial("tcp", bitcoindHost)
|
||||||
if err != nil || conn == nil {
|
if err != nil || conn == nil {
|
||||||
rpcPort = 18443
|
rpcPort = 18443
|
||||||
bitcoindHost = fmt.Sprintf("%v:%d",
|
bitcoindHost = fmt.Sprintf("%v:%d",
|
||||||
cfg.BitcoindMode.RPCHost,
|
bitcoindMode.RPCHost,
|
||||||
rpcPort)
|
rpcPort)
|
||||||
} else {
|
} else {
|
||||||
conn.Close()
|
conn.Close()
|
||||||
@ -259,8 +289,8 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
bitcoindUser := cfg.BitcoindMode.RPCUser
|
bitcoindUser := bitcoindMode.RPCUser
|
||||||
bitcoindPass := cfg.BitcoindMode.RPCPass
|
bitcoindPass := bitcoindMode.RPCPass
|
||||||
rpcConfig := &rpcclient.ConnConfig{
|
rpcConfig := &rpcclient.ConnConfig{
|
||||||
Host: bitcoindHost,
|
Host: bitcoindHost,
|
||||||
User: bitcoindUser,
|
User: bitcoindUser,
|
||||||
@ -271,7 +301,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
|||||||
HTTPPostMode: true,
|
HTTPPostMode: true,
|
||||||
}
|
}
|
||||||
cc.chainNotifier, err = bitcoindnotify.New(rpcConfig,
|
cc.chainNotifier, err = bitcoindnotify.New(rpcConfig,
|
||||||
cfg.BitcoindMode.ZMQPath, *activeNetParams.Params)
|
bitcoindMode.ZMQPath, *activeNetParams.Params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
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
|
// Next, we'll create an instance of the bitcoind chain view to
|
||||||
// be used within the routing layer.
|
// be used within the routing layer.
|
||||||
cc.chainView, err = chainview.NewBitcoindFilteredChainView(
|
cc.chainView, err = chainview.NewBitcoindFilteredChainView(
|
||||||
*rpcConfig, cfg.BitcoindMode.ZMQPath,
|
*rpcConfig, bitcoindMode.ZMQPath,
|
||||||
*activeNetParams.Params)
|
*activeNetParams.Params)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
srvrLog.Errorf("unable to create chain view: %v", err)
|
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.
|
// used by the wallet for notifications, calls, etc.
|
||||||
bitcoindConn, err = chain.NewBitcoindClient(
|
bitcoindConn, err = chain.NewBitcoindClient(
|
||||||
activeNetParams.Params, bitcoindHost, bitcoindUser,
|
activeNetParams.Params, bitcoindHost, bitcoindUser,
|
||||||
bitcoindPass, cfg.BitcoindMode.ZMQPath,
|
bitcoindPass, bitcoindMode.ZMQPath,
|
||||||
time.Millisecond*100)
|
time.Millisecond*100)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, nil, err
|
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
|
// If we're not in regtest mode, then we'll attempt to use a
|
||||||
// proper fee estimator for testnet.
|
// proper fee estimator for testnet.
|
||||||
if !cfg.Bitcoin.RegTest {
|
if cfg.Bitcoin.Active && !cfg.Bitcoin.RegTest {
|
||||||
ltndLog.Infof("Initializing bitcoind backed fee estimator")
|
ltndLog.Infof("Initializing bitcoind backed fee estimator")
|
||||||
|
|
||||||
// Finally, we'll re-initialize the fee estimator, as
|
// 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 {
|
if err := cc.feeEstimator.Start(); err != nil {
|
||||||
return nil, nil, err
|
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.
|
// Otherwise, we'll be speaking directly via RPC to a node.
|
||||||
//
|
//
|
||||||
// So first we'll load btcd/ltcd's TLS cert for the RPC
|
// 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.signer = wc
|
||||||
cc.chainIO = wc
|
cc.chainIO = wc
|
||||||
|
|
||||||
|
// Select the default channel constraints for the primary chain.
|
||||||
|
channelConstraints := defaultBtcChannelConstraints
|
||||||
|
if registeredChains.PrimaryChain() == litecoinChain {
|
||||||
|
channelConstraints = defaultLtcChannelConstraints
|
||||||
|
}
|
||||||
|
|
||||||
keyRing := keychain.NewBtcWalletKeyRing(
|
keyRing := keychain.NewBtcWalletKeyRing(
|
||||||
wc.InternalWallet(), activeNetParams.CoinType,
|
wc.InternalWallet(), activeNetParams.CoinType,
|
||||||
)
|
)
|
||||||
@ -451,7 +504,7 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB,
|
|||||||
FeeEstimator: cc.feeEstimator,
|
FeeEstimator: cc.feeEstimator,
|
||||||
SecretKeyRing: keyRing,
|
SecretKeyRing: keyRing,
|
||||||
ChainIO: cc.chainIO,
|
ChainIO: cc.chainIO,
|
||||||
DefaultConstraints: defaultChannelConstraints,
|
DefaultConstraints: channelConstraints,
|
||||||
NetParams: *activeNetParams.Params,
|
NetParams: *activeNetParams.Params,
|
||||||
}
|
}
|
||||||
wallet, err := lnwallet.NewLightningWallet(walletCfg)
|
wallet, err := lnwallet.NewLightningWallet(walletCfg)
|
||||||
|
88
config.go
88
config.go
@ -52,16 +52,6 @@ const (
|
|||||||
// HTLCs on our channels.
|
// HTLCs on our channels.
|
||||||
minTimeLockDelta = 4
|
minTimeLockDelta = 4
|
||||||
|
|
||||||
defaultBitcoinMinHTLCMSat = 1000
|
|
||||||
defaultBitcoinBaseFeeMSat = 1000
|
|
||||||
defaultBitcoinFeeRate = 1
|
|
||||||
defaultBitcoinTimeLockDelta = 144
|
|
||||||
|
|
||||||
defaultLitecoinMinHTLCMSat = 1000
|
|
||||||
defaultLitecoinBaseFeeMSat = 1000
|
|
||||||
defaultLitecoinFeeRate = 1
|
|
||||||
defaultLitecoinTimeLockDelta = 576
|
|
||||||
|
|
||||||
defaultAlias = ""
|
defaultAlias = ""
|
||||||
defaultColor = "#3399FF"
|
defaultColor = "#3399FF"
|
||||||
)
|
)
|
||||||
@ -82,14 +72,15 @@ var (
|
|||||||
defaultLtcdDir = btcutil.AppDataDir("ltcd", false)
|
defaultLtcdDir = btcutil.AppDataDir("ltcd", false)
|
||||||
defaultLtcdRPCCertFile = filepath.Join(defaultLtcdDir, "rpc.cert")
|
defaultLtcdRPCCertFile = filepath.Join(defaultLtcdDir, "rpc.cert")
|
||||||
|
|
||||||
defaultBitcoindDir = btcutil.AppDataDir("bitcoin", false)
|
defaultBitcoindDir = btcutil.AppDataDir("bitcoin", false)
|
||||||
|
defaultLitecoindDir = btcutil.AppDataDir("litecoin", false)
|
||||||
)
|
)
|
||||||
|
|
||||||
type chainConfig struct {
|
type chainConfig struct {
|
||||||
Active bool `long:"active" description:"If the chain should be active or not."`
|
Active bool `long:"active" description:"If the chain should be active or not."`
|
||||||
ChainDir string `long:"chaindir" description:"The directory to store the chain's data within."`
|
ChainDir string `long:"chaindir" description:"The directory to store the chain's data within."`
|
||||||
|
|
||||||
Node string `long:"node" description:"The blockchain interface to use." choice:"btcd" choice:"bitcoind" choice:"neutrino"`
|
Node string `long:"node" description:"The blockchain interface to use." choice:"btcd" choice:"bitcoind" choice:"neutrino" choice:"ltcd" choice:"litecoind"`
|
||||||
|
|
||||||
TestNet3 bool `long:"testnet" description:"Use the test network"`
|
TestNet3 bool `long:"testnet" description:"Use the test network"`
|
||||||
SimNet bool `long:"simnet" description:"Use the simulation test network"`
|
SimNet bool `long:"simnet" description:"Use the simulation test network"`
|
||||||
@ -182,8 +173,9 @@ type config struct {
|
|||||||
BitcoindMode *bitcoindConfig `group:"bitcoind" namespace:"bitcoind"`
|
BitcoindMode *bitcoindConfig `group:"bitcoind" namespace:"bitcoind"`
|
||||||
NeutrinoMode *neutrinoConfig `group:"neutrino" namespace:"neutrino"`
|
NeutrinoMode *neutrinoConfig `group:"neutrino" namespace:"neutrino"`
|
||||||
|
|
||||||
Litecoin *chainConfig `group:"Litecoin" namespace:"litecoin"`
|
Litecoin *chainConfig `group:"Litecoin" namespace:"litecoin"`
|
||||||
LtcdMode *btcdConfig `group:"ltcd" namespace:"ltcd"`
|
LtcdMode *btcdConfig `group:"ltcd" namespace:"ltcd"`
|
||||||
|
LitecoindMode *bitcoindConfig `group:"litecoind" namespace:"litecoind"`
|
||||||
|
|
||||||
Autopilot *autoPilotConfig `group:"autopilot" namespace:"autopilot"`
|
Autopilot *autoPilotConfig `group:"autopilot" namespace:"autopilot"`
|
||||||
|
|
||||||
@ -241,13 +233,17 @@ func loadConfig() (*config, error) {
|
|||||||
BaseFee: defaultLitecoinBaseFeeMSat,
|
BaseFee: defaultLitecoinBaseFeeMSat,
|
||||||
FeeRate: defaultLitecoinFeeRate,
|
FeeRate: defaultLitecoinFeeRate,
|
||||||
TimeLockDelta: defaultLitecoinTimeLockDelta,
|
TimeLockDelta: defaultLitecoinTimeLockDelta,
|
||||||
Node: "btcd",
|
Node: "ltcd",
|
||||||
},
|
},
|
||||||
LtcdMode: &btcdConfig{
|
LtcdMode: &btcdConfig{
|
||||||
Dir: defaultLtcdDir,
|
Dir: defaultLtcdDir,
|
||||||
RPCHost: defaultRPCHost,
|
RPCHost: defaultRPCHost,
|
||||||
RPCCert: defaultLtcdRPCCertFile,
|
RPCCert: defaultLtcdRPCCertFile,
|
||||||
},
|
},
|
||||||
|
LitecoindMode: &bitcoindConfig{
|
||||||
|
Dir: defaultLitecoindDir,
|
||||||
|
RPCHost: defaultRPCHost,
|
||||||
|
},
|
||||||
MaxPendingChannels: defaultMaxPendingChannels,
|
MaxPendingChannels: defaultMaxPendingChannels,
|
||||||
NoEncryptWallet: defaultNoEncryptWallet,
|
NoEncryptWallet: defaultNoEncryptWallet,
|
||||||
Autopilot: &autoPilotConfig{
|
Autopilot: &autoPilotConfig{
|
||||||
@ -333,6 +329,7 @@ func loadConfig() (*config, error) {
|
|||||||
cfg.BtcdMode.Dir = cleanAndExpandPath(cfg.BtcdMode.Dir)
|
cfg.BtcdMode.Dir = cleanAndExpandPath(cfg.BtcdMode.Dir)
|
||||||
cfg.LtcdMode.Dir = cleanAndExpandPath(cfg.LtcdMode.Dir)
|
cfg.LtcdMode.Dir = cleanAndExpandPath(cfg.LtcdMode.Dir)
|
||||||
cfg.BitcoindMode.Dir = cleanAndExpandPath(cfg.BitcoindMode.Dir)
|
cfg.BitcoindMode.Dir = cleanAndExpandPath(cfg.BitcoindMode.Dir)
|
||||||
|
cfg.LitecoindMode.Dir = cleanAndExpandPath(cfg.LitecoindMode.Dir)
|
||||||
|
|
||||||
// Setup dial and DNS resolution functions depending on the specified
|
// Setup dial and DNS resolution functions depending on the specified
|
||||||
// options. The default is to use the standard golang "net" package
|
// options. The default is to use the standard golang "net" package
|
||||||
@ -398,17 +395,16 @@ func loadConfig() (*config, error) {
|
|||||||
str := "%s: simnet mode for litecoin not currently supported"
|
str := "%s: simnet mode for litecoin not currently supported"
|
||||||
return nil, fmt.Errorf(str, funcName)
|
return nil, fmt.Errorf(str, funcName)
|
||||||
}
|
}
|
||||||
|
if cfg.Litecoin.RegTest {
|
||||||
|
str := "%s: regnet mode for litecoin not currently supported"
|
||||||
|
return nil, fmt.Errorf(str, funcName)
|
||||||
|
}
|
||||||
|
|
||||||
if cfg.Litecoin.TimeLockDelta < minTimeLockDelta {
|
if cfg.Litecoin.TimeLockDelta < minTimeLockDelta {
|
||||||
return nil, fmt.Errorf("timelockdelta must be at least %v",
|
return nil, fmt.Errorf("timelockdelta must be at least %v",
|
||||||
minTimeLockDelta)
|
minTimeLockDelta)
|
||||||
}
|
}
|
||||||
|
|
||||||
if cfg.Litecoin.Node != "btcd" {
|
|
||||||
str := "%s: only ltcd (`btcd`) mode supported for litecoin at this time"
|
|
||||||
return nil, fmt.Errorf(str, funcName)
|
|
||||||
}
|
|
||||||
|
|
||||||
// The litecoin chain is the current active chain. However
|
// The litecoin chain is the current active chain. However
|
||||||
// throughout the codebase we required chaincfg.Params. So as a
|
// throughout the codebase we required chaincfg.Params. So as a
|
||||||
// temporary hack, we'll mutate the default net params for
|
// temporary hack, we'll mutate the default net params for
|
||||||
@ -417,12 +413,31 @@ func loadConfig() (*config, error) {
|
|||||||
applyLitecoinParams(¶mCopy)
|
applyLitecoinParams(¶mCopy)
|
||||||
activeNetParams = paramCopy
|
activeNetParams = paramCopy
|
||||||
|
|
||||||
err := parseRPCParams(cfg.Litecoin, cfg.LtcdMode, litecoinChain,
|
switch cfg.Litecoin.Node {
|
||||||
funcName)
|
case "ltcd":
|
||||||
if err != nil {
|
err := parseRPCParams(cfg.Litecoin, cfg.LtcdMode,
|
||||||
err := fmt.Errorf("unable to load RPC credentials for "+
|
litecoinChain, funcName)
|
||||||
"ltcd: %v", err)
|
if err != nil {
|
||||||
return nil, err
|
err := fmt.Errorf("unable to load RPC "+
|
||||||
|
"credentials for ltcd: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
case "litecoind":
|
||||||
|
if cfg.Litecoin.SimNet {
|
||||||
|
return nil, fmt.Errorf("%s: litecoind does not "+
|
||||||
|
"support simnet", funcName)
|
||||||
|
}
|
||||||
|
err := parseRPCParams(cfg.Litecoin, cfg.LitecoindMode,
|
||||||
|
litecoinChain, funcName)
|
||||||
|
if err != nil {
|
||||||
|
err := fmt.Errorf("unable to load RPC "+
|
||||||
|
"credentials for litecoind: %v", err)
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
str := "%s: only ltcd and litecoind mode supported for " +
|
||||||
|
"litecoin at this time"
|
||||||
|
return nil, fmt.Errorf(str, funcName)
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.Litecoin.ChainDir = filepath.Join(cfg.DataDir,
|
cfg.Litecoin.ChainDir = filepath.Join(cfg.DataDir,
|
||||||
@ -485,6 +500,10 @@ func loadConfig() (*config, error) {
|
|||||||
}
|
}
|
||||||
case "neutrino":
|
case "neutrino":
|
||||||
// No need to get RPC parameters.
|
// No need to get RPC parameters.
|
||||||
|
default:
|
||||||
|
str := "%s: only btcd, bitcoind, and neutrino mode " +
|
||||||
|
"supported for bitcoin at this time"
|
||||||
|
return nil, fmt.Errorf(str, funcName)
|
||||||
}
|
}
|
||||||
|
|
||||||
cfg.Bitcoin.ChainDir = filepath.Join(cfg.DataDir,
|
cfg.Bitcoin.ChainDir = filepath.Join(cfg.DataDir,
|
||||||
@ -762,9 +781,16 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
|||||||
"bitcoind.zmqpath")
|
"bitcoind.zmqpath")
|
||||||
}
|
}
|
||||||
|
|
||||||
daemonName = "bitcoind"
|
switch net {
|
||||||
confDir = conf.Dir
|
case bitcoinChain:
|
||||||
confFile = "bitcoin"
|
daemonName = "bitcoind"
|
||||||
|
confDir = conf.Dir
|
||||||
|
confFile = "bitcoin"
|
||||||
|
case litecoinChain:
|
||||||
|
daemonName = "litecoind"
|
||||||
|
confDir = conf.Dir
|
||||||
|
confFile = "litecoin"
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're in simnet mode, then the running btcd instance won't read
|
// If we're in simnet mode, then the running btcd instance won't read
|
||||||
@ -780,7 +806,7 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
|||||||
|
|
||||||
confFile = filepath.Join(confDir, fmt.Sprintf("%v.conf", confFile))
|
confFile = filepath.Join(confDir, fmt.Sprintf("%v.conf", confFile))
|
||||||
switch cConfig.Node {
|
switch cConfig.Node {
|
||||||
case "btcd":
|
case "btcd", "ltcd":
|
||||||
nConf := nodeConfig.(*btcdConfig)
|
nConf := nodeConfig.(*btcdConfig)
|
||||||
rpcUser, rpcPass, err := extractBtcdRPCParams(confFile)
|
rpcUser, rpcPass, err := extractBtcdRPCParams(confFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@ -789,7 +815,7 @@ func parseRPCParams(cConfig *chainConfig, nodeConfig interface{}, net chainCode,
|
|||||||
err)
|
err)
|
||||||
}
|
}
|
||||||
nConf.RPCUser, nConf.RPCPass = rpcUser, rpcPass
|
nConf.RPCUser, nConf.RPCPass = rpcUser, rpcPass
|
||||||
case "bitcoind":
|
case "bitcoind", "litecoind":
|
||||||
nConf := nodeConfig.(*bitcoindConfig)
|
nConf := nodeConfig.(*bitcoindConfig)
|
||||||
rpcUser, rpcPass, zmqPath, err := extractBitcoindRPCParams(confFile)
|
rpcUser, rpcPass, zmqPath, err := extractBitcoindRPCParams(confFile)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -178,17 +178,33 @@ installing `lnd` in preparation for the
|
|||||||
lnd --bitcoin.active --bitcoin.testnet --debuglevel=debug --btcd.rpcuser=kek --btcd.rpcpass=kek --externalip=X.X.X.X
|
lnd --bitcoin.active --bitcoin.testnet --debuglevel=debug --btcd.rpcuser=kek --btcd.rpcpass=kek --externalip=X.X.X.X
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Running lnd using the bitcoind backend
|
#### Running lnd using the bitcoind or litecoind backend
|
||||||
|
|
||||||
To configure your bitcoind backend for use with lnd, first complete and verify the following:
|
The configuration for bitcoind and litecoind are nearly identical, the following
|
||||||
|
steps can be mirrored with loss of generality to enable a litecoind backend.
|
||||||
|
Setup will be described in regards to `bitciond`, but note that `lnd` uses a
|
||||||
|
distinct `litecoin.node=litecoind` argument and analogous subconfigurations
|
||||||
|
prefixed by `litecoind`.
|
||||||
|
|
||||||
- The `bitcoind` instance must
|
To configure your bitcoind backend for use with lnd, first complete and verify
|
||||||
be configured with `--txindex` just like `btcd` above
|
the following:
|
||||||
- Additionally, since `lnd` uses [ZeroMQ](https://github.com/bitcoin/bitcoin/blob/master/doc/zmq.md) to interface with `bitcoind`, *your `bitcoind` installation must be compiled with ZMQ*. If you installed it from source, this is likely the case, but if you installed it via Homebrew in the past it may not be included ([this has now been fixed](https://github.com/Homebrew/homebrew-core/pull/23088) in the latest Homebrew recipe for bitcoin)
|
|
||||||
- Configure the `bitcoind` instance for ZMQ with `--zmqpubrawblock` and `--zmqpubrawtx`
|
- The `bitcoind` instance must be configured with `--txindex` just like `btcd`
|
||||||
(the latter is optional but allows you to see unconfirmed transactions in your
|
above
|
||||||
wallet). They must be combined in the same ZMQ socket address (e.g. `--zmqpubrawblock=tcp://127.0.0.1:28332` and `--zmqpubrawtx=tcp://127.0.0.1:28332`).
|
- Additionally, since `lnd` uses
|
||||||
- Start `bitcoind` running against testnet, and let it complete a full sync with the testnet chain (alternatively, use `--bitcoind.regtest` instead).
|
[ZeroMQ](https://github.com/bitcoin/bitcoin/blob/master/doc/zmq.md) to
|
||||||
|
interface with `bitcoind`, *your `bitcoind` installation must be compiled with
|
||||||
|
ZMQ*. If you installed it from source, this is likely the case, but if you
|
||||||
|
installed it via Homebrew in the past it may not be included ([this has now
|
||||||
|
been fixed](https://github.com/Homebrew/homebrew-core/pull/23088) in the
|
||||||
|
latest Homebrew recipe for bitcoin)
|
||||||
|
- Configure the `bitcoind` instance for ZMQ with `--zmqpubrawblock` and
|
||||||
|
`--zmqpubrawtx` (the latter is optional but allows you to see unconfirmed
|
||||||
|
transactions in your wallet). They must be combined in the same ZMQ socket
|
||||||
|
address (e.g. `--zmqpubrawblock=tcp://127.0.0.1:28332` and
|
||||||
|
`--zmqpubrawtx=tcp://127.0.0.1:28332`).
|
||||||
|
- Start `bitcoind` running against testnet, and let it complete a full sync with
|
||||||
|
the testnet chain (alternatively, use `--bitcoind.regtest` instead).
|
||||||
|
|
||||||
Here's a sample `bitcoin.conf` for use with lnd:
|
Here's a sample `bitcoin.conf` for use with lnd:
|
||||||
```
|
```
|
||||||
@ -268,8 +284,8 @@ Notice the `[Bitcoin]` section. This section houses the parameters for the
|
|||||||
Bitcoin chain. `lnd` also supports Litecoin testnet4 (but not both BTC and LTC
|
Bitcoin chain. `lnd` also supports Litecoin testnet4 (but not both BTC and LTC
|
||||||
at the same time), so when working with Litecoin be sure to set to parameters
|
at the same time), so when working with Litecoin be sure to set to parameters
|
||||||
for Litecoin accordingly. For node configuration, the sections are called
|
for Litecoin accordingly. For node configuration, the sections are called
|
||||||
`[Btcd]`, `[Bitcoind]`, `[Neutrino]`, and `[Ltcd]` depending on which chain
|
`[Btcd]`, `[Bitcoind]`, `[Neutrino]`, `[Ltcd]`, and `[Litecoind]` depending on
|
||||||
and node type you're using.
|
which chain and node type you're using.
|
||||||
|
|
||||||
# Accurate as of:
|
# Accurate as of:
|
||||||
- _roasbeef/btcd commit:_ `f8c02aff4e7a807ba0c1349e2db03695d8e790e8`
|
- _roasbeef/btcd commit:_ `f8c02aff4e7a807ba0c1349e2db03695d8e790e8`
|
||||||
|
@ -42,12 +42,19 @@ const (
|
|||||||
// TODO(roasbeef): add command line param to modify
|
// TODO(roasbeef): add command line param to modify
|
||||||
maxFundingAmount = btcutil.Amount(1 << 24)
|
maxFundingAmount = btcutil.Amount(1 << 24)
|
||||||
|
|
||||||
// minRemoteDelay and maxRemoteDelay is the extremes of the CSV delay
|
// minBtcRemoteDelay and maxBtcRemoteDelay is the extremes of the
|
||||||
// we will require the remote to use for its commitment transaction.
|
// Bitcoin CSV delay we will require the remote to use for its
|
||||||
// The actual delay we will require will be somewhere between these
|
// commitment transaction. The actual delay we will require will be
|
||||||
// values, depending on channel size.
|
// somewhere between these values, depending on channel size.
|
||||||
minRemoteDelay = 144
|
minBtcRemoteDelay uint16 = 144
|
||||||
maxRemoteDelay = 2016
|
maxBtcRemoteDelay uint16 = 2016
|
||||||
|
|
||||||
|
// minLtcRemoteDelay and maxLtcRemoteDelay is the extremes of the
|
||||||
|
// Litecoin CSV delay we will require the remote to use for its
|
||||||
|
// commitment transaction. The actual delay we will require will be
|
||||||
|
// somewhere between these values, depending on channel size.
|
||||||
|
minLtcRemoteDelay uint16 = 576
|
||||||
|
maxLtcRemoteDelay uint16 = 8064
|
||||||
|
|
||||||
// maxWaitNumBlocksFundingConf is the maximum number of blocks to wait
|
// maxWaitNumBlocksFundingConf is the maximum number of blocks to wait
|
||||||
// for the funding transaction to be confirmed before forgetting about
|
// for the funding transaction to be confirmed before forgetting about
|
||||||
|
@ -166,7 +166,7 @@ func createTestWallet(cdb *channeldb.DB, netParams *chaincfg.Params,
|
|||||||
ChainIO: bio,
|
ChainIO: bio,
|
||||||
FeeEstimator: estimator,
|
FeeEstimator: estimator,
|
||||||
NetParams: *netParams,
|
NetParams: *netParams,
|
||||||
DefaultConstraints: defaultChannelConstraints,
|
DefaultConstraints: defaultBtcChannelConstraints,
|
||||||
})
|
})
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
17
lnd.go
17
lnd.go
@ -238,6 +238,17 @@ func lndMain() error {
|
|||||||
primaryChain := registeredChains.PrimaryChain()
|
primaryChain := registeredChains.PrimaryChain()
|
||||||
registeredChains.RegisterChain(primaryChain, activeChainControl)
|
registeredChains.RegisterChain(primaryChain, activeChainControl)
|
||||||
|
|
||||||
|
// Select the configuration and furnding parameters for Bitcoin or
|
||||||
|
// Litecoin, depending on the primary registered chain.
|
||||||
|
chainCfg := cfg.Bitcoin
|
||||||
|
minRemoteDelay := minBtcRemoteDelay
|
||||||
|
maxRemoteDelay := maxBtcRemoteDelay
|
||||||
|
if primaryChain == litecoinChain {
|
||||||
|
chainCfg = cfg.Litecoin
|
||||||
|
minRemoteDelay = minLtcRemoteDelay
|
||||||
|
maxRemoteDelay = maxLtcRemoteDelay
|
||||||
|
}
|
||||||
|
|
||||||
// TODO(roasbeef): add rotation
|
// TODO(roasbeef): add rotation
|
||||||
idPrivKey, err := activeChainControl.wallet.DerivePrivKey(keychain.KeyDescriptor{
|
idPrivKey, err := activeChainControl.wallet.DerivePrivKey(keychain.KeyDescriptor{
|
||||||
KeyLocator: keychain.KeyLocator{
|
KeyLocator: keychain.KeyLocator{
|
||||||
@ -340,7 +351,7 @@ func lndMain() error {
|
|||||||
// In case the user has explicitly specified
|
// In case the user has explicitly specified
|
||||||
// a default value for the number of
|
// a default value for the number of
|
||||||
// confirmations, we use it.
|
// confirmations, we use it.
|
||||||
defaultConf := uint16(cfg.Bitcoin.DefaultNumChanConfs)
|
defaultConf := uint16(chainCfg.DefaultNumChanConfs)
|
||||||
if defaultConf != 0 {
|
if defaultConf != 0 {
|
||||||
return defaultConf
|
return defaultConf
|
||||||
}
|
}
|
||||||
@ -373,13 +384,13 @@ func lndMain() error {
|
|||||||
// In case the user has explicitly specified
|
// In case the user has explicitly specified
|
||||||
// a default value for the remote delay, we
|
// a default value for the remote delay, we
|
||||||
// use it.
|
// use it.
|
||||||
defaultDelay := uint16(cfg.Bitcoin.DefaultRemoteDelay)
|
defaultDelay := uint16(chainCfg.DefaultRemoteDelay)
|
||||||
if defaultDelay > 0 {
|
if defaultDelay > 0 {
|
||||||
return defaultDelay
|
return defaultDelay
|
||||||
}
|
}
|
||||||
|
|
||||||
// If not we scale according to channel size.
|
// If not we scale according to channel size.
|
||||||
delay := uint16(maxRemoteDelay *
|
delay := uint16(btcutil.Amount(maxRemoteDelay) *
|
||||||
chanAmt / maxFundingAmount)
|
chanAmt / maxFundingAmount)
|
||||||
if delay < minRemoteDelay {
|
if delay < minRemoteDelay {
|
||||||
delay = minRemoteDelay
|
delay = minRemoteDelay
|
||||||
|
@ -2095,6 +2095,9 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
|
|||||||
default:
|
default:
|
||||||
// TODO(roasbeef): assumes set delta between versions
|
// TODO(roasbeef): assumes set delta between versions
|
||||||
defaultDelta := cfg.Bitcoin.TimeLockDelta
|
defaultDelta := cfg.Bitcoin.TimeLockDelta
|
||||||
|
if registeredChains.PrimaryChain() == litecoinChain {
|
||||||
|
defaultDelta = cfg.Litecoin.TimeLockDelta
|
||||||
|
}
|
||||||
options = append(options, zpay32.CLTVExpiry(uint64(defaultDelta)))
|
options = append(options, zpay32.CLTVExpiry(uint64(defaultDelta)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user