lightning-terminal/cmd/litcli/helpers.go
Elle Mouton 949c0bf7e2
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.
2025-02-09 10:37:40 +02:00

123 lines
3 KiB
Go

package main
import (
"bytes"
"crypto/rand"
"encoding/hex"
"encoding/json"
"os"
"github.com/lightninglabs/lightning-terminal/macaroons"
"github.com/urfave/cli"
)
// helperCommands are commands that do not require a connection to LiTd to
// return a response.
var helperCommands = cli.Command{
Name: "helper",
Usage: "Helper commands",
Description: "Helper commands.",
Category: "LiT",
Subcommands: []cli.Command{
generateSuperMacRootIDCmd,
isSuperMacaroonCmd,
},
}
// generateSuperMacRootIDCmd is a command that can be used to generate a root
// key ID for a super macaroon. A suffix may be specified.
var generateSuperMacRootIDCmd = cli.Command{
Name: "supermacrootkey",
Usage: "Generate a valid super macaroon root key ID from " +
"scratch or from a given root key ID suffix.",
Description: "This command can be used to generate a valid " +
"super macaroon root key ID from scratch or from " +
"a given root key ID suffix.",
Action: superMacRootKey,
Flags: []cli.Flag{
cli.StringFlag{
Name: "root_key_suffix",
Usage: "A 4-byte suffix to use in the construction " +
"of the root key ID. If not provided, then a " +
"random one will be generated. This must be " +
"specified as a hex string using a maximum " +
"of 8 characters.",
},
},
}
// superMacRootKey generates a super macaroon root key ID.
func superMacRootKey(ctx *cli.Context) error {
var suffix [4]byte
if ctx.IsSet("root_key_suffix") {
suffixBytes, err := hex.DecodeString(
ctx.String("root_key_suffix"),
)
if err != nil {
return err
}
copy(suffix[:], suffixBytes)
} else {
_, err := rand.Read(suffix[:])
if err != nil {
return err
}
}
id := macaroons.NewSuperMacaroonRootKeyID(suffix)
printJSON(struct {
RootKeyID uint64 `json:"root_key_id"`
}{
RootKeyID: id,
})
return nil
}
// isSuperMacaronoCmd is a command that a user can run in order to check if
// a macaroon is a super macaroon.
var isSuperMacaroonCmd = cli.Command{
Name: "issupermacaroon",
Usage: "Prints 'true' if the given macaroon is a super macaroon.",
Description: "This command can be used to verify if a macaroon is " +
"considered a super macaroon.",
Action: isSuperMacaroon,
Flags: []cli.Flag{
cli.StringFlag{
Name: "mac",
Usage: "The hex-encoded macaroon.",
Required: true,
},
},
}
// isSuperMacaroon checks if the users given macaroon is considered a super
// macaroon.
func isSuperMacaroon(ctx *cli.Context) error {
isSuperMac := macaroons.IsSuperMacaroon(ctx.String("mac"))
printJSON(struct {
IsSuperMacaroon bool `json:"is_super_macaroon"`
}{
IsSuperMacaroon: isSuperMac,
})
return nil
}
// printJSON marshals the given interface as a json byte slice, formats it to
// use easy to read indentation and writes it as a string to standard out.
func printJSON(resp interface{}) {
b, err := json.Marshal(resp)
if err != nil {
fatal(err)
}
var out bytes.Buffer
_ = json.Indent(&out, b, "", "\t")
_, _ = out.WriteString("\n")
_, _ = out.WriteTo(os.Stdout)
}