Skip to content

Commit 2e369ca

Browse files
committed
routing+lnrpc: add inbound fee policy update
1 parent 2dbda6c commit 2e369ca

File tree

7 files changed

+974
-828
lines changed

7 files changed

+974
-828
lines changed

cmd/lncli/commands.go

+44-3
Original file line numberDiff line numberDiff line change
@@ -2091,6 +2091,31 @@ var updateChannelPolicyCommand = cli.Command{
20912091
"0.000001 (millionths). Can not be set at " +
20922092
"the same time as fee_rate",
20932093
},
2094+
cli.Int64Flag{
2095+
Name: "inbound_base_fee_msat",
2096+
Usage: "the base inbound fee in milli-satoshis that " +
2097+
"will be charged for each forwarded HTLC, " +
2098+
"regardless of payment size. Its value must " +
2099+
"be zero or negative - it is a discount " +
2100+
"for using a particular incoming channel. " +
2101+
"Note that forwards will be rejected if the " +
2102+
"discount exceeds the outbound fee " +
2103+
"(forward at a loss), and lead to " +
2104+
"penalization by the sender",
2105+
},
2106+
cli.Int64Flag{
2107+
Name: "inbound_fee_rate_ppm",
2108+
Usage: "the inbound fee rate that will be charged " +
2109+
"proportionally based on the value of each " +
2110+
"forwarded HTLC and the outbound fee. Fee " +
2111+
"rate is expressed in parts per million and " +
2112+
"must be zero or negative - it is a discount " +
2113+
"for using a particular incoming channel." +
2114+
"Note that forwards will be rejected if the " +
2115+
"discount exceeds the outbound fee " +
2116+
"(forward at a loss), and lead to " +
2117+
"penalization by the sender",
2118+
},
20942119
cli.Uint64Flag{
20952120
Name: "time_lock_delta",
20962121
Usage: "the CLTV delta that will be applied to all " +
@@ -2242,10 +2267,26 @@ func updateChannelPolicy(ctx *cli.Context) error {
22422267
}
22432268
}
22442269

2270+
inboundBaseFeeMsat := ctx.Int64("inbound_base_fee_msat")
2271+
if inboundBaseFeeMsat < math.MinInt32 ||
2272+
inboundBaseFeeMsat > 0 {
2273+
2274+
return errors.New("inbound_base_fee_msat out of range")
2275+
}
2276+
2277+
inboundFeeRatePpm := ctx.Int64("inbound_fee_rate_ppm")
2278+
if inboundFeeRatePpm < math.MinInt32 ||
2279+
inboundFeeRatePpm > 0 {
2280+
2281+
return errors.New("inbound_fee_rate_ppm out of range")
2282+
}
2283+
22452284
req := &lnrpc.PolicyUpdateRequest{
2246-
BaseFeeMsat: baseFee,
2247-
TimeLockDelta: uint32(timeLockDelta),
2248-
MaxHtlcMsat: ctx.Uint64("max_htlc_msat"),
2285+
BaseFeeMsat: baseFee,
2286+
TimeLockDelta: uint32(timeLockDelta),
2287+
MaxHtlcMsat: ctx.Uint64("max_htlc_msat"),
2288+
InboundBaseFeeMsat: int32(inboundBaseFeeMsat),
2289+
InboundFeeRatePpm: int32(inboundFeeRatePpm),
22492290
}
22502291

22512292
if ctx.IsSet("min_htlc_msat") {

lnrpc/lightning.pb.go

+873-825
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lnrpc/lightning.proto

+12
Original file line numberDiff line numberDiff line change
@@ -4274,7 +4274,15 @@ message ChannelFeeReport {
42744274
// The effective fee rate in milli-satoshis. Computed by dividing the
42754275
// fee_per_mil value by 1 million.
42764276
double fee_rate = 4;
4277+
4278+
// The base fee charged regardless of the number of milli-satoshis sent.
4279+
int32 inbound_base_fee_msat = 6;
4280+
4281+
// The amount charged per milli-satoshis transferred expressed in
4282+
// millionths of a satoshi.
4283+
int32 inbound_fee_per_mil = 7;
42774284
}
4285+
42784286
message FeeReportResponse {
42794287
// An array of channel fee reports which describes the current fee schedule
42804288
// for each channel.
@@ -4325,7 +4333,11 @@ message PolicyUpdateRequest {
43254333

43264334
// If true, min_htlc_msat is applied.
43274335
bool min_htlc_msat_specified = 8;
4336+
4337+
int32 inbound_base_fee_msat = 10;
4338+
int32 inbound_fee_rate_ppm = 11;
43284339
}
4340+
43294341
enum UpdateFailure {
43304342
UPDATE_FAILURE_UNKNOWN = 0;
43314343
UPDATE_FAILURE_PENDING = 1;

lnrpc/lightning.swagger.json

+18
Original file line numberDiff line numberDiff line change
@@ -4194,6 +4194,16 @@
41944194
"type": "number",
41954195
"format": "double",
41964196
"description": "The effective fee rate in milli-satoshis. Computed by dividing the\nfee_per_mil value by 1 million."
4197+
},
4198+
"inbound_base_fee_msat": {
4199+
"type": "integer",
4200+
"format": "int32",
4201+
"description": "The base fee charged regardless of the number of milli-satoshis sent."
4202+
},
4203+
"inbound_fee_per_mil": {
4204+
"type": "integer",
4205+
"format": "int32",
4206+
"description": "The amount charged per milli-satoshis transferred expressed in\nmillionths of a satoshi."
41974207
}
41984208
}
41994209
},
@@ -6469,6 +6479,14 @@
64696479
"min_htlc_msat_specified": {
64706480
"type": "boolean",
64716481
"description": "If true, min_htlc_msat is applied."
6482+
},
6483+
"inbound_base_fee_msat": {
6484+
"type": "integer",
6485+
"format": "int32"
6486+
},
6487+
"inbound_fee_rate_ppm": {
6488+
"type": "integer",
6489+
"format": "int32"
64726490
}
64736491
}
64746492
},

