routing+lnrpc: add inbound fee policy update

This commit is contained in:
Joost Jager committed 2024-03-31 16:49:19 +02:00
1 parent e8c97deaef
commit 763787e08c
7 files changed
+983 -838

No files matched your search

+44 -3
View File
@@ -2166,6 +2166,31 @@ var updateChannelPolicyCommand = cli.Command{
"0.000001 (millionths). Can not be set at " + "0.000001 (millionths). Can not be set at " +
"the same time as fee_rate", "the same time as fee_rate",
}, },
cli.Int64Flag{
Name: "inbound_base_fee_msat",
Usage: "the base inbound fee in milli-satoshis that " +
"will be charged for each forwarded HTLC, " +
"regardless of payment size. Its value must " +
"be zero or negative - it is a discount " +
"for using a particular incoming channel. " +
"Note that forwards will be rejected if the " +
"discount exceeds the outbound fee " +
"(forward at a loss), and lead to " +
"penalization by the sender",
},
cli.Int64Flag{
Name: "inbound_fee_rate_ppm",
Usage: "the inbound fee rate that will be charged " +
"proportionally based on the value of each " +
"forwarded HTLC and the outbound fee. Fee " +
"rate is expressed in parts per million and " +
"must be zero or negative - it is a discount " +
"for using a particular incoming channel." +
"Note that forwards will be rejected if the " +
"discount exceeds the outbound fee " +
"(forward at a loss), and lead to " +
"penalization by the sender",
},
cli.Uint64Flag{ cli.Uint64Flag{
Name: "time_lock_delta", Name: "time_lock_delta",
Usage: "the CLTV delta that will be applied to all " + Usage: "the CLTV delta that will be applied to all " +
@@ -2318,10 +2343,26 @@ func updateChannelPolicy(ctx *cli.Context) error {
} }
} }
inboundBaseFeeMsat := ctx.Int64("inbound_base_fee_msat")
if inboundBaseFeeMsat < math.MinInt32 ||
inboundBaseFeeMsat > 0 {
return errors.New("inbound_base_fee_msat out of range")
}
inboundFeeRatePpm := ctx.Int64("inbound_fee_rate_ppm")
if inboundFeeRatePpm < math.MinInt32 ||
inboundFeeRatePpm > 0 {
return errors.New("inbound_fee_rate_ppm out of range")
}
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),
InboundFeeRatePpm: int32(inboundFeeRatePpm),
} }
if ctx.IsSet("min_htlc_msat") { if ctx.IsSet("min_htlc_msat") {
+882 -835
View File
File diff suppressed because it is too large. Load diff
+12
View File
@@ -4312,7 +4312,15 @@ message ChannelFeeReport {
// The effective fee rate in milli-satoshis. Computed by dividing the // The effective fee rate in milli-satoshis. Computed by dividing the
// fee_per_mil value by 1 million. // fee_per_mil value by 1 million.
double fee_rate = 4; double fee_rate = 4;
// The base fee charged regardless of the number of milli-satoshis sent.
int32 inbound_base_fee_msat = 6;
// The amount charged per milli-satoshis transferred expressed in
// millionths of a satoshi.
int32 inbound_fee_per_mil = 7;
} }
message FeeReportResponse { message FeeReportResponse {
// An array of channel fee reports which describes the current fee schedule // An array of channel fee reports which describes the current fee schedule
// for each channel. // for each channel.
@@ -4363,7 +4371,11 @@ 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;
int32 inbound_fee_rate_ppm = 11;
} }
enum UpdateFailure { enum UpdateFailure {
UPDATE_FAILURE_UNKNOWN = 0; UPDATE_FAILURE_UNKNOWN = 0;
UPDATE_FAILURE_PENDING = 1; UPDATE_FAILURE_PENDING = 1;
+18
View File
@@ -4238,6 +4238,16 @@
"type": "number", "type": "number",
"format": "double", "format": "double",
"description": "The effective fee rate in milli-satoshis. Computed by dividing the\nfee_per_mil value by 1 million." "description": "The effective fee rate in milli-satoshis. Computed by dividing the\nfee_per_mil value by 1 million."
},
"inbound_base_fee_msat": {
"type": "integer",
"format": "int32",
"description": "The base fee charged regardless of the number of milli-satoshis sent."
},
"inbound_fee_per_mil": {
"type": "integer",
"format": "int32",
"description": "The amount charged per milli-satoshis transferred expressed in\nmillionths of a satoshi."
} }
} }
}, },
@@ -6536,6 +6546,14 @@
"min_htlc_msat_specified": { "min_htlc_msat_specified": {
"type": "boolean", "type": "boolean",
"description": "If true, min_htlc_msat is applied." "description": "If true, min_htlc_msat is applied."
},
"inbound_base_fee_msat": {
"type": "integer",
"format": "int32"
},
"inbound_fee_rate_ppm": {
"type": "integer",
"format": "int32"
} }
} }
}, },
+7
View File
@@ -112,6 +112,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,
} }
return nil return nil
@@ -180,6 +181,12 @@ func (r *Manager) updateEdge(tx kvdb.RTx, chanPoint wire.OutPoint,
edge.FeeProportionalMillionths = lnwire.MilliSatoshi( edge.FeeProportionalMillionths = lnwire.MilliSatoshi(
newSchema.FeeRate, newSchema.FeeRate,
) )
inboundFee := newSchema.InboundFee.ToWire()
if err := edge.ExtraOpaqueData.PackRecords(&inboundFee); err != nil {
return err
}
edge.TimeLockDelta = uint16(newSchema.TimeLockDelta) edge.TimeLockDelta = uint16(newSchema.TimeLockDelta)
// Retrieve negotiated channel htlc amt limits. // Retrieve negotiated channel htlc amt limits.
+4
View File
@@ -287,6 +287,10 @@ type FeeSchema struct {
// the effective fee rate charged per mSAT will be: (amount * // the effective fee rate charged per mSAT will be: (amount *
// FeeRate/1,000,000). // FeeRate/1,000,000).
FeeRate uint32 FeeRate uint32
// InboundFee is the inbound fee schedule that applies to forwards
// coming in through a channel to which this FeeSchema pertains.
InboundFee models.InboundFee
} }
// ChannelPolicy holds the parameters that determine the policy we enforce // ChannelPolicy holds the parameters that determine the policy we enforce
+16
View File
@@ -6877,6 +6877,15 @@ func (r *rpcServer) FeeReport(ctx context.Context,
edgePolicy.FeeProportionalMillionths edgePolicy.FeeProportionalMillionths
feeRate := float64(feeRateFixedPoint) / feeBase feeRate := float64(feeRateFixedPoint) / feeBase
// Decode inbound fee from extra data.
var inboundFee lnwire.Fee
_, err := edgePolicy.ExtraOpaqueData.ExtractRecords(
&inboundFee,
)
if err != nil {
return err
}
// TODO(roasbeef): also add stats for revenue for each // TODO(roasbeef): also add stats for revenue for each
// channel // channel
feeReports = append(feeReports, &lnrpc.ChannelFeeReport{ feeReports = append(feeReports, &lnrpc.ChannelFeeReport{
@@ -6885,6 +6894,9 @@ func (r *rpcServer) FeeReport(ctx context.Context,
BaseFeeMsat: int64(edgePolicy.FeeBaseMSat), BaseFeeMsat: int64(edgePolicy.FeeBaseMSat),
FeePerMil: int64(feeRateFixedPoint), FeePerMil: int64(feeRateFixedPoint),
FeeRate: feeRate, FeeRate: feeRate,
InboundBaseFeeMsat: inboundFee.BaseFee,
InboundFeePerMil: inboundFee.FeeRate,
}) })
return nil return nil
@@ -7071,6 +7083,10 @@ func (r *rpcServer) UpdateChannelPolicy(ctx context.Context,
feeSchema := routing.FeeSchema{ feeSchema := routing.FeeSchema{
BaseFee: baseFeeMsat, BaseFee: baseFeeMsat,
FeeRate: feeRateFixed, FeeRate: feeRateFixed,
InboundFee: models.InboundFee{
Base: req.InboundBaseFeeMsat,
Rate: req.InboundFeeRatePpm,
},
} }
maxHtlc := lnwire.MilliSatoshi(req.MaxHtlcMsat) maxHtlc := lnwire.MilliSatoshi(req.MaxHtlcMsat)