Merge branch 'master' into enable-encode-invoice-via-rpc
This commit is contained in:
commit
12f8cdd6d5
258 files changed
+17089
-7125
No files matched your search
@@ -129,6 +129,11 @@ description):
|
||||
* BakeMacaroon
|
||||
* Bakes a new macaroon with the provided list of permissions and
|
||||
restrictions
|
||||
* ListMacaroonIDs
|
||||
* List all the macaroon root key IDs that are in use.
|
||||
* DeleteMacaroonID
|
||||
* Remove a specific macaroon root key ID from the database and invalidates
|
||||
all macaroons derived from the key with that ID.
|
||||
|
||||
## Service: WalletUnlocker
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ import (
|
||||
"github.com/grpc-ecosystem/grpc-gateway/runtime"
|
||||
"github.com/lightningnetwork/lnd/chainntnfs"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"google.golang.org/grpc"
|
||||
"gopkg.in/macaroon-bakery.v2/bakery"
|
||||
)
|
||||
@@ -67,7 +68,7 @@ var (
|
||||
|
||||
// ErrChainNotifierServerNotActive indicates that the chain notifier hasn't
|
||||
// finished the startup process.
|
||||
ErrChainNotifierServerNotActive = errors.New("chain notifier RPC is" +
|
||||
ErrChainNotifierServerNotActive = errors.New("chain notifier RPC is " +
|
||||
"still in the process of starting")
|
||||
)
|
||||
|
||||
@@ -119,8 +120,9 @@ func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) {
|
||||
// At this point, we know that the chain notifier macaroon
|
||||
// doesn't yet, exist, so we need to create it with the help of
|
||||
// the main macaroon service.
|
||||
chainNotifierMac, err := cfg.MacService.Oven.NewMacaroon(
|
||||
context.Background(), bakery.LatestVersion, nil,
|
||||
chainNotifierMac, err := cfg.MacService.NewMacaroon(
|
||||
context.Background(),
|
||||
macaroons.DefaultRootKeyID,
|
||||
macaroonOps...,
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
+184
-102
@@ -11,6 +11,7 @@ import (
|
||||
|
||||
"github.com/btcsuite/btcd/chaincfg"
|
||||
"github.com/btcsuite/btcd/chaincfg/chainhash"
|
||||
"github.com/btcsuite/btcd/wire"
|
||||
"github.com/btcsuite/btcutil"
|
||||
"github.com/davecgh/go-spew/spew"
|
||||
|
||||
@@ -255,113 +256,16 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig,
|
||||
return nil, nil, fmt.Errorf("could not fetch all channels")
|
||||
}
|
||||
|
||||
graph := cfg.ChanDB.ChannelGraph()
|
||||
|
||||
numHints := 0
|
||||
for _, channel := range openChannels {
|
||||
if len(openChannels) > 0 {
|
||||
// We'll restrict the number of individual route hints
|
||||
// to 20 to avoid creating overly large invoices.
|
||||
if numHints >= 20 {
|
||||
break
|
||||
}
|
||||
|
||||
// Since we're only interested in our private channels,
|
||||
// we'll skip public ones.
|
||||
isPublic := channel.ChannelFlags&lnwire.FFAnnounceChannel != 0
|
||||
if isPublic {
|
||||
continue
|
||||
}
|
||||
|
||||
// Make sure the counterparty has enough balance in the
|
||||
// channel for our amount. We do this in order to reduce
|
||||
// payment errors when attempting to use this channel
|
||||
// as a hint.
|
||||
chanPoint := lnwire.NewChanIDFromOutPoint(
|
||||
&channel.FundingOutpoint,
|
||||
const numMaxHophints = 20
|
||||
hopHints := selectHopHints(
|
||||
amtMSat, cfg, openChannels, numMaxHophints,
|
||||
)
|
||||
if amtMSat >= channel.LocalCommitment.RemoteBalance {
|
||||
log.Debugf("Skipping channel %v due to "+
|
||||
"not having enough remote balance",
|
||||
chanPoint)
|
||||
continue
|
||||
}
|
||||
|
||||
// Make sure the channel is active.
|
||||
if !cfg.IsChannelActive(chanPoint) {
|
||||
log.Debugf("Skipping channel %v due to not "+
|
||||
"being eligible to forward payments",
|
||||
chanPoint)
|
||||
continue
|
||||
}
|
||||
|
||||
// To ensure we don't leak unadvertised nodes, we'll
|
||||
// make sure our counterparty is publicly advertised
|
||||
// within the network. Otherwise, we'll end up leaking
|
||||
// information about nodes that intend to stay
|
||||
// unadvertised, like in the case of a node only having
|
||||
// private channels.
|
||||
var remotePub [33]byte
|
||||
copy(remotePub[:], channel.IdentityPub.SerializeCompressed())
|
||||
isRemoteNodePublic, err := graph.IsPublicNode(remotePub)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to determine if node %x "+
|
||||
"is advertised: %v", remotePub, err)
|
||||
continue
|
||||
}
|
||||
|
||||
if !isRemoteNodePublic {
|
||||
log.Debugf("Skipping channel %v due to "+
|
||||
"counterparty %x being unadvertised",
|
||||
chanPoint, remotePub)
|
||||
continue
|
||||
}
|
||||
|
||||
// Fetch the policies for each end of the channel.
|
||||
chanID := channel.ShortChanID().ToUint64()
|
||||
info, p1, p2, err := graph.FetchChannelEdgesByID(chanID)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to fetch the routing "+
|
||||
"policies for the edges of the channel "+
|
||||
"%v: %v", chanPoint, err)
|
||||
continue
|
||||
}
|
||||
|
||||
// Now, we'll need to determine which is the correct
|
||||
// policy for HTLCs being sent from the remote node.
|
||||
var remotePolicy *channeldb.ChannelEdgePolicy
|
||||
if bytes.Equal(remotePub[:], info.NodeKey1Bytes[:]) {
|
||||
remotePolicy = p1
|
||||
} else {
|
||||
remotePolicy = p2
|
||||
}
|
||||
|
||||
// If for some reason we don't yet have the edge for
|
||||
// the remote party, then we'll just skip adding this
|
||||
// channel as a routing hint.
|
||||
if remotePolicy == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Finally, create the routing hint for this channel and
|
||||
// add it to our list of route hints.
|
||||
hint := zpay32.HopHint{
|
||||
NodeID: channel.IdentityPub,
|
||||
ChannelID: chanID,
|
||||
FeeBaseMSat: uint32(remotePolicy.FeeBaseMSat),
|
||||
FeeProportionalMillionths: uint32(
|
||||
remotePolicy.FeeProportionalMillionths,
|
||||
),
|
||||
CLTVExpiryDelta: remotePolicy.TimeLockDelta,
|
||||
}
|
||||
|
||||
// Include the route hint in our set of options that
|
||||
// will be used when creating the invoice.
|
||||
routeHint := []zpay32.HopHint{hint}
|
||||
options = append(options, zpay32.RouteHint(routeHint))
|
||||
|
||||
numHints++
|
||||
options = append(options, hopHints...)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Set our desired invoice features and add them to our list of options.
|
||||
@@ -427,3 +331,181 @@ func AddInvoice(ctx context.Context, cfg *AddInvoiceConfig,
|
||||
|
||||
return &paymentHash, newInvoice, nil
|
||||
}
|
||||
|
||||
// chanCanBeHopHint returns true if the target channel is eligible to be a hop
|
||||
// hint.
|
||||
func chanCanBeHopHint(channel *channeldb.OpenChannel,
|
||||
graph *channeldb.ChannelGraph,
|
||||
cfg *AddInvoiceConfig) (*channeldb.ChannelEdgePolicy, bool) {
|
||||
|
||||
// Since we're only interested in our private channels, we'll skip
|
||||
// public ones.
|
||||
isPublic := channel.ChannelFlags&lnwire.FFAnnounceChannel != 0
|
||||
if isPublic {
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Make sure the channel is active.
|
||||
chanPoint := lnwire.NewChanIDFromOutPoint(
|
||||
&channel.FundingOutpoint,
|
||||
)
|
||||
if !cfg.IsChannelActive(chanPoint) {
|
||||
log.Debugf("Skipping channel %v due to not "+
|
||||
"being eligible to forward payments",
|
||||
chanPoint)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// To ensure we don't leak unadvertised nodes, we'll make sure our
|
||||
// counterparty is publicly advertised within the network. Otherwise,
|
||||
// we'll end up leaking information about nodes that intend to stay
|
||||
// unadvertised, like in the case of a node only having private
|
||||
// channels.
|
||||
var remotePub [33]byte
|
||||
copy(remotePub[:], channel.IdentityPub.SerializeCompressed())
|
||||
isRemoteNodePublic, err := graph.IsPublicNode(remotePub)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to determine if node %x "+
|
||||
"is advertised: %v", remotePub, err)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
if !isRemoteNodePublic {
|
||||
log.Debugf("Skipping channel %v due to "+
|
||||
"counterparty %x being unadvertised",
|
||||
chanPoint, remotePub)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Fetch the policies for each end of the channel.
|
||||
chanID := channel.ShortChanID().ToUint64()
|
||||
info, p1, p2, err := graph.FetchChannelEdgesByID(chanID)
|
||||
if err != nil {
|
||||
log.Errorf("Unable to fetch the routing "+
|
||||
"policies for the edges of the channel "+
|
||||
"%v: %v", chanPoint, err)
|
||||
return nil, false
|
||||
}
|
||||
|
||||
// Now, we'll need to determine which is the correct policy for HTLCs
|
||||
// being sent from the remote node.
|
||||
var remotePolicy *channeldb.ChannelEdgePolicy
|
||||
if bytes.Equal(remotePub[:], info.NodeKey1Bytes[:]) {
|
||||
remotePolicy = p1
|
||||
} else {
|
||||
remotePolicy = p2
|
||||
}
|
||||
|
||||
return remotePolicy, true
|
||||
}
|
||||
|
||||
// addHopHint creates a hop hint out of the passed channel and channel policy.
|
||||
// The new hop hint is appended to the passed slice.
|
||||
func addHopHint(hopHints *[]func(*zpay32.Invoice),
|
||||
channel *channeldb.OpenChannel, chanPolicy *channeldb.ChannelEdgePolicy) {
|
||||
|
||||
hopHint := zpay32.HopHint{
|
||||
NodeID: channel.IdentityPub,
|
||||
ChannelID: channel.ShortChanID().ToUint64(),
|
||||
FeeBaseMSat: uint32(chanPolicy.FeeBaseMSat),
|
||||
FeeProportionalMillionths: uint32(
|
||||
chanPolicy.FeeProportionalMillionths,
|
||||
),
|
||||
CLTVExpiryDelta: chanPolicy.TimeLockDelta,
|
||||
}
|
||||
*hopHints = append(
|
||||
*hopHints, zpay32.RouteHint([]zpay32.HopHint{hopHint}),
|
||||
)
|
||||
}
|
||||
|
||||
// selectHopHints will select up to numMaxHophints from the set of passed open
|
||||
// channels. The set of hop hints will be returned as a slice of functional
|
||||
// options that'll append the route hint to the set of all route hints.
|
||||
//
|
||||
// TODO(roasbeef): do proper sub-set sum max hints usually << numChans
|
||||
func selectHopHints(amtMSat lnwire.MilliSatoshi, cfg *AddInvoiceConfig,
|
||||
openChannels []*channeldb.OpenChannel,
|
||||
numMaxHophints int) []func(*zpay32.Invoice) {
|
||||
|
||||
graph := cfg.ChanDB.ChannelGraph()
|
||||
|
||||
// We'll add our hop hints in two passes, first we'll add all channels
|
||||
// that are eligible to be hop hints, and also have a local balance
|
||||
// above the payment amount.
|
||||
var totalHintBandwidth lnwire.MilliSatoshi
|
||||
hopHintChans := make(map[wire.OutPoint]struct{})
|
||||
hopHints := make([]func(*zpay32.Invoice), 0, numMaxHophints)
|
||||
for _, channel := range openChannels {
|
||||
// If this channel can't be a hop hint, then skip it.
|
||||
edgePolicy, canBeHopHint := chanCanBeHopHint(
|
||||
channel, graph, cfg,
|
||||
)
|
||||
if edgePolicy == nil || !canBeHopHint {
|
||||
continue
|
||||
}
|
||||
|
||||
// Similarly, in this first pass, we'll ignore all channels in
|
||||
// isolation can't satisfy this payment.
|
||||
if channel.LocalCommitment.RemoteBalance < amtMSat {
|
||||
continue
|
||||
}
|
||||
|
||||
// Now that we now this channel use usable, add it as a hop
|
||||
// hint and the indexes we'll use later.
|
||||
addHopHint(&hopHints, channel, edgePolicy)
|
||||
|
||||
hopHintChans[channel.FundingOutpoint] = struct{}{}
|
||||
totalHintBandwidth += channel.LocalCommitment.RemoteBalance
|
||||
}
|
||||
|
||||
// If we have enough hop hints at this point, then we'll exit early.
|
||||
// Otherwise, we'll continue to add more that may help out mpp users.
|
||||
if len(hopHints) >= numMaxHophints {
|
||||
return hopHints
|
||||
}
|
||||
|
||||
// In this second pass we'll add channels, and we'll either stop when
|
||||
// we have 20 hop hints, we've run through all the available channels,
|
||||
// or if the sum of available bandwidth in the routing hints exceeds 2x
|
||||
// the payment amount. We do 2x here to account for a margin of error
|
||||
// if some of the selected channels no longer become operable.
|
||||
hopHintFactor := lnwire.MilliSatoshi(2)
|
||||
for i := 0; i < len(openChannels); i++ {
|
||||
// If we hit either of our early termination conditions, then
|
||||
// we'll break the loop here.
|
||||
if totalHintBandwidth > amtMSat*hopHintFactor ||
|
||||
len(hopHints) >= numMaxHophints {
|
||||
|
||||
break
|
||||
}
|
||||
|
||||
channel := openChannels[i]
|
||||
|
||||
// Skip the channel if we already selected it.
|
||||
if _, ok := hopHintChans[channel.FundingOutpoint]; ok {
|
||||
continue
|
||||
}
|
||||
|
||||
// If the channel can't be a hop hint, then we'll skip it.
|
||||
// Otherwise, we'll use the policy information to populate the
|
||||
// hop hint.
|
||||
remotePolicy, canBeHopHint := chanCanBeHopHint(
|
||||
channel, graph, cfg,
|
||||
)
|
||||
if !canBeHopHint || remotePolicy == nil {
|
||||
continue
|
||||
}
|
||||
|
||||
// Include the route hint in our set of options that will be
|
||||
// used when creating the invoice.
|
||||
addHopHint(&hopHints, channel, remotePolicy)
|
||||
|
||||
// As we've just added a new hop hint, we'll accumulate it's
|
||||
// available balance now to update our tally.
|
||||
//
|
||||
// TODO(roasbeef): have a cut off based on min bandwidth?
|
||||
totalHintBandwidth += channel.LocalCommitment.RemoteBalance
|
||||
}
|
||||
|
||||
return hopHints
|
||||
}
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/channeldb"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -99,8 +100,8 @@ func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) {
|
||||
// At this point, we know that the invoices macaroon doesn't
|
||||
// yet, exist, so we need to create it with the help of the
|
||||
// main macaroon service.
|
||||
invoicesMac, err := cfg.MacService.Oven.NewMacaroon(
|
||||
context.Background(), bakery.LatestVersion, nil,
|
||||
invoicesMac, err := cfg.MacService.NewMacaroon(
|
||||
context.Background(), macaroons.DefaultRootKeyID,
|
||||
macaroonOps...,
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -133,6 +133,12 @@ http:
|
||||
- selector: lnrpc.Lightning.BakeMacaroon
|
||||
post: "/v1/macaroon"
|
||||
body: "*"
|
||||
- selector: lnrpc.Lightning.ListMacaroonIDs
|
||||
get: "/v1/macaroon/ids"
|
||||
- selector: lnrpc.Lightning.DeleteMacaroonID
|
||||
delete: "/v1/macaroon/{root_key_id}"
|
||||
- selector: lnrpc.Lightning.ListPermissions
|
||||
get: "/v1/macaroon/permissions"
|
||||
|
||||
# walletunlocker.proto
|
||||
- selector: lnrpc.WalletUnlocker.GenSeed
|
||||
|
||||
@@ -46,9 +46,9 @@ func DefaultConfig() *Config {
|
||||
AprioriWeight: routing.DefaultAprioriWeight,
|
||||
MinRouteProbability: routing.DefaultMinRouteProbability,
|
||||
PenaltyHalfLife: routing.DefaultPenaltyHalfLife,
|
||||
AttemptCost: routing.DefaultPaymentAttemptPenalty.
|
||||
ToSatoshis(),
|
||||
MaxMcHistory: routing.DefaultMaxMcHistory,
|
||||
AttemptCost: routing.DefaultAttemptCost.ToSatoshis(),
|
||||
AttemptCostPPM: routing.DefaultAttemptCostPPM,
|
||||
MaxMcHistory: routing.DefaultMaxMcHistory,
|
||||
}
|
||||
|
||||
return &Config{
|
||||
@@ -63,6 +63,7 @@ func GetRoutingConfig(cfg *Config) *RoutingConfig {
|
||||
AprioriWeight: cfg.AprioriWeight,
|
||||
MinRouteProbability: cfg.MinRouteProbability,
|
||||
AttemptCost: cfg.AttemptCost,
|
||||
AttemptCostPPM: cfg.AttemptCostPPM,
|
||||
PenaltyHalfLife: cfg.PenaltyHalfLife,
|
||||
MaxMcHistory: cfg.MaxMcHistory,
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lntypes"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"github.com/lightningnetwork/lnd/routing"
|
||||
"github.com/lightningnetwork/lnd/routing/route"
|
||||
|
||||
@@ -164,8 +165,8 @@ func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) {
|
||||
// At this point, we know that the router macaroon doesn't yet,
|
||||
// exist, so we need to create it with the help of the main
|
||||
// macaroon service.
|
||||
routerMac, err := cfg.MacService.Oven.NewMacaroon(
|
||||
context.Background(), bakery.LatestVersion, nil,
|
||||
routerMac, err := cfg.MacService.NewMacaroon(
|
||||
context.Background(), macaroons.DefaultRootKeyID,
|
||||
macaroonOps...,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -319,11 +320,13 @@ func (s *Server) EstimateRouteFee(ctx context.Context,
|
||||
// that target amount, we'll only request a single route. Set a
|
||||
// restriction for the default CLTV limit, otherwise we can find a route
|
||||
// that exceeds it and is useless to us.
|
||||
mc := s.cfg.RouterBackend.MissionControl
|
||||
route, err := s.cfg.Router.FindRoute(
|
||||
s.cfg.RouterBackend.SelfNode, destNode, amtMsat,
|
||||
&routing.RestrictParams{
|
||||
FeeLimit: feeLimit,
|
||||
CltvLimit: s.cfg.RouterBackend.MaxTotalTimelock,
|
||||
FeeLimit: feeLimit,
|
||||
CltvLimit: s.cfg.RouterBackend.MaxTotalTimelock,
|
||||
ProbabilitySource: mc.GetProbability,
|
||||
}, nil, nil, s.cfg.RouterBackend.DefaultFinalCltvDelta,
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -29,10 +29,16 @@ type RoutingConfig struct {
|
||||
// channel is back at 50% probability.
|
||||
PenaltyHalfLife time.Duration `long:"penaltyhalflife" description:"Defines the duration after which a penalized node or channel is back at 50% probability"`
|
||||
|
||||
// AttemptCost is the virtual cost in path finding weight units of
|
||||
// executing a payment attempt that fails. It is used to trade off
|
||||
// potentially better routes against their probability of succeeding.
|
||||
AttemptCost btcutil.Amount `long:"attemptcost" description:"The (virtual) cost in sats of a failed payment attempt"`
|
||||
// AttemptCost is the fixed virtual cost in path finding of a failed
|
||||
// payment attempt. It is used to trade off potentially better routes
|
||||
// against their probability of succeeding.
|
||||
AttemptCost btcutil.Amount `long:"attemptcost" description:"The fixed (virtual) cost in sats of a failed payment attempt"`
|
||||
|
||||
// AttemptCostPPM is the proportional virtual cost in path finding of a
|
||||
// failed payment attempt. It is used to trade off potentially better
|
||||
// routes against their probability of succeeding. This parameter is
|
||||
// expressed in parts per million of the total payment amount.
|
||||
AttemptCostPPM int64 `long:"attemptcostppm" description:"The proportional (virtual) cost in sats of a failed payment attempt expressed in parts per million of the total payment amount"`
|
||||
|
||||
// MaxMcHistory defines the maximum number of payment results that
|
||||
// are held on disk by mission control.
|
||||
|
||||
+1357
-755
File diff suppressed because it is too large.
Load diff
@@ -1913,6 +1913,96 @@ func local_request_Lightning_BakeMacaroon_0(ctx context.Context, marshaler runti
|
||||
|
||||
}
|
||||
|
||||
func request_Lightning_ListMacaroonIDs_0(ctx context.Context, marshaler runtime.Marshaler, client LightningClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ListMacaroonIDsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.ListMacaroonIDs(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Lightning_ListMacaroonIDs_0(ctx context.Context, marshaler runtime.Marshaler, server LightningServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ListMacaroonIDsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.ListMacaroonIDs(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Lightning_DeleteMacaroonID_0(ctx context.Context, marshaler runtime.Marshaler, client LightningClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq DeleteMacaroonIDRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["root_key_id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "root_key_id")
|
||||
}
|
||||
|
||||
protoReq.RootKeyId, err = runtime.Uint64(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "root_key_id", err)
|
||||
}
|
||||
|
||||
msg, err := client.DeleteMacaroonID(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Lightning_DeleteMacaroonID_0(ctx context.Context, marshaler runtime.Marshaler, server LightningServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq DeleteMacaroonIDRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
var (
|
||||
val string
|
||||
ok bool
|
||||
err error
|
||||
_ = err
|
||||
)
|
||||
|
||||
val, ok = pathParams["root_key_id"]
|
||||
if !ok {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "missing parameter %s", "root_key_id")
|
||||
}
|
||||
|
||||
protoReq.RootKeyId, err = runtime.Uint64(val)
|
||||
|
||||
if err != nil {
|
||||
return nil, metadata, status.Errorf(codes.InvalidArgument, "type mismatch, parameter: %s, error: %v", "root_key_id", err)
|
||||
}
|
||||
|
||||
msg, err := server.DeleteMacaroonID(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func request_Lightning_ListPermissions_0(ctx context.Context, marshaler runtime.Marshaler, client LightningClient, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ListPermissionsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := client.ListPermissions(ctx, &protoReq, grpc.Header(&metadata.HeaderMD), grpc.Trailer(&metadata.TrailerMD))
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
func local_request_Lightning_ListPermissions_0(ctx context.Context, marshaler runtime.Marshaler, server LightningServer, req *http.Request, pathParams map[string]string) (proto.Message, runtime.ServerMetadata, error) {
|
||||
var protoReq ListPermissionsRequest
|
||||
var metadata runtime.ServerMetadata
|
||||
|
||||
msg, err := server.ListPermissions(ctx, &protoReq)
|
||||
return msg, metadata, err
|
||||
|
||||
}
|
||||
|
||||
// RegisterLightningHandlerServer registers the http handlers for service Lightning to "mux".
|
||||
// UnaryRPC :call LightningServer directly.
|
||||
// StreamingRPC :currently unsupported pending https://github.com/grpc/grpc-go/issues/906.
|
||||
@@ -2874,6 +2964,66 @@ func RegisterLightningHandlerServer(ctx context.Context, mux *runtime.ServeMux,
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Lightning_ListMacaroonIDs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Lightning_ListMacaroonIDs_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Lightning_ListMacaroonIDs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("DELETE", pattern_Lightning_DeleteMacaroonID_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Lightning_DeleteMacaroonID_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Lightning_DeleteMacaroonID_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Lightning_ListPermissions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateIncomingContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := local_request_Lightning_ListPermissions_0(rctx, inboundMarshaler, server, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Lightning_ListPermissions_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -3975,6 +4125,66 @@ func RegisterLightningHandlerClient(ctx context.Context, mux *runtime.ServeMux,
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Lightning_ListMacaroonIDs_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Lightning_ListMacaroonIDs_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Lightning_ListMacaroonIDs_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("DELETE", pattern_Lightning_DeleteMacaroonID_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Lightning_DeleteMacaroonID_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Lightning_DeleteMacaroonID_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
mux.Handle("GET", pattern_Lightning_ListPermissions_0, func(w http.ResponseWriter, req *http.Request, pathParams map[string]string) {
|
||||
ctx, cancel := context.WithCancel(req.Context())
|
||||
defer cancel()
|
||||
inboundMarshaler, outboundMarshaler := runtime.MarshalerForRequest(mux, req)
|
||||
rctx, err := runtime.AnnotateContext(ctx, mux, req)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
resp, md, err := request_Lightning_ListPermissions_0(rctx, inboundMarshaler, client, req, pathParams)
|
||||
ctx = runtime.NewServerMetadataContext(ctx, md)
|
||||
if err != nil {
|
||||
runtime.HTTPError(ctx, mux, outboundMarshaler, w, req, err)
|
||||
return
|
||||
}
|
||||
|
||||
forward_Lightning_ListPermissions_0(ctx, mux, outboundMarshaler, w, req, resp, mux.GetForwardResponseOptions()...)
|
||||
|
||||
})
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
@@ -4084,6 +4294,12 @@ var (
|
||||
pattern_Lightning_SubscribeChannelBackups_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2, 2, 3}, []string{"v1", "channels", "backup", "subscribe"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Lightning_BakeMacaroon_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1}, []string{"v1", "macaroon"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Lightning_ListMacaroonIDs_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "macaroon", "ids"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Lightning_DeleteMacaroonID_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 1, 0, 4, 1, 5, 2}, []string{"v1", "macaroon", "root_key_id"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
|
||||
pattern_Lightning_ListPermissions_0 = runtime.MustPattern(runtime.NewPattern(1, []int{2, 0, 2, 1, 2, 2}, []string{"v1", "macaroon", "permissions"}, "", runtime.AssumeColonVerbOpt(true)))
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -4192,4 +4408,10 @@ var (
|
||||
forward_Lightning_SubscribeChannelBackups_0 = runtime.ForwardResponseStream
|
||||
|
||||
forward_Lightning_BakeMacaroon_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Lightning_ListMacaroonIDs_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Lightning_DeleteMacaroonID_0 = runtime.ForwardResponseMessage
|
||||
|
||||
forward_Lightning_ListPermissions_0 = runtime.ForwardResponseMessage
|
||||
)
|
||||
+105
-3
@@ -235,8 +235,10 @@ service Lightning {
|
||||
/* lncli: `abandonchannel`
|
||||
AbandonChannel removes all channel state from the database except for a
|
||||
close summary. This method can be used to get rid of permanently unusable
|
||||
channels due to bugs fixed in newer versions of lnd. Only available
|
||||
when in debug builds of lnd.
|
||||
channels due to bugs fixed in newer versions of lnd. This method can also be
|
||||
used to remove externally funded channels where the funding transaction was
|
||||
never broadcast. Only available for non-externally funded channels in dev
|
||||
build.
|
||||
*/
|
||||
rpc AbandonChannel (AbandonChannelRequest) returns (AbandonChannelResponse);
|
||||
|
||||
@@ -491,6 +493,26 @@ service Lightning {
|
||||
offline.
|
||||
*/
|
||||
rpc BakeMacaroon (BakeMacaroonRequest) returns (BakeMacaroonResponse);
|
||||
|
||||
/* lncli: `listmacaroonids`
|
||||
ListMacaroonIDs returns all root key IDs that are in use.
|
||||
*/
|
||||
rpc ListMacaroonIDs (ListMacaroonIDsRequest)
|
||||
returns (ListMacaroonIDsResponse);
|
||||
|
||||
/* lncli: `deletemacaroonid`
|
||||
DeleteMacaroonID deletes the specified macaroon ID and invalidates all
|
||||
macaroons derived from that ID.
|
||||
*/
|
||||
rpc DeleteMacaroonID (DeleteMacaroonIDRequest)
|
||||
returns (DeleteMacaroonIDResponse);
|
||||
|
||||
/* lncli: `listpermissions`
|
||||
ListPermissions lists all RPC method URIs and their required macaroon
|
||||
permissions to access them.
|
||||
*/
|
||||
rpc ListPermissions (ListPermissionsRequest)
|
||||
returns (ListPermissionsResponse);
|
||||
}
|
||||
|
||||
message Utxo {
|
||||
@@ -947,6 +969,12 @@ message ConnectPeerRequest {
|
||||
/* If set, the daemon will attempt to persistently connect to the target
|
||||
* peer. Otherwise, the call will be synchronous. */
|
||||
bool perm = 2;
|
||||
|
||||
/*
|
||||
The connection timeout value (in seconds) for this request. It won't affect
|
||||
other requests.
|
||||
*/
|
||||
uint64 timeout = 3;
|
||||
}
|
||||
message ConnectPeerResponse {
|
||||
}
|
||||
@@ -1393,6 +1421,20 @@ message Peer {
|
||||
spamming us with errors at no cost.
|
||||
*/
|
||||
repeated TimestampedError errors = 12;
|
||||
|
||||
/*
|
||||
The number of times we have recorded this peer going offline or coming
|
||||
online, recorded across restarts. Note that this value is decreased over
|
||||
time if the peer has not recently flapped, so that we can forgive peers
|
||||
with historically high flap counts.
|
||||
*/
|
||||
int32 flap_count = 13;
|
||||
|
||||
/*
|
||||
The timestamp of the last flap we observed for this peer. If this value is
|
||||
zero, we have not observed any flaps for this peer.
|
||||
*/
|
||||
int64 last_flap_ns = 14;
|
||||
}
|
||||
|
||||
message TimestampedError {
|
||||
@@ -1672,6 +1714,12 @@ message OpenChannelRequest {
|
||||
the channel. It only applies to the remote party.
|
||||
*/
|
||||
uint64 remote_max_value_in_flight_msat = 15;
|
||||
|
||||
/*
|
||||
The maximum number of concurrent HTLCs we will allow the remote party to add
|
||||
to the commitment transaction.
|
||||
*/
|
||||
uint32 remote_max_htlcs = 16;
|
||||
}
|
||||
message OpenStatusUpdate {
|
||||
oneof update {
|
||||
@@ -1817,12 +1865,19 @@ message FundingPsbtFinalize {
|
||||
/*
|
||||
The funded PSBT that contains all witness data to send the exact channel
|
||||
capacity amount to the PK script returned in the open channel message in a
|
||||
previous step.
|
||||
previous step. Cannot be set at the same time as final_raw_tx.
|
||||
*/
|
||||
bytes signed_psbt = 1;
|
||||
|
||||
// The pending channel ID of the channel to get the PSBT for.
|
||||
bytes pending_chan_id = 2;
|
||||
|
||||
/*
|
||||
As an alternative to the signed PSBT with all witness data, the final raw
|
||||
wire format transaction can also be specified directly. Cannot be set at the
|
||||
same time as signed_psbt.
|
||||
*/
|
||||
bytes final_raw_tx = 3;
|
||||
}
|
||||
|
||||
message FundingTransitionMsg {
|
||||
@@ -3039,6 +3094,8 @@ message DeleteAllPaymentsResponse {
|
||||
|
||||
message AbandonChannelRequest {
|
||||
ChannelPoint channel_point = 1;
|
||||
|
||||
bool pending_funding_shim_only = 2;
|
||||
}
|
||||
|
||||
message AbandonChannelResponse {
|
||||
@@ -3327,12 +3384,46 @@ message MacaroonPermission {
|
||||
message BakeMacaroonRequest {
|
||||
// The list of permissions the new macaroon should grant.
|
||||
repeated MacaroonPermission permissions = 1;
|
||||
|
||||
// The root key ID used to create the macaroon, must be a positive integer.
|
||||
uint64 root_key_id = 2;
|
||||
}
|
||||
message BakeMacaroonResponse {
|
||||
// The hex encoded macaroon, serialized in binary format.
|
||||
string macaroon = 1;
|
||||
}
|
||||
|
||||
message ListMacaroonIDsRequest {
|
||||
}
|
||||
message ListMacaroonIDsResponse {
|
||||
// The list of root key IDs that are in use.
|
||||
repeated uint64 root_key_ids = 1;
|
||||
}
|
||||
|
||||
message DeleteMacaroonIDRequest {
|
||||
// The root key ID to be removed.
|
||||
uint64 root_key_id = 1;
|
||||
}
|
||||
message DeleteMacaroonIDResponse {
|
||||
// A boolean indicates that the deletion is successful.
|
||||
bool deleted = 1;
|
||||
}
|
||||
|
||||
message MacaroonPermissionList {
|
||||
// A list of macaroon permissions.
|
||||
repeated MacaroonPermission permissions = 1;
|
||||
}
|
||||
|
||||
message ListPermissionsRequest {
|
||||
}
|
||||
message ListPermissionsResponse {
|
||||
/*
|
||||
A map between all RPC method URIs and their required macaroon permissions to
|
||||
access them.
|
||||
*/
|
||||
map<string, MacaroonPermissionList> method_permissions = 1;
|
||||
}
|
||||
|
||||
message Failure {
|
||||
enum FailureCode {
|
||||
/*
|
||||
@@ -3495,3 +3586,14 @@ message ChannelUpdate {
|
||||
*/
|
||||
bytes extra_opaque_data = 12;
|
||||
}
|
||||
|
||||
message MacaroonId {
|
||||
bytes nonce = 1;
|
||||
bytes storageId = 2;
|
||||
repeated Op ops = 3;
|
||||
}
|
||||
|
||||
message Op {
|
||||
string entity = 1;
|
||||
repeated string actions = 2;
|
||||
}
|
||||
+165
-2
@@ -151,7 +151,7 @@
|
||||
},
|
||||
"/v1/channels/abandon/{channel_point.funding_txid_str}/{channel_point.output_index}": {
|
||||
"delete": {
|
||||
"summary": "lncli: `abandonchannel`\nAbandonChannel removes all channel state from the database except for a\nclose summary. This method can be used to get rid of permanently unusable\nchannels due to bugs fixed in newer versions of lnd. Only available\nwhen in debug builds of lnd.",
|
||||
"summary": "lncli: `abandonchannel`\nAbandonChannel removes all channel state from the database except for a\nclose summary. This method can be used to get rid of permanently unusable\nchannels due to bugs fixed in newer versions of lnd. This method can also be\nused to remove externally funded channels where the funding transaction was\nnever broadcast. Only available for non-externally funded channels in dev\nbuild.",
|
||||
"operationId": "AbandonChannel",
|
||||
"responses": {
|
||||
"200": {
|
||||
@@ -190,6 +190,13 @@
|
||||
"required": false,
|
||||
"type": "string",
|
||||
"format": "byte"
|
||||
},
|
||||
{
|
||||
"name": "pending_funding_shim_only",
|
||||
"in": "query",
|
||||
"required": false,
|
||||
"type": "boolean",
|
||||
"format": "boolean"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
@@ -1426,6 +1433,85 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/macaroon/ids": {
|
||||
"get": {
|
||||
"summary": "lncli: `listmacaroonids`\nListMacaroonIDs returns all root key IDs that are in use.",
|
||||
"operationId": "ListMacaroonIDs",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/lnrpcListMacaroonIDsResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Lightning"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/macaroon/permissions": {
|
||||
"get": {
|
||||
"summary": "lncli: `listpermissions`\nListPermissions lists all RPC method URIs and their required macaroon\npermissions to access them.",
|
||||
"operationId": "ListPermissions",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/lnrpcListPermissionsResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
}
|
||||
}
|
||||
},
|
||||
"tags": [
|
||||
"Lightning"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/macaroon/{root_key_id}": {
|
||||
"delete": {
|
||||
"summary": "lncli: `deletemacaroonid`\nDeleteMacaroonID deletes the specified macaroon ID and invalidates all\nmacaroons derived from that ID.",
|
||||
"operationId": "DeleteMacaroonID",
|
||||
"responses": {
|
||||
"200": {
|
||||
"description": "A successful response.",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/lnrpcDeleteMacaroonIDResponse"
|
||||
}
|
||||
},
|
||||
"default": {
|
||||
"description": "An unexpected error response",
|
||||
"schema": {
|
||||
"$ref": "#/definitions/runtimeError"
|
||||
}
|
||||
}
|
||||
},
|
||||
"parameters": [
|
||||
{
|
||||
"name": "root_key_id",
|
||||
"description": "The root key ID to be removed.",
|
||||
"in": "path",
|
||||
"required": true,
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
}
|
||||
],
|
||||
"tags": [
|
||||
"Lightning"
|
||||
]
|
||||
}
|
||||
},
|
||||
"/v1/newaddress": {
|
||||
"get": {
|
||||
"summary": "lncli: `newaddress`\nNewAddress creates a new address under control of the local wallet.",
|
||||
@@ -2399,6 +2485,11 @@
|
||||
"$ref": "#/definitions/lnrpcMacaroonPermission"
|
||||
},
|
||||
"description": "The list of permissions the new macaroon should grant."
|
||||
},
|
||||
"root_key_id": {
|
||||
"type": "string",
|
||||
"format": "uint64",
|
||||
"description": "The root key ID used to create the macaroon, must be a positive integer."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3132,6 +3223,11 @@
|
||||
"type": "boolean",
|
||||
"format": "boolean",
|
||||
"description": "If set, the daemon will attempt to persistently connect to the target\npeer. Otherwise, the call will be synchronous."
|
||||
},
|
||||
"timeout": {
|
||||
"type": "string",
|
||||
"format": "uint64",
|
||||
"description": "The connection timeout value (in seconds) for this request. It won't affect\nother requests."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -3161,6 +3257,16 @@
|
||||
"lnrpcDeleteAllPaymentsResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
"lnrpcDeleteMacaroonIDResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"deleted": {
|
||||
"type": "boolean",
|
||||
"format": "boolean",
|
||||
"description": "A boolean indicates that the deletion is successful."
|
||||
}
|
||||
}
|
||||
},
|
||||
"lnrpcDisconnectPeerResponse": {
|
||||
"type": "object"
|
||||
},
|
||||
@@ -3436,12 +3542,17 @@
|
||||
"signed_psbt": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"description": "The funded PSBT that contains all witness data to send the exact channel\ncapacity amount to the PK script returned in the open channel message in a\nprevious step."
|
||||
"description": "The funded PSBT that contains all witness data to send the exact channel\ncapacity amount to the PK script returned in the open channel message in a\nprevious step. Cannot be set at the same time as final_raw_tx."
|
||||
},
|
||||
"pending_chan_id": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"description": "The pending channel ID of the channel to get the PSBT for."
|
||||
},
|
||||
"final_raw_tx": {
|
||||
"type": "string",
|
||||
"format": "byte",
|
||||
"description": "As an alternative to the signed PSBT with all witness data, the final raw\nwire format transaction can also be specified directly. Cannot be set at the\nsame time as signed_psbt."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4095,6 +4206,19 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"lnrpcListMacaroonIDsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"root_key_ids": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"type": "string",
|
||||
"format": "uint64"
|
||||
},
|
||||
"description": "The list of root key IDs that are in use."
|
||||
}
|
||||
}
|
||||
},
|
||||
"lnrpcListPaymentsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -4129,6 +4253,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"lnrpcListPermissionsResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"method_permissions": {
|
||||
"type": "object",
|
||||
"additionalProperties": {
|
||||
"$ref": "#/definitions/lnrpcMacaroonPermissionList"
|
||||
},
|
||||
"description": "A map between all RPC method URIs and their required macaroon permissions to\naccess them."
|
||||
}
|
||||
}
|
||||
},
|
||||
"lnrpcListUnspentResponse": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -4169,6 +4305,18 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"lnrpcMacaroonPermissionList": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
"permissions": {
|
||||
"type": "array",
|
||||
"items": {
|
||||
"$ref": "#/definitions/lnrpcMacaroonPermission"
|
||||
},
|
||||
"description": "A list of macaroon permissions."
|
||||
}
|
||||
}
|
||||
},
|
||||
"lnrpcMultiChanBackup": {
|
||||
"type": "object",
|
||||
"properties": {
|
||||
@@ -4410,6 +4558,11 @@
|
||||
"type": "string",
|
||||
"format": "uint64",
|
||||
"description": "The maximum amount of coins in millisatoshi that can be pending within\nthe channel. It only applies to the remote party."
|
||||
},
|
||||
"remote_max_htlcs": {
|
||||
"type": "integer",
|
||||
"format": "int64",
|
||||
"description": "The maximum number of concurrent HTLCs we will allow the remote party to add\nto the commitment transaction."
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -4657,6 +4810,16 @@
|
||||
"$ref": "#/definitions/lnrpcTimestampedError"
|
||||
},
|
||||
"description": "The latest errors received from our peer with timestamps, limited to the 10\nmost recent errors. These errors are tracked across peer connections, but\nare not persisted across lnd restarts. Note that these errors are only\nstored for peers that we have channels open with, to prevent peers from\nspamming us with errors at no cost."
|
||||
},
|
||||
"flap_count": {
|
||||
"type": "integer",
|
||||
"format": "int32",
|
||||
"description": "The number of times we have recorded this peer going offline or coming\nonline, recorded across restarts. Note that this value is decreased over\ntime if the peer has not recently flapped, so that we can forgive peers\nwith historically high flap counts."
|
||||
},
|
||||
"last_flap_ns": {
|
||||
"type": "string",
|
||||
"format": "int64",
|
||||
"description": "The timestamp of the last flap we observed for this peer. If this value is\nzero, we have not observed any flaps for this peer."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
+76
-59
@@ -673,12 +673,18 @@ type SharedKeyRequest struct {
|
||||
// The ephemeral public key to use for the DH key derivation.
|
||||
EphemeralPubkey []byte `protobuf:"bytes,1,opt,name=ephemeral_pubkey,json=ephemeralPubkey,proto3" json:"ephemeral_pubkey,omitempty"`
|
||||
//
|
||||
//The optional key locator of the local key that should be used. If this
|
||||
//parameter is not set then the node's identity private key will be used.
|
||||
KeyLoc *KeyLocator `protobuf:"bytes,2,opt,name=key_loc,json=keyLoc,proto3" json:"key_loc,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
//Deprecated. The optional key locator of the local key that should be used.
|
||||
//If this parameter is not set then the node's identity private key will be
|
||||
//used.
|
||||
KeyLoc *KeyLocator `protobuf:"bytes,2,opt,name=key_loc,json=keyLoc,proto3" json:"key_loc,omitempty"` // Deprecated: Do not use.
|
||||
//
|
||||
//A key descriptor describes the key used for performing ECDH. Either a key
|
||||
//locator or a raw public key is expected, if neither is supplied, defaults to
|
||||
//the node's identity private key.
|
||||
KeyDesc *KeyDescriptor `protobuf:"bytes,3,opt,name=key_desc,json=keyDesc,proto3" json:"key_desc,omitempty"`
|
||||
XXX_NoUnkeyedLiteral struct{} `json:"-"`
|
||||
XXX_unrecognized []byte `json:"-"`
|
||||
XXX_sizecache int32 `json:"-"`
|
||||
}
|
||||
|
||||
func (m *SharedKeyRequest) Reset() { *m = SharedKeyRequest{} }
|
||||
@@ -713,6 +719,7 @@ func (m *SharedKeyRequest) GetEphemeralPubkey() []byte {
|
||||
return nil
|
||||
}
|
||||
|
||||
// Deprecated: Do not use.
|
||||
func (m *SharedKeyRequest) GetKeyLoc() *KeyLocator {
|
||||
if m != nil {
|
||||
return m.KeyLoc
|
||||
@@ -720,6 +727,13 @@ func (m *SharedKeyRequest) GetKeyLoc() *KeyLocator {
|
||||
return nil
|
||||
}
|
||||
|
||||
func (m *SharedKeyRequest) GetKeyDesc() *KeyDescriptor {
|
||||
if m != nil {
|
||||
return m.KeyDesc
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
type SharedKeyResponse struct {
|
||||
// The shared public key, hashed with sha256.
|
||||
SharedKey []byte `protobuf:"bytes,1,opt,name=shared_key,json=sharedKey,proto3" json:"shared_key,omitempty"`
|
||||
@@ -780,55 +794,56 @@ func init() {
|
||||
func init() { proto.RegisterFile("signrpc/signer.proto", fileDescriptor_4ecd772f6c7ffacf) }
|
||||
|
||||
var fileDescriptor_4ecd772f6c7ffacf = []byte{
|
||||
// 756 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0x5d, 0x8f, 0xdb, 0x44,
|
||||
0x14, 0xd5, 0x26, 0x6c, 0x92, 0xbd, 0x4e, 0x76, 0xb3, 0xc3, 0xaa, 0xb8, 0x0b, 0x88, 0x60, 0xa9,
|
||||
0x28, 0x95, 0x20, 0x11, 0x01, 0x21, 0xc1, 0x13, 0x2a, 0xd5, 0xaa, 0x55, 0x8a, 0x5a, 0x39, 0x2b,
|
||||
0x1e, 0xfa, 0x62, 0x39, 0xce, 0xad, 0x33, 0xb2, 0x63, 0xcf, 0xce, 0x8c, 0xeb, 0xf8, 0x77, 0xf0,
|
||||
0xd7, 0xf8, 0x41, 0x68, 0x3e, 0xe2, 0xd8, 0x29, 0x54, 0xea, 0xd3, 0xfa, 0x9e, 0xb9, 0x73, 0xee,
|
||||
0xd9, 0x73, 0xae, 0x63, 0xb8, 0x11, 0x34, 0xce, 0x38, 0x8b, 0xe6, 0xea, 0x2f, 0xf2, 0x19, 0xe3,
|
||||
0xb9, 0xcc, 0x49, 0xdf, 0xa2, 0xde, 0x0b, 0x80, 0x25, 0x56, 0xaf, 0xf2, 0x28, 0x94, 0x39, 0x27,
|
||||
0x5f, 0x03, 0x24, 0x58, 0x05, 0xef, 0xc2, 0x1d, 0x4d, 0x2b, 0xf7, 0x6c, 0x72, 0x36, 0x3d, 0xf7,
|
||||
0x2f, 0x12, 0xac, 0xee, 0x34, 0x40, 0xbe, 0x04, 0x55, 0x04, 0x34, 0xdb, 0xe0, 0xde, 0xed, 0xe8,
|
||||
0xd3, 0x41, 0x82, 0xd5, 0x4b, 0x55, 0x7b, 0x21, 0x8c, 0x96, 0x58, 0x3d, 0x47, 0x11, 0x71, 0xca,
|
||||
0x14, 0x99, 0x07, 0x23, 0x1e, 0x96, 0x81, 0xba, 0xb1, 0xae, 0x24, 0x0a, 0xcd, 0x37, 0xf4, 0x1d,
|
||||
0x1e, 0x96, 0x4b, 0xac, 0x9e, 0x29, 0x88, 0x7c, 0x0f, 0x7d, 0x75, 0x9e, 0xe6, 0x91, 0xe6, 0x73,
|
||||
0x16, 0x9f, 0xcf, 0xac, 0xb2, 0xd9, 0x51, 0x96, 0xdf, 0x4b, 0xf4, 0xb3, 0xf7, 0x1b, 0x9c, 0xdf,
|
||||
0xef, 0x5f, 0x17, 0x92, 0xdc, 0xc0, 0xf9, 0xfb, 0x30, 0x2d, 0x50, 0x53, 0x76, 0x7d, 0x53, 0x28,
|
||||
0x79, 0x2c, 0x09, 0xcc, 0x7c, 0x4d, 0x37, 0xf4, 0x07, 0x2c, 0x59, 0xe9, 0xda, 0xfb, 0xbb, 0x03,
|
||||
0x97, 0x2b, 0x1a, 0x67, 0x0d, 0x81, 0x3f, 0x82, 0x52, 0x1f, 0x6c, 0x50, 0x44, 0x9a, 0xc8, 0x59,
|
||||
0x3c, 0x6a, 0x4e, 0x3f, 0x76, 0xfa, 0x4a, 0xa4, 0x2a, 0xc9, 0xb7, 0x30, 0x14, 0x34, 0x8b, 0x53,
|
||||
0x0c, 0x64, 0x89, 0x61, 0x62, 0xa7, 0x38, 0x06, 0xbb, 0x57, 0x90, 0x6a, 0xd9, 0xe4, 0xc5, 0xba,
|
||||
0x6e, 0xe9, 0x9a, 0x16, 0x83, 0x99, 0x96, 0x27, 0x70, 0x59, 0x52, 0x99, 0xa1, 0x10, 0x07, 0xb5,
|
||||
0x9f, 0xe9, 0xa6, 0x91, 0x45, 0x8d, 0x64, 0xf2, 0x1d, 0xf4, 0xf2, 0x42, 0xb2, 0x42, 0xba, 0xe7,
|
||||
0x5a, 0xdd, 0x65, 0xad, 0x4e, 0xbb, 0xe0, 0xdb, 0x53, 0xe2, 0x82, 0x8a, 0x73, 0x1b, 0x8a, 0xad,
|
||||
0xdb, 0x9f, 0x9c, 0x4d, 0x47, 0xfe, 0xa1, 0x24, 0xdf, 0x80, 0x43, 0x33, 0x56, 0x48, 0x1b, 0xd9,
|
||||
0x40, 0x47, 0x06, 0x1a, 0x32, 0xa1, 0x45, 0xd0, 0x57, 0xa6, 0xf8, 0xf8, 0x40, 0x26, 0x30, 0x54,
|
||||
0x71, 0xc9, 0x7d, 0x2b, 0x2d, 0xe0, 0x61, 0x79, 0xbf, 0x37, 0x61, 0xfd, 0x02, 0xa0, 0x04, 0x68,
|
||||
0xc3, 0x84, 0xdb, 0x99, 0x74, 0xa7, 0xce, 0xe2, 0x8b, 0x5a, 0x53, 0xdb, 0x5c, 0xff, 0x42, 0xd8,
|
||||
0x5a, 0x78, 0x4f, 0x60, 0x60, 0x86, 0x08, 0x46, 0x1e, 0xc3, 0x40, 0x4d, 0x11, 0x34, 0x56, 0x13,
|
||||
0xba, 0xd3, 0xa1, 0xdf, 0xe7, 0x61, 0xb9, 0xa2, 0xb1, 0xf0, 0xee, 0xc0, 0x79, 0xa9, 0x94, 0xd9,
|
||||
0xff, 0xde, 0x85, 0xbe, 0xb5, 0xe3, 0xd0, 0x68, 0x4b, 0xb5, 0xa5, 0x82, 0xc6, 0xed, 0xa0, 0xd5,
|
||||
0x38, 0x9b, 0xf4, 0x2b, 0xb8, 0x6a, 0xf0, 0xe8, 0xa9, 0xbf, 0xc2, 0xc8, 0xf8, 0x60, 0xee, 0x18,
|
||||
0x46, 0x67, 0x71, 0x53, 0x8b, 0x6f, 0x5e, 0x18, 0xd2, 0x63, 0x21, 0xbc, 0x37, 0x66, 0x6d, 0xfe,
|
||||
0x44, 0x21, 0xc2, 0x18, 0x95, 0x51, 0x63, 0xe8, 0xee, 0x44, 0x6c, 0xfd, 0x51, 0x8f, 0x9f, 0xb8,
|
||||
0xc5, 0x73, 0xb8, 0x6a, 0x31, 0x0a, 0x46, 0xbe, 0x02, 0x6d, 0x57, 0x28, 0x0b, 0x8e, 0x96, 0xf8,
|
||||
0x08, 0x78, 0x6f, 0x61, 0xfc, 0x17, 0x72, 0xfa, 0xae, 0xfa, 0xa8, 0x88, 0x16, 0x47, 0xe7, 0x84,
|
||||
0x83, 0x3c, 0x82, 0x1e, 0x2b, 0xd6, 0x09, 0x56, 0x76, 0x1f, 0x6d, 0xe5, 0x3d, 0x85, 0xeb, 0x13,
|
||||
0x6e, 0xc1, 0xec, 0xeb, 0x45, 0x37, 0x9a, 0x7e, 0xe0, 0x9b, 0xc2, 0x4b, 0x60, 0xbc, 0xda, 0x86,
|
||||
0x1c, 0x37, 0x4b, 0xac, 0x7c, 0x7c, 0x28, 0x50, 0x48, 0xf2, 0x14, 0xc6, 0xc8, 0xb6, 0xb8, 0x43,
|
||||
0x1e, 0xa6, 0x81, 0x1d, 0x60, 0x34, 0x5d, 0xd5, 0xf8, 0x1b, 0x0d, 0x7f, 0xa2, 0x49, 0x0b, 0xb8,
|
||||
0x6e, 0x0c, 0x13, 0x2c, 0xcf, 0x04, 0xea, 0xe0, 0x35, 0x18, 0x1c, 0xe7, 0x5c, 0x88, 0x43, 0xdb,
|
||||
0xe2, 0x9f, 0x0e, 0xf4, 0x56, 0xfa, 0x57, 0x8e, 0xfc, 0x0c, 0x23, 0xf5, 0xf4, 0x5a, 0xbf, 0x20,
|
||||
0x7e, 0x58, 0x92, 0x71, 0x6b, 0x4f, 0x7d, 0x7c, 0xb8, 0xbd, 0x3e, 0x41, 0x04, 0x23, 0xbf, 0x03,
|
||||
0xf9, 0x23, 0xdf, 0xb1, 0x42, 0x62, 0x73, 0x11, 0x3f, 0xbc, 0xea, 0xfe, 0xe7, 0xde, 0x18, 0x06,
|
||||
0xa7, 0x91, 0x2d, 0x69, 0xbf, 0x1d, 0xc7, 0xf8, 0x1a, 0x0c, 0xa7, 0xab, 0x70, 0x07, 0xa3, 0x56,
|
||||
0x20, 0xe4, 0x71, 0xdd, 0x7a, 0xba, 0x04, 0xb7, 0xb7, 0xff, 0x77, 0x24, 0x18, 0x79, 0x01, 0x57,
|
||||
0xcf, 0x91, 0xd3, 0xf7, 0x58, 0xdb, 0xd8, 0x60, 0x3a, 0xcd, 0xb1, 0xc1, 0xf4, 0x81, 0xeb, 0xcf,
|
||||
0xe6, 0x6f, 0x7f, 0x88, 0xa9, 0xdc, 0x16, 0xeb, 0x59, 0x94, 0xef, 0xe6, 0x29, 0x8d, 0xb7, 0x32,
|
||||
0xa3, 0x59, 0x9c, 0xa1, 0x2c, 0x73, 0x9e, 0xcc, 0xd3, 0x6c, 0x33, 0x4f, 0xeb, 0x2f, 0x0c, 0x67,
|
||||
0xd1, 0xba, 0xa7, 0xbf, 0x31, 0x3f, 0xfd, 0x1b, 0x00, 0x00, 0xff, 0xff, 0x73, 0xb0, 0xe9, 0x51,
|
||||
0x7b, 0x06, 0x00, 0x00,
|
||||
// 775 bytes of a gzipped FileDescriptorProto
|
||||
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0x94, 0x55, 0xed, 0x8e, 0xdb, 0x44,
|
||||
0x14, 0x55, 0x12, 0x36, 0xc9, 0x5e, 0x27, 0xbb, 0xd9, 0x61, 0x55, 0xdc, 0x05, 0xc4, 0x62, 0xa9,
|
||||
0x68, 0x2b, 0x41, 0x02, 0x01, 0x21, 0xc1, 0x2f, 0xb4, 0x54, 0xab, 0x56, 0x29, 0x6a, 0xe5, 0xac,
|
||||
0xf8, 0xd1, 0x3f, 0x96, 0xe3, 0xdc, 0x3a, 0x23, 0x3b, 0xf6, 0xec, 0xcc, 0xb8, 0x8e, 0x9f, 0x83,
|
||||
0x37, 0xe0, 0x99, 0x78, 0x20, 0x34, 0x1f, 0x71, 0xec, 0x14, 0x50, 0xf9, 0xb5, 0xbe, 0xc7, 0x77,
|
||||
0xce, 0x3d, 0x7b, 0xce, 0x9d, 0x18, 0x2e, 0x05, 0x8d, 0x33, 0xce, 0xa2, 0x99, 0xfa, 0x8b, 0x7c,
|
||||
0xca, 0x78, 0x2e, 0x73, 0x32, 0xb0, 0xa8, 0xf7, 0x1c, 0x60, 0x81, 0xd5, 0xcb, 0x3c, 0x0a, 0x65,
|
||||
0xce, 0xc9, 0xe7, 0x00, 0x09, 0x56, 0xc1, 0xdb, 0x70, 0x4b, 0xd3, 0xca, 0xed, 0x5c, 0x77, 0x6e,
|
||||
0x4e, 0xfc, 0xd3, 0x04, 0xab, 0x3b, 0x0d, 0x90, 0x4f, 0x41, 0x15, 0x01, 0xcd, 0xd6, 0xb8, 0x73,
|
||||
0xbb, 0xfa, 0xed, 0x30, 0xc1, 0xea, 0x85, 0xaa, 0xbd, 0x10, 0xc6, 0x0b, 0xac, 0x9e, 0xa1, 0x88,
|
||||
0x38, 0x65, 0x8a, 0xcc, 0x83, 0x31, 0x0f, 0xcb, 0x40, 0x9d, 0x58, 0x55, 0x12, 0x85, 0xe6, 0x1b,
|
||||
0xf9, 0x0e, 0x0f, 0xcb, 0x05, 0x56, 0xb7, 0x0a, 0x22, 0x5f, 0xc3, 0x40, 0xbd, 0x4f, 0xf3, 0x48,
|
||||
0xf3, 0x39, 0xf3, 0x8f, 0xa7, 0x56, 0xd9, 0xf4, 0x20, 0xcb, 0xef, 0x27, 0xfa, 0xd9, 0xfb, 0x19,
|
||||
0x4e, 0xee, 0x77, 0xaf, 0x0a, 0x49, 0x2e, 0xe1, 0xe4, 0x5d, 0x98, 0x16, 0xa8, 0x29, 0x7b, 0xbe,
|
||||
0x29, 0x94, 0x3c, 0x96, 0x04, 0x66, 0xbe, 0xa6, 0x1b, 0xf9, 0x43, 0x96, 0x2c, 0x75, 0xed, 0xfd,
|
||||
0xd1, 0x85, 0xb3, 0x25, 0x8d, 0xb3, 0x86, 0xc0, 0xef, 0x40, 0xa9, 0x0f, 0xd6, 0x28, 0x22, 0x4d,
|
||||
0xe4, 0xcc, 0x1f, 0x35, 0xa7, 0x1f, 0x3a, 0x7d, 0x25, 0x52, 0x95, 0xe4, 0x4b, 0x18, 0x09, 0x9a,
|
||||
0xc5, 0x29, 0x06, 0xb2, 0xc4, 0x30, 0xb1, 0x53, 0x1c, 0x83, 0xdd, 0x2b, 0x48, 0xb5, 0xac, 0xf3,
|
||||
0x62, 0x55, 0xb7, 0xf4, 0x4c, 0x8b, 0xc1, 0x4c, 0xcb, 0x13, 0x38, 0x2b, 0xa9, 0xcc, 0x50, 0x88,
|
||||
0xbd, 0xda, 0x8f, 0x74, 0xd3, 0xd8, 0xa2, 0x46, 0x32, 0xf9, 0x0a, 0xfa, 0x79, 0x21, 0x59, 0x21,
|
||||
0xdd, 0x13, 0xad, 0xee, 0xac, 0x56, 0xa7, 0x5d, 0xf0, 0xed, 0x5b, 0xe2, 0x82, 0x8a, 0x73, 0x13,
|
||||
0x8a, 0x8d, 0x3b, 0xb8, 0xee, 0xdc, 0x8c, 0xfd, 0x7d, 0x49, 0xbe, 0x00, 0x87, 0x66, 0xac, 0x90,
|
||||
0x36, 0xb2, 0xa1, 0x8e, 0x0c, 0x34, 0x64, 0x42, 0x8b, 0x60, 0xa0, 0x4c, 0xf1, 0xf1, 0x81, 0x5c,
|
||||
0xc3, 0x48, 0xc5, 0x25, 0x77, 0xad, 0xb4, 0x80, 0x87, 0xe5, 0xfd, 0xce, 0x84, 0xf5, 0x23, 0x80,
|
||||
0x12, 0xa0, 0x0d, 0x13, 0x6e, 0xf7, 0xba, 0x77, 0xe3, 0xcc, 0x3f, 0xa9, 0x35, 0xb5, 0xcd, 0xf5,
|
||||
0x4f, 0x85, 0xad, 0x85, 0xf7, 0x04, 0x86, 0x66, 0x88, 0x60, 0xe4, 0x31, 0x0c, 0xd5, 0x14, 0x41,
|
||||
0x63, 0x35, 0xa1, 0x77, 0x33, 0xf2, 0x07, 0x3c, 0x2c, 0x97, 0x34, 0x16, 0xde, 0x1d, 0x38, 0x2f,
|
||||
0x94, 0x32, 0xfb, 0xdf, 0xbb, 0x30, 0xb0, 0x76, 0xec, 0x1b, 0x6d, 0xa9, 0xb6, 0x54, 0xd0, 0xb8,
|
||||
0x1d, 0xb4, 0x1a, 0x67, 0x93, 0x7e, 0x09, 0xe7, 0x0d, 0x1e, 0x3d, 0xf5, 0x27, 0x18, 0x1b, 0x1f,
|
||||
0xcc, 0x19, 0xc3, 0xe8, 0xcc, 0x2f, 0x6b, 0xf1, 0xcd, 0x03, 0x23, 0x7a, 0x28, 0x84, 0xf7, 0xda,
|
||||
0xac, 0xcd, 0x6f, 0x28, 0x44, 0x18, 0xa3, 0x32, 0x6a, 0x02, 0xbd, 0xad, 0x88, 0xad, 0x3f, 0xea,
|
||||
0xf1, 0x7f, 0x6e, 0xf1, 0x0c, 0xce, 0x5b, 0x8c, 0x82, 0x91, 0xcf, 0x40, 0xdb, 0x15, 0xca, 0x82,
|
||||
0xa3, 0x25, 0x3e, 0x00, 0xde, 0x1b, 0x98, 0xfc, 0x8e, 0x9c, 0xbe, 0xad, 0xfe, 0x53, 0x44, 0x8b,
|
||||
0xa3, 0x7b, 0xc4, 0x41, 0x1e, 0x41, 0x9f, 0x15, 0xab, 0x04, 0x2b, 0xbb, 0x8f, 0xb6, 0xf2, 0x9e,
|
||||
0xc2, 0xc5, 0x11, 0xb7, 0x60, 0xf6, 0x7a, 0xd1, 0xb5, 0xa6, 0x1f, 0xfa, 0xa6, 0xf0, 0xfe, 0xec,
|
||||
0xc0, 0x64, 0xb9, 0x09, 0x39, 0xae, 0x17, 0x58, 0xf9, 0xf8, 0x50, 0xa0, 0x90, 0xe4, 0x29, 0x4c,
|
||||
0x90, 0x6d, 0x70, 0x8b, 0x3c, 0x4c, 0x03, 0x3b, 0xc1, 0x88, 0x3a, 0xaf, 0xf1, 0xd7, 0x1a, 0x26,
|
||||
0xdf, 0x7e, 0x88, 0x4b, 0xb7, 0x5d, 0xb7, 0xb3, 0x77, 0xaa, 0x75, 0x41, 0x7b, 0x1f, 0x74, 0x41,
|
||||
0xbd, 0x39, 0x5c, 0x34, 0x34, 0x0a, 0x96, 0x67, 0x02, 0xf5, 0xc2, 0x68, 0x30, 0x38, 0xc8, 0x3b,
|
||||
0x15, 0xfb, 0xb6, 0xf9, 0x5f, 0x5d, 0xe8, 0x2f, 0xf5, 0xaf, 0x23, 0xf9, 0x01, 0xc6, 0xea, 0xe9,
|
||||
0x95, 0xbe, 0x58, 0x7e, 0x58, 0x92, 0x49, 0x6b, 0xbf, 0x7d, 0x7c, 0xb8, 0xba, 0x38, 0x42, 0x04,
|
||||
0x23, 0xbf, 0x00, 0xf9, 0x35, 0xdf, 0xb2, 0x42, 0x62, 0x73, 0x81, 0xdf, 0x3f, 0xea, 0xfe, 0xe3,
|
||||
0xbe, 0x19, 0x06, 0xa7, 0xb1, 0x13, 0xa4, 0x7d, 0xab, 0x0e, 0xb1, 0x37, 0x18, 0x8e, 0x57, 0xe8,
|
||||
0x0e, 0xc6, 0xad, 0x20, 0xc9, 0xe3, 0xba, 0xf5, 0x78, 0x79, 0xae, 0xae, 0xfe, 0xed, 0x95, 0x60,
|
||||
0xe4, 0x39, 0x9c, 0x3f, 0x43, 0x4e, 0xdf, 0x61, 0x6d, 0x63, 0x83, 0xe9, 0x38, 0xfe, 0x06, 0xd3,
|
||||
0x7b, 0xae, 0xdf, 0xce, 0xde, 0x7c, 0x13, 0x53, 0xb9, 0x29, 0x56, 0xd3, 0x28, 0xdf, 0xce, 0x52,
|
||||
0x1a, 0x6f, 0x64, 0x46, 0xb3, 0x38, 0x43, 0x59, 0xe6, 0x3c, 0x99, 0xa5, 0xd9, 0x7a, 0x96, 0xd6,
|
||||
0x5f, 0x26, 0xce, 0xa2, 0x55, 0x5f, 0x7f, 0x9b, 0xbe, 0xff, 0x3b, 0x00, 0x00, 0xff, 0xff, 0x7d,
|
||||
0x28, 0x4a, 0xad, 0xb3, 0x06, 0x00, 0x00,
|
||||
}
|
||||
|
||||
// Reference imports to suppress errors if they are not otherwise used.
|
||||
@@ -882,8 +897,9 @@ type SignerClient interface {
|
||||
//
|
||||
//DeriveSharedKey returns a shared secret key by performing Diffie-Hellman key
|
||||
//derivation between the ephemeral public key in the request and the node's
|
||||
//key specified in the key_loc parameter (or the node's identity private key
|
||||
//if no key locator is specified):
|
||||
//key specified in the key_desc parameter. Either a key locator or a raw
|
||||
//public key is expected in the key_desc, if neither is supplied, defaults to
|
||||
//the node's identity private key:
|
||||
//P_shared = privKeyNode * ephemeralPubkey
|
||||
//The resulting shared public key is serialized in the compressed format and
|
||||
//hashed with sha256, resulting in the final key length of 256bit.
|
||||
@@ -984,8 +1000,9 @@ type SignerServer interface {
|
||||
//
|
||||
//DeriveSharedKey returns a shared secret key by performing Diffie-Hellman key
|
||||
//derivation between the ephemeral public key in the request and the node's
|
||||
//key specified in the key_loc parameter (or the node's identity private key
|
||||
//if no key locator is specified):
|
||||
//key specified in the key_desc parameter. Either a key locator or a raw
|
||||
//public key is expected in the key_desc, if neither is supplied, defaults to
|
||||
//the node's identity private key:
|
||||
//P_shared = privKeyNode * ephemeralPubkey
|
||||
//The resulting shared public key is serialized in the compressed format and
|
||||
//hashed with sha256, resulting in the final key length of 256bit.
|
||||
|
||||
@@ -54,8 +54,9 @@ service Signer {
|
||||
/*
|
||||
DeriveSharedKey returns a shared secret key by performing Diffie-Hellman key
|
||||
derivation between the ephemeral public key in the request and the node's
|
||||
key specified in the key_loc parameter (or the node's identity private key
|
||||
if no key locator is specified):
|
||||
key specified in the key_desc parameter. Either a key locator or a raw
|
||||
public key is expected in the key_desc, if neither is supplied, defaults to
|
||||
the node's identity private key:
|
||||
P_shared = privKeyNode * ephemeralPubkey
|
||||
The resulting shared public key is serialized in the compressed format and
|
||||
hashed with sha256, resulting in the final key length of 256bit.
|
||||
@@ -220,10 +221,18 @@ message SharedKeyRequest {
|
||||
bytes ephemeral_pubkey = 1;
|
||||
|
||||
/*
|
||||
The optional key locator of the local key that should be used. If this
|
||||
parameter is not set then the node's identity private key will be used.
|
||||
Deprecated. The optional key locator of the local key that should be used.
|
||||
If this parameter is not set then the node's identity private key will be
|
||||
used.
|
||||
*/
|
||||
KeyLocator key_loc = 2;
|
||||
KeyLocator key_loc = 2 [deprecated = true];
|
||||
|
||||
/*
|
||||
A key descriptor describes the key used for performing ECDH. Either a key
|
||||
locator or a raw public key is expected, if neither is supplied, defaults to
|
||||
the node's identity private key.
|
||||
*/
|
||||
KeyDescriptor key_desc = 3;
|
||||
}
|
||||
|
||||
message SharedKeyResponse {
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
},
|
||||
"/v2/signer/sharedkey": {
|
||||
"post": {
|
||||
"summary": "DeriveSharedKey returns a shared secret key by performing Diffie-Hellman key\nderivation between the ephemeral public key in the request and the node's\nkey specified in the key_loc parameter (or the node's identity private key\nif no key locator is specified):\nP_shared = privKeyNode * ephemeralPubkey\nThe resulting shared public key is serialized in the compressed format and\nhashed with sha256, resulting in the final key length of 256bit.",
|
||||
"summary": "DeriveSharedKey returns a shared secret key by performing Diffie-Hellman key\nderivation between the ephemeral public key in the request and the node's\nkey specified in the key_desc parameter. Either a key locator or a raw\npublic key is expected in the key_desc, if neither is supplied, defaults to\nthe node's identity private key:\nP_shared = privKeyNode * ephemeralPubkey\nThe resulting shared public key is serialized in the compressed format and\nhashed with sha256, resulting in the final key length of 256bit.",
|
||||
"operationId": "DeriveSharedKey",
|
||||
"responses": {
|
||||
"200": {
|
||||
@@ -284,7 +284,11 @@
|
||||
},
|
||||
"key_loc": {
|
||||
"$ref": "#/definitions/signrpcKeyLocator",
|
||||
"description": "The optional key locator of the local key that should be used. If this\nparameter is not set then the node's identity private key will be used."
|
||||
"description": "Deprecated. The optional key locator of the local key that should be used.\nIf this parameter is not set then the node's identity private key will be\nused."
|
||||
},
|
||||
"key_desc": {
|
||||
"$ref": "#/definitions/signrpcKeyDescriptor",
|
||||
"description": "A key descriptor describes the key used for performing ECDH. Either a key\nlocator or a raw public key is expected, if neither is supplied, defaults to\nthe node's identity private key."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
@@ -19,6 +19,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/keychain"
|
||||
"github.com/lightningnetwork/lnd/lnrpc"
|
||||
"github.com/lightningnetwork/lnd/lnwire"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"google.golang.org/grpc"
|
||||
"gopkg.in/macaroon-bakery.v2/bakery"
|
||||
)
|
||||
@@ -111,8 +112,8 @@ func New(cfg *Config) (*Server, lnrpc.MacaroonPerms, error) {
|
||||
// At this point, we know that the signer macaroon doesn't yet,
|
||||
// exist, so we need to create it with the help of the main
|
||||
// macaroon service.
|
||||
signerMac, err := cfg.MacService.Oven.NewMacaroon(
|
||||
context.Background(), bakery.LatestVersion, nil,
|
||||
signerMac, err := cfg.MacService.NewMacaroon(
|
||||
context.Background(), macaroons.DefaultRootKeyID,
|
||||
macaroonOps...,
|
||||
)
|
||||
if err != nil {
|
||||
@@ -253,27 +254,11 @@ func (s *Server) SignOutputRaw(ctx context.Context, in *SignReq) (*SignResp, err
|
||||
// If this method doesn't return nil, then we know that user is
|
||||
// attempting to include a raw serialized pub key.
|
||||
if keyDesc.GetRawKeyBytes() != nil {
|
||||
rawKeyBytes := keyDesc.GetRawKeyBytes()
|
||||
|
||||
switch {
|
||||
// If the user provided a raw key, but it's of the
|
||||
// wrong length, then we'll return with an error.
|
||||
case len(rawKeyBytes) != 0 && len(rawKeyBytes) != 33:
|
||||
|
||||
return nil, fmt.Errorf("pubkey must be " +
|
||||
"serialized in compressed format if " +
|
||||
"specified")
|
||||
|
||||
// If a proper raw key was provided, then we'll attempt
|
||||
// to decode and parse it.
|
||||
case len(rawKeyBytes) != 0 && len(rawKeyBytes) == 33:
|
||||
targetPubKey, err = btcec.ParsePubKey(
|
||||
rawKeyBytes, btcec.S256(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to "+
|
||||
"parse pubkey: %v", err)
|
||||
}
|
||||
targetPubKey, err = parseRawKeyBytes(
|
||||
keyDesc.GetRawKeyBytes(),
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
@@ -506,38 +491,82 @@ func (s *Server) VerifyMessage(ctx context.Context,
|
||||
|
||||
// DeriveSharedKey returns a shared secret key by performing Diffie-Hellman key
|
||||
// derivation between the ephemeral public key in the request and the node's
|
||||
// key specified in the key_loc parameter (or the node's identity private key
|
||||
// if no key locator is specified):
|
||||
// P_shared = privKeyNode * ephemeralPubkey
|
||||
// key specified in the key_desc parameter. Either a key locator or a raw public
|
||||
// key is expected in the key_desc, if neither is supplied, defaults to the
|
||||
// node's identity private key. The old key_loc parameter in the request
|
||||
// shouldn't be used anymore.
|
||||
// The resulting shared public key is serialized in the compressed format and
|
||||
// hashed with sha256, resulting in the final key length of 256bit.
|
||||
func (s *Server) DeriveSharedKey(_ context.Context, in *SharedKeyRequest) (
|
||||
*SharedKeyResponse, error) {
|
||||
|
||||
if len(in.EphemeralPubkey) != 33 {
|
||||
return nil, fmt.Errorf("ephemeral pubkey must be " +
|
||||
"serialized in compressed format")
|
||||
}
|
||||
ephemeralPubkey, err := btcec.ParsePubKey(
|
||||
in.EphemeralPubkey, btcec.S256(),
|
||||
)
|
||||
// Check that EphemeralPubkey is valid.
|
||||
ephemeralPubkey, err := parseRawKeyBytes(in.EphemeralPubkey)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unable to parse pubkey: %v", err)
|
||||
return nil, fmt.Errorf("error in ephemeral pubkey: %v", err)
|
||||
}
|
||||
if ephemeralPubkey == nil {
|
||||
return nil, fmt.Errorf("must provide ephemeral pubkey")
|
||||
}
|
||||
|
||||
// By default, use the node identity private key.
|
||||
locator := keychain.KeyLocator{
|
||||
Family: keychain.KeyFamilyNodeKey,
|
||||
Index: 0,
|
||||
// Check for backward compatibility. The caller either specifies the old
|
||||
// key_loc field, or the new key_desc field, but not both.
|
||||
if in.KeyDesc != nil && in.KeyLoc != nil {
|
||||
return nil, fmt.Errorf("use either key_desc or key_loc")
|
||||
}
|
||||
if in.KeyLoc != nil {
|
||||
locator.Family = keychain.KeyFamily(in.KeyLoc.KeyFamily)
|
||||
locator.Index = uint32(in.KeyLoc.KeyIndex)
|
||||
|
||||
// When key_desc is used, the key_desc.key_loc is expected as the caller
|
||||
// needs to specify the KeyFamily.
|
||||
if in.KeyDesc != nil && in.KeyDesc.KeyLoc == nil {
|
||||
return nil, fmt.Errorf("when setting key_desc the field " +
|
||||
"key_desc.key_loc must also be set")
|
||||
}
|
||||
|
||||
// We extract two params, rawKeyBytes and keyLoc. Notice their initial
|
||||
// values will be overwritten if not using the deprecated RPC param.
|
||||
var rawKeyBytes []byte
|
||||
keyLoc := in.KeyLoc
|
||||
if in.KeyDesc != nil {
|
||||
keyLoc = in.KeyDesc.GetKeyLoc()
|
||||
rawKeyBytes = in.KeyDesc.GetRawKeyBytes()
|
||||
}
|
||||
|
||||
// When no keyLoc is supplied, defaults to the node's identity private
|
||||
// key.
|
||||
if keyLoc == nil {
|
||||
keyLoc = &KeyLocator{
|
||||
KeyFamily: int32(keychain.KeyFamilyNodeKey),
|
||||
KeyIndex: 0,
|
||||
}
|
||||
}
|
||||
|
||||
// Check the caller is using either the key index or the raw public key
|
||||
// to perform the ECDH, we can't have both.
|
||||
if rawKeyBytes != nil && keyLoc.KeyIndex != 0 {
|
||||
return nil, fmt.Errorf("use either raw_key_bytes or key_index")
|
||||
}
|
||||
|
||||
// Check the raw public key is valid. Notice that if the rawKeyBytes is
|
||||
// empty, the parseRawKeyBytes won't return an error, a nil
|
||||
// *btcec.PublicKey is returned instead.
|
||||
pk, err := parseRawKeyBytes(rawKeyBytes)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("error in raw pubkey: %v", err)
|
||||
}
|
||||
|
||||
// Create a key descriptor. When the KeyIndex is not specified, it uses
|
||||
// the empty value 0, and when the raw public key is not specified, the
|
||||
// pk is nil.
|
||||
keyDescriptor := keychain.KeyDescriptor{
|
||||
KeyLocator: keychain.KeyLocator{
|
||||
Family: keychain.KeyFamily(keyLoc.KeyFamily),
|
||||
Index: uint32(keyLoc.KeyIndex),
|
||||
},
|
||||
PubKey: pk,
|
||||
}
|
||||
|
||||
// Derive the shared key using ECDH and hashing the serialized
|
||||
// compressed shared point.
|
||||
keyDescriptor := keychain.KeyDescriptor{KeyLocator: locator}
|
||||
sharedKeyHash, err := s.cfg.KeyRing.ECDH(keyDescriptor, ephemeralPubkey)
|
||||
if err != nil {
|
||||
err := fmt.Errorf("unable to derive shared key: %v", err)
|
||||
@@ -547,3 +576,29 @@ func (s *Server) DeriveSharedKey(_ context.Context, in *SharedKeyRequest) (
|
||||
|
||||
return &SharedKeyResponse{SharedKey: sharedKeyHash[:]}, nil
|
||||
}
|
||||
|
||||
// parseRawKeyBytes checks that the provided raw public key is valid and returns
|
||||
// the public key. A nil public key is returned if the length of the rawKeyBytes
|
||||
// is zero.
|
||||
func parseRawKeyBytes(rawKeyBytes []byte) (*btcec.PublicKey, error) {
|
||||
switch {
|
||||
|
||||
case len(rawKeyBytes) == 33:
|
||||
// If a proper raw key was provided, then we'll attempt
|
||||
// to decode and parse it.
|
||||
return btcec.ParsePubKey(
|
||||
rawKeyBytes, btcec.S256(),
|
||||
)
|
||||
|
||||
case len(rawKeyBytes) == 0:
|
||||
// No key is provided, return nil.
|
||||
return nil, nil
|
||||
|
||||
default:
|
||||
// If the user provided a raw key, but it's of the
|
||||
// wrong length, then we'll return with an error.
|
||||
return nil, fmt.Errorf("pubkey must be " +
|
||||
"serialized in compressed format if " +
|
||||
"specified")
|
||||
}
|
||||
}
|
||||
@@ -25,6 +25,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/lnwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/btcwallet"
|
||||
"github.com/lightningnetwork/lnd/lnwallet/chainfee"
|
||||
"github.com/lightningnetwork/lnd/macaroons"
|
||||
"github.com/lightningnetwork/lnd/sweep"
|
||||
"google.golang.org/grpc"
|
||||
"gopkg.in/macaroon-bakery.v2/bakery"
|
||||
@@ -156,8 +157,9 @@ func New(cfg *Config) (*WalletKit, lnrpc.MacaroonPerms, error) {
|
||||
// At this point, we know that the wallet kit macaroon doesn't
|
||||
// yet, exist, so we need to create it with the help of the
|
||||
// main macaroon service.
|
||||
walletKitMac, err := cfg.MacService.Oven.NewMacaroon(
|
||||
context.Background(), bakery.LatestVersion, nil,
|
||||
walletKitMac, err := cfg.MacService.NewMacaroon(
|
||||
context.Background(),
|
||||
macaroons.DefaultRootKeyID,
|
||||
macaroonOps...,
|
||||
)
|
||||
if err != nil {
|
||||
|
||||
@@ -21,6 +21,16 @@ const (
|
||||
// This is necessary because the WebSocket API specifies that a
|
||||
// handshake request must always be done through a GET request.
|
||||
MethodOverrideParam = "method"
|
||||
|
||||
// HeaderWebSocketProtocol is the name of the WebSocket protocol
|
||||
// exchange header field that we use to transport additional header
|
||||
// fields.
|
||||
HeaderWebSocketProtocol = "Sec-Websocket-Protocol"
|
||||
|
||||
// WebSocketProtocolDelimiter is the delimiter we use between the
|
||||
// additional header field and its value. We use the plus symbol because
|
||||
// the default delimiters aren't allowed in the protocol names.
|
||||
WebSocketProtocolDelimiter = "+"
|
||||
)
|
||||
|
||||
var (
|
||||
@@ -32,6 +42,13 @@ var (
|
||||
"Referer": true,
|
||||
"Grpc-Metadata-Macaroon": true,
|
||||
}
|
||||
|
||||
// defaultProtocolsToAllow are additional header fields that we allow
|
||||
// to be transported inside of the Sec-Websocket-Protocol field to be
|
||||
// forwarded to the backend.
|
||||
defaultProtocolsToAllow = map[string]bool{
|
||||
"Grpc-Metadata-Macaroon": true,
|
||||
}
|
||||
)
|
||||
|
||||
// NewWebSocketProxy attempts to expose the underlying handler as a response-
|
||||
@@ -101,13 +118,13 @@ func (p *WebsocketProxy) upgradeToWebSocketProxy(w http.ResponseWriter,
|
||||
p.logger.Errorf("WS: error preparing request:", err)
|
||||
return
|
||||
}
|
||||
for header := range r.Header {
|
||||
headerName := textproto.CanonicalMIMEHeaderKey(header)
|
||||
forward, ok := defaultHeadersToForward[headerName]
|
||||
if ok && forward {
|
||||
request.Header.Set(headerName, r.Header.Get(header))
|
||||
}
|
||||
}
|
||||
|
||||
// Allow certain headers to be forwarded, either from source headers
|
||||
// or the special Sec-Websocket-Protocol header field.
|
||||
forwardHeaders(r.Header, request.Header)
|
||||
|
||||
// Also allow the target request method to be overwritten, as all
|
||||
// WebSocket establishment calls MUST be GET requests.
|
||||
if m := r.URL.Query().Get(MethodOverrideParam); m != "" {
|
||||
request.Method = m
|
||||
}
|
||||
@@ -182,6 +199,38 @@ func (p *WebsocketProxy) upgradeToWebSocketProxy(w http.ResponseWriter,
|
||||
}
|
||||
}
|
||||
|
||||
// forwardHeaders forwards certain allowed header fields from the source request
|
||||
// to the target request. Because browsers are limited in what header fields
|
||||
// they can send on the WebSocket setup call, we also allow additional fields to
|
||||
// be transported in the special Sec-Websocket-Protocol field.
|
||||
func forwardHeaders(source, target http.Header) {
|
||||
// Forward allowed header fields directly.
|
||||
for header := range source {
|
||||
headerName := textproto.CanonicalMIMEHeaderKey(header)
|
||||
forward, ok := defaultHeadersToForward[headerName]
|
||||
if ok && forward {
|
||||
target.Set(headerName, source.Get(header))
|
||||
}
|
||||
}
|
||||
|
||||
// Browser aren't allowed to set custom header fields on WebSocket
|
||||
// requests. We need to allow them to submit the macaroon as a WS
|
||||
// protocol, which is the only allowed header. Set any "protocols" we
|
||||
// declare valid as header fields on the forwarded request.
|
||||
protocol := source.Get(HeaderWebSocketProtocol)
|
||||
for key := range defaultProtocolsToAllow {
|
||||
if strings.HasPrefix(protocol, key) {
|
||||
// The format is "<protocol name>+<value>". We know the
|
||||
// protocol string starts with the name so we only need
|
||||
// to set the value.
|
||||
values := strings.Split(
|
||||
protocol, WebSocketProtocolDelimiter,
|
||||
)
|
||||
target.Set(key, values[1])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// newRequestForwardingReader creates a new request forwarding pipe.
|
||||
func newRequestForwardingReader() *requestForwardingReader {
|
||||
r, w := io.Pipe()
|
||||
|
||||
Reference in new issue
Block a user