Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Relax relaying requirement on expiry #1497

Merged
merged 1 commit into from
Jul 29, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -179,13 +179,8 @@ object Commitments {
* @return either Left(failure, error message) where failure is a failure message (see BOLT #4 and the Failure Message class) or Right((new commitments, updateAddHtlc)
*/
def sendAdd(commitments: Commitments, cmd: CMD_ADD_HTLC, origin: Origin, blockHeight: Long, feeConf: OnChainFeeConf): Try[(Commitments, UpdateAddHtlc)] = {
// our counterparty needs a reasonable amount of time to pull the funds from downstream before we can get refunded (see BOLT 2 and BOLT 11 for a calculation and rationale)
val minExpiry = Channel.MIN_CLTV_EXPIRY_DELTA.toCltvExpiry(blockHeight)
if (cmd.cltvExpiry < minExpiry) {
return Failure(ExpiryTooSmall(commitments.channelId, minimum = minExpiry, actual = cmd.cltvExpiry, blockCount = blockHeight))
}
val maxExpiry = Channel.MAX_CLTV_EXPIRY_DELTA.toCltvExpiry(blockHeight)
// we don't want to use too high a refund timeout, because our funds will be locked during that time if the payment is never fulfilled
val maxExpiry = Channel.MAX_CLTV_EXPIRY_DELTA.toCltvExpiry(blockHeight)
if (cmd.cltvExpiry >= maxExpiry) {
return Failure(ExpiryTooBig(commitments.channelId, maximum = maxExpiry, actual = cmd.cltvExpiry, blockCount = blockHeight))
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -146,12 +146,22 @@ class NormalStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike with
import f._
val sender = TestProbe()
val initialState = alice.stateData.asInstanceOf[DATA_NORMAL]
// It's usually dangerous for Bob to accept HTLCs that are expiring soon. However it's not Alice's decision to reject
// them when she's asked to relay; she should forward those HTLCs to Bob, and Bob will choose whether to fail them
// or fulfill them (Bob could be #reckless and fulfill HTLCs with a very low expiry delta).
val expiryTooSmall = CltvExpiry(currentBlockHeight + 3)
val add = CMD_ADD_HTLC(500000000 msat, randomBytes32, expiryTooSmall, TestConstants.emptyOnionPacket, Upstream.Local(UUID.randomUUID()))
sender.send(alice, add)
val error = ExpiryTooSmall(channelId(alice), Channel.MIN_CLTV_EXPIRY_DELTA.toCltvExpiry(currentBlockHeight), expiryTooSmall, currentBlockHeight)
sender.expectMsg(Failure(AddHtlcFailed(channelId(alice), add.paymentHash, error, Origin.Local(add.upstream.asInstanceOf[Upstream.Local].id, Some(sender.ref)), Some(initialState.channelUpdate), Some(add))))
alice2bob.expectNoMsg(200 millis)
sender.expectMsg(ChannelCommandResponse.Ok)
val htlc = alice2bob.expectMsgType[UpdateAddHtlc]
assert(htlc.id === 0)
assert(htlc.cltvExpiry === expiryTooSmall)
awaitCond(alice.stateData == initialState.copy(
commitments = initialState.commitments.copy(
localNextHtlcId = 1,
localChanges = initialState.commitments.localChanges.copy(proposed = htlc :: Nil),
originChannels = Map(0L -> Origin.Local(add.upstream.asInstanceOf[Upstream.Local].id, Some(sender.ref)))
)))
}

test("recv CMD_ADD_HTLC (expiry too big)") { f =>
Expand Down