main: integrate macaroons into config, startup, and RPC server

This commit is contained in:
Alex 2017-08-17 19:50:57 -06:00 committed by Olaoluwa Osuntokun
parent 662731e719
commit 922b065de5
4 changed files with 414 additions and 33 deletions

View File

@ -24,6 +24,8 @@ const (
defaultDataDirname = "data"
defaultTLSCertFilename = "tls.cert"
defaultTLSKeyFilename = "tls.key"
defaultAdminMacFilename = "admin.macaroon"
defaultReadMacFilename = "readonly.macaroon"
defaultLogLevel = "info"
defaultLogDirname = "logs"
defaultLogFilename = "lnd.log"
@ -36,12 +38,14 @@ const (
)
var (
lndHomeDir = btcutil.AppDataDir("lnd", false)
defaultConfigFile = filepath.Join(lndHomeDir, defaultConfigFilename)
defaultDataDir = filepath.Join(lndHomeDir, defaultDataDirname)
defaultTLSCertPath = filepath.Join(lndHomeDir, defaultTLSCertFilename)
defaultTLSKeyPath = filepath.Join(lndHomeDir, defaultTLSKeyFilename)
defaultLogDir = filepath.Join(lndHomeDir, defaultLogDirname)
lndHomeDir = btcutil.AppDataDir("lnd", false)
defaultConfigFile = filepath.Join(lndHomeDir, defaultConfigFilename)
defaultDataDir = filepath.Join(lndHomeDir, defaultDataDirname)
defaultTLSCertPath = filepath.Join(lndHomeDir, defaultTLSCertFilename)
defaultTLSKeyPath = filepath.Join(lndHomeDir, defaultTLSKeyFilename)
defaultAdminMacPath = filepath.Join(lndHomeDir, defaultAdminMacFilename)
defaultReadMacPath = filepath.Join(lndHomeDir, defaultReadMacFilename)
defaultLogDir = filepath.Join(lndHomeDir, defaultLogDirname)
btcdHomeDir = btcutil.AppDataDir("btcd", false)
defaultBtcdRPCCertFile = filepath.Join(btcdHomeDir, "rpc.cert")
@ -88,11 +92,14 @@ type autoPilotConfig struct {
type config struct {
ShowVersion bool `short:"V" long:"version" description:"Display version information and exit"`
ConfigFile string `long:"C" long:"configfile" description:"Path to configuration file"`
DataDir string `short:"b" long:"datadir" description:"The directory to store lnd's data within"`
TLSCertPath string `long:"tlscertpath" description:"Path to TLS certificate for lnd's RPC and REST services"`
TLSKeyPath string `long:"tlskeypath" description:"Path to TLS private key for lnd's RPC and REST services"`
LogDir string `long:"logdir" description:"Directory to log output."`
ConfigFile string `long:"C" long:"configfile" description:"Path to configuration file"`
DataDir string `short:"b" long:"datadir" description:"The directory to store lnd's data within"`
TLSCertPath string `long:"tlscertpath" description:"Path to TLS certificate for lnd's RPC and REST services"`
TLSKeyPath string `long:"tlskeypath" description:"Path to TLS private key for lnd's RPC and REST services"`
NoMacaroons bool `long:"no-macaroons" description:"Disable macaroon authentication"`
AdminMacPath string `long:"adminmacaroonpath" description:"Path to write the admin macaroon for lnd's RPC and REST services if it doesn't exist"`
ReadMacPath string `long:"readonlymacaroonpath" description:"Path to write the read-only macaroon for lnd's RPC and REST services if it doesn't exist"`
LogDir string `long:"logdir" description:"Directory to log output."`
Listeners []string `long:"listen" description:"Add an interface/port to listen for connections (default all interfaces port: 5656)"`
ExternalIPs []string `long:"externalip" description:"Add an ip to the list of local addresses we claim to listen on to peers"`
@ -132,6 +139,8 @@ func loadConfig() (*config, error) {
DebugLevel: defaultLogLevel,
TLSCertPath: defaultTLSCertPath,
TLSKeyPath: defaultTLSKeyPath,
AdminMacPath: defaultAdminMacPath,
ReadMacPath: defaultReadMacPath,
LogDir: defaultLogDir,
PeerPort: defaultPeerPort,
RPCPort: defaultRPCPort,

64
lnd.go
View File

@ -12,6 +12,9 @@ import (
"strconv"
"time"
"gopkg.in/macaroon-bakery.v1/bakery"
"gopkg.in/macaroon-bakery.v1/bakery/checkers"
"golang.org/x/net/context"
"google.golang.org/grpc"
@ -24,6 +27,7 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/macaroons"
"github.com/roasbeef/btcd/btcec"
"github.com/roasbeef/btcutil"
)
@ -78,6 +82,30 @@ func lndMain() error {
}
defer chanDB.Close()
// Only process macaroons if --no-macaroons isn't set.
var macaroonService *bakery.Service
if !cfg.NoMacaroons {
// Create the macaroon authentication/authorization service.
macaroonService, err = macaroons.NewService(cfg.DataDir)
if err != nil {
srvrLog.Errorf("unable to create macaroon service: %v",
err)
return err
}
// Create macaroon files for lncli to use if they don't exist.
if !fileExists(cfg.AdminMacPath) &&
!fileExists(cfg.ReadMacPath) {
err = genMacaroons(macaroonService, cfg.AdminMacPath,
cfg.ReadMacPath)
if err != nil {
ltndLog.Errorf("unable to create macaroon "+
"files: %v", err)
return err
}
}
}
// With the information parsed from the configuration, create valid
// instances of the paertinent interfaces required to operate the
// Lightning Network Daemon.
@ -197,7 +225,7 @@ func lndMain() error {
// Initialize, and register our implementation of the gRPC interface
// exported by the rpcServer.
rpcServer := newRPCServer(server)
rpcServer := newRPCServer(server, macaroonService)
if err := rpcServer.Start(); err != nil {
return err
}
@ -375,3 +403,37 @@ func genCertPair(certFile, keyFile string) error {
rpcsLog.Infof("Done generating TLS certificates")
return nil
}
// genMacaroons generates a pair of macaroon files; one admin-level and one
// read-only. These can also be used to generate more granular macaroons.
func genMacaroons(svc *bakery.Service, admFile, roFile string) error {
// Generate the admin macaroon and write it to a file.
admMacaroon, err := svc.NewMacaroon("", nil, nil)
if err != nil {
return err
}
admBytes, err := admMacaroon.MarshalBinary()
if err != nil {
return err
}
if err = ioutil.WriteFile(admFile, admBytes, 0600); err != nil {
return err
}
// Generate the read-only macaroon and write it to a file.
caveat := checkers.AllowCaveat(roPermissions...)
roMacaroon := admMacaroon.Clone()
if err = svc.AddCaveat(roMacaroon, caveat); err != nil {
return err
}
roBytes, err := roMacaroon.MarshalBinary()
if err != nil {
return err
}
if err = ioutil.WriteFile(roFile, roBytes, 0644); err != nil {
os.Remove(admFile)
return err
}
return nil
}

View File

@ -15,6 +15,8 @@ import (
"sync"
"time"
macaroon "gopkg.in/macaroon.v1"
"golang.org/x/net/context"
"google.golang.org/grpc"
@ -25,6 +27,7 @@ import (
"github.com/go-errors/errors"
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/macaroons"
"github.com/roasbeef/btcd/chaincfg"
"github.com/roasbeef/btcd/chaincfg/chainhash"
"github.com/roasbeef/btcd/rpctest"
@ -137,6 +140,8 @@ func newLightningNode(btcrpcConfig *btcrpcclient.ConnConfig, lndArgs []string) (
}
cfg.TLSCertPath = filepath.Join(cfg.DataDir, "tls.cert")
cfg.TLSKeyPath = filepath.Join(cfg.DataDir, "tls.key")
cfg.AdminMacPath = filepath.Join(cfg.DataDir, "admin.macaroon")
cfg.ReadMacPath = filepath.Join(cfg.DataDir, "readonly.macaroon")
cfg.PeerPort, cfg.RPCPort = generateListeningPorts()
@ -177,6 +182,8 @@ func (l *lightningNode) genArgs() []string {
args = append(args, fmt.Sprintf("--tlscertpath=%v", l.cfg.TLSCertPath))
args = append(args, fmt.Sprintf("--tlskeypath=%v", l.cfg.TLSKeyPath))
args = append(args, fmt.Sprintf("--configfile=%v", l.cfg.DataDir))
args = append(args, fmt.Sprintf("--adminmacaroonpath=%v", l.cfg.AdminMacPath))
args = append(args, fmt.Sprintf("--readonlymacaroonpath=%v", l.cfg.ReadMacPath))
if l.extraArgs != nil {
args = append(args, l.extraArgs...)
@ -247,23 +254,34 @@ func (l *lightningNode) Start(lndError chan error) error {
return err
}
// Wait until TLS certificate is created before using it, up to 20 sec.
// Wait until TLS certificate and admin macaroon are created before
// using them, up to 20 sec.
tlsTimeout := time.After(20 * time.Second)
for !fileExists(l.cfg.TLSCertPath) {
for !fileExists(l.cfg.TLSCertPath) || !fileExists(l.cfg.AdminMacPath) {
time.Sleep(100 * time.Millisecond)
select {
case <-tlsTimeout:
panic(fmt.Errorf("timeout waiting for TLS cert file " +
"to be created after 20 seconds"))
"and admin macaroon file to be created after " +
"20 seconds"))
default:
}
}
creds, err := credentials.NewClientTLSFromFile(l.cfg.TLSCertPath, "")
tlsCreds, err := credentials.NewClientTLSFromFile(l.cfg.TLSCertPath, "")
if err != nil {
return err
}
macBytes, err := ioutil.ReadFile(l.cfg.AdminMacPath)
if err != nil {
return err
}
mac := &macaroon.Macaroon{}
if err = mac.UnmarshalBinary(macBytes); err != nil {
return err
}
opts := []grpc.DialOption{
grpc.WithTransportCredentials(creds),
grpc.WithTransportCredentials(tlsCreds),
grpc.WithPerRPCCredentials(macaroons.NewMacaroonCredential(mac)),
grpc.WithBlock(),
grpc.WithTimeout(time.Second * 20),
}

View File

@ -13,6 +13,8 @@ import (
"strings"
"time"
"gopkg.in/macaroon-bakery.v1/bakery"
"sync"
"sync/atomic"
@ -23,6 +25,7 @@ import (
"github.com/lightningnetwork/lnd/lnrpc"
"github.com/lightningnetwork/lnd/lnwallet"
"github.com/lightningnetwork/lnd/lnwire"
"github.com/lightningnetwork/lnd/macaroons"
"github.com/lightningnetwork/lnd/routing"
"github.com/lightningnetwork/lnd/zpay32"
"github.com/roasbeef/btcd/blockchain"
@ -39,6 +42,26 @@ import (
var (
defaultAccount uint32 = waddrmgr.DefaultAccountNum
// roPermissions is a slice of method names that are considered "read-only"
// for authorization purposes, all lowercase.
roPermissions = []string{
"verifymessage",
"getinfo",
"listpeers",
"walletbalance",
"channelbalance",
"listchannels",
"readinvoices",
"gettransactions",
"describegraph",
"getchaninfo",
"getnodeinfo",
"queryroutes",
"getnetworkinfo",
"listpayments",
"decodepayreq",
}
)
// rpcServer is a gRPC, RPC front end to the lnd daemon.
@ -49,6 +72,10 @@ type rpcServer struct {
server *server
// authSvc is the authentication/authorization service backed by
// macaroons.
authSvc *bakery.Service
wg sync.WaitGroup
quit chan struct{}
@ -59,8 +86,12 @@ type rpcServer struct {
var _ lnrpc.LightningServer = (*rpcServer)(nil)
// newRPCServer creates and returns a new instance of the rpcServer.
func newRPCServer(s *server) *rpcServer {
return &rpcServer{server: s, quit: make(chan struct{}, 1)}
func newRPCServer(s *server, authSvc *bakery.Service) *rpcServer {
return &rpcServer{
server: s,
authSvc: authSvc,
quit: make(chan struct{}, 1),
}
}
// Start launches any helper goroutines required for the rpcServer
@ -123,6 +154,13 @@ func (r *rpcServer) sendCoinsOnChain(paymentMap map[string]int64) (*chainhash.Ha
// SendMany, this RPC call only allows creating a single output at a time.
func (r *rpcServer) SendCoins(ctx context.Context,
in *lnrpc.SendCoinsRequest) (*lnrpc.SendCoinsResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "sendcoins",
r.authSvc); err != nil {
return nil, err
}
}
rpcsLog.Infof("[sendcoins] addr=%v, amt=%v", in.Addr, btcutil.Amount(in.Amount))
@ -141,6 +179,13 @@ func (r *rpcServer) SendCoins(ctx context.Context,
// outputs in parallel.
func (r *rpcServer) SendMany(ctx context.Context,
in *lnrpc.SendManyRequest) (*lnrpc.SendManyResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "sendcoins",
r.authSvc); err != nil {
return nil, err
}
}
txid, err := r.sendCoinsOnChain(in.AddrToAmount)
if err != nil {
@ -155,6 +200,13 @@ func (r *rpcServer) SendMany(ctx context.Context,
// NewAddress creates a new address under control of the local wallet.
func (r *rpcServer) NewAddress(ctx context.Context,
in *lnrpc.NewAddressRequest) (*lnrpc.NewAddressResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "newaddress",
r.authSvc); err != nil {
return nil, err
}
}
// Translate the gRPC proto address type to the wallet controller's
// available address types.
@ -181,6 +233,13 @@ func (r *rpcServer) NewAddress(ctx context.Context,
// the local wallet.
func (r *rpcServer) NewWitnessAddress(ctx context.Context,
in *lnrpc.NewWitnessAddressRequest) (*lnrpc.NewAddressResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "newaddress",
r.authSvc); err != nil {
return nil, err
}
}
addr, err := r.server.cc.wallet.NewAddress(lnwallet.WitnessPubKey, false)
if err != nil {
@ -197,6 +256,13 @@ func (r *rpcServer) NewWitnessAddress(ctx context.Context,
// verification.
func (r *rpcServer) SignMessage(ctx context.Context,
in *lnrpc.SignMessageRequest) (*lnrpc.SignMessageResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "signmessage",
r.authSvc); err != nil {
return nil, err
}
}
if in.Msg == nil {
return nil, fmt.Errorf("need a message to sign")
@ -217,6 +283,13 @@ func (r *rpcServer) SignMessage(ctx context.Context,
// VerifyMessage also returns the recovered pubkey from the signature.
func (r *rpcServer) VerifyMessage(ctx context.Context,
in *lnrpc.VerifyMessageRequest) (*lnrpc.VerifyMessageResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "verifymessage",
r.authSvc); err != nil {
return nil, err
}
}
if in.Msg == nil {
return nil, fmt.Errorf("need a message to verify")
@ -256,6 +329,13 @@ func (r *rpcServer) VerifyMessage(ctx context.Context,
// ConnectPeer attempts to establish a connection to a remote peer.
func (r *rpcServer) ConnectPeer(ctx context.Context,
in *lnrpc.ConnectPeerRequest) (*lnrpc.ConnectPeerResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "connectpeer",
r.authSvc); err != nil {
return nil, err
}
}
// The server hasn't yet started, so it won't be able to service any of
// our requests, so we'll bail early here.
@ -317,6 +397,13 @@ func (r *rpcServer) ConnectPeer(ctx context.Context,
// with the target peer, this action will be disallowed.
func (r *rpcServer) DisconnectPeer(ctx context.Context,
in *lnrpc.DisconnectPeerRequest) (*lnrpc.DisconnectPeerResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "disconnectpeer",
r.authSvc); err != nil {
return nil, err
}
}
rpcsLog.Debugf("[disconnectpeer] from peer(%s)", in.PubKey)
@ -366,6 +453,13 @@ func (r *rpcServer) DisconnectPeer(ctx context.Context,
// request to a remote peer.
func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest,
updateStream lnrpc.Lightning_OpenChannelServer) error {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(updateStream.Context(),
"openchannel", r.authSvc); err != nil {
return err
}
}
rpcsLog.Tracef("[openchannel] request to peerid(%v) "+
"allocation(us=%v, them=%v)", in.TargetPeerId,
@ -486,6 +580,13 @@ out:
// strings.
func (r *rpcServer) OpenChannelSync(ctx context.Context,
in *lnrpc.OpenChannelRequest) (*lnrpc.ChannelPoint, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "openchannel",
r.authSvc); err != nil {
return nil, err
}
}
rpcsLog.Tracef("[openchannel] request to peerid(%v) "+
"allocation(us=%v, them=%v)", in.TargetPeerId,
@ -569,6 +670,13 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context,
// a force close after a timeout period in the case of an inactive peer.
func (r *rpcServer) CloseChannel(in *lnrpc.CloseChannelRequest,
updateStream lnrpc.Lightning_CloseChannelServer) error {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(updateStream.Context(),
"closechannel", r.authSvc); err != nil {
return err
}
}
force := in.Force
index := in.ChannelPoint.OutputIndex
@ -815,6 +923,13 @@ func (r *rpcServer) forceCloseChan(channel *lnwallet.LightningChannel) (*chainha
// concerning the number of open+pending channels.
func (r *rpcServer) GetInfo(ctx context.Context,
in *lnrpc.GetInfoRequest) (*lnrpc.GetInfoResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "getinfo",
r.authSvc); err != nil {
return nil, err
}
}
var activeChannels uint32
serverPeers := r.server.Peers()
@ -864,6 +979,13 @@ func (r *rpcServer) GetInfo(ctx context.Context,
// ListPeers returns a verbose listing of all currently active peers.
func (r *rpcServer) ListPeers(ctx context.Context,
in *lnrpc.ListPeersRequest) (*lnrpc.ListPeersResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "listpeers",
r.authSvc); err != nil {
return nil, err
}
}
rpcsLog.Tracef("[listpeers] request")
@ -919,6 +1041,13 @@ func (r *rpcServer) ListPeers(ctx context.Context,
// TODO(roasbeef): add async hooks into wallet balance changes
func (r *rpcServer) WalletBalance(ctx context.Context,
in *lnrpc.WalletBalanceRequest) (*lnrpc.WalletBalanceResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "walletbalance",
r.authSvc); err != nil {
return nil, err
}
}
balance, err := r.server.cc.wallet.ConfirmedBalance(1, in.WitnessOnly)
if err != nil {
@ -936,6 +1065,13 @@ func (r *rpcServer) WalletBalance(ctx context.Context,
// channels in satoshis.
func (r *rpcServer) ChannelBalance(ctx context.Context,
in *lnrpc.ChannelBalanceRequest) (*lnrpc.ChannelBalanceResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "channelbalance",
r.authSvc); err != nil {
return nil, err
}
}
channels, err := r.server.chanDB.FetchAllChannels()
if err != nil {
@ -958,6 +1094,13 @@ func (r *rpcServer) ChannelBalance(ctx context.Context,
// process of closure, either initiated cooperatively or non-cooperatively.
func (r *rpcServer) PendingChannels(ctx context.Context,
in *lnrpc.PendingChannelRequest) (*lnrpc.PendingChannelResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "listchannels",
r.authSvc); err != nil {
return nil, err
}
}
rpcsLog.Debugf("[pendingchannels]")
@ -1091,6 +1234,13 @@ func (r *rpcServer) PendingChannels(ctx context.Context,
// is a participant in.
func (r *rpcServer) ListChannels(ctx context.Context,
in *lnrpc.ListChannelsRequest) (*lnrpc.ListChannelsResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "listchannels",
r.authSvc); err != nil {
return nil, err
}
}
resp := &lnrpc.ListChannelsResponse{}
@ -1196,6 +1346,14 @@ func (r *rpcServer) savePayment(route *routing.Route, amount btcutil.Amount,
// bi-directional stream allowing clients to rapidly send payments through the
// Lightning Network with a single persistent connection.
func (r *rpcServer) SendPayment(paymentStream lnrpc.Lightning_SendPaymentServer) error {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(paymentStream.Context(),
"sendpayment", r.authSvc); err != nil {
return err
}
}
errChan := make(chan error, 1)
payChan := make(chan *lnrpc.SendRequest)
@ -1355,6 +1513,13 @@ func (r *rpcServer) SendPayment(paymentStream lnrpc.Lightning_SendPaymentServer)
// hash (if any) to be encoded as hex strings.
func (r *rpcServer) SendPaymentSync(ctx context.Context,
nextPayment *lnrpc.SendRequest) (*lnrpc.SendResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "sendpayment",
r.authSvc); err != nil {
return nil, err
}
}
// We don't allow payments to be sent while the daemon itself is still
// syncing as we may be trying to sent a payment over a "stale"
@ -1439,6 +1604,13 @@ func (r *rpcServer) SendPaymentSync(ctx context.Context,
// unique payment preimage.
func (r *rpcServer) AddInvoice(ctx context.Context,
invoice *lnrpc.Invoice) (*lnrpc.AddInvoiceResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "addinvoice",
r.authSvc); err != nil {
return nil, err
}
}
var paymentPreimage [32]byte
@ -1521,6 +1693,13 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
// returned.
func (r *rpcServer) LookupInvoice(ctx context.Context,
req *lnrpc.PaymentHash) (*lnrpc.Invoice, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "readinvoices",
r.authSvc); err != nil {
return nil, err
}
}
var (
payHash [32]byte
@ -1579,6 +1758,13 @@ func (r *rpcServer) LookupInvoice(ctx context.Context,
// database. Any active debug invoices are ignored.
func (r *rpcServer) ListInvoices(ctx context.Context,
req *lnrpc.ListInvoiceRequest) (*lnrpc.ListInvoiceResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "readinvoices",
r.authSvc); err != nil {
return nil, err
}
}
dbInvoices, err := r.server.chanDB.FetchAllInvoices(req.PendingOnly)
if err != nil {
@ -1618,6 +1804,13 @@ func (r *rpcServer) ListInvoices(ctx context.Context,
// notifying the client of newly added/settled invoices.
func (r *rpcServer) SubscribeInvoices(req *lnrpc.InvoiceSubscription,
updateStream lnrpc.Lightning_SubscribeInvoicesServer) error {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(updateStream.Context(),
"readinvoices", r.authSvc); err != nil {
return err
}
}
invoiceClient := r.server.invoices.SubscribeNotifications()
defer invoiceClient.Cancel()
@ -1650,6 +1843,13 @@ func (r *rpcServer) SubscribeInvoices(req *lnrpc.InvoiceSubscription,
// over.
func (r *rpcServer) SubscribeTransactions(req *lnrpc.GetTransactionsRequest,
updateStream lnrpc.Lightning_SubscribeTransactionsServer) error {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(updateStream.Context(),
"gettransactions", r.authSvc); err != nil {
return err
}
}
txClient, err := r.server.cc.wallet.SubscribeTransactions()
if err != nil {
@ -1689,8 +1889,15 @@ func (r *rpcServer) SubscribeTransactions(req *lnrpc.GetTransactionsRequest,
// GetTransactions returns a list of describing all the known transactions
// relevant to the wallet.
func (r *rpcServer) GetTransactions(context.Context,
*lnrpc.GetTransactionsRequest) (*lnrpc.TransactionDetails, error) {
func (r *rpcServer) GetTransactions(ctx context.Context,
_ *lnrpc.GetTransactionsRequest) (*lnrpc.TransactionDetails, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "gettransactions",
r.authSvc); err != nil {
return nil, err
}
}
// TODO(btcsuite): add pagination support
transactions, err := r.server.cc.wallet.ListTransactionDetails()
@ -1722,8 +1929,15 @@ func (r *rpcServer) GetTransactions(context.Context,
// As this is a directed graph, the edges also contain the node directional
// specific routing policy which includes: the time lock delta, fee
// information, etc.
func (r *rpcServer) DescribeGraph(context.Context,
*lnrpc.ChannelGraphRequest) (*lnrpc.ChannelGraph, error) {
func (r *rpcServer) DescribeGraph(ctx context.Context,
_ *lnrpc.ChannelGraphRequest) (*lnrpc.ChannelGraph, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "describegraph",
r.authSvc); err != nil {
return nil, err
}
}
resp := &lnrpc.ChannelGraph{}
@ -1823,8 +2037,15 @@ func marshalDbEdge(edgeInfo *channeldb.ChannelEdgeInfo,
// given channel identified by its channel ID: an 8-byte integer which uniquely
// identifies the location of transaction's funding output within the block
// chain.
func (r *rpcServer) GetChanInfo(_ context.Context, in *lnrpc.ChanInfoRequest) (*lnrpc.ChannelEdge, error) {
func (r *rpcServer) GetChanInfo(ctx context.Context, in *lnrpc.ChanInfoRequest) (*lnrpc.ChannelEdge, error) {
graph := r.server.chanDB.ChannelGraph()
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "getchaninfo",
r.authSvc); err != nil {
return nil, err
}
}
edgeInfo, edge1, edge2, err := graph.FetchChannelEdgesByID(in.ChanId)
if err != nil {
@ -1841,7 +2062,14 @@ func (r *rpcServer) GetChanInfo(_ context.Context, in *lnrpc.ChanInfoRequest) (*
// GetNodeInfo returns the latest advertised and aggregate authenticated
// channel information for the specified node identified by its public key.
func (r *rpcServer) GetNodeInfo(_ context.Context, in *lnrpc.NodeInfoRequest) (*lnrpc.NodeInfo, error) {
func (r *rpcServer) GetNodeInfo(ctx context.Context, in *lnrpc.NodeInfoRequest) (*lnrpc.NodeInfo, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "getnodeinfo",
r.authSvc); err != nil {
return nil, err
}
}
graph := r.server.chanDB.ChannelGraph()
@ -1910,8 +2138,15 @@ func (r *rpcServer) GetNodeInfo(_ context.Context, in *lnrpc.NodeInfoRequest) (*
//
// TODO(roasbeef): should return a slice of routes in reality
// * create separate PR to send based on well formatted route
func (r *rpcServer) QueryRoutes(_ context.Context,
func (r *rpcServer) QueryRoutes(ctx context.Context,
in *lnrpc.QueryRoutesRequest) (*lnrpc.QueryRoutesResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "queryroutes",
r.authSvc); err != nil {
return nil, err
}
}
// First parse the hex-encdoed public key into a full public key objet
// we can properly manipulate.
@ -1967,7 +2202,14 @@ func marshalRoute(route *routing.Route) *lnrpc.Route {
// GetNetworkInfo returns some basic stats about the known channel graph from
// the PoV of the node.
func (r *rpcServer) GetNetworkInfo(context.Context, *lnrpc.NetworkInfoRequest) (*lnrpc.NetworkInfo, error) {
func (r *rpcServer) GetNetworkInfo(ctx context.Context, _ *lnrpc.NetworkInfoRequest) (*lnrpc.NetworkInfo, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "getnetworkinfo",
r.authSvc); err != nil {
return nil, err
}
}
graph := r.server.chanDB.ChannelGraph()
@ -2081,7 +2323,14 @@ func (r *rpcServer) GetNetworkInfo(context.Context, *lnrpc.NetworkInfoRequest) (
// StopDaemon will send a shutdown request to the interrupt handler, triggering
// a graceful shutdown of the daemon.
func (r *rpcServer) StopDaemon(context.Context, *lnrpc.StopRequest) (*lnrpc.StopResponse, error) {
func (r *rpcServer) StopDaemon(ctx context.Context, _ *lnrpc.StopRequest) (*lnrpc.StopResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "stopdaemon",
r.authSvc); err != nil {
return nil, err
}
}
shutdownRequestChannel <- struct{}{}
return &lnrpc.StopResponse{}, nil
@ -2095,6 +2344,13 @@ func (r *rpcServer) StopDaemon(context.Context, *lnrpc.StopRequest) (*lnrpc.Stop
// and finally when prior channels are closed on-chain.
func (r *rpcServer) SubscribeChannelGraph(req *lnrpc.GraphTopologySubscription,
updateStream lnrpc.Lightning_SubscribeChannelGraphServer) error {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(updateStream.Context(),
"describegraph", r.authSvc); err != nil {
return err
}
}
// First, we start by subscribing to a new intent to receive
// notifications from the channel router.
@ -2206,8 +2462,15 @@ func marshallTopologyChange(topChange *routing.TopologyChange) *lnrpc.GraphTopol
}
// ListPayments returns a list of all outgoing payments.
func (r *rpcServer) ListPayments(context.Context,
*lnrpc.ListPaymentsRequest) (*lnrpc.ListPaymentsResponse, error) {
func (r *rpcServer) ListPayments(ctx context.Context,
_ *lnrpc.ListPaymentsRequest) (*lnrpc.ListPaymentsResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "listpayments",
r.authSvc); err != nil {
return nil, err
}
}
rpcsLog.Debugf("[ListPayments]")
@ -2237,8 +2500,15 @@ func (r *rpcServer) ListPayments(context.Context,
}
// DeleteAllPayments deletes all outgoing payments from DB.
func (r *rpcServer) DeleteAllPayments(context.Context,
*lnrpc.DeleteAllPaymentsRequest) (*lnrpc.DeleteAllPaymentsResponse, error) {
func (r *rpcServer) DeleteAllPayments(ctx context.Context,
_ *lnrpc.DeleteAllPaymentsRequest) (*lnrpc.DeleteAllPaymentsResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "deleteallpayments",
r.authSvc); err != nil {
return nil, err
}
}
rpcsLog.Debugf("[DeleteAllPayments]")
@ -2250,7 +2520,15 @@ func (r *rpcServer) DeleteAllPayments(context.Context,
}
// SetAlias...
func (r *rpcServer) SetAlias(context.Context, *lnrpc.SetAliasRequest) (*lnrpc.SetAliasResponse, error) {
func (r *rpcServer) SetAlias(ctx context.Context, _ *lnrpc.SetAliasRequest) (*lnrpc.SetAliasResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "setalias",
r.authSvc); err != nil {
return nil, err
}
}
return nil, nil
}
@ -2260,6 +2538,13 @@ func (r *rpcServer) SetAlias(context.Context, *lnrpc.SetAliasRequest) (*lnrpc.Se
// sub-system.
func (r *rpcServer) DebugLevel(ctx context.Context,
req *lnrpc.DebugLevelRequest) (*lnrpc.DebugLevelResponse, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "debuglevel",
r.authSvc); err != nil {
return nil, err
}
}
// If show is set, then we simply print out the list of available
// sub-systems.
@ -2285,6 +2570,13 @@ func (r *rpcServer) DebugLevel(ctx context.Context,
// payment request.
func (r *rpcServer) DecodePayReq(ctx context.Context,
req *lnrpc.PayReqString) (*lnrpc.PayReq, error) {
// Check macaroon to see if this is allowed.
if r.authSvc != nil {
if err := macaroons.ValidateMacaroon(ctx, "decodepayreq",
r.authSvc); err != nil {
return nil, err
}
}
// Fist we'll attempt to decode the payment request string, if the
// request is invalid or the checksum doesn't match, then we'll exit