Skip to content

Commit

Permalink
multinode binary
Browse files Browse the repository at this point in the history
  • Loading branch information
ellemouton committed Nov 16, 2024
1 parent 648cd07 commit 322334e
Show file tree
Hide file tree
Showing 4 changed files with 222 additions and 3 deletions.
2 changes: 2 additions & 0 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,7 @@ build:
@$(call print, "Building debug lnd and lncli.")
$(GOBUILD) -tags="$(DEV_TAGS)" -o lnd-debug $(DEV_GCFLAGS) $(DEV_LDFLAGS) $(PKG)/cmd/lnd
$(GOBUILD) -tags="$(DEV_TAGS)" -o lncli-debug $(DEV_GCFLAGS) $(DEV_LDFLAGS) $(PKG)/cmd/lncli
$(GOBUILD) -tags="$(DEV_TAGS)" -o multinode-debug $(DEV_GCFLAGS) $(DEV_LDFLAGS) $(PKG)/cmd/multinode

#? build-itest: Build integration test binaries, place them in itest directory
build-itest:
Expand All @@ -136,6 +137,7 @@ install-binaries:
@$(call print, "Installing lnd and lncli.")
$(GOINSTALL) -tags="${tags}" -ldflags="$(RELEASE_LDFLAGS)" $(PKG)/cmd/lnd
$(GOINSTALL) -tags="${tags}" -ldflags="$(RELEASE_LDFLAGS)" $(PKG)/cmd/lncli
$(GOINSTALL) -tags="${tags}" -ldflags="$(RELEASE_LDFLAGS)" $(PKG)/cmd/multinode

#? manpages: generate and install man pages
manpages:
Expand Down
120 changes: 120 additions & 0 deletions cmd/multinode/main.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
package main

import (
"context"
"fmt"
"os"

"github.com/jessevdk/go-flags"
"github.com/lightningnetwork/lnd"
graphsources "github.com/lightningnetwork/lnd/graph/sources"
"github.com/lightningnetwork/lnd/routing/route"
"github.com/lightningnetwork/lnd/signal"
)

