1
0
Fork 0
mirror of https://github.com/ACINQ/eclair.git synced 2025-02-24 06:47:46 +01:00

move shachain into commitment data

This commit is contained in:
sstone 2016-06-17 14:49:56 +02:00
parent 2e61f8afa6
commit 25f5cd601f
3 changed files with 32 additions and 31 deletions

View file

@ -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)
}

View file

@ -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,

View file

@ -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")