mirror of
https://github.com/lightninglabs/loop
synced 2024-11-13 13:10:30 +00:00
129 lines
3.3 KiB
Go
129 lines
3.3 KiB
Go
package lsat
|
|
|
|
import (
|
|
"encoding/binary"
|
|
"encoding/hex"
|
|
"errors"
|
|
"fmt"
|
|
"io"
|
|
|
|
"github.com/lightningnetwork/lnd/lntypes"
|
|
)
|
|
|
|
const (
|
|
// LatestVersion is the latest version used for minting new LSATs.
|
|
LatestVersion = 0
|
|
|
|
// SecretSize is the size in bytes of a LSAT's secret, also known as
|
|
// the root key of the macaroon.
|
|
SecretSize = 32
|
|
|
|
// TokenIDSize is the size in bytes of an LSAT's ID encoded in its
|
|
// macaroon identifier.
|
|
TokenIDSize = 32
|
|
)
|
|
|
|
var (
|
|
// byteOrder is the byte order used to encode/decode a macaroon's raw
|
|
// identifier.
|
|
byteOrder = binary.BigEndian
|
|
|
|
// ErrUnknownVersion is an error returned when attempting to decode an
|
|
// LSAT identifier with an unknown version.
|
|
ErrUnknownVersion = errors.New("unknown LSAT version")
|
|
)
|
|
|
|
// TokenID is the type that stores the token identifier of an LSAT token.
|
|
type TokenID [TokenIDSize]byte
|
|
|
|
// String returns the hex encoded representation of the token ID as a string.
|
|
func (t *TokenID) String() string {
|
|
return hex.EncodeToString(t[:])
|
|
}
|
|
|
|
// MakeIDFromString parses the hex encoded string and parses it into a token ID.
|
|
func MakeIDFromString(newID string) (TokenID, error) {
|
|
if len(newID) != hex.EncodedLen(TokenIDSize) {
|
|
return TokenID{}, fmt.Errorf("invalid id string length of %v, "+
|
|
"want %v", len(newID), hex.EncodedLen(TokenIDSize))
|
|
}
|
|
|
|
idBytes, err := hex.DecodeString(newID)
|
|
if err != nil {
|
|
return TokenID{}, err
|
|
}
|
|
var id TokenID
|
|
copy(id[:], idBytes)
|
|
|
|
return id, nil
|
|
}
|
|
|
|
// Identifier contains the static identifying details of an LSAT. This is
|
|
// intended to be used as the identifier of the macaroon within an LSAT.
|
|
type Identifier struct {
|
|
// Version is the version of an LSAT. Having a version allows us to
|
|
// introduce new fields to the identifier in a backwards-compatible
|
|
// manner.
|
|
Version uint16
|
|
|
|
// PaymentHash is the payment hash linked to an LSAT. Verification of
|
|
// an LSAT depends on a valid payment, which is enforced by ensuring a
|
|
// preimage is provided that hashes to our payment hash.
|
|
PaymentHash lntypes.Hash
|
|
|
|
// TokenID is the unique identifier of an LSAT.
|
|
TokenID TokenID
|
|
}
|
|
|
|
// EncodeIdentifier encodes an LSAT's identifier according to its version.
|
|
func EncodeIdentifier(w io.Writer, id *Identifier) error {
|
|
if err := binary.Write(w, byteOrder, id.Version); err != nil {
|
|
return err
|
|
}
|
|
|
|
switch id.Version {
|
|
// A version 0 identifier consists of its linked payment hash, followed
|
|
// by the token ID.
|
|
case 0:
|
|
if _, err := w.Write(id.PaymentHash[:]); err != nil {
|
|
return err
|
|
}
|
|
_, err := w.Write(id.TokenID[:])
|
|
return err
|
|
|
|
default:
|
|
return fmt.Errorf("%w: %v", ErrUnknownVersion, id.Version)
|
|
}
|
|
}
|
|
|
|
// DecodeIdentifier decodes an LSAT's identifier according to its version.
|
|
func DecodeIdentifier(r io.Reader) (*Identifier, error) {
|
|
var version uint16
|
|
if err := binary.Read(r, byteOrder, &version); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
switch version {
|
|
// A version 0 identifier consists of its linked payment hash, followed
|
|
// by the token ID.
|
|
case 0:
|
|
var paymentHash lntypes.Hash
|
|
if _, err := r.Read(paymentHash[:]); err != nil {
|
|
return nil, err
|
|
}
|
|
var tokenID TokenID
|
|
if _, err := r.Read(tokenID[:]); err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
return &Identifier{
|
|
Version: version,
|
|
PaymentHash: paymentHash,
|
|
TokenID: tokenID,
|
|
}, nil
|
|
|
|
default:
|
|
return nil, fmt.Errorf("%w: %v", ErrUnknownVersion, version)
|
|
}
|
|
}
|