func main() {
// Hook interceptor for os signals.
shutdownInterceptor, err := signal.Intercept()
if err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
lndProviders := setupGraphSourceNode(shutdownInterceptor)
setupDependentNode(shutdownInterceptor, lndProviders)
<-shutdownInterceptor.ShutdownChannel()
}
func setupGraphSourceNode(interceptor signal.Interceptor) lnd.Providers {
preCfg := graphConfig()
cfg, err := lnd.LoadConfigNoFlags(*preCfg, interceptor)
if err != nil {
os.Exit(1)
}
implCfg := cfg.ImplementationConfig(interceptor)
lndProviders := make(chan lnd.Providers, 1)
go func() {
if err := lnd.Main(
cfg, lnd.ListenerCfg{}, implCfg, interceptor,
lndProviders,
); err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
}
fmt.Println("Graph node has stopped")
os.Exit(1)
}()
return <-lndProviders
}
func setupDependentNode(interceptor signal.Interceptor,
lndProviders lnd.Providers) {
// Load the configuration, and parse any command line options. This
// function will also set up logging properly.
loadedConfig, err := lnd.LoadConfig(interceptor)
if err != nil {
if e, ok := err.(*flags.Error); !ok || e.Type != flags.ErrHelp {
// Print error if not due to help request.
err = fmt.Errorf("failed to load config: %w", err)
_, _ = fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
// Help was requested, exit normally.
os.Exit(0)
}
loadedConfig.Gossip.NoSync = true
implCfg := loadedConfig.ImplementationConfig(interceptor)
implCfg.GraphProvider = &graphProvider{lndProviders: lndProviders}
// Call the "real" main in a nested manner so the defers will properly
// be executed in the case of a graceful shutdown.
if err = lnd.Main(
loadedConfig, lnd.ListenerCfg{}, implCfg, interceptor, nil,
); err != nil {
_, _ = fmt.Fprintln(os.Stderr, err)
os.Exit(1)
}
}

type graphProvider struct {
lndProviders lnd.Providers
}

func (g *graphProvider) Graph(_ context.Context,
dbs *lnd.DatabaseInstances) (graphsources.GraphSource, error) {

graphSource, err := g.lndProviders.GraphSource()
if err != nil {
return nil, err
}

getLocalPub := func() (route.Vertex, error) {
node, err := dbs.GraphDB.SourceNode()
if err != nil {
return route.Vertex{}, err
}

return route.NewVertexFromBytes(node.PubKeyBytes[:])
}

return graphsources.NewGraphBackend(
graphsources.NewDBGSource(dbs.GraphDB), graphSource,
getLocalPub,
), nil
}

func graphConfig() *lnd.Config {
cfg := lnd.DefaultConfig()
cfg.Bitcoin.RegTest = true
cfg.LndDir = "/Users/elle/.lnd-dev-graph"
cfg.BitcoindMode.RPCHost = "localhost:18443"
cfg.Bitcoin.Node = "bitcoind"
cfg.RawRPCListeners = []string{"localhost:10020"}
cfg.BitcoindMode.RPCUser = "lightning"
cfg.BitcoindMode.RPCPass = "lightning"
cfg.BitcoindMode.ZMQPubRawBlock = "tcp://localhost:28332"
cfg.BitcoindMode.ZMQPubRawTx = "tcp://localhost:28333"
cfg.TrickleDelay = 50
cfg.NoSeedBackup = true
cfg.RawRESTListeners = []string{"localhost:11020"}
cfg.RawListeners = []string{"localhost:9736"}
cfg.DebugLevel = "debug"
cfg.LogConfig.Console.Disable = true

return &cfg
}
94 changes: 91 additions & 3 deletions config.go
Original file line number Diff line number Diff line change
Expand Up @@ -861,6 +861,87 @@ func LoadConfig(interceptor signal.Interceptor) (*Config, error) {
return cleanCfg, nil
}

func LoadConfigNoFlags(preCfg Config, interceptor signal.Interceptor) (*Config, error) {
// Show the version and exit if the version flag was specified.
appName := filepath.Base(os.Args[0])
appName = strings.TrimSuffix(appName, filepath.Ext(appName))
usageMessage := fmt.Sprintf("Use %s -h to show usage", appName)
if preCfg.ShowVersion {
fmt.Println(appName, "version", build.Version(),
"commit="+build.Commit)
os.Exit(0)
}
// If the config file path has not been modified by the user, then we'll
// use the default config file path. However, if the user has modified
// their lnddir, then we should assume they intend to use the config
// file within it.
configFileDir := CleanAndExpandPath(preCfg.LndDir)
configFilePath := CleanAndExpandPath(preCfg.ConfigFile)
switch {
// User specified --lnddir but no --configfile. Update the config file
// path to the lnd config directory, but don't require it to exist.
case configFileDir != DefaultLndDir &&
configFilePath == DefaultConfigFile:
configFilePath = filepath.Join(
configFileDir, lncfg.DefaultConfigFilename,
)
// User did specify an explicit --configfile, so we check that it does
// exist under that path to avoid surprises.
case configFilePath != DefaultConfigFile:
if !lnrpc.FileExists(configFilePath) {
return nil, fmt.Errorf("specified config file does "+
"not exist in %s", configFilePath)
}
}
// Next, load any additional configuration options from the file.
var configFileError error
cfg := preCfg
fileParser := flags.NewParser(&cfg, flags.Default)
err := flags.NewIniParser(fileParser).ParseFile(configFilePath)
if err != nil {
// If it's a parsing related error, then we'll return
// immediately, otherwise we can proceed as possibly the config
// file doesn't exist which is OK.
if lnutils.ErrorAs[*flags.IniError](err) ||
lnutils.ErrorAs[*flags.Error](err) {
return nil, err
}
configFileError = err
}
// Make sure everything we just loaded makes sense.
cleanCfg, err := ValidateConfig(
cfg, interceptor, fileParser, nil,
)
var usageErr *lncfg.UsageError
if errors.As(err, &usageErr) {
// The logging system might not yet be initialized, so we also
// write to stderr to make sure the error appears somewhere.
_, _ = fmt.Fprintln(os.Stderr, usageMessage)
ltndLog.Warnf("Incorrect usage: %v", usageMessage)
// The log subsystem might not yet be initialized. But we still
// try to log the error there since some packaging solutions
// might only look at the log and not stdout/stderr.
ltndLog.Warnf("Error validating config: %v", err)
return nil, err
}
if err != nil {
// The log subsystem might not yet be initialized. But we still
// try to log the error there since some packaging solutions
// might only look at the log and not stdout/stderr.
ltndLog.Warnf("Error validating config: %v", err)
return nil, err
}
// Warn about missing config file only after all other configuration is
// done. This prevents the warning on help messages and invalid options.
// Note this should go directly before the return.
if configFileError != nil {
ltndLog.Warnf("%v", configFileError)
}
// Finally, log warnings for deprecated config options if they are set.
logWarningsForDeprecation(*cleanCfg)
return cleanCfg, nil
}

// ValidateConfig check the given configuration to be sane. This makes sure no
// illegal values or combination of values are set. All file system paths are
// normalized. The cleaned up config is returned on success.
Expand Down Expand Up @@ -941,11 +1022,18 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser,
fileOptionNested := fileParser.FindOptionByLongName(
"lnd." + long,
)
flagOption := flagParser.FindOptionByLongName(long)
flagOptionNested := flagParser.FindOptionByLongName(
"lnd." + long,
var (
flagOption *flags.Option
flagOptionNested *flags.Option
)

if flagParser != nil {
flagOption = flagParser.FindOptionByLongName(long)
flagOptionNested = flagParser.FindOptionByLongName(
"lnd." + long,
)
}

return (fileOption != nil && fileOption.IsSet()) ||
(fileOptionNested != nil && fileOptionNested.IsSet()) ||
(flagOption != nil && flagOption.IsSet()) ||
Expand Down
9 changes: 9 additions & 0 deletions graph/sources/chan_graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -447,3 +447,12 @@ func extractKVDBRTx(tx session.RTx) (kvdb.RTx, error) {

return kvdbTx, nil
}

func (s *DBSource) SelfNode() (route.Vertex, error) {
node, err := s.db.SourceNode()
if err != nil {
return route.Vertex{}, err
}

return route.NewVertexFromBytes(node.PubKeyBytes[:])
}

0 comments on commit 322334e

Please sign in to comment.