Skip to content

Commit ee6191f

Browse files
committed
lndclient: add new macaroonPouch struct
In this commit, we add a new struct, the `macaroonPouch`. This struct bundles all the macaroons we need for each sub-server. Along the way, we also export the set of default* paths for lnd, and add a new set of variables that store the default file names of each of the macaroons for each sub-server. The `WithMacaroonAuth` method on the `serializedMacaroon` type will allow us to attach a macaroon for each call rather than attaching it at the connection level. This slight change will allow us to use multiple macaroons over a single RPC connection, rather than a single global macaroon.
1 parent 3d0d733 commit ee6191f

File tree

2 files changed

+110
-6
lines changed

2 files changed

+110
-6
lines changed

lndclient/lnd_services.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -122,11 +122,17 @@ var (
122122
defaultRPCPort = "10009"
123123
defaultLndDir = btcutil.AppDataDir("lnd", false)
124124
defaultTLSCertFilename = "tls.cert"
125-
defaultTLSCertPath = filepath.Join(defaultLndDir,
126-
defaultTLSCertFilename)
127-
defaultDataDir = "data"
128-
defaultChainSubDir = "chain"
129-
defaultMacaroonFilename = "admin.macaroon"
125+
defaultTLSCertPath = filepath.Join(
126+
defaultLndDir, defaultTLSCertFilename,
127+
)
128+
defaultDataDir = "data"
129+
defaultChainSubDir = "chain"
130+
131+
defaultAdminMacaroonFilename = "admin.macaroon"
132+
defaultInvoiceMacaroonFilename = "invoices.macaroon"
133+
defaultChainMacaroonFilename = "chainnotifier.macaroon"
134+
defaultWalletKitMacaroonFilename = "walletkit.macaroon"
135+
defaultSignerFilename = "signer.macaroon"
130136
)
131137

132138
func getClientConn(address string, network string, macPath, tlsPath string) (
@@ -151,7 +157,7 @@ func getClientConn(address string, network string, macPath, tlsPath string) (
151157
if macPath == "" {
152158
macPath = filepath.Join(
153159
defaultLndDir, defaultDataDir, defaultChainSubDir,
154-
"bitcoin", network, defaultMacaroonFilename,
160+
"bitcoin", network, defaultAdminMacaroonFilename,
155161
)
156162
}
157163

lndclient/macaroon_pouch.go

Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
package lndclient
2+
3+
import (
4+
"context"
5+
"encoding/hex"
6+
"io/ioutil"
7+
"path/filepath"
8+
9+
"google.golang.org/grpc/metadata"
10+
)
11+
12+
// serializedMacaroon is a type that represents a hex-encoded macaroon. We'll
13+
// use this primarily vs the raw binary format as the gRPC metadata feature
14+
// requires that all keys and values be strings.
15+
type serializedMacaroon string
16+
17+
// newSerializedMacaroon reads a new serializedMacaroon from that target
18+
// macaroon path. If the file can't be found, then an error is returned.
19+
func newSerializedMacaroon(macaroonPath string) (serializedMacaroon, error) {
20+
macBytes, err := ioutil.ReadFile(macaroonPath)
21+
if err != nil {
22+
return "", err
23+
}
24+
25+
return serializedMacaroon(hex.EncodeToString(macBytes)), nil
26+
}
27+
28+
// WithMacaroonAuth modifies the passed context to include the macaroon KV
29+
// metadata of the target macaroon. This method can be used to add the macaroon
30+
// at call time, rather than when the connection to the gRPC server is created.
31+
func (s serializedMacaroon) WithMacaroonAuth(ctx context.Context) context.Context {
32+
return metadata.AppendToOutgoingContext(ctx, "macaroon", string(s))
33+
}
34+
35+
// macaroonPouch holds the set of macaroons we need to interact with lnd for
36+
// Loop. Each sub-server has its own macaroon, and for the remaining temporary
37+
// calls that directly hit lnd, we'll use the admin macaroon.
38+
type macaroonPouch struct {
39+
// invoiceMac is the macaroon for the invoices sub-server.
40+
invoiceMac serializedMacaroon
41+
42+
// chainMac is the macaroon for the ChainNotifier sub-server.
43+
chainMac serializedMacaroon
44+
45+
// signerMac is the macaroon for the Signer sub-server.
46+
signerMac serializedMacaroon
47+
48+
// walletKitMac is the macaroon for the WalletKit sub-server.
49+
walletKitMac serializedMacaroon
50+
51+
// adminMac is the primary admin macaroon for lnd.
52+
adminMac serializedMacaroon
53+
}
54+
55+
// newMacaroonPouch returns a new instance of a fully populated macaroonPouch
56+
// given the directory where all the macaroons are stored.
57+
func newMacaroonPouch(macaroonDir string) (*macaroonPouch, error) {
58+
m := &macaroonPouch{}
59+
60+
var err error
61+
62+
m.invoiceMac, err = newSerializedMacaroon(
63+
filepath.Join(macaroonDir, defaultInvoiceMacaroonFilename),
64+
)
65+
if err != nil {
66+
return nil, err
67+
}
68+
69+
m.chainMac, err = newSerializedMacaroon(
70+
filepath.Join(macaroonDir, defaultChainMacaroonFilename),
71+
)
72+
if err != nil {
73+
return nil, err
74+
}
75+
76+
m.signerMac, err = newSerializedMacaroon(
77+
filepath.Join(macaroonDir, defaultSignerFilename),
78+
)
79+
if err != nil {
80+
return nil, err
81+
}
82+
83+
m.walletKitMac, err = newSerializedMacaroon(
84+
filepath.Join(macaroonDir, defaultWalletKitMacaroonFilename),
85+
)
86+
if err != nil {
87+
return nil, err
88+
}
89+
90+
m.adminMac, err = newSerializedMacaroon(
91+
filepath.Join(macaroonDir, defaultAdminMacaroonFilename),
92+
)
93+
if err != nil {
94+
return nil, err
95+
}
96+
97+
return m, nil
98+
}

0 commit comments

Comments
 (0)