From ddb98fcc41081fcb2dd09b63806dce42a19edf20 Mon Sep 17 00:00:00 2001 From: Joost Jager Date: Fri, 15 Nov 2019 10:09:27 +0100 Subject: [PATCH] multi: distinguish between htlc in and out constraints --- chainregistry.go | 8 ++++++-- fundingmanager.go | 16 ++++++++++------ fundingmanager_test.go | 22 ++++++++++++---------- htlcswitch/link.go | 10 ++++------ htlcswitch/link_test.go | 6 +++--- htlcswitch/test_utils.go | 2 +- peer.go | 4 ++-- pilot.go | 4 ++-- routing/localchans/manager.go | 2 +- rpcserver.go | 8 ++++---- server.go | 5 +++-- 11 files changed, 48 insertions(+), 39 deletions(-) diff --git a/chainregistry.go b/chainregistry.go index ee07caaa..49805f19 100644 --- a/chainregistry.go +++ b/chainregistry.go @@ -130,6 +130,8 @@ type chainControl struct { wallet *lnwallet.LightningWallet routingPolicy htlcswitch.ForwardingPolicy + + minHtlcIn lnwire.MilliSatoshi } // newChainControlFromConfig attempts to create a chainControl instance @@ -157,21 +159,23 @@ func newChainControlFromConfig(cfg *config, chanDB *channeldb.DB, switch registeredChains.PrimaryChain() { case bitcoinChain: cc.routingPolicy = htlcswitch.ForwardingPolicy{ - MinHTLC: cfg.Bitcoin.MinHTLC, + MinHTLCOut: cfg.Bitcoin.MinHTLC, BaseFee: cfg.Bitcoin.BaseFee, FeeRate: cfg.Bitcoin.FeeRate, TimeLockDelta: cfg.Bitcoin.TimeLockDelta, } + cc.minHtlcIn = cfg.Bitcoin.MinHTLC cc.feeEstimator = chainfee.NewStaticEstimator( defaultBitcoinStaticFeePerKW, 0, ) case litecoinChain: cc.routingPolicy = htlcswitch.ForwardingPolicy{ - MinHTLC: cfg.Litecoin.MinHTLC, + MinHTLCOut: cfg.Litecoin.MinHTLC, BaseFee: cfg.Litecoin.BaseFee, FeeRate: cfg.Litecoin.FeeRate, TimeLockDelta: cfg.Litecoin.TimeLockDelta, } + cc.minHtlcIn = cfg.Litecoin.MinHTLC cc.feeEstimator = chainfee.NewStaticEstimator( defaultLitecoinStaticFeePerKW, 0, ) diff --git a/fundingmanager.go b/fundingmanager.go index 3c4538e2..77b3f24f 100644 --- a/fundingmanager.go +++ b/fundingmanager.go @@ -285,6 +285,10 @@ type fundingConfig struct { // initially announcing channels. DefaultRoutingPolicy htlcswitch.ForwardingPolicy + // DefaultMinHtlcIn is the default minimum incoming htlc value that is + // set as a channel parameter. + DefaultMinHtlcIn lnwire.MilliSatoshi + // NumRequiredConfs is a function closure that helps the funding // manager decide how many confirmations it should require for a // channel extended to it. The function is able to take into account @@ -1300,7 +1304,7 @@ func (f *fundingManager) handleFundingOpen(fmsg *fundingOpenMsg) { chanReserve := f.cfg.RequiredRemoteChanReserve(amt, msg.DustLimit) maxValue := f.cfg.RequiredRemoteMaxValue(amt) maxHtlcs := f.cfg.RequiredRemoteMaxHTLCs(amt) - minHtlc := f.cfg.DefaultRoutingPolicy.MinHTLC + minHtlc := f.cfg.DefaultMinHtlcIn // Once the reservation has been created successfully, we add it to // this peer's map of pending reservations to track this particular @@ -2806,7 +2810,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { var ( peerKey = msg.peer.IdentityKey() localAmt = msg.localFundingAmt - minHtlc = msg.minHtlc + minHtlcIn = msg.minHtlcIn remoteCsvDelay = msg.remoteCsvDelay ) @@ -2922,8 +2926,8 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { } // If no minimum HTLC value was specified, use the default one. - if minHtlc == 0 { - minHtlc = f.cfg.DefaultRoutingPolicy.MinHTLC + if minHtlcIn == 0 { + minHtlcIn = f.cfg.DefaultMinHtlcIn } // If a pending channel map for this peer isn't already created, then @@ -2938,7 +2942,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { resCtx := &reservationWithCtx{ chanAmt: capacity, remoteCsvDelay: remoteCsvDelay, - remoteMinHtlc: minHtlc, + remoteMinHtlc: minHtlcIn, reservation: reservation, peer: msg.peer, updates: msg.updates, @@ -2972,7 +2976,7 @@ func (f *fundingManager) handleInitFundingMsg(msg *initFundingMsg) { DustLimit: ourContribution.DustLimit, MaxValueInFlight: maxValue, ChannelReserve: chanReserve, - HtlcMinimum: minHtlc, + HtlcMinimum: minHtlcIn, FeePerKiloWeight: uint32(commitFeePerKw), CsvDelay: remoteCsvDelay, MaxAcceptedHTLCs: maxHtlcs, diff --git a/fundingmanager_test.go b/fundingmanager_test.go index 77bfbaa6..3221f20d 100644 --- a/fundingmanager_test.go +++ b/fundingmanager_test.go @@ -336,11 +336,12 @@ func createTestFundingManager(t *testing.T, privKey *btcec.PrivateKey, return nil, fmt.Errorf("unable to find channel") }, DefaultRoutingPolicy: htlcswitch.ForwardingPolicy{ - MinHTLC: 5, + MinHTLCOut: 5, BaseFee: 100, FeeRate: 1000, TimeLockDelta: 10, }, + DefaultMinHtlcIn: 5, NumRequiredConfs: func(chanAmt btcutil.Amount, pushAmt lnwire.MilliSatoshi) uint16 { return 3 @@ -464,11 +465,12 @@ func recreateAliceFundingManager(t *testing.T, alice *testNode) { TempChanIDSeed: oldCfg.TempChanIDSeed, FindChannel: oldCfg.FindChannel, DefaultRoutingPolicy: htlcswitch.ForwardingPolicy{ - MinHTLC: 5, + MinHTLCOut: 5, BaseFee: 100, FeeRate: 1000, TimeLockDelta: 10, }, + DefaultMinHtlcIn: 5, RequiredRemoteMaxValue: oldCfg.RequiredRemoteMaxValue, PublishTransaction: func(txn *wire.MsgTx) error { publishChan <- txn @@ -926,7 +928,7 @@ func assertChannelAnnouncements(t *testing.T, alice, bob *testNode, // _other_ node. other := (j + 1) % 2 minHtlc := nodes[other].fundingMgr.cfg. - DefaultRoutingPolicy.MinHTLC + DefaultMinHtlcIn // We might expect a custom MinHTLC value. if len(customMinHtlc) > 0 { @@ -2325,7 +2327,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { // This is the custom parameters we'll use. const csvDelay = 67 - const minHtlc = 1234 + const minHtlcIn = 1234 // We will consume the channel updates as we go, so no buffering is // needed. @@ -2344,7 +2346,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { localFundingAmt: localAmt, pushAmt: lnwire.NewMSatFromSatoshis(pushAmt), private: false, - minHtlc: minHtlc, + minHtlcIn: minHtlcIn, remoteCsvDelay: csvDelay, updates: updateChan, err: errChan, @@ -2381,9 +2383,9 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { } // Check that the custom minHTLC value is sent. - if openChannelReq.HtlcMinimum != minHtlc { + if openChannelReq.HtlcMinimum != minHtlcIn { t.Fatalf("expected OpenChannel to have minHtlc %v, got %v", - minHtlc, openChannelReq.HtlcMinimum) + minHtlcIn, openChannelReq.HtlcMinimum) } chanID := openChannelReq.PendingChannelID @@ -2468,7 +2470,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { // The minimum HTLC value Alice can offer should be 5, and the minimum // Bob can offer should be 1234. - if err := assertMinHtlc(resCtx, 5, minHtlc); err != nil { + if err := assertMinHtlc(resCtx, 5, minHtlcIn); err != nil { t.Fatal(err) } @@ -2482,7 +2484,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { t.Fatal(err) } - if err := assertMinHtlc(resCtx, minHtlc, 5); err != nil { + if err := assertMinHtlc(resCtx, minHtlcIn, 5); err != nil { t.Fatal(err) } @@ -2543,7 +2545,7 @@ func TestFundingManagerCustomChannelParameters(t *testing.T) { // announcements. Alice should advertise the default MinHTLC value of // 5, while bob should advertise the value minHtlc, since Alice // required him to use it. - assertChannelAnnouncements(t, alice, bob, capacity, 5, minHtlc) + assertChannelAnnouncements(t, alice, bob, capacity, 5, minHtlcIn) // The funding transaction is now confirmed, wait for the // OpenStatusUpdate_ChanOpen update diff --git a/htlcswitch/link.go b/htlcswitch/link.go index 4a68172b..ce4d0073 100644 --- a/htlcswitch/link.go +++ b/htlcswitch/link.go @@ -71,10 +71,8 @@ const ( // the error possibly carrying along a ChannelUpdate message that includes the // latest policy. type ForwardingPolicy struct { - // MinHTLC is the smallest HTLC that is to be forwarded. This is - // set when a channel is first opened, and will be static for the - // lifetime of the channel. - MinHTLC lnwire.MilliSatoshi + // MinHTLC is the smallest HTLC that is to be forwarded. + MinHTLCOut lnwire.MilliSatoshi // MaxHTLC is the largest HTLC that is to be forwarded. MaxHTLC lnwire.MilliSatoshi @@ -2218,9 +2216,9 @@ func (l *channelLink) canSendHtlc(policy ForwardingPolicy, // As our first sanity check, we'll ensure that the passed HTLC isn't // too small for the next hop. If so, then we'll cancel the HTLC // directly. - if amt < policy.MinHTLC { + if amt < policy.MinHTLCOut { l.log.Errorf("outgoing htlc(%x) is too small: min_htlc=%v, "+ - "htlc_value=%v", payHash[:], policy.MinHTLC, + "htlc_value=%v", payHash[:], policy.MinHTLCOut, amt) // As part of the returned error, we'll send our latest routing diff --git a/htlcswitch/link_test.go b/htlcswitch/link_test.go index 810b5831..dc796ba3 100644 --- a/htlcswitch/link_test.go +++ b/htlcswitch/link_test.go @@ -1694,7 +1694,7 @@ func newSingleLinkTestHarness(chanAmt, chanReserve btcutil.Amount) ( quit: make(chan struct{}), } globalPolicy = ForwardingPolicy{ - MinHTLC: lnwire.NewMSatFromSatoshis(5), + MinHTLCOut: lnwire.NewMSatFromSatoshis(5), MaxHTLC: lnwire.NewMSatFromSatoshis(chanAmt), BaseFee: lnwire.NewMSatFromSatoshis(1), TimeLockDelta: 6, @@ -4253,7 +4253,7 @@ func (h *persistentLinkHarness) restartLink( } globalPolicy = ForwardingPolicy{ - MinHTLC: lnwire.NewMSatFromSatoshis(5), + MinHTLCOut: lnwire.NewMSatFromSatoshis(5), BaseFee: lnwire.NewMSatFromSatoshis(1), TimeLockDelta: 6, } @@ -5512,7 +5512,7 @@ func TestCheckHtlcForward(t *testing.T) { cfg: ChannelLinkConfig{ FwrdingPolicy: ForwardingPolicy{ TimeLockDelta: 20, - MinHTLC: 500, + MinHTLCOut: 500, MaxHTLC: 1000, BaseFee: 10, }, diff --git a/htlcswitch/test_utils.go b/htlcswitch/test_utils.go index 1308bf79..9ed8179a 100644 --- a/htlcswitch/test_utils.go +++ b/htlcswitch/test_utils.go @@ -1078,7 +1078,7 @@ func newHopNetwork() *hopNetwork { defaultDelta := uint32(6) globalPolicy := ForwardingPolicy{ - MinHTLC: lnwire.NewMSatFromSatoshis(5), + MinHTLCOut: lnwire.NewMSatFromSatoshis(5), BaseFee: lnwire.NewMSatFromSatoshis(1), TimeLockDelta: defaultDelta, } diff --git a/peer.go b/peer.go index 93f079ef..be8a1d26 100644 --- a/peer.go +++ b/peer.go @@ -531,7 +531,7 @@ func (p *peer) loadActiveChannels(chans []*channeldb.OpenChannel) ( var forwardingPolicy *htlcswitch.ForwardingPolicy if selfPolicy != nil { forwardingPolicy = &htlcswitch.ForwardingPolicy{ - MinHTLC: selfPolicy.MinHTLC, + MinHTLCOut: selfPolicy.MinHTLC, MaxHTLC: selfPolicy.MaxHTLC, BaseFee: selfPolicy.FeeBaseMSat, FeeRate: selfPolicy.FeeProportionalMillionths, @@ -1862,7 +1862,7 @@ out: fwdMinHtlc := lnChan.FwdMinHtlc() defaultPolicy := p.server.cc.routingPolicy forwardingPolicy := &htlcswitch.ForwardingPolicy{ - MinHTLC: fwdMinHtlc, + MinHTLCOut: fwdMinHtlc, MaxHTLC: newChan.LocalChanCfg.MaxPendingAmount, BaseFee: defaultPolicy.BaseFee, FeeRate: defaultPolicy.FeeRate, diff --git a/pilot.go b/pilot.go index 6fa3a6c6..cc665073 100644 --- a/pilot.go +++ b/pilot.go @@ -92,7 +92,7 @@ func (c *chanController) OpenChannel(target *btcec.PublicKey, } // TODO(halseth): make configurable? - minHtlc := lnwire.NewMSatFromSatoshis(1) + minHtlcIn := lnwire.NewMSatFromSatoshis(1) // Construct the open channel request and send it to the server to begin // the funding workflow. @@ -102,7 +102,7 @@ func (c *chanController) OpenChannel(target *btcec.PublicKey, subtractFees: true, localFundingAmt: amt, pushAmt: 0, - minHtlc: minHtlc, + minHtlcIn: minHtlcIn, fundingFeePerKw: feePerKw, private: c.private, remoteCsvDelay: 0, diff --git a/routing/localchans/manager.go b/routing/localchans/manager.go index 9d1c3e49..e99a5a35 100644 --- a/routing/localchans/manager.go +++ b/routing/localchans/manager.go @@ -93,7 +93,7 @@ func (r *Manager) UpdatePolicy(newSchema routing.ChannelPolicy, BaseFee: edge.FeeBaseMSat, FeeRate: edge.FeeProportionalMillionths, TimeLockDelta: uint32(edge.TimeLockDelta), - MinHTLC: edge.MinHTLC, + MinHTLCOut: edge.MinHTLC, MaxHTLC: edge.MaxHTLC, } diff --git a/rpcserver.go b/rpcserver.go index d5461a6e..9e501232 100644 --- a/rpcserver.go +++ b/rpcserver.go @@ -1449,7 +1449,7 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, localFundingAmt := btcutil.Amount(in.LocalFundingAmount) remoteInitialBalance := btcutil.Amount(in.PushSat) - minHtlc := lnwire.MilliSatoshi(in.MinHtlcMsat) + minHtlcIn := lnwire.MilliSatoshi(in.MinHtlcMsat) remoteCsvDelay := uint16(in.RemoteCsvDelay) // Ensure that the initial balance of the remote party (if pushing @@ -1537,7 +1537,7 @@ func (r *rpcServer) OpenChannel(in *lnrpc.OpenChannelRequest, chainHash: *activeNetParams.GenesisHash, localFundingAmt: localFundingAmt, pushAmt: lnwire.NewMSatFromSatoshis(remoteInitialBalance), - minHtlc: minHtlc, + minHtlcIn: minHtlcIn, fundingFeePerKw: feeRate, private: in.Private, remoteCsvDelay: remoteCsvDelay, @@ -1631,7 +1631,7 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context, localFundingAmt := btcutil.Amount(in.LocalFundingAmount) remoteInitialBalance := btcutil.Amount(in.PushSat) - minHtlc := lnwire.MilliSatoshi(in.MinHtlcMsat) + minHtlcIn := lnwire.MilliSatoshi(in.MinHtlcMsat) remoteCsvDelay := uint16(in.RemoteCsvDelay) // Ensure that the initial balance of the remote party (if pushing @@ -1679,7 +1679,7 @@ func (r *rpcServer) OpenChannelSync(ctx context.Context, chainHash: *activeNetParams.GenesisHash, localFundingAmt: localFundingAmt, pushAmt: lnwire.NewMSatFromSatoshis(remoteInitialBalance), - minHtlc: minHtlc, + minHtlcIn: minHtlcIn, fundingFeePerKw: feeRate, private: in.Private, remoteCsvDelay: remoteCsvDelay, diff --git a/server.go b/server.go index 74888bc4..bb9493f8 100644 --- a/server.go +++ b/server.go @@ -985,6 +985,7 @@ func newServer(listenAddrs []net.Addr, chanDB *channeldb.DB, return nil, fmt.Errorf("unable to find channel") }, DefaultRoutingPolicy: cc.routingPolicy, + DefaultMinHtlcIn: cc.minHtlcIn, NumRequiredConfs: func(chanAmt btcutil.Amount, pushAmt lnwire.MilliSatoshi) uint16 { // For large channels we increase the number @@ -3084,8 +3085,8 @@ type openChanReq struct { private bool - // minHtlc is the minimum incoming htlc that we accept. - minHtlc lnwire.MilliSatoshi + // minHtlcIn is the minimum incoming htlc that we accept. + minHtlcIn lnwire.MilliSatoshi remoteCsvDelay uint16