Skip to content

Commit 763787e

Browse files
committed
routing+lnrpc: add inbound fee policy update
1 parent e8c97de commit 763787e

File tree

7 files changed

+981
-836
lines changed

7 files changed

+981
-836
lines changed

cmd/lncli/commands.go

Lines changed: 44 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2166,6 +2166,31 @@ var updateChannelPolicyCommand = cli.Command{
21662166
"0.000001 (millionths). Can not be set at " +
21672167
"the same time as fee_rate",
21682168
},
2169+
cli.Int64Flag{
2170+
Name: "inbound_base_fee_msat",
2171+
Usage: "the base inbound fee in milli-satoshis that " +
2172+
"will be charged for each forwarded HTLC, " +
2173+
"regardless of payment size. Its value must " +
2174+
"be zero or negative - it is a discount " +
2175+
"for using a particular incoming channel. " +
2176+
"Note that forwards will be rejected if the " +
2177+
"discount exceeds the outbound fee " +
2178+
"(forward at a loss), and lead to " +
2179+
"penalization by the sender",
2180+
},
2181+
cli.Int64Flag{
2182+
Name: "inbound_fee_rate_ppm",
2183+
Usage: "the inbound fee rate that will be charged " +
2184+
"proportionally based on the value of each " +
2185+
"forwarded HTLC and the outbound fee. Fee " +
2186+
"rate is expressed in parts per million and " +
2187+
"must be zero or negative - it is a discount " +
2188+
"for using a particular incoming channel." +
2189+
"Note that forwards will be rejected if the " +
2190+
"discount exceeds the outbound fee " +
2191+
"(forward at a loss), and lead to " +
2192+
"penalization by the sender",
2193+
},
21692194
cli.Uint64Flag{
21702195
Name: "time_lock_delta",
21712196
Usage: "the CLTV delta that will be applied to all " +
@@ -2318,10 +2343,26 @@ func updateChannelPolicy(ctx *cli.Context) error {
23182343
}
23192344
}
23202345

2346+
inboundBaseFeeMsat := ctx.Int64("inbound_base_fee_msat")
2347+
if inboundBaseFeeMsat < math.MinInt32 ||
2348+
inboundBaseFeeMsat > 0 {
2349+
2350+
return errors.New("inbound_base_fee_msat out of range")
2351+
}
2352+
2353+
inboundFeeRatePpm := ctx.Int64("inbound_fee_rate_ppm")
2354+
if inboundFeeRatePpm < math.MinInt32 ||
2355+
inboundFeeRatePpm > 0 {
2356+
2357+
return errors.New("inbound_fee_rate_ppm out of range")
2358+
}
2359+
23212360
req := &lnrpc.PolicyUpdateRequest{
2322-
BaseFeeMsat: baseFee,
2323-
TimeLockDelta: uint32(timeLockDelta),
2324-
MaxHtlcMsat: ctx.Uint64("max_htlc_msat"),
2361+
BaseFeeMsat: baseFee,
2362+
TimeLockDelta: uint32(timeLockDelta),
2363+
MaxHtlcMsat: ctx.Uint64("max_htlc_msat"),
2364+
InboundBaseFeeMsat: int32(inboundBaseFeeMsat),
2365+
InboundFeeRatePpm: int32(inboundFeeRatePpm),
23252366
}
23262367

