routing+lnrpc: add inbound fee policy update

This commit is contained in:
Joost Jager 2022-09-21 14:05:53 +02:00
parent e8c97deaef
commit 763787e08c
7 changed files with 983 additions and 838 deletions

View File

@ -2166,6 +2166,31 @@ var updateChannelPolicyCommand = cli.Command{
"0.000001 (millionths). Can not be set at " +
"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{
Name: "time_lock_delta",
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{
BaseFeeMsat: baseFee,
TimeLockDelta: uint32(timeLockDelta),
MaxHtlcMsat: ctx.Uint64("max_htlc_msat"),
BaseFeeMsat: baseFee,
TimeLockDelta: uint32(timeLockDelta),
MaxHtlcMsat: ctx.Uint64("max_htlc_msat"),
InboundBaseFeeMsat: int32(inboundBaseFeeMsat),
InboundFeeRatePpm: int32(inboundFeeRatePpm),
}
if ctx.IsSet("min_htlc_msat") {

File diff suppressed because it is too large Load Diff

View File

@ -4312,7 +4312,15 @@ message ChannelFeeReport {
// The effective fee rate in milli-satoshis. Computed by dividing the
// fee_per_mil value by 1 million.
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 {
// An array of channel fee reports which describes the current fee schedule
// for each channel.
@ -4363,7 +4371,11 @@ message PolicyUpdateRequest {
// If true, min_htlc_msat is applied.
bool min_htlc_msat_specified = 8;
int32 inbound_base_fee_msat = 10;
int32 inbound_fee_rate_ppm = 11;
}
enum UpdateFailure {
UPDATE_FAILURE_UNKNOWN = 0;
UPDATE_FAILURE_PENDING = 1;

View File

@ -4238,6 +4238,16 @@
"type": "number",
"format": "double",
"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": {
"type": "boolean",
"description": "If true, min_htlc_msat is applied."
},
"inbound_base_fee_msat": {
"type": "integer",
"format": "int32"
},
"inbound_fee_rate_ppm": {
"type": "integer",
"format": "int32"
}
}
},

View File

@ -112,6 +112,7 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy,
TimeLockDelta: uint32(edge.TimeLockDelta),
MinHTLCOut: edge.MinHTLC,
MaxHTLC: edge.MaxHTLC,
InboundFee: newSchema.InboundFee,
}
return nil
@ -180,6 +181,12 @@ func (r *Manager) updateEdge(tx kvdb.RTx, chanPoint wire.OutPoint,
edge.FeeProportionalMillionths = lnwire.MilliSatoshi(
newSchema.FeeRate,
)
inboundFee := newSchema.InboundFee.ToWire()
if err := edge.ExtraOpaqueData.PackRecords(&inboundFee); err != nil {
return err
}
edge.TimeLockDelta = uint16(newSchema.TimeLockDelta)
// Retrieve negotiated channel htlc amt limits.

View File

@ -287,6 +287,10 @@ type FeeSchema struct {
// the effective fee rate charged per mSAT will be: (amount *
// FeeRate/1,000,000).
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

View File

@ -6877,6 +6877,15 @@ func (r *rpcServer) FeeReport(ctx context.Context,
edgePolicy.FeeProportionalMillionths
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
// channel
feeReports = append(feeReports, &lnrpc.ChannelFeeReport{
@ -6885,6 +6894,9 @@ func (r *rpcServer) FeeReport(ctx context.Context,
BaseFeeMsat: int64(edgePolicy.FeeBaseMSat),
FeePerMil: int64(feeRateFixedPoint),
FeeRate: feeRate,
InboundBaseFeeMsat: inboundFee.BaseFee,
InboundFeePerMil: inboundFee.FeeRate,
})
return nil
@ -7071,6 +7083,10 @@ func (r *rpcServer) UpdateChannelPolicy(ctx context.Context,
feeSchema := routing.FeeSchema{
BaseFee: baseFeeMsat,
FeeRate: feeRateFixed,
InboundFee: models.InboundFee{
Base: req.InboundBaseFeeMsat,
Rate: req.InboundFeeRatePpm,
},
}
maxHtlc := lnwire.MilliSatoshi(req.MaxHtlcMsat)