Files
lspd/shared/nodes_service.go
2023-11-06 14:11:30 +01:00

128 lines
2.9 KiB
Go

package shared
import (
"encoding/hex"
"errors"
"fmt"
"github.com/breez/lspd/cln"
"github.com/breez/lspd/config"
"github.com/breez/lspd/lightning"
"github.com/breez/lspd/lnd"
"github.com/btcsuite/btcd/btcec/v2"
ecies "github.com/ecies/go/v2"
"golang.org/x/sync/singleflight"
)
type Node struct {
Client lightning.Client
NodeConfig *config.NodeConfig
PrivateKey *btcec.PrivateKey
PublicKey *btcec.PublicKey
EciesPrivateKey *ecies.PrivateKey
EciesPublicKey *ecies.PublicKey
OpenChannelReqGroup singleflight.Group
}
type NodesService interface {
GetNode(token string) (*Node, error)
GetNodes() []*Node
}
type nodesService struct {
nodes []*Node
nodeLookup map[string]*Node
}
func NewNodesService(configs []*config.NodeConfig) (NodesService, error) {
if len(configs) == 0 {
return nil, fmt.Errorf("no nodes supplied")
}
nodes := []*Node{}
nodeLookup := make(map[string]*Node)
for _, config := range configs {
pk, err := hex.DecodeString(config.LspdPrivateKey)
if err != nil {
return nil, fmt.Errorf("hex.DecodeString(config.lspdPrivateKey=%v) error: %v", config.LspdPrivateKey, err)
}
eciesPrivateKey := ecies.NewPrivateKeyFromBytes(pk)
eciesPublicKey := eciesPrivateKey.PublicKey
privateKey, publicKey := btcec.PrivKeyFromBytes(pk)
node := &Node{
NodeConfig: config,
PrivateKey: privateKey,
PublicKey: publicKey,
EciesPrivateKey: eciesPrivateKey,
EciesPublicKey: eciesPublicKey,
}
if config.Lnd == nil && config.Cln == nil {
return nil, fmt.Errorf("node has to be either cln or lnd")
}
if config.Lnd != nil && config.Cln != nil {
return nil, fmt.Errorf("node cannot be both cln and lnd")
}
if config.Lnd != nil {
node.Client, err = lnd.NewLndClient(config.Lnd)
if err != nil {
return nil, err
}
}
if config.Cln != nil {
node.Client, err = cln.NewClnClient(config.Cln.SocketPath)
if err != nil {
return nil, err
}
}
// Make sure the nodes is available and set name and pubkey if not set
// in config.
info, err := node.Client.GetInfo()
if err != nil {
return nil, fmt.Errorf("failed to get info from host %s", node.NodeConfig.Host)
}
if node.NodeConfig.Name == "" {
node.NodeConfig.Name = info.Alias
}
if node.NodeConfig.NodePubkey == "" {
node.NodeConfig.NodePubkey = info.Pubkey
}
nodes = append(nodes, node)
for _, token := range config.Tokens {
_, exists := nodeLookup[token]
if exists {
return nil, fmt.Errorf("cannot have multiple nodes with the same token")
}
nodeLookup[token] = node
}
}
return &nodesService{
nodes: nodes,
nodeLookup: nodeLookup,
}, nil
}
var ErrNodeNotFound = errors.New("node not found")
func (s *nodesService) GetNode(token string) (*Node, error) {
node, ok := s.nodeLookup[token]
if !ok {
return nil, ErrNodeNotFound
}
return node, nil
}
func (s *nodesService) GetNodes() []*Node {
return s.nodes
}