routing/localchans/manager.go

+7
Original file line numberDiff line numberDiff line change
@@ -112,6 +112,7 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy,
112112
TimeLockDelta: uint32(edge.TimeLockDelta),
113113
MinHTLCOut: edge.MinHTLC,
114114
MaxHTLC: edge.MaxHTLC,
115+
InboundFee: newSchema.InboundFee,
115116
}
116117

117118
return nil
@@ -180,6 +181,12 @@ func (r *Manager) updateEdge(tx kvdb.RTx, chanPoint wire.OutPoint,
180181
edge.FeeProportionalMillionths = lnwire.MilliSatoshi(
181182
newSchema.FeeRate,
182183
)
184+
185+
inboundFee := newSchema.InboundFee.ToWire()
186+
if err := edge.ExtraOpaqueData.PackRecords(&inboundFee); err != nil {
187+
return err
188+
}
189+
183190
edge.TimeLockDelta = uint16(newSchema.TimeLockDelta)
184191

185192
// Retrieve negotiated channel htlc amt limits.

routing/router.go

+4
Original file line numberDiff line numberDiff line change
@@ -287,6 +287,10 @@ type FeeSchema struct {
287287
// the effective fee rate charged per mSAT will be: (amount *
288288
// FeeRate/1,000,000).
289289
FeeRate uint32
290+
291+
// InboundFee is the inbound fee schedule that applies to forwards
292+
// coming in through a channel to which this FeeSchema pertains.
293+
InboundFee models.InboundFee
290294
}
291295

292296
// ChannelPolicy holds the parameters that determine the policy we enforce

rpcserver.go

+16
Original file line numberDiff line numberDiff line change
@@ -6811,6 +6811,15 @@ func (r *rpcServer) FeeReport(ctx context.Context,
68116811
edgePolicy.FeeProportionalMillionths
68126812
feeRate := float64(feeRateFixedPoint) / feeBase
68136813

6814+
// Decode inbound fee from extra data.
6815+
var inboundFee lnwire.Fee
6816+
_, err := edgePolicy.ExtraOpaqueData.ExtractRecords(
6817+
&inboundFee,
6818+
)
6819+
if err != nil {
6820+
return err
6821+
}
6822+
68146823
// TODO(roasbeef): also add stats for revenue for each
68156824
// channel
68166825
feeReports = append(feeReports, &lnrpc.ChannelFeeReport{
@@ -6819,6 +6828,9 @@ func (r *rpcServer) FeeReport(ctx context.Context,
68196828
BaseFeeMsat: int64(edgePolicy.FeeBaseMSat),
68206829
FeePerMil: int64(feeRateFixedPoint),
68216830
FeeRate: feeRate,
6831+
6832+
InboundBaseFeeMsat: inboundFee.BaseFee,
6833+
InboundFeePerMil: inboundFee.FeeRate,
68226834
})
68236835

68246836
return nil
@@ -7005,6 +7017,10 @@ func (r *rpcServer) UpdateChannelPolicy(ctx context.Context,
70057017
feeSchema := routing.FeeSchema{
70067018
BaseFee: baseFeeMsat,
70077019
FeeRate: feeRateFixed,
7020+
InboundFee: models.InboundFee{
7021+
Base: req.InboundBaseFeeMsat,
7022+
Rate: req.InboundFeeRatePpm,
7023+
},
70087024
}
70097025

70107026
maxHtlc := lnwire.MilliSatoshi(req.MaxHtlcMsat)

0 commit comments

Comments
 (0)