From 25f5cd601f5778f647e4f759baf0bdef721203ce Mon Sep 17 00:00:00 2001 From: sstone Date: Fri, 17 Jun 2016 14:49:56 +0200 Subject: [PATCH] move shachain into commitment data --- .../fr/acinq/eclair/channel/Channel.scala | 52 +++++++++---------- .../acinq/eclair/channel/ChannelTypes.scala | 10 ++-- .../fr/acinq/eclair/channel/Commitments.scala | 1 + 3 files changed, 32 insertions(+), 31 deletions(-) diff --git a/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Channel.scala b/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Channel.scala index 11d46d066..03ebfd7b9 100644 --- a/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Channel.scala +++ b/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Channel.scala @@ -89,8 +89,8 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann val commitments = Commitments(ourParams, theirParams, OurCommit(0, ourSpec, ourTx), TheirCommit(0, theirSpec, theirRevocationHash), OurChanges(Nil, Nil, Nil), TheirChanges(Nil, Nil), - Right(theirNextRevocationHash), anchorOutput) - goto(OPEN_WAITING_THEIRANCHOR) using DATA_OPEN_WAITING(commitments, ShaChain.init, None) + Right(theirNextRevocationHash), ShaChain.init, anchorOutput) + goto(OPEN_WAITING_THEIRANCHOR) using DATA_OPEN_WAITING(commitments, None) } when(OPEN_WAIT_FOR_COMMIT_SIG) { @@ -119,18 +119,18 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann val commitments = Commitments(ourParams, theirParams, OurCommit(0, ourSpec, signedTx), theirCommitment, OurChanges(Nil, Nil, Nil), TheirChanges(Nil, Nil), - Right(theirNextRevocationHash), anchorOutput) - goto(OPEN_WAITING_OURANCHOR) using DATA_OPEN_WAITING(commitments, ShaChain.init, None) + Right(theirNextRevocationHash), ShaChain.init, anchorOutput) + goto(OPEN_WAITING_OURANCHOR) using DATA_OPEN_WAITING(commitments, None) } } when(OPEN_WAITING_THEIRANCHOR) { - case Event(BITCOIN_ANCHOR_DEPTHOK, d@DATA_OPEN_WAITING(commitments, shaChain, deferred)) => + case Event(BITCOIN_ANCHOR_DEPTHOK, d@DATA_OPEN_WAITING(commitments, deferred)) => blockchain ! WatchLost(self, commitments.anchorId, commitments.ourParams.minDepth, BITCOIN_ANCHOR_LOST) them ! open_complete(None) deferred.map(self ! _) //TODO htlcIdx should not be 0 when resuming connection - goto(OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR) using DATA_NORMAL(commitments, shaChain, 0, None) + goto(OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR) using DATA_NORMAL(commitments, 0, None) case Event(msg@open_complete(blockId_opt), d: DATA_OPEN_WAITING) => log.info(s"received their open_complete, deferring message") @@ -150,12 +150,12 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann } when(OPEN_WAITING_OURANCHOR) { - case Event(BITCOIN_ANCHOR_DEPTHOK, d@DATA_OPEN_WAITING(commitments, shaChain, deferred)) => + case Event(BITCOIN_ANCHOR_DEPTHOK, d@DATA_OPEN_WAITING(commitments, deferred)) => blockchain ! WatchLost(self, commitments.anchorId, commitments.ourParams.minDepth, BITCOIN_ANCHOR_LOST) them ! open_complete(None) deferred.map(self ! _) //TODO htlcIdx should not be 0 when resuming connection - goto(OPEN_WAIT_FOR_COMPLETE_OURANCHOR) using DATA_NORMAL(commitments, shaChain, 0, None) + goto(OPEN_WAIT_FOR_COMPLETE_OURANCHOR) using DATA_NORMAL(commitments, 0, None) case Event(msg@open_complete(blockId_opt), d: DATA_OPEN_WAITING) => log.info(s"received their open_complete, deferring message") @@ -163,11 +163,11 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann case Event(e@error(problem), d: DATA_OPEN_WAITING) => blockchain ! Publish(d.commitments.ourCommit.publishableTx) - goto(CLOSING) using DATA_CLOSING(d.commitments, d.shaChain, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) + goto(CLOSING) using DATA_CLOSING(d.commitments, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) case Event(cmd: CMD_CLOSE, d: DATA_OPEN_WAITING) => blockchain ! Publish(d.commitments.ourCommit.publishableTx) - goto(CLOSING) using DATA_CLOSING(d.commitments, d.shaChain, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) + goto(CLOSING) using DATA_CLOSING(d.commitments, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) case Event((BITCOIN_ANCHOR_SPENT, _), _) => goto(ERR_INFORMATION_LEAK) @@ -200,11 +200,11 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann case Event(e@error(problem), d: DATA_OPEN_WAITING) => log.error(s"received error message: $e") blockchain ! Publish(d.commitments.ourCommit.publishableTx) - goto(CLOSING) using DATA_CLOSING(d.commitments, d.shaChain, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) + goto(CLOSING) using DATA_CLOSING(d.commitments, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) case Event(cmd: CMD_CLOSE, d: DATA_OPEN_WAITING) => blockchain ! Publish(d.commitments.ourCommit.publishableTx) - goto(CLOSING) using DATA_CLOSING(d.commitments, d.shaChain, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) + goto(CLOSING) using DATA_CLOSING(d.commitments, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) } @@ -221,7 +221,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann when(NORMAL) { - case Event(CMD_ADD_HTLC(amount, rHash, expiry, nodeIds, origin, id_opt), d@DATA_NORMAL(commitments, _, htlcIdx, _)) => + case Event(CMD_ADD_HTLC(amount, rHash, expiry, nodeIds, origin, id_opt), d@DATA_NORMAL(commitments, htlcIdx, _)) => // TODO: should we take pending htlcs into account? // TODO: assert(commitment.state.commit_changes(staged).us.pay_msat >= amount, "insufficient funds!") // TODO: nodeIds are ignored @@ -230,7 +230,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann them ! htlc stay using d.copy(htlcIdx = htlc.id, commitments = commitments.addOurProposal(htlc)) - case Event(htlc@update_add_htlc(htlcId, amount, rHash, expiry, nodeIds), d@DATA_NORMAL(commitments, _, _, _)) => + case Event(htlc@update_add_htlc(htlcId, amount, rHash, expiry, nodeIds), d@DATA_NORMAL(commitments, _, _)) => // TODO: should we take pending htlcs into account? // assert(commitment.state.commit_changes(staged).them.pay_msat >= amount, "insufficient funds!") // TODO : we should fail the channel // TODO: nodeIds are ignored @@ -266,7 +266,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann log.error(cause, "received a bad signature") them ! error(Some("Bad signature")) publish_ourcommit(d.commitments.ourCommit) - goto(CLOSING) using DATA_CLOSING(d.commitments, d.shaChain, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) + goto(CLOSING) using DATA_CLOSING(d.commitments, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) } case Event(msg@update_revocation(revocationPreimage, nextRevocationHash), d: DATA_NORMAL) => @@ -275,7 +275,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann // TODO: check preimage stay using d.copy(commitments = Commitments.receiveRevocation(d.commitments, msg)) - case Event(theirClearing@close_clearing(theirScriptPubKey), d@DATA_NORMAL(commitments, _, _, ourClearingOpt)) => + case Event(theirClearing@close_clearing(theirScriptPubKey), d@DATA_NORMAL(commitments, _, ourClearingOpt)) => val ourClearing: close_clearing = ourClearingOpt.getOrElse { val ourScriptPubKey: BinaryData = Script.write(Scripts.pay2pkh(commitments.ourParams.finalPubKey)) log.info(s"our final tx can be redeemed with ${Base58Check.encode(Base58.Prefix.SecretKeyTestnet, d.commitments.ourParams.finalPrivKey)}") @@ -285,9 +285,9 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann if (commitments.hasNoPendingHtlcs) { val (finalTx, ourCloseSig) = makeFinalTx(commitments, ourClearing.scriptPubkey, theirScriptPubKey) them ! ourCloseSig - goto(NEGOCIATING) using DATA_NEGOCIATING(commitments, d.shaChain, d.htlcIdx, ourClearing, theirClearing, ourCloseSig) + goto(NEGOCIATING) using DATA_NEGOCIATING(commitments, d.htlcIdx, ourClearing, theirClearing, ourCloseSig) } else { - goto(CLEARING) using DATA_CLEARING(commitments, d.shaChain, d.htlcIdx, ourClearing, theirClearing) + goto(CLEARING) using DATA_CLEARING(commitments, d.htlcIdx, ourClearing, theirClearing) } case Event(CMD_CLOSE(scriptPubKeyOpt), d: DATA_NORMAL) => @@ -302,7 +302,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann case Event(e@error(problem), d: DATA_NORMAL) => log.error(s"peer send $e") blockchain ! Publish(d.commitments.ourCommit.publishableTx) - goto(CLOSING) using DATA_CLOSING(d.commitments, d.shaChain, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) + goto(CLOSING) using DATA_CLOSING(d.commitments, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) case Event((BITCOIN_ANCHOR_SPENT, tx: Transaction), d: DATA_NORMAL) => log.warning(s"anchor spent in ${tx.txid}") @@ -348,14 +348,14 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann them ! commit stay using d.copy(commitments = commitments1) - case Event(msg@update_commit(theirSig), d@DATA_CLEARING(commitments, _, _, ourClearing, theirClearing)) => + case Event(msg@update_commit(theirSig), d@DATA_CLEARING(commitments, _, ourClearing, theirClearing)) => Try(Commitments.receiveCommit(d.commitments, msg)) match { case Success((commitments1, revocation)) => them ! revocation if (commitments1.hasNoPendingHtlcs) { val (finalTx, ourCloseSig) = makeFinalTx(commitments1, ourClearing.scriptPubkey, theirClearing.scriptPubkey) them ! ourCloseSig - goto(NEGOCIATING) using DATA_NEGOCIATING(commitments1, d.shaChain, d.htlcIdx, ourClearing, theirClearing, ourCloseSig) + goto(NEGOCIATING) using DATA_NEGOCIATING(commitments1, d.htlcIdx, ourClearing, theirClearing, ourCloseSig) } else { stay using d.copy(commitments = commitments1) } @@ -363,16 +363,16 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann log.error(cause, "received a bad signature") them ! error(Some("Bad signature")) publish_ourcommit(d.commitments.ourCommit) - goto(CLOSING) using DATA_CLOSING(d.commitments, d.shaChain, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) + goto(CLOSING) using DATA_CLOSING(d.commitments, ourCommitPublished = Some(d.commitments.ourCommit.publishableTx)) } - case Event(msg@update_revocation(revocationPreimage, nextRevocationHash), d@DATA_CLEARING(commitments, _, _, ourClearing, theirClearing)) => + case Event(msg@update_revocation(revocationPreimage, nextRevocationHash), d@DATA_CLEARING(commitments, _, ourClearing, theirClearing)) => val commitments1 = Commitments.receiveRevocation(commitments, msg) if (commitments1.hasNoPendingHtlcs) { val (finalTx, ourCloseSig) = makeFinalTx(commitments1, ourClearing.scriptPubkey, theirClearing.scriptPubkey) them ! ourCloseSig - goto(NEGOCIATING) using DATA_NEGOCIATING(commitments1, d.shaChain, d.htlcIdx, ourClearing, theirClearing, ourCloseSig) + goto(NEGOCIATING) using DATA_NEGOCIATING(commitments1, d.htlcIdx, ourClearing, theirClearing, ourCloseSig) } else { stay using d.copy(commitments = commitments1) } @@ -384,7 +384,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann case Success(signedTx) => blockchain ! Publish(signedTx) blockchain ! WatchConfirmed(self, signedTx.txid, d.commitments.ourParams.minDepth, BITCOIN_CLOSE_DONE) - goto(CLOSING) using DATA_CLOSING(d.commitments, d.shaChain, ourSignature = Some(d.ourSignature), mutualClosePublished = Some(signedTx)) + goto(CLOSING) using DATA_CLOSING(d.commitments, ourSignature = Some(d.ourSignature), mutualClosePublished = Some(signedTx)) case Failure(cause) => log.error(cause, "cannot verify their close signature") throw new RuntimeException("cannot verify their close signature", cause) @@ -403,7 +403,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann val signedTx = addSigs(d.commitments.ourParams, d.commitments.theirParams, d.commitments.anchorOutput.amount.toLong, finalTx, ourCloseSig.sig, theirSig) blockchain ! Publish(signedTx) blockchain ! WatchConfirmed(self, signedTx.txid, d.commitments.ourParams.minDepth, BITCOIN_CLOSE_DONE) - goto(CLOSING) using DATA_CLOSING(d.commitments, d.shaChain, ourSignature = Some(ourCloseSig), mutualClosePublished = Some(signedTx)) + goto(CLOSING) using DATA_CLOSING(d.commitments, ourSignature = Some(ourCloseSig), mutualClosePublished = Some(signedTx)) } else { stay using d.copy(ourSignature = ourCloseSig) } diff --git a/eclair-demo/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala b/eclair-demo/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala index f741a79e4..c7c38144a 100644 --- a/eclair-demo/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala +++ b/eclair-demo/src/main/scala/fr/acinq/eclair/channel/ChannelTypes.scala @@ -144,14 +144,14 @@ final case class DATA_OPEN_WAIT_FOR_OPEN (ourParams: OurChannelPara final case class DATA_OPEN_WITH_ANCHOR_WAIT_FOR_ANCHOR(ourParams: OurChannelParams, theirParams: TheirChannelParams, theirRevocationHash: BinaryData, theirNextRevocationHash: sha256_hash) extends Data final case class DATA_OPEN_WAIT_FOR_ANCHOR (ourParams: OurChannelParams, theirParams: TheirChannelParams, theirRevocationHash: sha256_hash, theirNextRevocationHash: sha256_hash) extends Data final case class DATA_OPEN_WAIT_FOR_COMMIT_SIG (ourParams: OurChannelParams, theirParams: TheirChannelParams, anchorTx: Transaction, anchorOutputIndex: Int, initialCommitment: TheirCommit, theirNextRevocationHash: sha256_hash) extends Data -final case class DATA_OPEN_WAITING (commitments: Commitments, shaChain: ShaChain, deferred: Option[open_complete]) extends Data -final case class DATA_NORMAL (commitments: Commitments, shaChain: ShaChain, htlcIdx: Long, +final case class DATA_OPEN_WAITING (commitments: Commitments, deferred: Option[open_complete]) extends Data +final case class DATA_NORMAL (commitments: Commitments, htlcIdx: Long, ourClearing: Option[close_clearing]) extends Data -final case class DATA_CLEARING (commitments: Commitments, shaChain: ShaChain, htlcIdx: Long, +final case class DATA_CLEARING (commitments: Commitments, htlcIdx: Long, ourClearing: close_clearing, theirClearing: close_clearing) extends Data -final case class DATA_NEGOCIATING (commitments: Commitments, shaChain: ShaChain, htlcIdx: Long, +final case class DATA_NEGOCIATING (commitments: Commitments, htlcIdx: Long, ourClearing: close_clearing, theirClearing: close_clearing, ourSignature: close_signature) extends Data -final case class DATA_CLOSING (commitments: Commitments, shaChain: ShaChain, +final case class DATA_CLOSING (commitments: Commitments, ourSignature: Option[close_signature] = None, mutualClosePublished: Option[Transaction] = None, ourCommitPublished: Option[Transaction] = None, diff --git a/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Commitments.scala b/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Commitments.scala index 43a4a2e46..c60068d96 100644 --- a/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Commitments.scala +++ b/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Commitments.scala @@ -19,6 +19,7 @@ case class Commitments(ourParams: OurChannelParams, theirParams: TheirChannelPar ourCommit: OurCommit, theirCommit: TheirCommit, ourChanges: OurChanges, theirChanges: TheirChanges, theirNextCommitInfo: Either[TheirCommit, BinaryData], + theirShaChain: ShaChain, anchorOutput: TxOut) { def anchorId: BinaryData = { assert(ourCommit.publishableTx.txIn.size == 1, "commitment tx should only have one input")