multi: Inbound fees are retained when not provided
Fixes the problem that inbound base fee and fee rate are overwritten with 0 if they are not specified in PolicyUpdateRequest. This ensures backward compatibility with older rpc clients that do not yet support the inbound feature.
This commit is contained in:
8 files changed
+1457
-1322
No files matched your search
+21
-5
@@ -2387,12 +2387,28 @@ func updateChannelPolicy(ctx *cli.Context) error {
|
|||||||
return errors.New("inbound_fee_rate_ppm out of range")
|
return errors.New("inbound_fee_rate_ppm out of range")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Inbound fees are optional. However, if an update is required,
|
||||||
|
// both the base fee and the fee rate must be provided.
|
||||||
|
var inboundFee *lnrpc.InboundFee
|
||||||
|
if ctx.IsSet("inbound_base_fee_msat") !=
|
||||||
|
ctx.IsSet("inbound_fee_rate_ppm") {
|
||||||
|
|
||||||
|
return errors.New("both parameters must be provided: " +
|
||||||
|
"inbound_base_fee_msat and inbound_fee_rate_ppm")
|
||||||
|
}
|
||||||
|
|
||||||
|
if ctx.IsSet("inbound_fee_rate_ppm") {
|
||||||
|
inboundFee = &lnrpc.InboundFee{
|
||||||
|
BaseFeeMsat: int32(inboundBaseFeeMsat),
|
||||||
|
FeeRatePpm: int32(inboundFeeRatePpm),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
req := &lnrpc.PolicyUpdateRequest{
|
req := &lnrpc.PolicyUpdateRequest{
|
||||||
BaseFeeMsat: baseFee,
|
BaseFeeMsat: baseFee,
|
||||||
TimeLockDelta: uint32(timeLockDelta),
|
TimeLockDelta: uint32(timeLockDelta),
|
||||||
MaxHtlcMsat: ctx.Uint64("max_htlc_msat"),
|
MaxHtlcMsat: ctx.Uint64("max_htlc_msat"),
|
||||||
InboundBaseFeeMsat: int32(inboundBaseFeeMsat),
|
InboundFee: inboundFee,
|
||||||
InboundFeeRatePpm: int32(inboundFeeRatePpm),
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if ctx.IsSet("min_htlc_msat") {
|
if ctx.IsSet("min_htlc_msat") {
|
||||||
|
|||||||
@@ -257,9 +257,11 @@ func updateChannelPolicy(ht *lntest.HarnessTest, hn *node.HarnessNode,
|
|||||||
Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{
|
Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{
|
||||||
ChanPoint: chanPoint,
|
ChanPoint: chanPoint,
|
||||||
},
|
},
|
||||||
MaxHtlcMsat: maxHtlc,
|
MaxHtlcMsat: maxHtlc,
|
||||||
InboundBaseFeeMsat: inboundBaseFee,
|
InboundFee: &lnrpc.InboundFee{
|
||||||
InboundFeeRatePpm: inboundFeeRate,
|
BaseFeeMsat: inboundBaseFee,
|
||||||
|
FeeRatePpm: inboundFeeRate,
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
hn.RPC.UpdateChannelPolicy(updateFeeReq)
|
hn.RPC.UpdateChannelPolicy(updateFeeReq)
|
||||||
|
|||||||
+1359
-1290
File diff suppressed because it is too large.
Load diff
+13
-2
@@ -4369,6 +4369,16 @@ message FeeReportResponse {
|
|||||||
uint64 month_fee_sum = 4;
|
uint64 month_fee_sum = 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
message InboundFee {
|
||||||
|
// The inbound base fee charged regardless of the number of milli-satoshis
|
||||||
|
// received in the channel. By default, only negative values are accepted.
|
||||||
|
int32 base_fee_msat = 1;
|
||||||
|
|
||||||
|
// The effective inbound fee rate in micro-satoshis (parts per million).
|
||||||
|
// By default, only negative values are accepted.
|
||||||
|
int32 fee_rate_ppm = 2;
|
||||||
|
}
|
||||||
|
|
||||||
message PolicyUpdateRequest {
|
message PolicyUpdateRequest {
|
||||||
oneof scope {
|
oneof scope {
|
||||||
// If set, then this update applies to all currently active channels.
|
// If set, then this update applies to all currently active channels.
|
||||||
@@ -4402,8 +4412,9 @@ message PolicyUpdateRequest {
|
|||||||
// If true, min_htlc_msat is applied.
|
// If true, min_htlc_msat is applied.
|
||||||
bool min_htlc_msat_specified = 8;
|
bool min_htlc_msat_specified = 8;
|
||||||
|
|
||||||
int32 inbound_base_fee_msat = 10;
|
// Optional inbound fee. If unset, the previously set value will be
|
||||||
int32 inbound_fee_rate_ppm = 11;
|
// retained [EXPERIMENTAL].
|
||||||
|
InboundFee inbound_fee = 10;
|
||||||
}
|
}
|
||||||
|
|
||||||
enum UpdateFailure {
|
enum UpdateFailure {
|
||||||
|
|||||||
@@ -5297,6 +5297,21 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"lnrpcInboundFee": {
|
||||||
|
"type": "object",
|
||||||
|
"properties": {
|
||||||
|
"base_fee_msat": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32",
|
||||||
|
"description": "The inbound base fee charged regardless of the number of milli-satoshis\nreceived in the channel. By default, only negative values are accepted."
|
||||||
|
},
|
||||||
|
"fee_rate_ppm": {
|
||||||
|
"type": "integer",
|
||||||
|
"format": "int32",
|
||||||
|
"description": "The effective inbound fee rate in micro-satoshis (parts per million).\nBy default, only negative values are accepted."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"lnrpcInitiator": {
|
"lnrpcInitiator": {
|
||||||
"type": "string",
|
"type": "string",
|
||||||
"enum": [
|
"enum": [
|
||||||
@@ -6585,13 +6600,9 @@
|
|||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"description": "If true, min_htlc_msat is applied."
|
"description": "If true, min_htlc_msat is applied."
|
||||||
},
|
},
|
||||||
"inbound_base_fee_msat": {
|
"inbound_fee": {
|
||||||
"type": "integer",
|
"$ref": "#/definitions/lnrpcInboundFee",
|
||||||
"format": "int32"
|
"description": "Optional inbound fee. If unset, the previously set value will be\nretained [EXPERIMENTAL]."
|
||||||
},
|
|
||||||
"inbound_fee_rate_ppm": {
|
|
||||||
"type": "integer",
|
|
||||||
"format": "int32"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||||
"github.com/lightningnetwork/lnd/discovery"
|
"github.com/lightningnetwork/lnd/discovery"
|
||||||
|
"github.com/lightningnetwork/lnd/fn"
|
||||||
"github.com/lightningnetwork/lnd/kvdb"
|
"github.com/lightningnetwork/lnd/kvdb"
|
||||||
"github.com/lightningnetwork/lnd/lnrpc"
|
"github.com/lightningnetwork/lnd/lnrpc"
|
||||||
"github.com/lightningnetwork/lnd/lnwire"
|
"github.com/lightningnetwork/lnd/lnwire"
|
||||||
@@ -105,6 +106,14 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy,
|
|||||||
Edge: edge,
|
Edge: edge,
|
||||||
})
|
})
|
||||||
|
|
||||||
|
// Extract inbound fees from the ExtraOpaqueData.
|
||||||
|
var inboundWireFee lnwire.Fee
|
||||||
|
_, err = edge.ExtraOpaqueData.ExtractRecords(&inboundWireFee)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
inboundFee := models.NewInboundFeeFromWire(inboundWireFee)
|
||||||
|
|
||||||
// Add updated policy to list of policies to send to switch.
|
// Add updated policy to list of policies to send to switch.
|
||||||
policiesToUpdate[info.ChannelPoint] = models.ForwardingPolicy{
|
policiesToUpdate[info.ChannelPoint] = models.ForwardingPolicy{
|
||||||
BaseFee: edge.FeeBaseMSat,
|
BaseFee: edge.FeeBaseMSat,
|
||||||
@@ -112,7 +121,7 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy,
|
|||||||
TimeLockDelta: uint32(edge.TimeLockDelta),
|
TimeLockDelta: uint32(edge.TimeLockDelta),
|
||||||
MinHTLCOut: edge.MinHTLC,
|
MinHTLCOut: edge.MinHTLC,
|
||||||
MaxHTLC: edge.MaxHTLC,
|
MaxHTLC: edge.MaxHTLC,
|
||||||
InboundFee: newSchema.InboundFee,
|
InboundFee: inboundFee,
|
||||||
}
|
}
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
@@ -182,8 +191,15 @@ func (r *Manager) updateEdge(tx kvdb.RTx, chanPoint wire.OutPoint,
|
|||||||
newSchema.FeeRate,
|
newSchema.FeeRate,
|
||||||
)
|
)
|
||||||
|
|
||||||
inboundFee := newSchema.InboundFee.ToWire()
|
// If inbound fees are set, we update the edge with them.
|
||||||
if err := edge.ExtraOpaqueData.PackRecords(&inboundFee); err != nil {
|
err := fn.MapOptionZ(newSchema.InboundFee,
|
||||||
|
func(f models.InboundFee) error {
|
||||||
|
inboundWireFee := f.ToWire()
|
||||||
|
return edge.ExtraOpaqueData.PackRecords(
|
||||||
|
&inboundWireFee,
|
||||||
|
)
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+2
-1
@@ -22,6 +22,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/channeldb"
|
"github.com/lightningnetwork/lnd/channeldb"
|
||||||
"github.com/lightningnetwork/lnd/channeldb/models"
|
"github.com/lightningnetwork/lnd/channeldb/models"
|
||||||
"github.com/lightningnetwork/lnd/clock"
|
"github.com/lightningnetwork/lnd/clock"
|
||||||
|
"github.com/lightningnetwork/lnd/fn"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
"github.com/lightningnetwork/lnd/input"
|
"github.com/lightningnetwork/lnd/input"
|
||||||
"github.com/lightningnetwork/lnd/kvdb"
|
"github.com/lightningnetwork/lnd/kvdb"
|
||||||
@@ -290,7 +291,7 @@ type FeeSchema struct {
|
|||||||
|
|
||||||
// InboundFee is the inbound fee schedule that applies to forwards
|
// InboundFee is the inbound fee schedule that applies to forwards
|
||||||
// coming in through a channel to which this FeeSchema pertains.
|
// coming in through a channel to which this FeeSchema pertains.
|
||||||
InboundFee models.InboundFee
|
InboundFee fn.Option[models.InboundFee]
|
||||||
}
|
}
|
||||||
|
|
||||||
// ChannelPolicy holds the parameters that determine the policy we enforce
|
// ChannelPolicy holds the parameters that determine the policy we enforce
|
||||||
|
|||||||
+20
-11
@@ -46,6 +46,7 @@ import (
|
|||||||
"github.com/lightningnetwork/lnd/contractcourt"
|
"github.com/lightningnetwork/lnd/contractcourt"
|
||||||
"github.com/lightningnetwork/lnd/discovery"
|
"github.com/lightningnetwork/lnd/discovery"
|
||||||
"github.com/lightningnetwork/lnd/feature"
|
"github.com/lightningnetwork/lnd/feature"
|
||||||
|
"github.com/lightningnetwork/lnd/fn"
|
||||||
"github.com/lightningnetwork/lnd/funding"
|
"github.com/lightningnetwork/lnd/funding"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch"
|
"github.com/lightningnetwork/lnd/htlcswitch"
|
||||||
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
"github.com/lightningnetwork/lnd/htlcswitch/hop"
|
||||||
@@ -7216,27 +7217,35 @@ func (r *rpcServer) UpdateChannelPolicy(ctx context.Context,
|
|||||||
}
|
}
|
||||||
|
|
||||||
// By default, positive inbound fees are rejected.
|
// By default, positive inbound fees are rejected.
|
||||||
if !r.cfg.AcceptPositiveInboundFees {
|
if !r.cfg.AcceptPositiveInboundFees && req.InboundFee != nil {
|
||||||
if req.InboundBaseFeeMsat > 0 {
|
if req.InboundFee.BaseFeeMsat > 0 {
|
||||||
return nil, fmt.Errorf("positive values for inbound "+
|
return nil, fmt.Errorf("positive values for inbound "+
|
||||||
"base fee msat are not supported: %v",
|
"base fee msat are not supported: %v",
|
||||||
req.InboundBaseFeeMsat)
|
req.InboundFee.BaseFeeMsat)
|
||||||
}
|
}
|
||||||
if req.InboundFeeRatePpm > 0 {
|
if req.InboundFee.FeeRatePpm > 0 {
|
||||||
return nil, fmt.Errorf("positive values for inbound "+
|
return nil, fmt.Errorf("positive values for inbound "+
|
||||||
"fee rate ppm are not supported: %v",
|
"fee rate ppm are not supported: %v",
|
||||||
req.InboundFeeRatePpm)
|
req.InboundFee.FeeRatePpm)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If no inbound fees have been specified, we indicate with an empty
|
||||||
|
// option that the previous inbound fee should be retained during the
|
||||||
|
// edge update.
|
||||||
|
inboundFee := fn.None[models.InboundFee]()
|
||||||
|
if req.InboundFee != nil {
|
||||||
|
inboundFee = fn.Some(models.InboundFee{
|
||||||
|
Base: req.InboundFee.BaseFeeMsat,
|
||||||
|
Rate: req.InboundFee.FeeRatePpm,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
baseFeeMsat := lnwire.MilliSatoshi(req.BaseFeeMsat)
|
baseFeeMsat := lnwire.MilliSatoshi(req.BaseFeeMsat)
|
||||||
feeSchema := routing.FeeSchema{
|
feeSchema := routing.FeeSchema{
|
||||||
BaseFee: baseFeeMsat,
|
BaseFee: baseFeeMsat,
|
||||||
FeeRate: feeRateFixed,
|
FeeRate: feeRateFixed,
|
||||||
InboundFee: models.InboundFee{
|
InboundFee: inboundFee,
|
||||||
Base: req.InboundBaseFeeMsat,
|
|
||||||
Rate: req.InboundFeeRatePpm,
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
maxHtlc := lnwire.MilliSatoshi(req.MaxHtlcMsat)
|
maxHtlc := lnwire.MilliSatoshi(req.MaxHtlcMsat)
|
||||||
|
|||||||
Reference in new issue
Block a user