mirror of
https://github.com/lightningnetwork/lnd.git
synced 2025-01-18 13:27:56 +01:00
multi: add blinded paths to invoices
Expose the ability to add blinded paths to an invoice. Also expose various configuration values. We also let the lncfg.Invoices struct satisfy the Validator interface so that we can verify all its config values in one place.
This commit is contained in:
parent
e12a226272
commit
de975334cd
20
config.go
20
config.go
@ -680,6 +680,13 @@ func DefaultConfig() Config {
|
||||
},
|
||||
Invoices: &lncfg.Invoices{
|
||||
HoldExpiryDelta: lncfg.DefaultHoldInvoiceExpiryDelta,
|
||||
BlindedPaths: lncfg.BlindedPaths{
|
||||
MinNumRealHops: lncfg.DefaultMinNumRealBlindedPathHops,
|
||||
NumHops: lncfg.DefaultNumBlindedPathHops,
|
||||
MaxNumPaths: lncfg.DefaultMaxNumBlindedPaths,
|
||||
PolicyIncreaseMultiplier: lncfg.DefaultBlindedPathPolicyIncreaseMultiplier,
|
||||
PolicyDecreaseMultiplier: lncfg.DefaultBlindedPathPolicyDecreaseMultiplier,
|
||||
},
|
||||
},
|
||||
MaxOutgoingCltvExpiry: htlcswitch.DefaultMaxOutgoingCltvExpiry,
|
||||
MaxChannelFeeAllocation: htlcswitch.DefaultMaxLinkFeeAllocation,
|
||||
@ -1656,18 +1663,6 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser,
|
||||
return nil, mkErr("error parsing gossip syncer: %v", err)
|
||||
}
|
||||
|
||||
// Log a warning if our expiry delta is not greater than our incoming
|
||||
// broadcast delta. We do not fail here because this value may be set
|
||||
// to zero to intentionally keep lnd's behavior unchanged from when we
|
||||
// didn't auto-cancel these invoices.
|
||||
if cfg.Invoices.HoldExpiryDelta <= lncfg.DefaultIncomingBroadcastDelta {
|
||||
ltndLog.Warnf("Invoice hold expiry delta: %v <= incoming "+
|
||||
"delta: %v, accepted hold invoices will force close "+
|
||||
"channels if they are not canceled manually",
|
||||
cfg.Invoices.HoldExpiryDelta,
|
||||
lncfg.DefaultIncomingBroadcastDelta)
|
||||
}
|
||||
|
||||
// If the experimental protocol options specify any protocol messages
|
||||
// that we want to handle as custom messages, set them now.
|
||||
customMsg := cfg.ProtocolOptions.CustomMessageOverrides()
|
||||
@ -1690,6 +1685,7 @@ func ValidateConfig(cfg Config, interceptor signal.Interceptor, fileParser,
|
||||
cfg.RemoteSigner,
|
||||
cfg.Sweeper,
|
||||
cfg.Htlcswitch,
|
||||
cfg.Invoices,
|
||||
)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -1,14 +1,94 @@
|
||||
package lncfg
|
||||
|
||||
// DefaultHoldInvoiceExpiryDelta defines the number of blocks before the expiry
|
||||
// height of a hold invoice's htlc that lnd will automatically cancel the
|
||||
// invoice to prevent the channel from force closing. This value *must* be
|
||||
// greater than DefaultIncomingBroadcastDelta to prevent force closes.
|
||||
const DefaultHoldInvoiceExpiryDelta = DefaultIncomingBroadcastDelta + 2
|
||||
import "fmt"
|
||||
|
||||
const (
|
||||
// DefaultHoldInvoiceExpiryDelta defines the number of blocks before the
|
||||
// expiry height of a hold invoice's htlc that lnd will automatically
|
||||
// cancel the invoice to prevent the channel from force closing. This
|
||||
// value *must* be greater than DefaultIncomingBroadcastDelta to prevent
|
||||
// force closes.
|
||||
DefaultHoldInvoiceExpiryDelta = DefaultIncomingBroadcastDelta + 2
|
||||
|
||||
// DefaultMinNumRealBlindedPathHops is the minimum number of _real_
|
||||
// hops to include in a blinded payment path. This doesn't include our
|
||||
// node (the destination node), so if the minimum is 1, then the path
|
||||
// will contain at minimum our node along with an introduction node hop.
|
||||
DefaultMinNumRealBlindedPathHops = 1
|
||||
|
||||
// DefaultNumBlindedPathHops is the number of hops to include in a
|
||||
// blinded payment path. If paths shorter than this number are found,
|
||||
// then dummy hops are used to pad the path to this length.
|
||||
DefaultNumBlindedPathHops = 2
|
||||
|
||||
// DefaultMaxNumBlindedPaths is the maximum number of different blinded
|
||||
// payment paths to include in an invoice.
|
||||
DefaultMaxNumBlindedPaths = 3
|
||||
|
||||
// DefaultBlindedPathPolicyIncreaseMultiplier is the default multiplier
|
||||
// used to increase certain blinded hop policy values in order to add
|
||||
// a probing buffer.
|
||||
DefaultBlindedPathPolicyIncreaseMultiplier = 1.1
|
||||
|
||||
// DefaultBlindedPathPolicyDecreaseMultiplier is the default multiplier
|
||||
// used to decrease certain blinded hop policy values in order to add a
|
||||
// probing buffer.
|
||||
DefaultBlindedPathPolicyDecreaseMultiplier = 0.9
|
||||
)
|
||||
|
||||
// Invoices holds the configuration options for invoices.
|
||||
//
|
||||
//nolint:lll
|
||||
type Invoices struct {
|
||||
HoldExpiryDelta uint32 `long:"holdexpirydelta" description:"The number of blocks before a hold invoice's htlc expires that the invoice should be canceled to prevent a force close. Force closes will not be prevented if this value is not greater than DefaultIncomingBroadcastDelta."`
|
||||
|
||||
BlindedPaths BlindedPaths `group:"blinding" namespace:"blinding"`
|
||||
}
|
||||
|
||||
// BlindedPaths holds the configuration options for blinded paths added to
|
||||
// invoices.
|
||||
//
|
||||
//nolint:lll
|
||||
type BlindedPaths struct {
|
||||
MinNumRealHops uint8 `long:"min-num-real-hops" description:"The minimum number of real hops to include in a blinded path. This doesn't include our node, so if the minimum is 1, then the path will contain at minimum our node along with an introduction node hop. If it is zero then the shortest path will use our node as an introduction node."`
|
||||
NumHops uint8 `long:"num-hops" description:"The number of hops to include in a blinded path. This doesn't include our node, so if it is 1, then the path will contain our node along with an introduction node or dummy node hop. If paths shorter than NumHops is found, then they will be padded using dummy hops."`
|
||||
MaxNumPaths uint8 `long:"max-num-paths" description:"The maximum number of blinded paths to select and add to an invoice."`
|
||||
PolicyIncreaseMultiplier float64 `long:"policy-increase-multiplier" description:"The amount by which to increase certain policy values of hops on a blinded path in order to add a probing buffer."`
|
||||
PolicyDecreaseMultiplier float64 `long:"policy-decrease-multiplier" description:"The amount by which to decrease certain policy values of hops on a blinded path in order to add a probing buffer."`
|
||||
}
|
||||
|
||||
// Validate checks that the various invoice config options are sane.
|
||||
//
|
||||
// NOTE: this is part of the Validator interface.
|
||||
func (i *Invoices) Validate() error {
|
||||
// Log a warning if our expiry delta is not greater than our incoming
|
||||
// broadcast delta. We do not fail here because this value may be set
|
||||
// to zero to intentionally keep lnd's behavior unchanged from when we
|
||||
// didn't auto-cancel these invoices.
|
||||
if i.HoldExpiryDelta <= DefaultIncomingBroadcastDelta {
|
||||
log.Warnf("Invoice hold expiry delta: %v <= incoming "+
|
||||
"delta: %v, accepted hold invoices will force close "+
|
||||
"channels if they are not canceled manually",
|
||||
i.HoldExpiryDelta, DefaultIncomingBroadcastDelta)
|
||||
}
|
||||
|
||||
if i.BlindedPaths.MinNumRealHops > i.BlindedPaths.NumHops {
|
||||
return fmt.Errorf("the minimum number of real hops in a " +
|
||||
"blinded path must be smaller than or equal to the " +
|
||||
"number of hops expected to be included in each path")
|
||||
}
|
||||
|
||||
if i.BlindedPaths.PolicyIncreaseMultiplier < 1 {
|
||||
return fmt.Errorf("the blinded route policy increase " +
|
||||
"multiplier must be greater than or equal to 1")
|
||||
}
|
||||
|
||||
if i.BlindedPaths.PolicyDecreaseMultiplier > 1 ||
|
||||
i.BlindedPaths.PolicyDecreaseMultiplier < 0 {
|
||||
|
||||
return fmt.Errorf("the blinded route policy decrease " +
|
||||
"multiplier must be in the range (0,1]")
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
32
lncfg/log.go
Normal file
32
lncfg/log.go
Normal file
@ -0,0 +1,32 @@
|
||||
package lncfg
|
||||
|
||||
import (
|
||||
"github.com/btcsuite/btclog"
|
||||
"github.com/lightningnetwork/lnd/build"
|
||||
)
|
||||
|
||||
// log is a logger that is initialized with no output filters. This
|
||||
// means the package will not perform any logging by default until the caller
|
||||
// requests it.
|
||||
var log btclog.Logger
|
||||
|
||||
// Subsystem defines the logging code for this subsystem.
|
||||
const Subsystem = "CNFG"
|
||||
|
||||
// The default amount of logging is none.
|
||||
func init() {
|
||||
UseLogger(build.NewSubLogger(Subsystem, nil))
|
||||
}
|
||||
|
||||
// DisableLog disables all library log output. Logging output is disabled
|
||||
// by default until UseLogger is called.
|
||||
func DisableLog() {
|
||||
UseLogger(btclog.Disabled)
|
||||
}
|
||||
|
||||
// UseLogger uses a specified Logger to output package logging info.
|
||||
// This should be used in preference to SetLogWriter if the caller is also
|
||||
// using btclog.
|
||||
func UseLogger(logger btclog.Logger) {
|
||||
log = logger
|
||||
}
|
@ -578,6 +578,10 @@
|
||||
},
|
||||
"description": "Maps a 32-byte hex-encoded set ID to the sub-invoice AMP state for the\ngiven set ID. This field is always populated for AMP invoices, and can be\nused along side LookupInvoice to obtain the HTLC information related to a\ngiven sub-invoice.\nNote: Output only, don't specify for creating an invoice.",
|
||||
"title": "[EXPERIMENTAL]:"
|
||||
},
|
||||
"blind": {
|
||||
"type": "boolean",
|
||||
"description": "Signals that the invoice should include blinded paths to hide the true\nidentity of the recipient."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -3836,6 +3836,12 @@ message Invoice {
|
||||
Note: Output only, don't specify for creating an invoice.
|
||||
*/
|
||||
map<string, AMPInvoiceState> amp_invoice_state = 28;
|
||||
|
||||
/*
|
||||
Signals that the invoice should include blinded paths to hide the true
|
||||
identity of the recipient.
|
||||
*/
|
||||
bool blind = 29;
|
||||
}
|
||||
|
||||
enum InvoiceHTLCState {
|
||||
|
@ -5490,6 +5490,10 @@
|
||||
},
|
||||
"description": "Maps a 32-byte hex-encoded set ID to the sub-invoice AMP state for the\ngiven set ID. This field is always populated for AMP invoices, and can be\nused along side LookupInvoice to obtain the HTLC information related to a\ngiven sub-invoice.\nNote: Output only, don't specify for creating an invoice.",
|
||||
"title": "[EXPERIMENTAL]:"
|
||||
},
|
||||
"blind": {
|
||||
"type": "boolean",
|
||||
"description": "Signals that the invoice should include blinded paths to hide the true\nidentity of the recipient."
|
||||
}
|
||||
}
|
||||
},
|
||||
|
2
log.go
2
log.go
@ -22,6 +22,7 @@ import (
|
||||
"github.com/lightningnetwork/lnd/healthcheck"
|
||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||
"github.com/lightningnetwork/lnd/invoices"
|
||||
"github.com/lightningnetwork/lnd/lncfg"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/autopilotrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/chainrpc"
|
||||
"github.com/lightningnetwork/lnd/lnrpc/devrpc"
|
||||
@ -181,6 +182,7 @@ func SetupLoggers(root *build.RotatingLogWriter, interceptor signal.Interceptor)
|
||||
AddSubLogger(root, rpcwallet.Subsystem, interceptor, rpcwallet.UseLogger)
|
||||
AddSubLogger(root, peersrpc.Subsystem, interceptor, peersrpc.UseLogger)
|
||||
AddSubLogger(root, graph.Subsystem, interceptor, graph.UseLogger)
|
||||
AddSubLogger(root, lncfg.Subsystem, interceptor, lncfg.UseLogger)
|
||||
}
|
||||
|
||||
// AddSubLogger is a helper method to conveniently create and register the
|
||||
|
43
rpcserver.go
43
rpcserver.go
@ -5743,6 +5743,13 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
|
||||
|
||||
defaultDelta := r.cfg.Bitcoin.TimeLockDelta
|
||||
|
||||
blindingRestrictions := &routing.BlindedPathRestrictions{
|
||||
MinDistanceFromIntroNode: r.server.cfg.Invoices.BlindedPaths.
|
||||
MinNumRealHops,
|
||||
NumHops: r.server.cfg.Invoices.BlindedPaths.NumHops,
|
||||
MaxNumPaths: r.server.cfg.Invoices.BlindedPaths.MaxNumPaths,
|
||||
}
|
||||
|
||||
addInvoiceCfg := &invoicesrpc.AddInvoiceConfig{
|
||||
AddInvoice: r.server.invoices.AddInvoice,
|
||||
IsChannelActive: r.server.htlcSwitch.HasActiveLink,
|
||||
@ -5752,12 +5759,45 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
|
||||
ChanDB: r.server.chanStateDB,
|
||||
Graph: r.server.graphDB,
|
||||
GenInvoiceFeatures: func() *lnwire.FeatureVector {
|
||||
return r.server.featureMgr.Get(feature.SetInvoice)
|
||||
v := r.server.featureMgr.Get(feature.SetInvoice)
|
||||
|
||||
if invoice.Blind {
|
||||
// If an invoice includes blinded paths, then a
|
||||
// payment address is not required since we use
|
||||
// the PathID in the final hop's encrypted data
|
||||
// as equivalent to the payment address
|
||||
v.Unset(lnwire.PaymentAddrRequired)
|
||||
v.Set(lnwire.PaymentAddrOptional)
|
||||
|
||||
// The invoice payer will also need to
|
||||
// understand the new BOLT 11 tagged field
|
||||
// containing the blinded path, so we switch
|
||||
// the bit to required.
|
||||
v.Unset(lnwire.Bolt11BlindedPathsOptional)
|
||||
v.Set(lnwire.Bolt11BlindedPathsRequired)
|
||||
}
|
||||
|
||||
return v
|
||||
},
|
||||
GenAmpInvoiceFeatures: func() *lnwire.FeatureVector {
|
||||
return r.server.featureMgr.Get(feature.SetInvoiceAmp)
|
||||
},
|
||||
GetAlias: r.server.aliasMgr.GetPeerAlias,
|
||||
BestHeight: r.server.cc.BestBlockTracker.BestHeight,
|
||||
BlindedRoutePolicyIncrMultiplier: r.server.cfg.Invoices.
|
||||
BlindedPaths.PolicyIncreaseMultiplier,
|
||||
BlindedRoutePolicyDecrMultiplier: r.server.cfg.Invoices.
|
||||
BlindedPaths.PolicyDecreaseMultiplier,
|
||||
QueryBlindedRoutes: func(amt lnwire.MilliSatoshi) (
|
||||
[]*route.Route, error) {
|
||||
|
||||
return r.server.chanRouter.FindBlindedPaths(
|
||||
r.selfNode, amt,
|
||||
r.server.missionControl.GetProbability,
|
||||
blindingRestrictions,
|
||||
)
|
||||
},
|
||||
MinNumHops: r.server.cfg.Invoices.BlindedPaths.NumHops,
|
||||
}
|
||||
|
||||
value, err := lnrpc.UnmarshallAmt(invoice.Value, invoice.ValueMsat)
|
||||
@ -5780,6 +5820,7 @@ func (r *rpcServer) AddInvoice(ctx context.Context,
|
||||
Private: invoice.Private,
|
||||
RouteHints: routeHints,
|
||||
Amp: invoice.IsAmp,
|
||||
Blind: invoice.Blind,
|
||||
}
|
||||
|
||||
if invoice.RPreimage != nil {
|
||||
|
@ -1649,6 +1649,40 @@
|
||||
; enough to prevent force closes.
|
||||
; invoices.holdexpirydelta=12
|
||||
|
||||
; The minimum number of real (non-dummy) blinded hops to select for a blinded
|
||||
; path. This doesn't include our node, so if the maximum is 1, then the
|
||||
; shortest paths will contain our node along with an introduction node hop.
|
||||
; invoices.blinding.min-num-real-hops=1
|
||||
|
||||
; The number of hops to include in a blinded path. This does not include
|
||||
; our node, so if is is 1, then the path will at least contain our node along
|
||||
; with an introduction node hop. If it is 0, then it will use this node as
|
||||
; the introduction node. This number must be greater than or equal to the
|
||||
; the number of real hops (invoices.blinding.min-num-real-hops). Any paths
|
||||
; shorter than this number will be padded with dummy hops.
|
||||
; invoices.blinding.num-hops=2
|
||||
|
||||
; The maximum number of blinded paths to select and add to an invoice.
|
||||
; invoices.blinding.max-num-paths=3
|
||||
|
||||
; The amount by which to increase certain policy values of hops on a blinded
|
||||
; path in order to add a probing buffer. The higher this multiplier, the more
|
||||
; buffer is added to the policy values of hops along a blinded path meaning
|
||||
; that if they were to increase their policy values before the blinded path
|
||||
; expires, the better the chances that the path would still be valid meaning
|
||||
; that the path is less prone to probing attacks. However, if the multiplier
|
||||
; is too high, the resulting buffered fees might be too much for the payer.
|
||||
; invoices.blinding.policy-increase-multiplier=1.1
|
||||
|
||||
; The amount by which to decrease certain policy values of hops on a blinded
|
||||
; path in order to add a probing buffer. The lower this multiplier, the more
|
||||
; buffer is added to the policy values of hops along a blinded path meaning
|
||||
; that if they were to increase their policy values before the blinded path
|
||||
; expires, the better the chances that the path would still be valid meaning
|
||||
; that the path is less prone to probing attacks. However, since this value
|
||||
; is being applied to the MaxHTLC value of the route, the lower it is, the
|
||||
; lower payment amount will need to be.
|
||||
; invoices.blinding.policy-decrease-multiplier=0.9
|
||||
|
||||
[routing]
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user