Skip to content

Commit

Permalink
htlcswitch: properly verify OutgoingCTLV+Timeout when final hop in link
Browse files Browse the repository at this point in the history
This commit fixes an existing bug in the way we perform validation of
the timelock information as the final hop in the route. Previously, we
would assert that the outgoing time lock in the per-hop payload would
exactly match our time lock delta.

Instead, we should be asserting two things:
   1. That the time lock in the payload is >= the expected time lock
   2. That timeout on the HTLC is exactly equal to the payload
  • Loading branch information
Roasbeef committed Sep 12, 2017
1 parent 246164e commit bf071c1
Showing 1 changed file with 49 additions and 24 deletions.
73 changes: 49 additions & 24 deletions htlcswitch/link.go
Original file line number Diff line number Diff line change
Expand Up @@ -865,6 +865,7 @@ func (l *channelLink) Bandwidth() lnwire.MilliSatoshi {
// NOTE: Should be used inside main goroutine only, otherwise the result might
// not be accurate.
func (l *channelLink) getBandwidth() lnwire.MilliSatoshi {
// TODO(roasbeef): factor in reserve, just grab mutex
return l.channel.LocalAvailableBalance() - l.overflowQueue.pendingAmount()
}

Expand Down Expand Up @@ -1026,15 +1027,19 @@ func (l *channelLink) processLockedInHtlcs(
// to produce initial obfuscation of the onion
// failureCode.
onionReader := bytes.NewReader(onionBlob[:])
obfuscator, failureCode := l.cfg.DecodeOnionObfuscator(onionReader)
obfuscator, failureCode := l.cfg.DecodeOnionObfuscator(
onionReader,
)
if failureCode != lnwire.CodeNone {
// If we unable to process the onion blob than
// we should send the malformed htlc error to
// payment sender.
l.sendMalformedHTLCError(pd.RHash, failureCode, onionBlob[:])
// If we're unable to process the onion blob
// than we should send the malformed htlc error
// to payment sender.
l.sendMalformedHTLCError(pd.RHash, failureCode,
onionBlob[:])
needUpdate = true

log.Error("unable to decode onion obfuscator")
log.Errorf("unable to decode onion "+
"obfuscator: %v", failureCode)
continue
}

Expand All @@ -1054,13 +1059,15 @@ func (l *channelLink) processLockedInHtlcs(
onionReader, pd.RHash[:],
)
if failureCode != lnwire.CodeNone {
// If we unable to process the onion blob than
// we should send the malformed htlc error to
// payment sender.
l.sendMalformedHTLCError(pd.RHash, failureCode, onionBlob[:])
// If we're unable to process the onion blob
// than we should send the malformed htlc error
// to payment sender.
l.sendMalformedHTLCError(pd.RHash, failureCode,
onionBlob[:])
needUpdate = true

log.Error("unable to decode onion hop iterator")
log.Errorf("unable to decode onion hop "+
"iterator: %v", failureCode)
continue
}

Expand Down Expand Up @@ -1122,19 +1129,35 @@ func (l *channelLink) processLockedInHtlcs(

// We'll also ensure that our time-lock value
// has been computed correctly.
if !l.cfg.DebugHTLC &&
fwdInfo.OutgoingCTLV != l.cfg.FwrdingPolicy.TimeLockDelta {

log.Errorf("Onion payload of incoming "+
"htlc(%x) has incorrect time-lock: "+
"expected %v, got %v",
pd.RHash[:], l.cfg.FwrdingPolicy.TimeLockDelta,
fwdInfo.OutgoingCTLV)

failure := lnwire.NewFinalIncorrectCltvExpiry(fwdInfo.OutgoingCTLV)
l.sendHTLCError(pd.RHash, failure, obfuscator)
needUpdate = true
continue
expectedHeight := heightNow + l.cfg.FwrdingPolicy.TimeLockDelta
if !l.cfg.DebugHTLC {
switch {
case fwdInfo.OutgoingCTLV < expectedHeight:
log.Errorf("Onion payload of incoming "+
"htlc(%x) has incorrect time-lock: "+
"expected %v, got %v",
pd.RHash[:], expectedHeight,
fwdInfo.OutgoingCTLV)

failure := lnwire.NewFinalIncorrectCltvExpiry(
fwdInfo.OutgoingCTLV,
)
l.sendHTLCError(pd.RHash, failure, obfuscator)
needUpdate = true
continue
case pd.Timeout != fwdInfo.OutgoingCTLV:
log.Errorf("HTLC(%x) has incorrect "+
"time-lock: expected %v, got %v",
pd.RHash[:], pd.Timeout,
fwdInfo.OutgoingCTLV)

failure := lnwire.NewFinalIncorrectCltvExpiry(
fwdInfo.OutgoingCTLV,
)
l.sendHTLCError(pd.RHash, failure, obfuscator)
needUpdate = true
continue
}
}

// If we're not currently in debug mode, and
Expand Down Expand Up @@ -1307,6 +1330,8 @@ func (l *channelLink) processLockedInHtlcs(
continue
}

// TODO(roasbeef): also add max timeout value

// With all our forwarding constraints met,
// we'll create the outgoing HTLC using the
// parameters as specified in the forwarding
Expand Down

0 comments on commit bf071c1

Please sign in to comment.