diff --git a/eclair-node/src/main/resources/gui/main/main.fxml b/eclair-node/src/main/resources/gui/main/main.fxml index f0dcd6755..6ce4e3a19 100644 --- a/eclair-node/src/main/resources/gui/main/main.fxml +++ b/eclair-node/src/main/resources/gui/main/main.fxml @@ -3,8 +3,7 @@ - - + - - + + @@ -61,7 +60,7 @@ - + diff --git a/eclair-node/src/main/scala/fr/acinq/eclair/channel/Channel.scala b/eclair-node/src/main/scala/fr/acinq/eclair/channel/Channel.scala index 5d9f8892a..e1eeaa40a 100644 --- a/eclair-node/src/main/scala/fr/acinq/eclair/channel/Channel.scala +++ b/eclair-node/src/main/scala/fr/acinq/eclair/channel/Channel.scala @@ -246,7 +246,7 @@ class Channel(val r: ActorRef, val blockchain: ActorRef, router: ActorRef, relay val commitments = Commitments(params.localParams, params.remoteParams, LocalCommit(0, localSpec, PublishableTxs(signedLocalCommitTx, Nil)), RemoteCommit(0, remoteSpec, remoteCommitTx.tx.txid, remoteFirstPerCommitmentPoint), - LocalChanges(Nil, Nil, Nil), RemoteChanges(Nil, Nil), + LocalChanges(Nil, Nil, Nil), RemoteChanges(Nil, Nil, Nil), localNextHtlcId = 0L, remoteNextHtlcId = 0L, remoteNextCommitInfo = Right(null), // TODO: we will receive their next per-commitment point in the next message, so we temporarily put an empty byte array commitInput, ShaChain.init, channelId = 0) // TODO: we will compute the channelId at the next step, so we temporarily put 0 @@ -278,7 +278,7 @@ class Channel(val r: ActorRef, val blockchain: ActorRef, router: ActorRef, relay val commitments = Commitments(params.localParams, params.remoteParams, LocalCommit(0, localSpec, PublishableTxs(signedLocalCommitTx, Nil)), remoteCommit, - LocalChanges(Nil, Nil, Nil), RemoteChanges(Nil, Nil), + LocalChanges(Nil, Nil, Nil), RemoteChanges(Nil, Nil, Nil), localNextHtlcId = 0L, remoteNextHtlcId = 0L, remoteNextCommitInfo = Right(null), // TODO: we will receive their next per-commitment point in the next message, so we temporarily put an empty byte array commitInput, ShaChain.init, channelId = 0) @@ -463,10 +463,6 @@ class Channel(val r: ActorRef, val blockchain: ActorRef, router: ActorRef, relay Try(Commitments.receiveCommit(d.commitments, msg)) match { case Success((commitments1, revocation)) => remote ! revocation - // now that we have their sig, we should propagate the htlcs newly received - (commitments1.localCommit.spec.htlcs -- d.commitments.localCommit.spec.htlcs) - .filter(_.direction == IN) - .foreach(htlc => relayer ! htlc.add) context.system.eventStream.publish(ChannelSignatureReceived(self, commitments1)) stay using d.copy(commitments = commitments1) case Failure(cause) => handleLocalError(cause, d) @@ -477,6 +473,9 @@ class Channel(val r: ActorRef, val blockchain: ActorRef, router: ActorRef, relay // => all our changes have been acked Try(Commitments.receiveRevocation(d.commitments, msg)) match { case Success(commitments1) => + // we forward HTLCs only when they have been committed by both sides + // it always happen when we receive a revocation, because, we always sign our changes before they sign them + val newlySignedHtlcs = d.commitments.remoteChanges.signed.collect { case htlc: UpdateAddHtlc => relayer ! htlc} stay using d.copy(commitments = commitments1) case Failure(cause) => handleLocalError(cause, d) } diff --git a/eclair-node/src/main/scala/fr/acinq/eclair/channel/Commitments.scala b/eclair-node/src/main/scala/fr/acinq/eclair/channel/Commitments.scala index 028ce95eb..42aa66480 100644 --- a/eclair-node/src/main/scala/fr/acinq/eclair/channel/Commitments.scala +++ b/eclair-node/src/main/scala/fr/acinq/eclair/channel/Commitments.scala @@ -13,7 +13,7 @@ import grizzled.slf4j.Logging case class LocalChanges(proposed: List[UpdateMessage], signed: List[UpdateMessage], acked: List[UpdateMessage]) { def all: List[UpdateMessage] = proposed ++ signed ++ acked } -case class RemoteChanges(proposed: List[UpdateMessage], acked: List[UpdateMessage]) +case class RemoteChanges(proposed: List[UpdateMessage], acked: List[UpdateMessage], signed: List[UpdateMessage]) case class Changes(ourChanges: LocalChanges, theirChanges: RemoteChanges) case class HtlcTxAndSigs(txinfo: TransactionWithInputInfo, localSig: BinaryData, remoteSig: BinaryData) case class PublishableTxs(commitTx: CommitTx, htlcTxsAndSigs: Seq[HtlcTxAndSigs]) @@ -207,7 +207,7 @@ object Commitments extends Logging { val commitments1 = commitments.copy( remoteNextCommitInfo = Left((RemoteCommit(remoteCommit.index + 1, spec, remoteCommitTx.tx.txid, remoteNextPerCommitmentPoint), commitSig)), localChanges = localChanges.copy(proposed = Nil, signed = localChanges.proposed), - remoteChanges = remoteChanges.copy(acked = Nil)) + remoteChanges = remoteChanges.copy(acked = Nil, signed = remoteChanges.acked)) (commitments1, commitSig) case Left(_) => throw new RuntimeException("cannot sign until next revocation hash is received") @@ -314,6 +314,7 @@ object Commitments extends Logging { commitments.copy( localChanges = localChanges.copy(signed = Nil, acked = localChanges.acked ++ localChanges.signed), + remoteChanges = remoteChanges.copy(signed = Nil), remoteCommit = theirNextCommit, remoteNextCommitInfo = Right(revocation.nextPerCommitmentPoint), remotePerCommitmentSecrets = commitments.remotePerCommitmentSecrets.addHash(revocation.perCommitmentSecret, 0xFFFFFFFFFFFFL - commitments.remoteCommit.index)) diff --git a/eclair-node/src/main/scala/fr/acinq/eclair/gui/FxApp.scala b/eclair-node/src/main/scala/fr/acinq/eclair/gui/FxApp.scala index e7f4b6025..ff48dd327 100644 --- a/eclair-node/src/main/scala/fr/acinq/eclair/gui/FxApp.scala +++ b/eclair-node/src/main/scala/fr/acinq/eclair/gui/FxApp.scala @@ -26,11 +26,12 @@ class FxApp extends Application with Logging { override def start(primaryStage: Stage): Unit = { + val icon = new Image(getClass.getResource("/gui/commons/images/eclair02.png").toExternalForm, false) + primaryStage.getIcons.add(icon) - val icon = new Image("/gui/commons/images/eclair02.png", true) - primaryStage.getIcons().add(icon) val splashStage = new SplashStage() splashStage.initOwner(primaryStage) + splashStage.getIcons.add(icon) splashStage.show new Thread(new Runnable { diff --git a/eclair-node/src/main/scala/fr/acinq/eclair/gui/stages/SplashStage.scala b/eclair-node/src/main/scala/fr/acinq/eclair/gui/stages/SplashStage.scala index b0ea6ed89..c4a8fb5a8 100644 --- a/eclair-node/src/main/scala/fr/acinq/eclair/gui/stages/SplashStage.scala +++ b/eclair-node/src/main/scala/fr/acinq/eclair/gui/stages/SplashStage.scala @@ -20,9 +20,6 @@ class SplashStage() extends Stage() { initStyle(StageStyle.TRANSPARENT) setResizable(false) - val icon = new Image("/gui/commons/images/eclair02.png", false) - this.getIcons().add(icon) - // get fxml/controller val splash = new FXMLLoader(getClass.getResource("/gui/splash/splash.fxml")) val root = splash.load[Parent] diff --git a/eclair-node/src/main/scala/fr/acinq/eclair/payment/LocalPaymentHandler.scala b/eclair-node/src/main/scala/fr/acinq/eclair/payment/LocalPaymentHandler.scala index 183862614..e080b91a9 100644 --- a/eclair-node/src/main/scala/fr/acinq/eclair/payment/LocalPaymentHandler.scala +++ b/eclair-node/src/main/scala/fr/acinq/eclair/payment/LocalPaymentHandler.scala @@ -34,15 +34,11 @@ class LocalPaymentHandler extends Actor with ActorLogging { case htlc: UpdateAddHtlc if h2r.contains(htlc.paymentHash) => val r = h2r(htlc.paymentHash) - sender ! CMD_SIGN - sender ! CMD_FULFILL_HTLC(htlc.id, r) - sender ! CMD_SIGN + sender ! CMD_FULFILL_HTLC(htlc.id, r, commit = true) context.become(run(h2r - htlc.paymentHash)) case htlc: UpdateAddHtlc => - sender ! CMD_SIGN - sender ! CMD_FAIL_HTLC(htlc.id, "unkown H") - sender ! CMD_SIGN + sender ! CMD_FAIL_HTLC(htlc.id, "unkown H", commit = true) }