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:
Olaoluwa Osuntokun 2016-08-25 16:30:22 -07:00
parent 04e7a88a83
commit 4e416da4cd
No known key found for this signature in database
GPG Key ID: 9CC5B105D03521A2
2 changed files with 52 additions and 10 deletions

@ -240,6 +240,8 @@ out:
h.handleRegisterLink(req)
case *unregisterLinkMsg:
h.handleUnregisterLink(req)
case *linkInfoUpdateMsg:
h.handleLinkUpdate(req)
}
case <-h.quit:
break out
@ -333,6 +335,16 @@ func (h *htlcSwitch) handleCloseLink(req *closeLinkReq) {
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.
type registerLinkMsg struct {
peer *peer
@ -406,3 +418,19 @@ func (h *htlcSwitch) CloseLink(chanPoint *wire.OutPoint) (chan *closeLinkResp, c
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

@ -17,6 +17,7 @@ import (
"github.com/roasbeef/btcd/btcec"
"github.com/roasbeef/btcd/txscript"
"github.com/roasbeef/btcd/wire"
"github.com/roasbeef/btcutil"
)
var (
@ -776,8 +777,7 @@ type pendingPayment struct {
type commitmentState struct {
// 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.
// TODO(roasbeef): should send sig to settle once preimage is known.
htlcsToSettle map[uint32][32]byte
htlcsToSettle map[uint32]invoice
// TODO(roasbeef): use once trickle+batch logic is in
pendingBatch []*pendingPayment
@ -839,7 +839,7 @@ func (p *peer) htlcManager(channel *lnwallet.LightningChannel,
channel: channel,
chanPoint: channel.ChannelPoint(),
clearedHTCLs: make(map[uint32]*pendingPayment),
htlcsToSettle: make(map[uint32][32]byte),
htlcsToSettle: make(map[uint32]invoice),
switchChan: htlcPlex,
}
@ -964,8 +964,9 @@ func (p *peer) handleUpstreamMsg(state *commitmentState, msg lnwire.Message) {
// TODO(roasbeef): check value
// * onion layer strip should also be before invoice lookup
// * also can immediately send the settle msg
pre := invoice.paymentPreimage
state.htlcsToSettle[index] = pre
invCopy := *invoice
invCopy.value = btcutil.Amount(htlcPkt.Amount)
state.htlcsToSettle[index] = invCopy
}
case *lnwire.HTLCSettleRequest:
// 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
// goroutine in order not to block the post-processing of
// HTLC's that are eligble for forwarding.
// TODO(roasbeef): no need to forward if have settled any of
// these.
go func() {
for _, htlc := range htlcsToForward {
// Send this fully activated HTLC to the htlc switch to
// continue the chained clear/settle.
// Send this fully activated HTLC to the htlc
// switch to continue the chained clear/settle.
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
// can them from the pending set, and signal the requster (if
// existing) that the payment has been fully fulfilled.
var bandwidthUpdate btcutil.Amount
numSettled := 0
for _, htlc := range htlcsToForward {
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
// can halt processing here.
preimage, ok := state.htlcsToSettle[htlc.Index]
invoice, ok := state.htlcsToSettle[htlc.Index]
if !ok {
continue
}
@ -1060,7 +1064,7 @@ func (p *peer) handleUpstreamMsg(state *commitmentState, msg lnwire.Message) {
// Otherwise, we settle this HTLC within our local
// state update log, then send the update entry to the
// remote party.
logIndex, err := state.channel.SettleHTLC(preimage)
logIndex, err := state.channel.SettleHTLC(invoice.paymentPreimage)
if err != nil {
peerLog.Errorf("unable to settle htlc: %v", err)
p.Disconnect()
@ -1070,11 +1074,13 @@ func (p *peer) handleUpstreamMsg(state *commitmentState, msg lnwire.Message) {
settleMsg := &lnwire.HTLCSettleRequest{
ChannelPoint: state.chanPoint,
HTLCKey: lnwire.HTLCKey(logIndex),
RedemptionProofs: [][32]byte{preimage},
RedemptionProofs: [][32]byte{invoice.paymentPreimage},
}
p.queueMsg(settleMsg, nil)
delete(state.htlcsToSettle, htlc.Index)
bandwidthUpdate += invoice.value
numSettled++
}
@ -1082,6 +1088,14 @@ func (p *peer) handleUpstreamMsg(state *commitmentState, msg lnwire.Message) {
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
// HTLC logs, initiate a state transition by updating the
// remote commitment chain.