Skip to content

Commit 949c0bf

Browse files
committed
multi: move macaroon helpers to macaroons dir
... and out of the `sessions` directory. This is to avoid import cycles when we start explicitly linking accounts to sessions.
1 parent df0e867 commit 949c0bf

File tree

10 files changed

+131
-102
lines changed

10 files changed

+131
-102
lines changed

accounts/rpcserver.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import (
88

99
"github.com/btcsuite/btcd/btcutil"
1010
"github.com/lightninglabs/lightning-terminal/litrpc"
11+
litmac "github.com/lightninglabs/lightning-terminal/macaroons"
1112
"github.com/lightninglabs/lightning-terminal/session"
1213
"github.com/lightningnetwork/lnd/lntypes"
1314
"github.com/lightningnetwork/lnd/lnwire"
@@ -79,7 +80,7 @@ func (s *RPCServer) CreateAccount(ctx context.Context,
7980

8081
var rootKeyIdSuffix [4]byte
8182
copy(rootKeyIdSuffix[:], account.ID[0:4])
82-
macRootKey := session.NewSuperMacaroonRootKeyID(rootKeyIdSuffix)
83+
macRootKey := litmac.NewSuperMacaroonRootKeyID(rootKeyIdSuffix)
8384

8485
accountCaveat := checkers.Condition(
8586
macaroons.CondLndCustom,

cmd/litcli/helpers.go

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ import (
77
"encoding/json"
88
"os"
99

10-
"github.com/lightninglabs/lightning-terminal/session"
10+
"github.com/lightninglabs/lightning-terminal/macaroons"
1111
"github.com/urfave/cli"
1212
)
1313

@@ -66,7 +66,7 @@ func superMacRootKey(ctx *cli.Context) error {
6666
}
6767
}
6868

69-
id := session.NewSuperMacaroonRootKeyID(suffix)
69+
id := macaroons.NewSuperMacaroonRootKeyID(suffix)
7070

7171
printJSON(struct {
7272
RootKeyID uint64 `json:"root_key_id"`
@@ -97,7 +97,7 @@ var isSuperMacaroonCmd = cli.Command{
9797
// isSuperMacaroon checks if the users given macaroon is considered a super
9898
// macaroon.
9999
func isSuperMacaroon(ctx *cli.Context) error {
100-
isSuperMac := session.IsSuperMacaroon(ctx.String("mac"))
100+
isSuperMac := macaroons.IsSuperMacaroon(ctx.String("mac"))
101101

102102
printJSON(struct {
103103
IsSuperMacaroon bool `json:"is_super_macaroon"`

itest/litd_firewall_test.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ import (
2222
"github.com/lightninglabs/lightning-terminal/firewall"
2323
"github.com/lightninglabs/lightning-terminal/firewalldb"
2424
"github.com/lightninglabs/lightning-terminal/litrpc"
25+
"github.com/lightninglabs/lightning-terminal/macaroons"
2526
"github.com/lightninglabs/lightning-terminal/rules"
2627
"github.com/lightninglabs/lightning-terminal/session"
2728
"github.com/lightningnetwork/lnd"
@@ -2566,7 +2567,7 @@ func (c *caveatCredentials) GetRequestMetadata(ctx context.Context,
25662567
return metadata, nil
25672568
}
25682569

2569-
mac, err := session.ParseMacaroon(macHex)
2570+
mac, err := macaroons.ParseMacaroon(macHex)
25702571
if err != nil {
25712572
return nil, err
25722573
}

macaroons/macaroons.go

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
package macaroons
2+
3+
import (
4+
"fmt"
5+
"strconv"
6+
7+
"github.com/lightningnetwork/lnd/lnrpc"
8+
"google.golang.org/protobuf/proto"
9+
"gopkg.in/macaroon-bakery.v2/bakery"
10+
"gopkg.in/macaroon.v2"
11+
)
12+
13+
// RootKeyIDFromMacaroon extracts the root key ID of the passed macaroon.
14+
func RootKeyIDFromMacaroon(mac *macaroon.Macaroon) (uint64, error) {
15+
rawID := mac.Id()
16+
if rawID[0] != byte(bakery.LatestVersion) {
17+
return 0, fmt.Errorf("mac id is not on the latest version")
18+
}
19+
20+
decodedID := &lnrpc.MacaroonId{}
21+
idProto := rawID[1:]
22+
err := proto.Unmarshal(idProto, decodedID)
23+
if err != nil {
24+
return 0, err
25+
}
26+
27+
// The storage ID is a string representation of a 64-bit unsigned
28+
// number.
29+
return strconv.ParseUint(string(decodedID.StorageId), 10, 64)
30+
}

macaroons/super_mac.go

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
package macaroons
2+
3+
import (
4+
"bytes"
5+
"context"
6+
"encoding/binary"
7+
"encoding/hex"
8+
9+
"gopkg.in/macaroon-bakery.v2/bakery"
10+
"gopkg.in/macaroon.v2"
11+
)
12+
13+
// SuperMacaroonRootKeyPrefix is the prefix we set on a super macaroon's root
14+
// key to clearly mark it as such.
15+
var SuperMacaroonRootKeyPrefix = [4]byte{0xFF, 0xEE, 0xDD, 0xCC}
16+
17+
// SuperMacaroonValidator is a function type for validating a super macaroon.
18+
type SuperMacaroonValidator func(ctx context.Context,
19+
superMacaroon []byte, requiredPermissions []bakery.Op,
20+
fullMethod string) error
21+
22+
// NewSuperMacaroonRootKeyID returns a new macaroon root key ID that has the
23+
// prefix to mark it as a super macaroon root key.
24+
func NewSuperMacaroonRootKeyID(id [4]byte) uint64 {
25+
rootKeyBytes := make([]byte, 8)
26+
copy(rootKeyBytes[:], SuperMacaroonRootKeyPrefix[:])
27+
copy(rootKeyBytes[4:], id[:])
28+
29+
return binary.BigEndian.Uint64(rootKeyBytes)
30+
}
31+
32+
// ParseMacaroon parses a hex encoded macaroon into its native struct.
33+
func ParseMacaroon(macHex string) (*macaroon.Macaroon, error) {
34+
macBytes, err := hex.DecodeString(macHex)
35+
if err != nil {
36+
return nil, err
37+
}
38+
39+
mac := &macaroon.Macaroon{}
40+
if err := mac.UnmarshalBinary(macBytes); err != nil {
41+
return nil, err
42+
}
43+
44+
return mac, nil
45+
}
46+
47+
// IsSuperMacaroon returns true if the given hex encoded macaroon is a super
48+
// macaroon baked by LiT which can be identified by its root key ID.
49+
func IsSuperMacaroon(macHex string) bool {
50+
mac, err := ParseMacaroon(macHex)
51+
if err != nil {
52+
return false
53+
}
54+
55+
rootKeyID, err := RootKeyIDFromMacaroon(mac)
56+
if err != nil {
57+
return false
58+
}
59+
60+
return isSuperMacaroonRootKeyID(rootKeyID)
61+
}
62+
63+
// isSuperMacaroonRootKeyID returns true if the given macaroon root key ID (also
64+
// known as storage ID) is a super macaroon, which can be identified by its
65+
// first 4 bytes.
66+
func isSuperMacaroonRootKeyID(rootKeyID uint64) bool {
67+
rootKeyBytes := make([]byte, 8)
68+
binary.BigEndian.PutUint64(rootKeyBytes, rootKeyID)
69+
return bytes.HasPrefix(rootKeyBytes, SuperMacaroonRootKeyPrefix[:])
70+
}

session/macaroon_test.go renamed to macaroons/super_mac_test.go

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package session
1+
package macaroons
22

33
import (
44
"testing"
@@ -25,13 +25,21 @@ var (
2525
"60a6caf"
2626
)
2727

28+
// TestSuperMacaroonRootKeyID tests that adding the super macaroon prefix to
29+
// a root key ID results in a valid super macaroon root key ID.
2830
func TestSuperMacaroonRootKeyID(t *testing.T) {
31+
t.Parallel()
32+
2933
someBytes := [4]byte{02, 03, 44, 88}
3034
rootKeyID := NewSuperMacaroonRootKeyID(someBytes)
3135
require.True(t, isSuperMacaroonRootKeyID(rootKeyID))
3236
require.False(t, isSuperMacaroonRootKeyID(123))
3337
}
3438

39+
// TestIsSuperMacaroon tests that we can correctly identify an example super
40+
// macaroon.
3541
func TestIsSuperMacaroon(t *testing.T) {
42+
t.Parallel()
43+
3644
require.True(t, IsSuperMacaroon(testMacHex))
3745
}

rpc_proxy.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -13,8 +13,8 @@ import (
1313

1414
"github.com/improbable-eng/grpc-web/go/grpcweb"
1515
"github.com/lightninglabs/lightning-terminal/litrpc"
16+
litmac "github.com/lightninglabs/lightning-terminal/macaroons"
1617
"github.com/lightninglabs/lightning-terminal/perms"
17-
"github.com/lightninglabs/lightning-terminal/session"
1818
litstatus "github.com/lightninglabs/lightning-terminal/status"
1919
"github.com/lightninglabs/lightning-terminal/subservers"
2020
"github.com/lightningnetwork/lnd/lncfg"
@@ -71,7 +71,7 @@ func (e *proxyErr) Unwrap() error {
7171
// or REST request and delegate (and convert if necessary) it to the correct
7272
// component.
7373
func newRpcProxy(cfg *Config, validator macaroons.MacaroonValidator,
74-
superMacValidator session.SuperMacaroonValidator,
74+
superMacValidator litmac.SuperMacaroonValidator,
7575
permsMgr *perms.Manager, subServerMgr *subservers.Manager,
7676
statusMgr *litstatus.Manager, getLNDClient lndBasicClientFn) *rpcProxy {
7777

@@ -176,7 +176,7 @@ type rpcProxy struct {
176176
bakeSuperMac bakeSuperMac
177177

178178
macValidator macaroons.MacaroonValidator
179-
superMacValidator session.SuperMacaroonValidator
179+
superMacValidator litmac.SuperMacaroonValidator
180180

181181
superMacaroon string
182182

@@ -331,7 +331,9 @@ func (p *rpcProxy) makeDirector(allowLitRPC bool) func(ctx context.Context,
331331
))
332332
}
333333

334-
case len(macHeader) == 1 && session.IsSuperMacaroon(macHeader[0]):
334+
case len(macHeader) == 1 &&
335+
litmac.IsSuperMacaroon(macHeader[0]):
336+
335337
// If we have a macaroon, and it's a super macaroon,
336338
// then we need to convert it into the actual daemon
337339
// macaroon if they're running in remote mode.

session/interface.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import (
77

88
"github.com/btcsuite/btcd/btcec/v2"
99
"github.com/lightninglabs/lightning-node-connect/mailbox"
10+
"github.com/lightninglabs/lightning-terminal/macaroons"
1011
"gopkg.in/macaroon-bakery.v2/bakery"
1112
"gopkg.in/macaroon.v2"
1213
)
@@ -86,7 +87,7 @@ func NewSession(id ID, localPrivKey *btcec.PrivateKey, label string, typ Type,
8687
return nil, fmt.Errorf("error deriving pairing secret: %v", err)
8788
}
8889

89-
macRootKey := NewSuperMacaroonRootKeyID(id)
90+
macRootKey := macaroons.NewSuperMacaroonRootKeyID(id)
9091

9192
// The group ID will by default be the same as the Session ID
9293
// unless this session links to a previous session.

session/macaroon.go

Lines changed: 2 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,21 @@
11
package session
22

33
import (
4-
"bytes"
5-
"context"
64
"encoding/binary"
7-
"encoding/hex"
85
"fmt"
9-
"strconv"
106

117
"github.com/btcsuite/btcd/btcec/v2"
12-
"github.com/lightningnetwork/lnd/lnrpc"
13-
"google.golang.org/protobuf/proto"
14-
"gopkg.in/macaroon-bakery.v2/bakery"
8+
"github.com/lightninglabs/lightning-terminal/macaroons"
159
"gopkg.in/macaroon.v2"
1610
)
1711

18-
var (
19-
// SuperMacaroonRootKeyPrefix is the prefix we set on a super macaroon's
20-
// root key to clearly mark it as such.
21-
SuperMacaroonRootKeyPrefix = [4]byte{0xFF, 0xEE, 0xDD, 0xCC}
22-
)
23-
2412
// ID represents the id of a session.
2513
type ID [4]byte
2614

27-
// SuperMacaroonValidator is a function type for validating a super macaroon.
28-
type SuperMacaroonValidator func(ctx context.Context,
29-
superMacaroon []byte, requiredPermissions []bakery.Op,
30-
fullMethod string) error
31-
32-
// NewSuperMacaroonRootKeyID returns a new macaroon root key ID that has the
33-
// prefix to mark it as a super macaroon root key.
34-
func NewSuperMacaroonRootKeyID(id [4]byte) uint64 {
35-
rootKeyBytes := make([]byte, 8)
36-
copy(rootKeyBytes[:], SuperMacaroonRootKeyPrefix[:])
37-
copy(rootKeyBytes[4:], id[:])
38-
return binary.BigEndian.Uint64(rootKeyBytes)
39-
}
40-
41-
// ParseMacaroon parses a hex encoded macaroon into its native struct.
42-
func ParseMacaroon(macHex string) (*macaroon.Macaroon, error) {
43-
macBytes, err := hex.DecodeString(macHex)
44-
if err != nil {
45-
return nil, err
46-
}
47-
48-
mac := &macaroon.Macaroon{}
49-
if err := mac.UnmarshalBinary(macBytes); err != nil {
50-
return nil, err
51-
}
52-
53-
return mac, nil
54-
}
55-
56-
// IsSuperMacaroon returns true if the given hex encoded macaroon is a super
57-
// macaroon baked by LiT which can be identified by its root key ID.
58-
func IsSuperMacaroon(macHex string) bool {
59-
mac, err := ParseMacaroon(macHex)
60-
if err != nil {
61-
return false
62-
}
63-
64-
rootKeyID, err := RootKeyIDFromMacaroon(mac)
65-
if err != nil {
66-
return false
67-
}
68-
69-
return isSuperMacaroonRootKeyID(rootKeyID)
70-
}
71-
72-
// isSuperMacaroonRootKeyID returns true if the given macaroon root key ID (also
73-
// known as storage ID) is a super macaroon, which can be identified by its
74-
// first 4 bytes.
75-
func isSuperMacaroonRootKeyID(rootKeyID uint64) bool {
76-
rootKeyBytes := make([]byte, 8)
77-
binary.BigEndian.PutUint64(rootKeyBytes, rootKeyID)
78-
return bytes.HasPrefix(rootKeyBytes, SuperMacaroonRootKeyPrefix[:])
79-
}
80-
8115
// IDFromMacaroon is a helper function that creates a session ID from
8216
// a macaroon ID.
8317
func IDFromMacaroon(mac *macaroon.Macaroon) (ID, error) {
84-
rootKeyID, err := RootKeyIDFromMacaroon(mac)
18+
rootKeyID, err := macaroons.RootKeyIDFromMacaroon(mac)
8519
if err != nil {
8620
return ID{}, err
8721
}
@@ -110,25 +44,6 @@ func IDFromBytes(b []byte) (ID, error) {
11044
return id, nil
11145
}
11246

113-
// RootKeyIDFromMacaroon extracts the root key ID of the passed macaroon.
114-
func RootKeyIDFromMacaroon(mac *macaroon.Macaroon) (uint64, error) {
115-
rawID := mac.Id()
116-
if rawID[0] != byte(bakery.LatestVersion) {
117-
return 0, fmt.Errorf("mac id is not on the latest version")
118-
}
119-
120-
decodedID := &lnrpc.MacaroonId{}
121-
idProto := rawID[1:]
122-
err := proto.Unmarshal(idProto, decodedID)
123-
if err != nil {
124-
return 0, err
125-
}
126-
127-
// The storage ID is a string representation of a 64-bit unsigned
128-
// number.
129-
return strconv.ParseUint(string(decodedID.StorageId), 10, 64)
130-
}
131-
13247
// NewSessionPrivKeyAndID randomly derives a new private key and session ID
13348
// pair.
13449
func NewSessionPrivKeyAndID() (*btcec.PrivateKey, ID, error) {

0 commit comments

Comments
 (0)