Merge pull request #2839 from joostjager/htlc-expiry-check

link: increase expiry grace delta for exit hop and forwarded htlcs
This commit is contained in:
Olaoluwa Osuntokun authored and GitHub committed 2019-04-01 18:15:56 -07:00
commit 893cff60c4
7 files changed
+81 -49

No files matched your search

+19 -17
View File
@@ -30,16 +30,6 @@ func init() {
}
const (
// expiryGraceDelta is a grace period that the timeout of incoming
// HTLC's that pay directly to us (i.e we're the "exit node") must up
// hold. We'll reject any HTLC's who's timeout minus this value is less
// that or equal to the current block height. We require this in order
// to ensure that if the extending party goes to the chain, then we'll
// be able to claim the HTLC still.
//
// TODO(roasbeef): must be < default delta
expiryGraceDelta = 2
// maxCltvExpiry is the maximum outgoing time lock that the node accepts
// for forwarded payments. The value is relative to the current block
// height. The reason to have a maximum is to prevent funds getting
@@ -244,6 +234,18 @@ type ChannelLinkConfig struct {
// fee rate. A random timeout will be selected between these values.
MinFeeUpdateTimeout time.Duration
MaxFeeUpdateTimeout time.Duration
// ExpiryGraceDelta is the minimum difference between the current block
// height and the CLTV we require on 1) an outgoing HTLC in order to
// forward as an intermediary hop, or 2) an incoming HTLC to reveal the
// preimage as the final hop. We'll reject any HTLC's who's timeout minus
// this value is less than or equal to the current block height. We require
// this in order to ensure that we have sufficient time to claim or
// timeout an HTLC on chain.
//
// This MUST be greater than the maximum BroadcastDelta of the
// ChannelArbitrator for the outbound channel.
ExpiryGraceDelta uint32
}
// channelLink is the service which drives a channel's commitment update
@@ -2151,14 +2153,13 @@ func (l *channelLink) HtlcSatifiesPolicy(payHash [32]byte,
return failure
}
// We want to avoid accepting an HTLC which will expire in the near
// future, so we'll reject an HTLC if its expiration time is too close
// to the current height.
timeDelta := policy.TimeLockDelta
if incomingTimeout-timeDelta <= heightNow {
// We want to avoid offering an HTLC which will expire in the near
// future, so we'll reject an HTLC if the outgoing expiration time is too
// close to the current height.
if outgoingTimeout-l.cfg.ExpiryGraceDelta <= heightNow {
l.errorf("htlc(%x) has an expiry that's too soon: "+
"outgoing_expiry=%v, best_height=%v", payHash[:],
incomingTimeout-timeDelta, heightNow)
outgoingTimeout, heightNow)
var failure lnwire.FailureMessage
update, err := l.cfg.FetchLastChannelUpdate(
@@ -2185,6 +2186,7 @@ func (l *channelLink) HtlcSatifiesPolicy(payHash [32]byte,
// the following constraint: the incoming time-lock minus our time-lock
// delta should equal the outgoing time lock. Otherwise, whether the
// sender messed up, or an intermediate node tampered with the HTLC.
timeDelta := policy.TimeLockDelta
if incomingTimeout-timeDelta < outgoingTimeout {
l.errorf("Incoming htlc(%x) has incorrect time-lock value: "+
"expected at least %v block delta, got %v block delta",
@@ -2677,7 +2679,7 @@ func (l *channelLink) processExitHop(pd *lnwallet.PaymentDescriptor,
// First, we'll check the expiry of the HTLC itself against, the current
// block height. If the timeout is too soon, then we'll reject the HTLC.
if pd.Timeout-expiryGraceDelta <= heightNow {
if pd.Timeout-l.cfg.ExpiryGraceDelta <= heightNow {
log.Errorf("htlc(%x) has an expiry that's too soon: expiry=%v"+
", best_height=%v", pd.RHash[:], pd.Timeout, heightNow)
+13 -7
View File
@@ -1336,10 +1336,13 @@ func TestChannelLinkExpiryTooSoonExitNode(t *testing.T) {
amount := lnwire.NewMSatFromSatoshis(btcutil.SatoshiPerBitcoin)
// We'll craft an HTLC packet, but set the starting height to 10 blocks
// before the current true height.
// We'll craft an HTLC packet, but set the final hop CLTV to 3 blocks
// after the current true height. This is less or equal to the expiry
// grace delta of 3, so we expect the incoming htlc to be failed by the
// exit hop.
lastHopDelta := n.firstBobChannelLink.cfg.FwrdingPolicy.TimeLockDelta
htlcAmt, totalTimelock, hops := generateHops(amount,
startingHeight-10, n.firstBobChannelLink)
startingHeight+3-lastHopDelta, n.firstBobChannelLink)
// Now we'll send out the payment from Alice to Bob.
firstHop := n.firstBobChannelLink.ShortChanID()
@@ -1395,11 +1398,14 @@ func TestChannelLinkExpiryTooSoonMidNode(t *testing.T) {
amount := lnwire.NewMSatFromSatoshis(btcutil.SatoshiPerBitcoin)
// We'll craft an HTLC packet, but set the starting height to 10 blocks
// before the current true height. The final route will be three hops,
// so the middle hop should detect the issue.
// We'll craft an HTLC packet, but set the starting height to 3 blocks
// before the current true height. This means that the outgoing time
// lock of the middle hop will be at starting height + 3 blocks (channel
// policy time lock delta is 6 blocks). There is an expiry grace delta
// of 3 blocks relative to the current height, meaning that htlc will
// not be sent out by the middle hop.
htlcAmt, totalTimelock, hops := generateHops(amount,
startingHeight-10, n.firstBobChannelLink, n.carolChannelLink)
startingHeight-3, n.firstBobChannelLink, n.carolChannelLink)
// Now we'll send out the payment from Alice to Bob.
firstHop := n.firstBobChannelLink.ShortChanID()
+2
View File
@@ -1019,6 +1019,7 @@ func (h *hopNetwork) createChannelLink(server, peer *mockServer,
fwdPkgTimeout = 15 * time.Second
minFeeUpdateTimeout = 30 * time.Minute
maxFeeUpdateTimeout = 40 * time.Minute
expiryGraceDelta = 3
)
link := NewChannelLink(
@@ -1048,6 +1049,7 @@ func (h *hopNetwork) createChannelLink(server, peer *mockServer,
MinFeeUpdateTimeout: minFeeUpdateTimeout,
MaxFeeUpdateTimeout: maxFeeUpdateTimeout,
OnChannelFailure: func(lnwire.ChannelID, lnwire.ShortChannelID, LinkFailureError) {},
ExpiryGraceDelta: expiryGraceDelta,
},
channel,
)