Skip to content

Commit

Permalink
Accept remote's closing fee when we have nothing at stake (#1633)
Browse files Browse the repository at this point in the history
If we have nothing at stake there is no need to negotiate and we accept
their fee right away.
  • Loading branch information
pm47 committed Dec 15, 2020
1 parent addc7a4 commit ac8dd4d
Show file tree
Hide file tree
Showing 2 changed files with 25 additions and 4 deletions.
11 changes: 8 additions & 3 deletions eclair-core/src/main/scala/fr/acinq/eclair/channel/Channel.scala
Original file line number Diff line number Diff line change
Expand Up @@ -1186,9 +1186,14 @@ class Channel(val nodeParams: NodeParams, val wallet: EclairWallet, remoteNodeId
case Success(signedClosingTx) =>
// if we are fundee and we were waiting for them to send their first closing_signed, we don't have a lastLocalClosingFee, so we compute a firstClosingFee
val lastLocalClosingFee = d.closingTxProposed.last.lastOption.map(_.localClosingSigned.feeSatoshis)
val nextClosingFee = Closing.nextClosingFee(
localClosingFee = lastLocalClosingFee.getOrElse(Closing.firstClosingFee(d.commitments, d.localShutdown.scriptPubKey, d.remoteShutdown.scriptPubKey, nodeParams.onChainFeeConf.feeEstimator, nodeParams.onChainFeeConf.feeTargets)),
remoteClosingFee = remoteClosingFee)
val nextClosingFee = if (d.commitments.localCommit.spec.toLocal == 0.msat) {
// if we have nothing at stake there is no need to negotiate and we accept their fee right away
remoteClosingFee
} else {
Closing.nextClosingFee(
localClosingFee = lastLocalClosingFee.getOrElse(Closing.firstClosingFee(d.commitments, d.localShutdown.scriptPubKey, d.remoteShutdown.scriptPubKey, nodeParams.onChainFeeConf.feeEstimator, nodeParams.onChainFeeConf.feeTargets)),
remoteClosingFee = remoteClosingFee)
}
val (closingTx, closingSigned) = Closing.makeClosingTx(keyManager, d.commitments, d.localShutdown.scriptPubKey, d.remoteShutdown.scriptPubKey, nextClosingFee)
if (lastLocalClosingFee.contains(nextClosingFee)) {
// next computed fee is the same than the one we previously sent (probably because of rounding), let's close now
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,7 +50,7 @@ class NegotiatingStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
val setup = init()
import setup._
within(30 seconds) {
reachNormal(setup)
reachNormal(setup, test.tags)
val sender = TestProbe()
// alice initiates a closing
if (test.tags.contains("fee2")) {
Expand Down Expand Up @@ -131,6 +131,22 @@ class NegotiatingStateSpec extends TestKitBaseClass with FixtureAnyFunSuiteLike
testFeeConverge(f)
}

test("recv ClosingSigned (nothing at stake)", Tag("no_push_msat")) { f =>
import f._
val aliceCloseFee = alice2bob.expectMsgType[ClosingSigned].feeSatoshis
alice2bob.forward(bob)
val bobCloseFee = bob2alice.expectMsgType[ClosingSigned].feeSatoshis
assert(aliceCloseFee === bobCloseFee)
bob2alice.forward(alice)
val mutualCloseTxAlice = alice2blockchain.expectMsgType[PublishAsap].tx
val mutualCloseTxBob = bob2blockchain.expectMsgType[PublishAsap].tx
assert(mutualCloseTxAlice === mutualCloseTxBob)
assert(alice2blockchain.expectMsgType[WatchConfirmed].event === BITCOIN_TX_CONFIRMED(mutualCloseTxAlice))
assert(bob2blockchain.expectMsgType[WatchConfirmed].event === BITCOIN_TX_CONFIRMED(mutualCloseTxBob))
assert(alice.stateData.asInstanceOf[DATA_CLOSING].mutualClosePublished == List(mutualCloseTxAlice))
assert(bob.stateData.asInstanceOf[DATA_CLOSING].mutualClosePublished == List(mutualCloseTxBob))
}

test("recv ClosingSigned (fee too high)") { f =>
import f._
val aliceCloseSig = alice2bob.expectMsgType[ClosingSigned]
Expand Down

0 comments on commit ac8dd4d

Please sign in to comment.