Skip to content

Commit

Permalink
feat: allow node configuration through datadir + network
Browse files Browse the repository at this point in the history
  • Loading branch information
jackstar12 committed Jan 31, 2024
1 parent 4c7c2c2 commit 6d12f3c
Show file tree
Hide file tree
Showing 6 changed files with 131 additions and 67 deletions.
15 changes: 9 additions & 6 deletions cmd/boltzd/boltzd.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,8 @@ import (
"path"
"strings"

boltzClient "github.com/BoltzExchange/boltz-client"
"github.com/BoltzExchange/boltz-client/boltz"
"github.com/BoltzExchange/boltz-client/config"
"github.com/BoltzExchange/boltz-client/electrum"
"github.com/BoltzExchange/boltz-client/logger"
"github.com/BoltzExchange/boltz-client/mempool"
Expand All @@ -26,7 +26,10 @@ func main() {
os.Exit(1)
}

cfg := boltzClient.LoadConfig(defaultDataDir)
cfg, err := config.LoadConfig(defaultDataDir)
if err != nil {
logger.Fatal("Could not load config: " + err.Error())
}

logger.Init(cfg.LogFile, cfg.LogLevel)

Expand All @@ -42,7 +45,7 @@ func main() {
Start(cfg)
}

func Init(cfg *boltzClient.Config) {
func Init(cfg *config.Config) {

err := cfg.Database.Connect()

Expand Down Expand Up @@ -102,7 +105,7 @@ func Init(cfg *boltzClient.Config) {
}
}

func Start(cfg *boltzClient.Config) {
func Start(cfg *config.Config) {
errChannel := cfg.RPC.Start()

err := <-errChannel
Expand All @@ -112,7 +115,7 @@ func Start(cfg *boltzClient.Config) {
}
}

func setLightningNode(cfg *boltzClient.Config) {
func setLightningNode(cfg *config.Config) {
isClnConfigured := cfg.Cln.RootCert != ""
isLndConfigured := cfg.LND.Macaroon != ""

Expand Down Expand Up @@ -149,7 +152,7 @@ func setBoltzEndpoint(boltzCfg *boltz.Boltz, network *boltz.Network) {
logger.Info("Using default Boltz endpoint for network " + network.Name + ": " + boltzCfg.URL)
}

func initOnchain(cfg *boltzClient.Config, network *boltz.Network) (*onchain.Onchain, error) {
func initOnchain(cfg *config.Config, network *boltz.Network) (*onchain.Onchain, error) {
onchain := &onchain.Onchain{
Btc: &onchain.Currency{
Listener: cfg.Lightning,
Expand Down
29 changes: 15 additions & 14 deletions cmd/boltzd/boltzd_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,8 +24,8 @@ import (
"github.com/BoltzExchange/boltz-client/lightning"
"github.com/BoltzExchange/boltz-client/test"

boltzlnd "github.com/BoltzExchange/boltz-client"
"github.com/BoltzExchange/boltz-client/boltzrpc"
"github.com/BoltzExchange/boltz-client/config"
"github.com/BoltzExchange/boltz-client/logger"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"
Expand All @@ -34,9 +34,10 @@ import (
"google.golang.org/grpc/test/bufconn"
)

func loadConfig() *boltzlnd.Config {
func loadConfig(t *testing.T) *config.Config {
dataDir := "test"
cfg := boltzlnd.LoadConfig(dataDir)
cfg, err := config.LoadConfig(dataDir)
require.NoError(t, err)
cfg.Database.Path = "file:test.db?cache=shared&mode=memory"
cfg.Node = "cln"
cfg.Node = "lnd"
Expand All @@ -48,9 +49,9 @@ var password = "password"
var walletInfo = &boltzrpc.WalletInfo{Currency: "L-BTC", Name: walletName}
var credentials *wallet.Credentials

func setup(t *testing.T, cfg *boltzlnd.Config, password string) (client.Boltz, client.AutoSwap, func()) {
func setup(t *testing.T, cfg *config.Config, password string) (client.Boltz, client.AutoSwap, func()) {
if cfg == nil {
cfg = loadConfig()
cfg = loadConfig(t)
}

logger.Init("", "debug")
Expand Down Expand Up @@ -192,7 +193,7 @@ func TestGetInfo(t *testing.T) {
for _, node := range nodes {
node := node
t.Run(node, func(t *testing.T) {
cfg := loadConfig()
cfg := loadConfig(t)
cfg.Node = node
client, _, stop := setup(t, cfg, "")
defer stop()
Expand Down Expand Up @@ -238,7 +239,7 @@ func checkTxOutAddress(t *testing.T, chain onchain.Onchain, pair boltz.Pair, txI
func TestSwap(t *testing.T) {
nodes := []string{"CLN", "LND"}

cfg := loadConfig()
cfg := loadConfig(t)
setBoltzEndpoint(cfg.Boltz, boltz.Regtest)
cfg.Node = "LND"

Expand Down Expand Up @@ -451,7 +452,7 @@ func TestReverseSwap(t *testing.T) {
t.Run(node, func(t *testing.T) {
for _, tc := range tests {
t.Run(tc.desc, func(t *testing.T) {
cfg := loadConfig()
cfg := loadConfig(t)
client, _, stop := setup(t, cfg, "")
cfg.Node = node
boltzClient := &boltz.Boltz{URL: cfg.Boltz.URL}
Expand Down Expand Up @@ -534,7 +535,7 @@ func TestReverseSwap(t *testing.T) {

func TestAutoSwap(t *testing.T) {

cfg := loadConfig()
cfg := loadConfig(t)
cfg.Node = "cln"

require.NoError(t, cfg.Cln.Connect())
Expand Down Expand Up @@ -780,7 +781,7 @@ func TestAutoSwap(t *testing.T) {
}

func TestWallet(t *testing.T) {
cfg := loadConfig()
cfg := loadConfig(t)
client, _, stop := setup(t, cfg, "")
defer stop()

Expand Down Expand Up @@ -822,7 +823,7 @@ func TestWallet(t *testing.T) {
}

func TestUnlock(t *testing.T) {
cfg := loadConfig()
cfg := loadConfig(t)
password := "password"
client, _, stop := setup(t, cfg, password)
defer stop()
Expand Down Expand Up @@ -853,7 +854,7 @@ func TestUnlock(t *testing.T) {
}

func TestCreateWalletWithPassword(t *testing.T) {
cfg := loadConfig()
cfg := loadConfig(t)
client, _, stop := setup(t, cfg, "")
defer stop()

Expand All @@ -877,7 +878,7 @@ func TestCreateWalletWithPassword(t *testing.T) {
}

func TestImportDuplicateCredentials(t *testing.T) {
cfg := loadConfig()
cfg := loadConfig(t)
client, _, stop := setup(t, cfg, "")
defer stop()

Expand All @@ -891,7 +892,7 @@ func TestImportDuplicateCredentials(t *testing.T) {
}

func TestChangePassword(t *testing.T) {
cfg := loadConfig()
cfg := loadConfig(t)
client, _, stop := setup(t, cfg, "")
defer stop()

Expand Down
67 changes: 54 additions & 13 deletions config.go → config/config.go
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
package boltz_lnd
package config

import (
"fmt"
"os"
"path"
"runtime"
"strings"

"github.com/BurntSushi/toml"
"github.com/jessevdk/go-flags"
Expand Down Expand Up @@ -32,6 +33,8 @@ type Config struct {
LogFile string `short:"l" long:"logfile" description:"Path to the log file"`
LogLevel string `long:"loglevel" description:"Log level (fatal, error, warn, info, debug, silly)"`

Network string `long:"network" description:"Network to use (mainnet, testnet, regtest)"`

Boltz *boltz.Boltz `group:"Boltz Options"`
LND *lnd.LND `group:"LND Options"`
Cln *cln.Cln `group:"Cln Options"`
Expand All @@ -54,7 +57,7 @@ type Config struct {
Help *helpOptions `group:"Help Options"`
}

func LoadConfig(dataDir string) *Config {
func LoadConfig(dataDir string) (*Config, error) {
cfg := Config{
DataDir: dataDir,

Expand All @@ -63,6 +66,8 @@ func LoadConfig(dataDir string) *Config {
LogFile: "",
LogLevel: "info",

Network: "mainnet",

Boltz: &boltz.Boltz{
URL: "",
},
Expand All @@ -75,7 +80,7 @@ func LoadConfig(dataDir string) *Config {
},

Cln: &cln.Cln{
Host: "",
Host: "127.0.0.1",
Port: 10009,

RootCert: "",
Expand Down Expand Up @@ -106,6 +111,9 @@ func LoadConfig(dataDir string) *Config {

parser := flags.NewParser(&cfg, flags.IgnoreUnknown)
_, err := parser.Parse()
if err != nil {
printCouldNotParse(err)
}

if cfg.Help.ShowVersion {
fmt.Println(build.GetVersion())
Expand All @@ -118,29 +126,62 @@ func LoadConfig(dataDir string) *Config {
os.Exit(0)
}

if err != nil {
printCouldNotParse(err)
}

cfg.ConfigFile = utils.ExpandDefaultPath(cfg.DataDir, cfg.ConfigFile, "boltz.toml")

if cfg.ConfigFile != "" {
_, err := toml.DecodeFile(cfg.ConfigFile, &cfg)

if err != nil {
fmt.Printf("Could not read config file: " + err.Error() + "\n")
return nil, fmt.Errorf("Could not read config file: %v", err)
}
}

// parse a second time to ensure cli flags go over config values
_, err = parser.Parse()
if err != nil {
printCouldNotParse(err)
}

fmt.Println("Using data dir: " + cfg.DataDir)

if strings.EqualFold(cfg.Node, "CLN") && cfg.Cln.DataDir == "" {
cfg.Cln.DataDir = "~/.lightning"
} else if strings.EqualFold(cfg.Node, "LND") && cfg.LND.DataDir == "" {
cfg.LND.DataDir = "~/.lnd"
}

cfg.LND.Macaroon = utils.ExpandHomeDir(cfg.LND.Macaroon)
cfg.LND.Certificate = utils.ExpandHomeDir(cfg.LND.Certificate)

cfg.Cln.DataDir = utils.ExpandHomeDir(cfg.Cln.DataDir)
cfg.Cln.RootCert = utils.ExpandDefaultPath(cfg.Cln.DataDir, cfg.Cln.RootCert, "ca.pem")
cfg.Cln.PrivateKey = utils.ExpandDefaultPath(cfg.Cln.DataDir, cfg.Cln.PrivateKey, "client-key.pem")
cfg.Cln.CertChain = utils.ExpandDefaultPath(cfg.Cln.DataDir, cfg.Cln.CertChain, "client.pem")
if cfg.LND.DataDir != "" {
cfg.LND.DataDir = utils.ExpandHomeDir(cfg.LND.DataDir)
if cfg.Network == "" {
return nil, fmt.Errorf("network must be set when lnd datadir is configured")
}

defaultMacaroon := fmt.Sprintf("./data/chain/bitcoin/%s/admin.macaroon", cfg.Network)
cfg.LND.Macaroon = utils.ExpandDefaultPath(cfg.LND.DataDir, cfg.LND.Macaroon, defaultMacaroon)
cfg.LND.Certificate = utils.ExpandDefaultPath(cfg.LND.DataDir, cfg.LND.Certificate, "tls.cert")
}

cfg.Cln.RootCert = utils.ExpandHomeDir(cfg.Cln.RootCert)
cfg.Cln.PrivateKey = utils.ExpandHomeDir(cfg.Cln.PrivateKey)
cfg.Cln.CertChain = utils.ExpandHomeDir(cfg.Cln.CertChain)

if cfg.Cln.DataDir != "" {
cfg.Cln.DataDir = utils.ExpandHomeDir(cfg.Cln.DataDir)
if cfg.Network == "" {
return nil, fmt.Errorf("network must be set when cln datadir is configured")
}
if cfg.Network == "mainnet" {
cfg.Cln.DataDir += "/bitcoin"
} else {
cfg.Cln.DataDir += "/" + cfg.Network
}
cfg.Cln.RootCert = utils.ExpandDefaultPath(cfg.Cln.DataDir, cfg.Cln.RootCert, "ca.pem")
cfg.Cln.PrivateKey = utils.ExpandDefaultPath(cfg.Cln.DataDir, cfg.Cln.PrivateKey, "client-key.pem")
cfg.Cln.CertChain = utils.ExpandDefaultPath(cfg.Cln.DataDir, cfg.Cln.CertChain, "client.pem")
}

cfg.LogFile = utils.ExpandDefaultPath(cfg.DataDir, cfg.LogFile, "boltz.log")
cfg.Database.Path = utils.ExpandDefaultPath(cfg.DataDir, cfg.Database.Path, "boltz.db")
Expand All @@ -156,7 +197,7 @@ func LoadConfig(dataDir string) *Config {
createDirIfNotExists(cfg.DataDir)
createDirIfNotExists(macaroonDir)

return &cfg
return &cfg, nil
}

func createDirIfNotExists(dir string) {
Expand Down
38 changes: 21 additions & 17 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,11 @@ Boltz Client connects to [CLN](https://github.com/ElementsProject/lightning/) or

Design principles:

* CLI-first, fine-grained control and enhanced setup UX via `boltzcli`
* CLN-first: full support of all features
* [Liquid](https://liquid.net/)-first: optimized for Lightning -> Liquid -> mainchain swaps
* Create or import Liquid/mainchain wallets, swap to read-only wallets
* Fully backwards compatible with last [boltz-lnd release](https://github.com/BoltzExchange/boltz-client/releases/tag/v1.2.7)
- CLI-first, fine-grained control and enhanced setup UX via `boltzcli`
- CLN-first: full support of all features
- [Liquid](https://liquid.net/)-first: optimized for Lightning -> Liquid -> mainchain swaps
- Create or import Liquid/mainchain wallets, swap to read-only wallets
- Fully backwards compatible with last [boltz-lnd release](https://github.com/BoltzExchange/boltz-client/releases/tag/v1.2.7)

It consists of two main components:

Expand Down Expand Up @@ -57,30 +57,34 @@ Binaries for the latest release of Boltz Client can be found on the [release pag

### Configuration

`boltzd` requires a connection to a lightning node. It can connect to either CLN or LND.
Configuration can be done via cli params or a TOML configuration file (default `~/.boltz/boltz.toml`). An example configuration file can be found [here](configuration.md). We suggest you start off with it. We suggest you start off with it.

`boltzd` requires a connection to a lightning node, which ban be CLN or LND. If you set configuration values for both, you can specify which to use with the `node` param.

To view all CLI flags use `--help`.

#### LND

The LND node to which the daemon connects has to be version `v0.10.0-beta` or higher. Also, LND needs to be compiled with these build flags (official binaries from Lightning Labs releases include them):

* `invoicerpc` (hold invoices)
* `routerrpc` (multi path payments)
* `chainrpc` (block listener)
* `walletrpc` (fee estimations)
- `invoicerpc` (hold invoices)
- `routerrpc` (multi path payments)
- `chainrpc` (block listener)
- `walletrpc` (fee estimations)

In most cases, the CLI flags `--lnd.certificate <path to the tls.cert of LND>` and `--lnd.macaroon <path to the admin.macaroon of LND>` should be enough.
By default, boltzd will attempt to connect to lnd running at `localhost:10009` (`lnd.host` and `lnd.port`) and looking for certificate and macaroon inside the data directory `~/.lnd` (`lnd.datadir`).

You can manually set the location of the tls certificate (`lnd.certificate`) and admin macaroon (`lnd.macaroon`) instead of speciyfing the data directory aswell.

#### CLN

The daemon connects to CLN through [gRPC](https://docs.corelightning.org/docs/grpc). You need start CLN with the `--grpc-port` CLI flag, or set it in your config:

* `--cln.port` same port as used for `--grpc-port`
* `--cln.host` host of the machine CLN is running on
* `--cln.datadir` data directory of cln

To view all CLI flags use `--help`.
- `--cln.port` same port as used for `--grpc-port`
- `--cln.host` host of the machine CLN is running on
- `--cln.datadir` data directory of cln (`~/.lightning` by default)

`boltzd` can also be configured via a TOML file. The documentation for the configuration file can be found [here](configuration.md).
You can manually set the paths of `cln.rootcert`, `cln.privatekey` and `cln.certchain` instead of speciyfing the data directory aswell.

### Macaroons

Expand Down
Loading

0 comments on commit 6d12f3c

Please sign in to comment.