rpcserver+lnrpc: allow users to update max HTLC channel policies

In this commit, we enable callers of UpdateChannelPolicy to
specify their desired max HTLC forwarding policy for one or
multiple channels.
This commit is contained in:
Valentine Wallace 2019-08-19 17:55:30 -07:00 committed by Joost Jager
parent 9a52cb6dab
commit 4b9da07e78
No known key found for this signature in database
GPG Key ID: A61B9D4C393C59C7
5 changed files with 571 additions and 522 deletions

File diff suppressed because it is too large Load Diff

View File

@ -2395,6 +2395,9 @@ message PolicyUpdateRequest {
/// The required timelock delta for HTLCs forwarded over the channel.
uint32 time_lock_delta = 5 [json_name = "time_lock_delta"];
/// If set, the maximum HTLC size in milli-satoshis. If unset, the maximum HTLC will be unchanged.
uint64 max_htlc_msat = 6 [json_name = "max_htlc_msat"];
}
message PolicyUpdateResponse {
}

View File

@ -3150,6 +3150,11 @@
"type": "integer",
"format": "int64",
"description": "/ The required timelock delta for HTLCs forwarded over the channel."
},
"max_htlc_msat": {
"type": "string",
"format": "uint64",
"description": "/ If set, the maximum HTLC size in milli-satoshis. If unset, the maximum HTLC will be unchanged."
}
}
},

View File

