htlcswitch: properly update channel bandwidth after payment recv
This commit fixes an omission within the htlcSwitch. With this commit, a channels bandwidth is now properly updated once an incoming HTLC is settled. This also fixes a bug where if a node received a payment, it wouldn’t be able to then utilize the newly available bandwidth to send further payments.
This commit is contained in:
parent
04e7a88a83
commit
4e416da4cd
@ -240,6 +240,8 @@ out:
|
|||||||
h.handleRegisterLink(req)
|
h.handleRegisterLink(req)
|
||||||
case *unregisterLinkMsg:
|
case *unregisterLinkMsg:
|
||||||
h.handleUnregisterLink(req)
|
h.handleUnregisterLink(req)
|
||||||
|
case *linkInfoUpdateMsg:
|
||||||
|
h.handleLinkUpdate(req)
|
||||||
}
|
}
|
||||||
case <-h.quit:
|
case <-h.quit:
|
||||||
break out
|
break out
|
||||||
@ -333,6 +335,16 @@ func (h *htlcSwitch) handleCloseLink(req *closeLinkReq) {
|
|||||||
targetLink.peer.localCloseChanReqs <- req
|
targetLink.peer.localCloseChanReqs <- req
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// handleLinkUpdate processes the link info update message by adjusting the
|
||||||
|
// channels available bandwidth by the delta specified within the message.
|
||||||
|
func (h *htlcSwitch) handleLinkUpdate(req *linkInfoUpdateMsg) {
|
||||||
|
link := h.chanIndex[*req.targetLink]
|
||||||
|
link.availableBandwidth += req.bandwidthDelta
|
||||||
|
|
||||||
|
hswcLog.Tracef("adjusting bandwidth of link %v by %v", req.targetLink,
|
||||||
|
req.bandwidthDelta)
|
||||||
|
}
|
||||||
|
|
||||||
// registerLinkMsg is message which requests a new link to be registered.
|
// registerLinkMsg is message which requests a new link to be registered.
|
||||||
type registerLinkMsg struct {
|
type registerLinkMsg struct {
|
||||||
peer *peer
|
peer *peer
|
||||||
@ -406,3 +418,19 @@ func (h *htlcSwitch) CloseLink(chanPoint *wire.OutPoint) (chan *closeLinkResp, c
|
|||||||
|
|
||||||
return respChan, errChan
|
return respChan, errChan
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// linkInfoUpdateMsg encapsulates a request for the htlc switch to update the
|
||||||
|
// meta-data related to the target link.
|
||||||
|
type linkInfoUpdateMsg struct {
|
||||||
|
targetLink *wire.OutPoint
|
||||||
|
|
||||||
|
bandwidthDelta btcutil.Amount
|
||||||
|
}
|
||||||
|
|
||||||
|
// UpdateLink sends a message to the switch to update the available bandwidth
|
||||||
|
// within the link by the passed satoshi delta. This function may be used when
|
||||||
|
// re-anchoring to boost the capacity of a channel, or once a peer settles an
|
||||||
|
// HTLC invoice.
|
||||||
|
func (h *htlcSwitch) UpdateLink(chanPoint *wire.OutPoint, bandwidthDelta btcutil.Amount) {
|
||||||
|
h.linkControl <- &linkInfoUpdateMsg{chanPoint, bandwidthDelta}
|
||||||
|
}
|
||||||
|
34
peer.go
34
peer.go
@ -17,6 +17,7 @@ import (
|
|||||||
"github.com/roasbeef/btcd/btcec"
|
"github.com/roasbeef/btcd/btcec"
|
||||||
"github.com/roasbeef/btcd/txscript"
|
"github.com/roasbeef/btcd/txscript"
|
||||||
"github.com/roasbeef/btcd/wire"
|
"github.com/roasbeef/btcd/wire"
|
||||||
|
"github.com/roasbeef/btcutil"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
@ -776,8 +777,7 @@ type pendingPayment struct {
|
|||||||
type commitmentState struct {
|
type commitmentState struct {
|
||||||
// htlcsToSettle is a list of preimages which allow us to settle one or
|
// htlcsToSettle is a list of preimages which allow us to settle one or
|
||||||
// many of the pending HTLC's we've received from the upstream peer.
|
// many of the pending HTLC's we've received from the upstream peer.
|
||||||
// TODO(roasbeef): should send sig to settle once preimage is known.
|
htlcsToSettle map[uint32]invoice
|
||||||
htlcsToSettle map[uint32][32]byte
|
|
||||||
|
|
||||||
// TODO(roasbeef): use once trickle+batch logic is in
|
// TODO(roasbeef): use once trickle+batch logic is in
|
||||||
pendingBatch []*pendingPayment
|
pendingBatch []*pendingPayment
|
||||||
@ -839,7 +839,7 @@ func (p *peer) htlcManager(channel *lnwallet.LightningChannel,
|
|||||||
channel: channel,
|
channel: channel,
|
||||||
chanPoint: channel.ChannelPoint(),
|
chanPoint: channel.ChannelPoint(),
|
||||||
clearedHTCLs: make(map[uint32]*pendingPayment),
|
clearedHTCLs: make(map[uint32]*pendingPayment),
|
||||||
htlcsToSettle: make(map[uint32][32]byte),
|
htlcsToSettle: make(map[uint32]invoice),
|
||||||
switchChan: htlcPlex,
|
switchChan: htlcPlex,
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -964,8 +964,9 @@ func (p *peer) handleUpstreamMsg(state *commitmentState, msg lnwire.Message) {
|
|||||||
// TODO(roasbeef): check value
|
// TODO(roasbeef): check value
|
||||||
// * onion layer strip should also be before invoice lookup
|
// * onion layer strip should also be before invoice lookup
|
||||||
// * also can immediately send the settle msg
|
// * also can immediately send the settle msg
|
||||||
pre := invoice.paymentPreimage
|
invCopy := *invoice
|
||||||
state.htlcsToSettle[index] = pre
|
invCopy.value = btcutil.Amount(htlcPkt.Amount)
|
||||||
|
state.htlcsToSettle[index] = invCopy
|
||||||
}
|
}
|
||||||
case *lnwire.HTLCSettleRequest:
|
case *lnwire.HTLCSettleRequest:
|
||||||
// TODO(roasbeef): this assumes no "multi-sig"
|
// TODO(roasbeef): this assumes no "multi-sig"
|
||||||
@ -1024,10 +1025,12 @@ func (p *peer) handleUpstreamMsg(state *commitmentState, msg lnwire.Message) {
|
|||||||
// We perform the HTLC forwarding to the switch in a distinct
|
// We perform the HTLC forwarding to the switch in a distinct
|
||||||
// goroutine in order not to block the post-processing of
|
// goroutine in order not to block the post-processing of
|
||||||
// HTLC's that are eligble for forwarding.
|
// HTLC's that are eligble for forwarding.
|
||||||
|
// TODO(roasbeef): no need to forward if have settled any of
|
||||||
|
// these.
|
||||||
go func() {
|
go func() {
|
||||||
for _, htlc := range htlcsToForward {
|
for _, htlc := range htlcsToForward {
|
||||||
// Send this fully activated HTLC to the htlc switch to
|
// Send this fully activated HTLC to the htlc
|
||||||
// continue the chained clear/settle.
|
// switch to continue the chained clear/settle.
|
||||||
state.switchChan <- p.logEntryToHtlcPkt(htlc)
|
state.switchChan <- p.logEntryToHtlcPkt(htlc)
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1037,6 +1040,7 @@ func (p *peer) handleUpstreamMsg(state *commitmentState, msg lnwire.Message) {
|
|||||||
// settling or timeing out previous outgoing payments, then we
|
// settling or timeing out previous outgoing payments, then we
|
||||||
// can them from the pending set, and signal the requster (if
|
// can them from the pending set, and signal the requster (if
|
||||||
// existing) that the payment has been fully fulfilled.
|
// existing) that the payment has been fully fulfilled.
|
||||||
|
var bandwidthUpdate btcutil.Amount
|
||||||
numSettled := 0
|
numSettled := 0
|
||||||
for _, htlc := range htlcsToForward {
|
for _, htlc := range htlcsToForward {
|
||||||
if p, ok := state.clearedHTCLs[htlc.ParentIndex]; ok {
|
if p, ok := state.clearedHTCLs[htlc.ParentIndex]; ok {
|
||||||
@ -1052,7 +1056,7 @@ func (p *peer) handleUpstreamMsg(state *commitmentState, msg lnwire.Message) {
|
|||||||
|
|
||||||
// If we can't immediately settle this HTLC, then we
|
// If we can't immediately settle this HTLC, then we
|
||||||
// can halt processing here.
|
// can halt processing here.
|
||||||
preimage, ok := state.htlcsToSettle[htlc.Index]
|
invoice, ok := state.htlcsToSettle[htlc.Index]
|
||||||
if !ok {
|
if !ok {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@ -1060,7 +1064,7 @@ func (p *peer) handleUpstreamMsg(state *commitmentState, msg lnwire.Message) {
|
|||||||
// Otherwise, we settle this HTLC within our local
|
// Otherwise, we settle this HTLC within our local
|
||||||
// state update log, then send the update entry to the
|
// state update log, then send the update entry to the
|
||||||
// remote party.
|
// remote party.
|
||||||
logIndex, err := state.channel.SettleHTLC(preimage)
|
logIndex, err := state.channel.SettleHTLC(invoice.paymentPreimage)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
peerLog.Errorf("unable to settle htlc: %v", err)
|
peerLog.Errorf("unable to settle htlc: %v", err)
|
||||||
p.Disconnect()
|
p.Disconnect()
|
||||||
@ -1070,11 +1074,13 @@ func (p *peer) handleUpstreamMsg(state *commitmentState, msg lnwire.Message) {
|
|||||||
settleMsg := &lnwire.HTLCSettleRequest{
|
settleMsg := &lnwire.HTLCSettleRequest{
|
||||||
ChannelPoint: state.chanPoint,
|
ChannelPoint: state.chanPoint,
|
||||||
HTLCKey: lnwire.HTLCKey(logIndex),
|
HTLCKey: lnwire.HTLCKey(logIndex),
|
||||||
RedemptionProofs: [][32]byte{preimage},
|
RedemptionProofs: [][32]byte{invoice.paymentPreimage},
|
||||||
}
|
}
|
||||||
p.queueMsg(settleMsg, nil)
|
p.queueMsg(settleMsg, nil)
|
||||||
delete(state.htlcsToSettle, htlc.Index)
|
delete(state.htlcsToSettle, htlc.Index)
|
||||||
|
|
||||||
|
bandwidthUpdate += invoice.value
|
||||||
|
|
||||||
numSettled++
|
numSettled++
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1082,6 +1088,14 @@ func (p *peer) handleUpstreamMsg(state *commitmentState, msg lnwire.Message) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Send an update to the htlc switch of our newly available
|
||||||
|
// payment bandwidth.
|
||||||
|
// TODO(roasbeef): ideally should wait for next state update.
|
||||||
|
if bandwidthUpdate != 0 {
|
||||||
|
p.server.htlcSwitch.UpdateLink(state.chanPoint,
|
||||||
|
bandwidthUpdate)
|
||||||
|
}
|
||||||
|
|
||||||
// With all the settle updates added to the local and remote
|
// With all the settle updates added to the local and remote
|
||||||
// HTLC logs, initiate a state transition by updating the
|
// HTLC logs, initiate a state transition by updating the
|
||||||
// remote commitment chain.
|
// remote commitment chain.
|
||||||
|
Loading…
Reference in New Issue
Block a user