23272368
if ctx.IsSet("min_htlc_msat") {

lnrpc/lightning.pb.go

Lines changed: 880 additions & 833 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

lnrpc/lightning.proto

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4312,7 +4312,15 @@ message ChannelFeeReport {
43124312
// The effective fee rate in milli-satoshis. Computed by dividing the
43134313
// fee_per_mil value by 1 million.
43144314
double fee_rate = 4;
4315+
4316+
// The base fee charged regardless of the number of milli-satoshis sent.
4317+
int32 inbound_base_fee_msat = 6;
4318+
4319+
// The amount charged per milli-satoshis transferred expressed in
4320+
// millionths of a satoshi.
4321+
int32 inbound_fee_per_mil = 7;
43154322
}
4323+
43164324
message FeeReportResponse {
43174325
// An array of channel fee reports which describes the current fee schedule
43184326
// for each channel.
@@ -4363,7 +4371,11 @@ message PolicyUpdateRequest {
43634371

43644372
// If true, min_htlc_msat is applied.
43654373
bool min_htlc_msat_specified = 8;
4374+
4375+
int32 inbound_base_fee_msat = 10;
4376+
int32 inbound_fee_rate_ppm = 11;
43664377
}
4378+
43674379
enum UpdateFailure {
43684380
UPDATE_FAILURE_UNKNOWN = 0;
43694381
UPDATE_FAILURE_PENDING = 1;

lnrpc/lightning.swagger.json

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4238,6 +4238,16 @@
42384238
"type": "number",
42394239
"format": "double",
42404240
"description": "The effective fee rate in milli-satoshis. Computed by dividing the\nfee_per_mil value by 1 million."
4241+
},
4242+
"inbound_base_fee_msat": {
4243+
"type": "integer",
4244+
"format": "int32",
4245+
"description": "The base fee charged regardless of the number of milli-satoshis sent."
4246+
},
4247+
"inbound_fee_per_mil": {
4248+
"type": "integer",
4249+
"format": "int32",
4250+
"description": "The amount charged per milli-satoshis transferred expressed in\nmillionths of a satoshi."
42414251
}
42424252
}
42434253
},
@@ -6536,6 +6546,14 @@
65366546
"min_htlc_msat_specified": {
65376547
"type": "boolean",
65386548
"description": "If true, min_htlc_msat is applied."
6549+
},
6550+
"inbound_base_fee_msat": {
6551+
"type": "integer",
6552+
"format": "int32"
6553+
},
6554+
"inbound_fee_rate_ppm": {
6555+
"type": "integer",
6556+
"format": "int32"
65396557
}
65406558
}
65416559
},

routing/localchans/manager.go

Lines changed: 7 additions & 0 deletions
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

Lines changed: 4 additions & 0 deletions
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

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6877,6 +6877,15 @@ func (r *rpcServer) FeeReport(ctx context.Context,
68776877
edgePolicy.FeeProportionalMillionths
68786878
feeRate := float64(feeRateFixedPoint) / feeBase
68796879

6880+
// Decode inbound fee from extra data.
6881+
var inboundFee lnwire.Fee
6882+
_, err := edgePolicy.ExtraOpaqueData.ExtractRecords(
6883+
&inboundFee,
6884+
)
6885+
if err != nil {
6886+
return err
6887+
}
6888+
68806889
// TODO(roasbeef): also add stats for revenue for each
68816890
// channel
68826891
feeReports = append(feeReports, &lnrpc.ChannelFeeReport{
@@ -6885,6 +6894,9 @@ func (r *rpcServer) FeeReport(ctx context.Context,
68856894
BaseFeeMsat: int64(edgePolicy.FeeBaseMSat),
68866895
FeePerMil: int64(feeRateFixedPoint),
68876896
FeeRate: feeRate,
6897+
6898+
InboundBaseFeeMsat: inboundFee.BaseFee,
6899+
InboundFeePerMil: inboundFee.FeeRate,
68886900
})
68896901

68906902
return nil
@@ -7071,6 +7083,10 @@ func (r *rpcServer) UpdateChannelPolicy(ctx context.Context,
70717083
feeSchema := routing.FeeSchema{
70727084
BaseFee: baseFeeMsat,
70737085
FeeRate: feeRateFixed,
7086+
InboundFee: models.InboundFee{
7087+
Base: req.InboundBaseFeeMsat,
7088+
Rate: req.InboundFeeRatePpm,
7089+
},
70747090
}
70757091

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

0 commit comments

Comments
 (0)