@ -1122,6 +1122,15 @@ type expectedChanUpdate struct {
chanPoint *lnrpc.ChannelPoint
}
// calculateMaxHtlc re-implements the RequiredRemoteChannelReserve of the
// funding manager's config, which corresponds to the maximum MaxHTLC value we
// allow users to set when updating a channel policy.
func calculateMaxHtlc(chanCap btcutil.Amount) uint64 {
reserve := lnwire.NewMSatFromSatoshis(chanCap / 100)
max := lnwire.NewMSatFromSatoshis(chanCap) - reserve
return uint64(max)
}
// waitForChannelUpdate waits for a node to receive the expected channel
// updates.
func waitForChannelUpdate(t *harnessTest, subscription graphSubscription,
@ -1292,6 +1301,10 @@ func checkChannelPolicy(policy, expectedPolicy *lnrpc.RoutingPolicy) error {
return fmt.Errorf("expected min htlc %v, got %v",
expectedPolicy.MinHtlc, policy.MinHtlc)
}
if policy.MaxHtlcMsat != expectedPolicy.MaxHtlcMsat {
return fmt.Errorf("expected max htlc %v, got %v",
expectedPolicy.MaxHtlcMsat, policy.MaxHtlcMsat)
}
if policy.Disabled != expectedPolicy.Disabled {
return errors.New("edge should be disabled but isn't")
}
@ -1310,6 +1323,7 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
defaultTimeLockDelta = lnd.DefaultBitcoinTimeLockDelta
defaultMinHtlc = 1000
)
defaultMaxHtlc := calculateMaxHtlc(lnd.MaxBtcFundingAmount)
// Launch notification clients for all nodes, such that we can
// get notified when they discover new channels and updates in the
@ -1344,6 +1358,7 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
FeeRateMilliMsat: defaultFeeRate,
TimeLockDelta: defaultTimeLockDelta,
MinHtlc: defaultMinHtlc,
MaxHtlcMsat: defaultMaxHtlc,
}
for _, graphSub := range graphSubs {
@ -1422,6 +1437,7 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
FeeRateMilliMsat: defaultFeeRate,
TimeLockDelta: defaultTimeLockDelta,
MinHtlc: customMinHtlc,
MaxHtlcMsat: defaultMaxHtlc,
}
expectedPolicyCarol := &lnrpc.RoutingPolicy{
@ -1429,6 +1445,7 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
FeeRateMilliMsat: defaultFeeRate,
TimeLockDelta: defaultTimeLockDelta,
MinHtlc: defaultMinHtlc,
MaxHtlcMsat: defaultMaxHtlc,
}
for _, graphSub := range graphSubs {
@ -1589,24 +1606,27 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
sendResp.PaymentError)
}
// With our little cluster set up, we'll update the fees for the
// channel Bob side of the Alice->Bob channel, and make sure all nodes
// learn about it.
// With our little cluster set up, we'll update the fees and the max htlc
// size for the Bob side of the Alice->Bob channel, and make sure
// all nodes learn about it.
baseFee := int64(1500)
feeRate := int64(12)
timeLockDelta := uint32(66)
maxHtlc := uint64(500000)
expectedPolicy = &lnrpc.RoutingPolicy{
FeeBaseMsat: baseFee,
FeeRateMilliMsat: testFeeBase * feeRate,
TimeLockDelta: timeLockDelta,
MinHtlc: defaultMinHtlc,
MaxHtlcMsat: maxHtlc,
}
req := &lnrpc.PolicyUpdateRequest{
BaseFeeMsat: baseFee,
FeeRate: float64(feeRate),
TimeLockDelta: timeLockDelta,
MaxHtlcMsat: maxHtlc,
Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{
ChanPoint: chanPoint,
},
@ -1689,22 +1709,25 @@ func testUpdateChannelPolicy(net *lntest.NetworkHarness, t *harnessTest) {
baseFee = int64(800)
feeRate = int64(123)
timeLockDelta = uint32(22)
maxHtlc = maxHtlc * 2
expectedPolicy.FeeBaseMsat = baseFee
expectedPolicy.FeeRateMilliMsat = testFeeBase * feeRate
expectedPolicy.TimeLockDelta = timeLockDelta
expectedPolicy.MaxHtlcMsat = maxHtlc
req = &lnrpc.PolicyUpdateRequest{
BaseFeeMsat: baseFee,
FeeRate: float64(feeRate),
TimeLockDelta: timeLockDelta,
MaxHtlcMsat: maxHtlc,
}
req.Scope = &lnrpc.PolicyUpdateRequest_Global{}
ctxt, _ = context.WithTimeout(ctxb, defaultTimeout)
_, err = net.Alice.UpdateChannelPolicy(ctxt, req)
if err != nil {
t.Fatalf("unable to get alice's balance: %v", err)
t.Fatalf("unable to update alice's channel policy: %v", err)
}
// Wait for all nodes to have seen the policy updates for both of
@ -3950,7 +3973,8 @@ func assertAmountPaid(t *harnessTest, channelName string,
// listenerNode has received the policy update.
func updateChannelPolicy(t *harnessTest, node *lntest.HarnessNode,
chanPoint *lnrpc.ChannelPoint, baseFee int64, feeRate int64,
timeLockDelta uint32, listenerNode *lntest.HarnessNode) {
timeLockDelta uint32, maxHtlc uint64, listenerNode *lntest.HarnessNode) {
ctxb := context.Background()
expectedPolicy := &lnrpc.RoutingPolicy{
@ -3958,6 +3982,7 @@ func updateChannelPolicy(t *harnessTest, node *lntest.HarnessNode,
FeeRateMilliMsat: feeRate,
TimeLockDelta: timeLockDelta,
MinHtlc: 1000, // default value
MaxHtlcMsat: maxHtlc,
}
updateFeeReq := &lnrpc.PolicyUpdateRequest{
@ -3967,6 +3992,7 @@ func updateChannelPolicy(t *harnessTest, node *lntest.HarnessNode,
Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{
ChanPoint: chanPoint,
},
MaxHtlcMsat: maxHtlc,
}
ctxt, _ := context.WithTimeout(ctxb, defaultTimeout)
@ -4143,14 +4169,15 @@ func testMultiHopPayments(net *lntest.NetworkHarness, t *harnessTest) {
// Set the fee policies of the Alice -> Bob and the Dave -> Alice
// channel edges to relatively large non default values. This makes it
// possible to pick up more subtle fee calculation errors.
maxHtlc := uint64(calculateMaxHtlc(chanAmt))
updateChannelPolicy(
t, net.Alice, chanPointAlice, 1000, 100000,
lnd.DefaultBitcoinTimeLockDelta, carol,
lnd.DefaultBitcoinTimeLockDelta, maxHtlc, carol,
)
updateChannelPolicy(
t, dave, chanPointDave, 5000, 150000,
lnd.DefaultBitcoinTimeLockDelta, carol,
lnd.DefaultBitcoinTimeLockDelta, maxHtlc, carol,
)
// Using Carol as the source, pay to the 5 invoices from Bob created
@ -12372,18 +12399,21 @@ func testRouteFeeCutoff(net *lntest.NetworkHarness, t *harnessTest) {
baseFee := int64(10000)
feeRate := int64(5)
timeLockDelta := uint32(lnd.DefaultBitcoinTimeLockDelta)
maxHtlc := calculateMaxHtlc(chanAmt)
expectedPolicy := &lnrpc.RoutingPolicy{
FeeBaseMsat: baseFee,
FeeRateMilliMsat: testFeeBase * feeRate,
TimeLockDelta: timeLockDelta,
MinHtlc: 1000, // default value
MaxHtlcMsat: maxHtlc,
}
updateFeeReq := &lnrpc.PolicyUpdateRequest{
BaseFeeMsat: baseFee,
FeeRate: float64(feeRate),
TimeLockDelta: timeLockDelta,
MaxHtlcMsat: maxHtlc,
Scope: &lnrpc.PolicyUpdateRequest_ChanPoint{
ChanPoint: chanPointCarolDave,
},
@ -12634,6 +12664,7 @@ func testSendUpdateDisableChannel(net *lntest.NetworkHarness, t *harnessTest) {
FeeRateMilliMsat: int64(lnd.DefaultBitcoinFeeRate),
TimeLockDelta: lnd.DefaultBitcoinTimeLockDelta,
MinHtlc: 1000, // default value
MaxHtlcMsat: calculateMaxHtlc(chanAmt),
Disabled: true,
}

View File

@ -4602,6 +4602,7 @@ func (r *rpcServer) UpdateChannelPolicy(ctx context.Context,
chanPolicy := routing.ChannelPolicy{
FeeSchema: feeSchema,
TimeLockDelta: req.TimeLockDelta,
MaxHTLC: lnwire.MilliSatoshi(req.MaxHtlcMsat),
}
rpcsLog.Debugf("[updatechanpolicy] updating channel policy base_fee=%v, "+