1
0
mirror of https://github.com/ACINQ/eclair.git synced 2024-11-19 18:10:42 +01:00

fixed tests covering OPEN->NORMAL

This commit is contained in:
pm47 2016-12-09 17:08:16 +01:00
parent 0e40569a7d
commit eef13e369c
23 changed files with 255 additions and 213 deletions

View File

@ -55,9 +55,9 @@ curl -X POST -H "Content-Type: application/json" -d '{
"params" : [ "localhost", 46000, 3000000 ]
}' http://localhost:8080
```
Since eclair is funder, it will create and publish the anchor tx
Since eclair is funder, it will create and publish the funding tx
Mine a few blocks to confirm the anchor tx:
Mine a few blocks to confirm the funding tx:
```shell
bitcoin-cli generate 10
```

View File

@ -120,7 +120,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
toSelfDelay = open.toSelfDelay,
maxAcceptedHtlcs = open.maxAcceptedHtlcs,
fundingPubkey = open.fundingPubkey,
revocationBasepoint = open.fundingPubkey,
revocationBasepoint = open.revocationBasepoint,
paymentBasepoint = open.paymentBasepoint,
delayedPaymentBasepoint = open.delayedPaymentBasepoint)
log.debug(s"remote params: $remoteParams")
@ -177,7 +177,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
when(WAIT_FOR_FUNDING_CREATED_INTERNAL)(handleExceptions {
case Event((fundingTx: Transaction, fundingTxOutputIndex: Int), DATA_WAIT_FOR_FUNDING_INTERNAL(temporaryChannelId, params, pushMsat, remoteFirstPerCommitmentPoint)) =>
// our wallet provided us with a funding tx
log.info(s"anchor txid=${fundingTx.txid}")
log.info(s"funding tx txid=${fundingTx.txid}")
// let's create the first commitment tx that spends the yet uncommitted funding tx
val (localSpec, localTx, remoteSpec, remoteTx, fundingTxOutput) = Funding.makeFirstCommitmentTx(funder = true, params, pushMsat, fundingTx.hash, fundingTxOutputIndex, remoteFirstPerCommitmentPoint)
@ -189,7 +189,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
outputIndex = fundingTxOutputIndex,
signature = localSigOfRemoteTx
)
goto(WAIT_FOR_FUNDING_SIGNED) using DATA_WAIT_FOR_FUNDING_SIGNED(temporaryChannelId, params, fundingTx, fundingTxOutputIndex, fundingTxOutput, localSpec, localTx, RemoteCommit(0, remoteSpec, fundingTx.hash, remoteFirstPerCommitmentPoint))
goto(WAIT_FOR_FUNDING_SIGNED) using DATA_WAIT_FOR_FUNDING_SIGNED(temporaryChannelId, params, fundingTx, fundingTxOutputIndex, fundingTxOutput, localSpec, localTx, RemoteCommit(0, remoteSpec, remoteTx.txid, remoteFirstPerCommitmentPoint))
case Event(CMD_CLOSE(_), _) => goto(CLOSED)
@ -200,11 +200,12 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
when(WAIT_FOR_FUNDING_CREATED)(handleExceptions {
case Event(FundingCreated(_, fundingTxHash, fundingTxOutputIndex, remoteSig), DATA_WAIT_FOR_FUNDING_CREATED(temporaryChannelId, params, pushMsat, remoteFirstPerCommitmentPoint)) =>
// they fund the channel with their anchor tx, so the money is theirs (but we are paid pushMsat)
// they fund the channel with their funding tx, so the money is theirs (but we are paid pushMsat)
val (localSpec, localTx, remoteSpec, remoteTx, fundingTxOutput) = Funding.makeFirstCommitmentTx(funder = false, params, pushMsat, fundingTxHash, fundingTxOutputIndex, remoteFirstPerCommitmentPoint)
// check remote signature validity
signAndCheckSig(params.localParams, params.remoteParams, fundingTxOutput, localTx, remoteSig) match {
val firstPerCommitmentPoint = Generators.perCommitPoint(localParams.shaSeed, 0)
signAndCheckSig(params.localParams, params.remoteParams, fundingTxOutput, firstPerCommitmentPoint, localTx, remoteSig) match {
case Failure(cause) =>
log.error(cause, "their FundingCreated message contains an invalid signature")
them ! Error(temporaryChannelId, cause.getMessage.getBytes)
@ -218,7 +219,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
signature = localSigOfRemoteTx
)
// watch the funding transaction
// watch the funding tx transaction
val fundingTxid = fundingTxHash.reverse //see https://github.com/ElementsProject/lightning/issues/17
blockchain ! WatchSpent(self, fundingTxid, fundingTxOutputIndex, 0, BITCOIN_FUNDING_SPENT) // TODO: should we wait for an acknowledgment from the watcher?
blockchain ! WatchConfirmed(self, fundingTxid, params.minimumDepth.toInt, BITCOIN_FUNDING_DEPTHOK)
@ -230,7 +231,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
remoteNextCommitInfo = Right(BinaryData("")), // we will receive their next per-commitment point in the next message, so we temporarily put an empty byte array
fundingTxOutput, ShaChain.init, new BasicTxDb)
context.system.eventStream.publish(ChannelIdAssigned(self, commitments.anchorId, Satoshi(params.fundingSatoshis)))
goto(WAIT_FOR_FUNDING_LOCKED) using DATA_WAIT_FOR_FUNDING_LOCKED(temporaryChannelId, params, commitments, None)
goto(WAIT_FOR_FUNDING_LOCKED_INTERNAL) using DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL(temporaryChannelId, params, commitments, None)
}
case Event(CMD_CLOSE(_), _) => goto(CLOSED)
@ -244,15 +245,16 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
case Event(FundingSigned(_, remoteSig), DATA_WAIT_FOR_FUNDING_SIGNED(temporaryChannelId, params, fundingTx, fundingTxOutputIndex, fundingTxOutput, localSpec, localTx, remoteCommit)) =>
// we make sure that their sig checks out and that our first commit tx is spendable
log.info(s"checking our tx: $localTx")
signAndCheckSig(params.localParams, params.remoteParams, fundingTxOutput, localTx, remoteSig) match {
val firstPerCommitmentPoint = Generators.perCommitPoint(localParams.shaSeed, 0)
signAndCheckSig(params.localParams, params.remoteParams, fundingTxOutput, firstPerCommitmentPoint, localTx, remoteSig) match {
case Failure(cause) =>
log.error(cause, "their FundingSigned message contains an invalid signature")
them ! Error(temporaryChannelId, cause.getMessage.getBytes)
// we haven't published anything yet, we can just stop
goto(CLOSED)
case Success(signedTx) =>
blockchain ! WatchSpent(self, fundingTx.txid, fundingTxOutputIndex, 0, BITCOIN_FUNDING_SPENT) // TODO: should we wait for an acknowledgment from the watcher?
blockchain ! WatchConfirmed(self, fundingTx.txid, params.minimumDepth, BITCOIN_FUNDING_DEPTHOK)
blockchain ! WatchSpent(self, fundingTx.txid, fundingTxOutputIndex, 0, BITCOIN_FUNDING_SPENT)
blockchain ! Publish(fundingTx)
val commitments = Commitments(params.localParams, params.remoteParams,
LocalCommit(0, localSpec, signedTx), remoteCommit,
@ -262,7 +264,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
fundingTxOutput, ShaChain.init, new BasicTxDb)
context.system.eventStream.publish(ChannelIdAssigned(self, commitments.anchorId, Satoshi(params.fundingSatoshis)))
context.system.eventStream.publish(ChannelSignatureReceived(self, commitments))
goto(WAIT_FOR_FUNDING_LOCKED) using DATA_WAIT_FOR_FUNDING_LOCKED(temporaryChannelId, params, commitments, None)
goto(WAIT_FOR_FUNDING_LOCKED_INTERNAL) using DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL(temporaryChannelId, params, commitments, None)
}
case Event(CMD_CLOSE(_), _) => goto(CLOSED)
@ -273,11 +275,12 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
})
when(WAIT_FOR_FUNDING_LOCKED_INTERNAL)(handleExceptions {
case Event(msg: FundingLocked, d: DATA_WAIT_FOR_FUNDING_LOCKED) =>
case Event(msg: FundingLocked, d: DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL) =>
log.info(s"received their FundingLocked, deferring message")
stay using d.copy(deferred = Some(msg))
case Event(BITCOIN_FUNDING_DEPTHOK, d@DATA_WAIT_FOR_FUNDING_LOCKED(temporaryChannelId, params, commitments, deferred)) =>
case Event(BITCOIN_FUNDING_DEPTHOK, d@DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL(temporaryChannelId, params, commitments, deferred)) =>
// TODO: set channelId
val channelId = 0L
blockchain ! WatchLost(self, commitments.anchorId, params.minimumDepth, BITCOIN_FUNDING_LOST)
val nextPerCommitmentPoint = Generators.perCommitPoint(localParams.shaSeed, 1)
@ -287,23 +290,19 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
goto(WAIT_FOR_FUNDING_LOCKED) using DATA_NORMAL(channelId, params, commitments, None, Map())
case Event(BITCOIN_FUNDING_TIMEOUT, _) =>
them ! Error(0, "Anchor timed out".getBytes)
them ! Error(0, "Funding tx timed out".getBytes)
goto(CLOSED)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_WAIT_FOR_FUNDING_LOCKED) if tx.txid == d.commitments.remoteCommit.txid =>
// they are funding the anchor, we have nothing at stake
log.warning(s"their anchor ${d.commitments.anchorId} was spent, sending error and closing")
them ! Error(0, s"your anchor ${d.commitments.anchorId} was spent".getBytes())
goto(CLOSED)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL) if tx.txid == d.commitments.remoteCommit.txid => handleRemoteSpentCurrent(tx, d)
case Event((BITCOIN_FUNDING_SPENT, _), d: DATA_WAIT_FOR_FUNDING_LOCKED) => handleInformationLeak(d)
case Event((BITCOIN_FUNDING_SPENT, _), d: DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL) => handleInformationLeak(d)
case Event(cmd: CMD_CLOSE, d: DATA_WAIT_FOR_FUNDING_LOCKED) =>
case Event(cmd: CMD_CLOSE, d: DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL) =>
blockchain ! Publish(d.commitments.localCommit.publishableTx)
blockchain ! WatchConfirmed(self, d.commitments.localCommit.publishableTx.txid, d.params.minimumDepth, BITCOIN_CLOSE_DONE)
goto(CLOSING) using DATA_CLOSING(d.commitments, ourCommitPublished = Some(d.commitments.localCommit.publishableTx))
case Event(e: Error, d: DATA_WAIT_FOR_FUNDING_LOCKED) =>
case Event(e: Error, d: DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL) =>
log.error(s"peer sent $e, closing connection") // see bolt #2: A node MUST fail the connection if it receives an err message
blockchain ! Publish(d.commitments.localCommit.publishableTx)
blockchain ! WatchConfirmed(self, d.commitments.localCommit.publishableTx.txid, d.params.minimumDepth, BITCOIN_CLOSE_DONE)
@ -316,6 +315,8 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
Register.create_alias(theirNodeId, d.commitments.anchorId)
goto(NORMAL)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_NORMAL) if tx.txid == d.commitments.remoteCommit.txid => handleRemoteSpentCurrent(tx, d)
case Event((BITCOIN_FUNDING_SPENT, _), d: DATA_NORMAL) => handleInformationLeak(d)
case Event(cmd: CMD_CLOSE, d: DATA_NORMAL) =>
@ -323,7 +324,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
blockchain ! WatchConfirmed(self, d.commitments.localCommit.publishableTx.txid, d.params.minimumDepth, BITCOIN_CLOSE_DONE)
goto(CLOSING) using DATA_CLOSING(d.commitments, ourCommitPublished = Some(d.commitments.localCommit.publishableTx))
case Event(e: Error, d: DATA_NORMAL) => handleTheirError(e, d)
case Event(e: Error, d: DATA_NORMAL) => handleRemoteError(e, d)
})
@ -358,7 +359,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
import scala.concurrent.ExecutionContext.Implicits.global
params.autoSignInterval.map(interval => context.system.scheduler.scheduleOnce(interval, self, CMD_SIGN))
stay using d.copy(commitments = commitments1)
case Failure(cause) => handleOurError(cause, d)
case Failure(cause) => handleLocalError(cause, d)
}
case Event(c@CMD_FULFILL_HTLC(id, r, do_commit), d: DATA_NORMAL) =>
@ -376,7 +377,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
import scala.concurrent.ExecutionContext.Implicits.global
params.autoSignInterval.map(interval => context.system.scheduler.scheduleOnce(interval, self, CMD_SIGN))
stay using d.copy(commitments = commitments1, downstreams = downstreams - id)
case Failure(cause) => handleOurError(cause, d)
case Failure(cause) => handleLocalError(cause, d)
}
case Event(c@CMD_FAIL_HTLC(id, reason, do_commit), d: DATA_NORMAL) =>
@ -394,7 +395,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
import scala.concurrent.ExecutionContext.Implicits.global
params.autoSignInterval.map(interval => context.system.scheduler.scheduleOnce(interval, self, CMD_SIGN))
stay using d.copy(commitments = commitments1, downstreams = downstreams - id)
case Failure(cause) => handleOurError(cause, d)
case Failure(cause) => handleLocalError(cause, d)
}
case Event(CMD_SIGN, d: DATA_NORMAL) if d.commitments.remoteNextCommitInfo.isLeft =>
@ -424,7 +425,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
.foreach(htlc => propagateUpstream(htlc.add, d.commitments.anchorId))
context.system.eventStream.publish(ChannelSignatureReceived(self, commitments1))
stay using d.copy(commitments = commitments1)
case Failure(cause) => handleOurError(cause, d)
case Failure(cause) => handleLocalError(cause, d)
}
case Event(msg: RevokeAndAck, d: DATA_NORMAL) =>
@ -433,7 +434,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
Try(Commitments.receiveRevocation(d.commitments, msg)) match {
case Success(commitments1) =>
stay using d.copy(commitments = commitments1)
case Failure(cause) => handleOurError(cause, d)
case Failure(cause) => handleLocalError(cause, d)
}
case Event(CMD_CLOSE(ourScriptPubKey_opt), d: DATA_NORMAL) =>
@ -464,11 +465,11 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
goto(SHUTDOWN) using DATA_SHUTDOWN(channelId, params, commitments, ourShutdown, theirShutdown, downstreams)
}
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_NORMAL) if tx.txid == d.commitments.remoteCommit.txid => handleTheirSpentCurrent(tx, d)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_NORMAL) if tx.txid == d.commitments.remoteCommit.txid => handleRemoteSpentCurrent(tx, d)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_NORMAL) => handleTheirSpentOther(tx, d)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_NORMAL) => handleRemoteSpentOther(tx, d)
case Event(e: Error, d: DATA_NORMAL) => handleTheirError(e, d)
case Event(e: Error, d: DATA_NORMAL) => handleRemoteError(e, d)
}
@ -495,7 +496,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
case Success((commitments1, htlc)) =>
propagateDownstream(htlc, Right(fulfill), d.downstreams(id))
stay using d.copy(commitments = commitments1, downstreams = d.downstreams - id)
case Failure(cause) => handleOurError(cause, d)
case Failure(cause) => handleLocalError(cause, d)
}
case Event(c@CMD_FAIL_HTLC(id, reason, do_commit), d: DATA_SHUTDOWN) =>
@ -509,7 +510,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
case Success((commitments1, htlc)) =>
propagateDownstream(htlc, Left(fail), d.downstreams(id))
stay using d.copy(commitments = commitments1, downstreams = d.downstreams - id)
case Failure(cause) => handleOurError(cause, d)
case Failure(cause) => handleLocalError(cause, d)
}
case Event(CMD_SIGN, d: DATA_SHUTDOWN) if d.commitments.remoteNextCommitInfo.isLeft =>
@ -541,7 +542,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
case Success((commitments1, revocation)) =>
them ! revocation
stay using d.copy(commitments = commitments1)
case Failure(cause) => handleOurError(cause, d)
case Failure(cause) => handleLocalError(cause, d)
}
case Event(msg: RevokeAndAck, d@DATA_SHUTDOWN(channelId, params, commitments, ourShutdown, theirShutdown, _)) =>
@ -555,14 +556,14 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
goto(NEGOTIATING) using DATA_NEGOTIATING(channelId, params, commitments1, ourShutdown, theirShutdown, closingSigned)
case Success(commitments1) =>
stay using d.copy(commitments = commitments1)
case Failure(cause) => handleOurError(cause, d)
case Failure(cause) => handleLocalError(cause, d)
}
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_SHUTDOWN) if tx.txid == d.commitments.remoteCommit.txid => handleTheirSpentCurrent(tx, d)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_SHUTDOWN) if tx.txid == d.commitments.remoteCommit.txid => handleRemoteSpentCurrent(tx, d)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_SHUTDOWN) => handleTheirSpentOther(tx, d)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_SHUTDOWN) => handleRemoteSpentOther(tx, d)
case Event(e: Error, d: DATA_SHUTDOWN) => handleTheirError(e, d)
case Event(e: Error, d: DATA_SHUTDOWN) => handleRemoteError(e, d)
}
when(NEGOTIATING) {
@ -578,19 +579,19 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
throw new RuntimeException("cannot verify their close signature", cause)
}
case Event(ClosingSigned(channelId, theirCloseFee, theirSig), d: DATA_NEGOTIATING) =>
checkCloseSignature(theirSig, Satoshi(theirCloseFee), d) match {
case Event(ClosingSigned(channelId, theirCloseFee, remoteSig), d: DATA_NEGOTIATING) =>
checkCloseSignature(remoteSig, Satoshi(theirCloseFee), d) match {
case Success(_) =>
val closeFee = ((theirCloseFee + d.ourClosingSigned.feeSatoshis) / 4) * 2 match {
case value if value == d.ourClosingSigned.feeSatoshis => value + 2
case value => value
}
val (finalTx, fee, ourCloseSig) = makeFinalTx(d.commitments, d.ourShutdown.scriptPubKey, d.theirShutdown.scriptPubKey, Satoshi(closeFee))
val closingSigned = ClosingSigned(channelId, fee, ourCloseSig)
val (finalTx, fee, localSig) = makeFinalTx(d.commitments, d.ourShutdown.scriptPubKey, d.theirShutdown.scriptPubKey, Satoshi(closeFee))
val closingSigned = ClosingSigned(channelId, fee, localSig)
log.info(s"finalTxId=${finalTx.txid}")
them ! closingSigned
if (closeFee == theirCloseFee) {
val signedTx = addSigs(d.commitments.localParams, d.commitments.remoteParams, d.commitments.fundingTxOutput.amount, finalTx, ourCloseSig, theirSig)
val signedTx = addSigs(finalTx, d.commitments.localParams.fundingPrivkey.point, d.commitments.remoteParams.fundingPubkey, localSig, remoteSig)
blockchain ! Publish(signedTx)
blockchain ! WatchConfirmed(self, signedTx.txid, 3, BITCOIN_CLOSE_DONE) // hardcoded mindepth
goto(CLOSING) using DATA_CLOSING(d.commitments, ourSignature = Some(closingSigned), mutualClosePublished = Some(signedTx))
@ -606,11 +607,11 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
// happens when we agreed on a closeSig, but we don't know it yet: we receive the watcher notification before their ClosingSigned (which will match ours)
stay()
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_NEGOTIATING) if tx.txid == d.commitments.remoteCommit.txid => handleTheirSpentCurrent(tx, d)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_NEGOTIATING) if tx.txid == d.commitments.remoteCommit.txid => handleRemoteSpentCurrent(tx, d)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_NEGOTIATING) => handleTheirSpentOther(tx, d)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_NEGOTIATING) => handleRemoteSpentOther(tx, d)
case Event(e: Error, d: DATA_NEGOTIATING) => handleTheirError(e, d)
case Event(e: Error, d: DATA_NEGOTIATING) => handleRemoteError(e, d)
}
@ -626,11 +627,11 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_CLOSING) if tx.txid == d.commitments.remoteCommit.txid =>
// counterparty may attempt to spend its last commit tx at any time
handleTheirSpentCurrent(tx, d)
handleRemoteSpentCurrent(tx, d)
case Event((BITCOIN_FUNDING_SPENT, tx: Transaction), d: DATA_CLOSING) =>
// counterparty may attempt to spend a revoked commit tx at any time
handleTheirSpentOther(tx, d)
handleRemoteSpentOther(tx, d)
case Event(BITCOIN_CLOSE_DONE, d: DATA_CLOSING) if d.mutualClosePublished.isDefined => goto(CLOSED)
@ -657,7 +658,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
whenUnhandled {
case Event(BITCOIN_FUNDING_LOST, _) => goto(ERR_ANCHOR_LOST)
case Event(BITCOIN_FUNDING_LOST, _) => goto(ERR_FUNDING_LOST)
case Event(CMD_GETSTATE, _) =>
sender ! stateName
@ -673,7 +674,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
case c: DATA_WAIT_FOR_OPEN_CHANNEL => 0L
case c: DATA_WAIT_FOR_ACCEPT_CHANNEL => c.temporaryChannelId
case c: DATA_WAIT_FOR_FUNDING_CREATED => c.temporaryChannelId
case c: DATA_WAIT_FOR_FUNDING_LOCKED => c.temporaryChannelId
case c: DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL => c.temporaryChannelId
case c: DATA_NORMAL => c.channelId
case c: DATA_SHUTDOWN => c.channelId
case c: DATA_NEGOTIATING => c.channelId
@ -760,27 +761,28 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
stay
}
def handleOurError(cause: Throwable, d: HasCommitments) = {
def handleLocalError(cause: Throwable, d: HasCommitments) = {
log.error(cause, "")
them ! Error(0, cause.getMessage)
spendOurCurrent(d)
spendLocalCurrent(d)
}
def handleTheirError(e: Error, d: HasCommitments) = {
def handleRemoteError(e: Error, d: HasCommitments) = {
log.error(s"peer sent $e, closing connection") // see bolt #2: A node MUST fail the connection if it receives an err message
spendOurCurrent(d)
spendLocalCurrent(d)
}
def spendOurCurrent(d: HasCommitments) = {
def spendLocalCurrent(d: HasCommitments) = {
val tx = d.commitments.localCommit.publishableTx
blockchain ! Publish(tx)
blockchain ! WatchConfirmed(self, tx.txid, 3, BITCOIN_SPEND_OURS_DONE) // TODO hardcoded mindepth
val txs1 = claimReceivedHtlcs(tx, Commitments.makeLocalTxTemplate(d.commitments), d.commitments)
// TODO: fix this!
/*val txs1 = claimReceivedHtlcs(tx, Commitments.makeLocalTxTemplate(d.commitments), d.commitments)
val txs2 = claimSentHtlcs(tx, Commitments.makeLocalTxTemplate(d.commitments), d.commitments)
val txs = txs1 ++ txs2
txs.map(tx => blockchain ! PublishAsap(tx))
txs.map(tx => blockchain ! PublishAsap(tx))*/
val nextData = d match {
case closing: DATA_CLOSING => closing.copy(ourCommitPublished = Some(tx))
@ -790,7 +792,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
goto(CLOSING) using nextData
}
def handleTheirSpentCurrent(tx: Transaction, d: HasCommitments) = {
def handleRemoteSpentCurrent(tx: Transaction, d: HasCommitments) = {
log.warning(s"they published their current commit in txid=${tx.txid}")
assert(tx.txid == d.commitments.remoteCommit.txid)
@ -809,8 +811,8 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
goto(CLOSING) using nextData
}
def handleTheirSpentOther(tx: Transaction, d: HasCommitments) = {
log.warning(s"anchor spent in txid=${tx.txid}")
def handleRemoteSpentOther(tx: Transaction, d: HasCommitments) = {
log.warning(s"funding tx spent in txid=${tx.txid}")
d.commitments.txDb.get(tx.txid) match {
case Some(spendingTx) =>
log.warning(s"txid=${tx.txid} was a revoked commitment, publishing the punishment tx")
@ -832,7 +834,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
def handleInformationLeak(d: HasCommitments) = {
// this is never supposed to happen !!
log.error(s"our anchor ${d.commitments.anchorId} was spent !!")
log.error(s"our funding tx ${d.commitments.anchorId} was spent !!")
// TODO! channel id
them ! Error(0, "Anchor has been spent".getBytes)
blockchain ! Publish(d.commitments.localCommit.publishableTx)
@ -848,7 +850,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, paymentHandler: Acto
s(event)
} catch {
case t: Throwable => event.stateData match {
case d: HasCommitments => handleOurError(t, d)
case d: HasCommitments => handleLocalError(t, d)
case _ =>
log.error(t, "")
goto(CLOSED)

View File

@ -39,8 +39,8 @@ case object SHUTDOWN extends State
case object NEGOTIATING extends State
case object CLOSING extends State
case object CLOSED extends State
case object ERR_ANCHOR_LOST extends State
case object ERR_ANCHOR_TIMEOUT extends State
case object ERR_FUNDING_LOST extends State
case object ERR_FUNDING_TIMEOUT extends State
case object ERR_INFORMATION_LEAK extends State
/*
@ -125,7 +125,7 @@ final case class DATA_WAIT_FOR_ACCEPT_CHANNEL(temporaryChannelId: Long, localPar
final case class DATA_WAIT_FOR_FUNDING_INTERNAL(temporaryChannelId: Long, params: ChannelParams, pushMsat: Long, remoteFirstPerCommitmentPoint: BinaryData) extends Data
final case class DATA_WAIT_FOR_FUNDING_CREATED(temporaryChannelId: Long, params: ChannelParams, pushMsat: Long, remoteFirstPerCommitmentPoint: BinaryData) extends Data
final case class DATA_WAIT_FOR_FUNDING_SIGNED(temporaryChannelId: Long, params: ChannelParams, fundingTx: Transaction, fundingTxOutputIndex: Int, fundingTxOutput: TxOut, localSpec: CommitmentSpec, localTx: Transaction, remoteCommit: RemoteCommit) extends Data
final case class DATA_WAIT_FOR_FUNDING_LOCKED(temporaryChannelId: Long, params: ChannelParams, commitments: Commitments, deferred: Option[FundingLocked]) extends Data with HasCommitments
final case class DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL(temporaryChannelId: Long, params: ChannelParams, commitments: Commitments, deferred: Option[FundingLocked]) extends Data with HasCommitments
final case class DATA_NORMAL(channelId: Long, params: ChannelParams, commitments: Commitments, ourShutdown: Option[Shutdown], downstreams: Map[Long, Option[Origin]]) extends Data with HasCommitments
final case class DATA_SHUTDOWN(channelId: Long, params: ChannelParams, commitments: Commitments,
ourShutdown: Shutdown, theirShutdown: Shutdown,

View File

@ -179,7 +179,7 @@ object Helpers {
val htlcTemplates = txTemplate.htlcReceived ++ txTemplate.htlcSent
//@tailrec
def loop(htlcs: Seq[HTLCTemplate], acc: Seq[Transaction] = Seq.empty[Transaction]): Seq[Transaction] = ???
def loop(htlcs: Seq[HTLCTemplate], acc: Seq[Transaction] = Seq.empty[Transaction]): Seq[Transaction] = Nil
/*{
htlcs.headOption match {
@ -207,7 +207,8 @@ object Helpers {
tx1.updateWitness(0, witness)
}
def claimSentHtlcs(tx: Transaction, txTemplate: CommitTxTemplate, commitments: Commitments): Seq[Transaction] = ???
// TODO: fix this!
def claimSentHtlcs(tx: Transaction, txTemplate: CommitTxTemplate, commitments: Commitments): Seq[Transaction] = Nil
/*{
// txTemplate could be our template (we published our commit tx) or their template (they published their commit tx)

View File

@ -79,17 +79,16 @@ object CommitmentSpec {
}
def makeLocalTxTemplate(localParams: LocalParams, remoteParams: RemoteParams, inputs: Seq[TxIn], localPerCommitmentPoint: Point, spec: CommitmentSpec): CommitTxTemplate = {
// TODO: derivePrivkey(key).point or derivePubkey(key.point) ?
val localDelayedPubkey = Generators.derivePubKey(localParams.delayedPaymentKey.point, localPerCommitmentPoint)
val localPubkey = Generators.derivePubKey(localParams.delayedPaymentKey.point, localPerCommitmentPoint)
val remotePubkey = Generators.derivePubKey(remoteParams.paymentBasepoint, localPerCommitmentPoint)
val localRevocationPubkey = Generators.revocationPubKey(localParams.revocationSecret.point, localPerCommitmentPoint)
CommitTxTemplate.makeCommitTxTemplate(inputs, localParams.toSelfDelay, localDelayedPubkey, remotePubkey, localRevocationPubkey, spec)
CommitTxTemplate.makeCommitTxTemplate(inputs, localRevocationPubkey, localParams.toSelfDelay, localPubkey, remotePubkey, spec)
}
def makeRemoteTxTemplate(localParams: LocalParams, remoteParams: RemoteParams, inputs: Seq[TxIn], remotePerCommitmentPoint: Point, spec: CommitmentSpec): CommitTxTemplate = {
val localPubkey = Generators.derivePubKey(localParams.paymentSecret.point, remotePerCommitmentPoint)
val remoteDelayedPubkey = Generators.derivePubKey(remoteParams.delayedPaymentBasepoint, remotePerCommitmentPoint)
val remoteRevocationPubkey = Generators.revocationPubKey(localParams.revocationSecret.point, remotePerCommitmentPoint)
CommitTxTemplate.makeCommitTxTemplate(inputs, remoteParams.toSelfDelay, remoteDelayedPubkey, localPubkey, remoteRevocationPubkey, spec)
val remotePubkey = Generators.derivePubKey(remoteParams.delayedPaymentBasepoint, remotePerCommitmentPoint)
val remoteRevocationPubkey = Generators.revocationPubKey(remoteParams.revocationBasepoint, remotePerCommitmentPoint)
CommitTxTemplate.makeCommitTxTemplate(inputs, remoteRevocationPubkey, remoteParams.toSelfDelay, remotePubkey, localPubkey, spec)
}
}

View File

@ -75,12 +75,12 @@ object OldScripts {
*
* @param pubkey1 public key for A
* @param pubkey2 public key for B
* @param amount anchor tx amount
* @param previousTx tx that will fund the anchor; it * must * be a P2PWPK embedded in a standard P2SH tx: the p2sh
* @param amount funding tx amount
* @param previousTx tx that will fund the funding tx; it * must * be a P2PWPK embedded in a standard P2SH tx: the p2sh
* script is just the P2WPK script for the public key that matches our "key" parameter
* @param outputIndex index of the output in the funding tx
* @param key private key that can redeem the funding tx
* @return a signed anchor tx
* @return a signed funding tx
*/
def makeAnchorTx(pubkey1: BinaryData, pubkey2: BinaryData, amount: Long, previousTx: Transaction, outputIndex: Int, key: BinaryData): (Transaction, Int) = {
val tx = Transaction(version = 2,
@ -173,7 +173,7 @@ object OldScripts {
* Create a "final" channel transaction that will be published when the channel is closed
*
* @param inputs inputs to include in the tx. In most cases, there's only one input that points to the output of
* the anchor tx
* the funding tx
* @param ourPubkeyScript our public key script
* @param theirPubkeyScript their public key script
* @param amount_us pay to us
@ -193,7 +193,7 @@ object OldScripts {
lockTime = 0))
}
//def isFunder(o: open_channel): Boolean = o.anch == open_channel.anchor_offer.WILL_CREATE_ANCHOR
//def isFunder(o: open_channel): Boolean = o.anch == open_channel.anchor_offer.WILL_CREATE_FUNDING
def findPublicKeyScriptIndex(tx: Transaction, publicKeyScript: BinaryData): Option[Int] =
tx.txOut.zipWithIndex.find {

View File

@ -7,7 +7,7 @@ import fr.acinq.bitcoin.{BinaryData, OP_2, OP_CHECKLOCKTIMEVERIFY, OP_CHECKMULTI
*/
object OutputScripts {
def toLocal(revocationPubKey: BinaryData, toSelfDelay: Long, localDelayedKey: BinaryData) = {
def toLocal(revocationPubKey: BinaryData, toSelfDelay: Int, localDelayedKey: BinaryData) = {
// @formatter:off
OP_IF ::
OP_PUSHDATA(revocationPubKey) ::

View File

@ -1,7 +1,8 @@
package fr.acinq.eclair.transactions
import fr.acinq.bitcoin.{BinaryData, Satoshi, ScriptFlags, Transaction, TxOut}
import fr.acinq.bitcoin.{BinaryData, SIGHASH_ALL, Satoshi, ScriptFlags, Transaction, TxOut}
import fr.acinq.eclair.channel.{LocalParams, RemoteParams}
import fr.acinq.eclair.crypto.Generators.{Point, Scalar}
import scala.util.Try
@ -10,27 +11,24 @@ import scala.util.Try
*/
object Signature {
def sign(localParams: LocalParams, remoteParams: RemoteParams, fundingSatoshis: Satoshi, tx: Transaction): BinaryData = ???
def sign(localParams: LocalParams, remoteParams: RemoteParams, fundingSatoshis: Satoshi, tx: Transaction): BinaryData = {
// this is because by convention in bitcoin-core-speak 32B keys are 'uncompressed' and 33B keys (ending by 0x01) are 'compressed'
val localCompressedFundingPrivkey: Seq[Byte] = localParams.fundingPrivkey.data.toSeq :+ 1.toByte
Transaction.signInput(tx, 0, OldScripts.multiSig2of2(localParams.fundingPrivkey.point, remoteParams.fundingPubkey), SIGHASH_ALL, fundingSatoshis, 1, localCompressedFundingPrivkey)
}
// Transaction.signInput(tx, 0, OldScripts.multiSig2of2(ourParams.commitPubKey, theirParams.commitPubKey), SIGHASH_ALL, anchorAmount, 1, ourParams.commitPrivKey)
def addSigs(tx: Transaction, localFundingPubkey: Point, remoteFundingPubkey: Point, localSig: BinaryData, remoteSig: BinaryData): Transaction = {
val witness = OldScripts.witness2of2(localSig, remoteSig, localFundingPubkey, remoteFundingPubkey)
tx.updateWitness(0, witness)
}
def addSigs(localParams: LocalParams, remoteParams: RemoteParams, fundingSatoshis: Satoshi, tx: Transaction, localSig: BinaryData, remoteSig: BinaryData): Transaction = ???
/*{
// TODO: Transaction.sign(...) should handle multisig
val ourSig = Transaction.signInput(tx, 0, multiSig2of2(ourParams.commitPubKey, theirParams.commitPubKey), SIGHASH_ALL, anchorAmount, 1, ourParams.commitPrivKey)
val witness = witness2of2(theirSig, ourSig, theirParams.commitPubKey, ourParams.commitPubKey)
tx.updateWitness(0, witness)
}*/
def checksig(localParams: LocalParams, remoteParams: RemoteParams, anchorOutput: TxOut, tx: Transaction): Try[Unit] =
def checksig(anchorOutput: TxOut, tx: Transaction): Try[Unit] =
Try(Transaction.correctlySpends(tx, Map(tx.txIn(0).outPoint -> anchorOutput), ScriptFlags.STANDARD_SCRIPT_VERIFY_FLAGS))
def signAndCheckSig(localParams: LocalParams, remoteParams: RemoteParams, anchorOutput: TxOut, tx: Transaction, remoteSig: BinaryData): Try[Transaction] = {
val localSig = sign(localParams, remoteParams, anchorOutput.amount, tx)
val signedTx = addSigs(localParams, remoteParams, anchorOutput.amount, tx, localSig, remoteSig)
checksig(localParams, remoteParams, anchorOutput, signedTx).map(_ => signedTx)
def signAndCheckSig(localParams: LocalParams, remoteParams: RemoteParams, anchorOutput: TxOut, localPerCommitmentPoint: Point, tx: Transaction, remoteSig: BinaryData): Try[Transaction] = {
val localSig = sign(localParams: LocalParams, remoteParams: RemoteParams, anchorOutput.amount, tx)
val signedTx = addSigs(tx, localParams.fundingPrivkey.point, remoteParams.fundingPubkey, localSig, remoteSig)
checksig(anchorOutput, signedTx).map(_ => signedTx)
}
}

View File

@ -33,14 +33,28 @@ object CommitTxTemplate {
/**
* Creates a commitment publishable by 'Local' (meaning that main output to local is delayed)
* @param inputs
* @param toLocalDelay
* @param localDelayedPubkey
* @param remotePubkey
* @param localRevocationPubkey
* @param commitmentSpec
* @param toLocalDelay
* @param localPubkey
* @param remotePubkey
* @param spec
* @return
*/
def makeCommitTxTemplate(inputs: Seq[TxIn], toLocalDelay: Int, localDelayedPubkey: BinaryData, remotePubkey: BinaryData, localRevocationPubkey: BinaryData, commitmentSpec: CommitmentSpec): CommitTxTemplate = ???
def makeCommitTxTemplate(inputs: Seq[TxIn], localRevocationPubkey: BinaryData, toLocalDelay: Int, localPubkey: BinaryData, remotePubkey: BinaryData, spec: CommitmentSpec): CommitTxTemplate = {
// TODO: no fees!!!
val (toLocal: Satoshi, toRemote: Satoshi) = (Satoshi(spec.to_local_msat / 1000), Satoshi(spec.to_remote_msat / 1000))
val toLocalDelayedOutputScript = OutputScripts.toLocal(localRevocationPubkey, toLocalDelay, localPubkey)
val toLocalDelayedOutput_opt = if (spec.to_local_msat >= 546000) Some(P2WSHTemplate(toLocal, toLocalDelayedOutputScript)) else None
val toRemoteOutputScript = OutputScripts.toRemote(remotePubkey)
val toRemoteOutput_opt = if (spec.to_remote_msat >= 546000) Some(P2WSHTemplate(toRemote, toRemoteOutputScript)) else None
assert(spec.htlcs.isEmpty, "not implemented")
CommitTxTemplate(inputs, toLocalDelayedOutput_opt, toRemoteOutput_opt, Nil, Nil)
}
/*def makeCommitTxTemplate(inputs: Seq[TxIn], ourFinalKey: BinaryData, theirFinalKey: BinaryData, theirDelay: Int, revocationHash: BinaryData, commitmentSpec: CommitmentSpec): CommitTxTemplate = {
val redeemScript = redeemSecretOrDelay(ourFinalKey, toSelfDelay2csv(theirDelay), theirFinalKey, revocationHash: BinaryData)

View File

@ -63,8 +63,8 @@ class PaymentFSMSpec extends TestKit(ActorSystem("test")) with FunSuiteLike with
router ! ChannelDiscovered(ChannelDesc("01", node_a, node_b))
router ! ChannelDiscovered(ChannelDesc("02", node_b, node_c))
selector ! ChannelChangedState(channel00.ref, node_b, OPEN_WAIT_FOR_COMPLETE_OURANCHOR, NORMAL, DATA_NORMAL_2(0, Commitments(null, null, null, TheirCommit(0L, CommitmentSpec(Set(), 0L, 0L, 100000), null, null), null, null, 0L, null, null, null, null, null), null, null))
selector ! ChannelChangedState(channel01.ref, node_b, OPEN_WAIT_FOR_COMPLETE_OURANCHOR, NORMAL, DATA_NORMAL(Commitments(null, null, null, TheirCommit(0L, CommitmentSpec(Set(), 0L, 0L, 100000000), null, null), null, null, 0L, null, null, null, null, null), null, null))
selector ! ChannelChangedState(channel00.ref, node_b, OPEN_WAIT_FOR_COMPLETE_OURFUNDING, NORMAL, DATA_NORMAL_2(0, Commitments(null, null, null, TheirCommit(0L, CommitmentSpec(Set(), 0L, 0L, 100000), null, null), null, null, 0L, null, null, null, null, null), null, null))
selector ! ChannelChangedState(channel01.ref, node_b, OPEN_WAIT_FOR_COMPLETE_OURFUNDING, NORMAL, DATA_NORMAL(Commitments(null, null, null, TheirCommit(0L, CommitmentSpec(Set(), 0L, 0L, 100000000), null, null), null, null, 0L, null, null, null, null, null), null, null))
val paymentFsm = system.actorOf(PaymentLifecycle.props(router, selector, 1440))
@ -99,8 +99,8 @@ class PaymentFSMSpec extends TestKit(ActorSystem("test")) with FunSuiteLike with
router ! ChannelDiscovered(ChannelDesc("01", node_a, node_b))
router ! ChannelDiscovered(ChannelDesc("02", node_b, node_c))
selector ! ChannelChangedState(channel00.ref, node_b, OPEN_WAIT_FOR_COMPLETE_OURANCHOR, NORMAL, DATA_NORMAL(Commitments(null, null, null, TheirCommit(0L, CommitmentSpec(Set(), 0L, 0L, 100000), null, null), null, null, 0L, null, null, null, null, null), null, null))
selector ! ChannelChangedState(channel01.ref, node_b, OPEN_WAIT_FOR_COMPLETE_OURANCHOR, NORMAL, DATA_NORMAL(Commitments(null, null, null, TheirCommit(0L, CommitmentSpec(Set(), 0L, 0L, 100000000), null, null), null, null, 0L, null, null, null, null, null), null, null))
selector ! ChannelChangedState(channel00.ref, node_b, OPEN_WAIT_FOR_COMPLETE_OURFUNDING, NORMAL, DATA_NORMAL(Commitments(null, null, null, TheirCommit(0L, CommitmentSpec(Set(), 0L, 0L, 100000), null, null), null, null, 0L, null, null, null, null, null), null, null))
selector ! ChannelChangedState(channel01.ref, node_b, OPEN_WAIT_FOR_COMPLETE_OURFUNDING, NORMAL, DATA_NORMAL(Commitments(null, null, null, TheirCommit(0L, CommitmentSpec(Set(), 0L, 0L, 100000000), null, null), null, null, 0L, null, null, null, null, null), null, null))
val paymentFsm = system.actorOf(PaymentLifecycle.props(router, selector, 1440))

View File

@ -48,7 +48,7 @@ class WaitForAcceptChannelStateSpec extends StateSpecBaseClass {
}
}
/*test("recv anchor") { case (alice, alice2bob, bob2alice, alice2blockchain, blockchain) =>
/*test("recv funding tx") { case (alice, alice2bob, bob2alice, alice2blockchain, blockchain) =>
within(30 seconds) {
bob2alice.expectMsgType[OpenChannel]
bob2alice.forward(alice)
@ -59,7 +59,7 @@ class WaitForAcceptChannelStateSpec extends StateSpecBaseClass {
}
}*/
test("recv error") { case (bob, alice2bob, bob2alice, _, _) =>
test("recv Error") { case (bob, alice2bob, bob2alice, _, _) =>
within(30 seconds) {
bob ! Error(0, "oops".getBytes)
awaitCond(bob.stateName == CLOSED)

View File

@ -43,7 +43,7 @@ class WaitForOpenChannelStateSpec extends StateSpecBaseClass {
}
}
test("recv error") { case (bob, alice2bob, bob2alice, bob2blockchain) =>
test("recv Error") { case (bob, alice2bob, bob2alice, bob2blockchain) =>
within(30 seconds) {
bob ! Error(0, "oops".getBytes())
awaitCond(bob.stateName == CLOSED)

View File

@ -37,12 +37,12 @@ class WaitForFundingCreatedInternalStateSpec extends StateSpecBaseClass {
alice2bob.forward(bob)
bob2alice.expectMsgType[AcceptChannel]
bob2alice.forward(alice)
awaitCond(alice.stateName == WAIT_FOR_FUNDING_CREATED_INTERNAL)
awaitCond(bob.stateName == WAIT_FOR_FUNDING_CREATED)
}
test((alice, alice2bob, bob2alice, alice2blockchain, blockchainA))
}
test("recv funding tx") { case (alice, alice2bob, bob2alice, alice2blockchain, blockchain) =>
test("recv funding transaction") { case (alice, alice2bob, bob2alice, alice2blockchain, blockchain) =>
within(30 seconds) {
alice2blockchain.expectMsgType[MakeFundingTx]
alice2blockchain.forward(blockchain)
@ -51,7 +51,7 @@ class WaitForFundingCreatedInternalStateSpec extends StateSpecBaseClass {
}
}
test("recv error") { case (bob, alice2bob, bob2alice, _, _) =>
test("recv Error") { case (bob, alice2bob, bob2alice, _, _) =>
within(30 seconds) {
bob ! Error(0, "oops".getBytes)
awaitCond(bob.stateName == CLOSED)

View File

@ -2,7 +2,7 @@ package fr.acinq.eclair.channel.states.b
import akka.actor.Props
import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.eclair.TestBitcoinClient
import fr.acinq.eclair.{TestBitcoinClient, TestConstants}
import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain.{PeerWatcher, WatchConfirmed, WatchSpent}
import fr.acinq.eclair.channel._
@ -29,11 +29,15 @@ class WaitForFundingCreatedStateSpec extends StateSpecBaseClass {
val paymentHandler = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, blockchainA, paymentHandler.ref, Alice.channelParams, "B"))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, paymentHandler.ref, Bob.channelParams, "A"))
alice2bob.expectMsgType[OpenChannel]
alice2bob.forward(bob)
bob2alice.expectMsgType[AcceptChannel]
bob2alice.forward(alice)
awaitCond(bob.stateName == WAIT_FOR_FUNDING_CREATED)
alice ! INPUT_INIT_FUNDER(TestConstants.anchorAmount, 0)
bob ! INPUT_INIT_FUNDEE()
within(30 seconds) {
alice2bob.expectMsgType[OpenChannel]
alice2bob.forward(bob)
bob2alice.expectMsgType[AcceptChannel]
bob2alice.forward(alice)
awaitCond(bob.stateName == WAIT_FOR_FUNDING_CREATED)
}
test((bob, alice2bob, bob2alice, bob2blockchain))
}
@ -41,14 +45,14 @@ class WaitForFundingCreatedStateSpec extends StateSpecBaseClass {
within(30 seconds) {
alice2bob.expectMsgType[FundingCreated]
alice2bob.forward(bob)
awaitCond(bob.stateName == WAIT_FOR_FUNDING_CREATED)
awaitCond(bob.stateName == WAIT_FOR_FUNDING_LOCKED_INTERNAL)
bob2alice.expectMsgType[FundingSigned]
bob2blockchain.expectMsgType[WatchConfirmed]
bob2blockchain.expectMsgType[WatchSpent]
bob2blockchain.expectMsgType[WatchConfirmed]
}
}
test("recv error") { case (bob, alice2bob, bob2alice, bob2blockchain) =>
test("recv Error") { case (bob, alice2bob, bob2alice, bob2blockchain) =>
within(30 seconds) {
bob ! Error(0, "oops".getBytes)
awaitCond(bob.stateName == CLOSED)

View File

@ -3,7 +3,7 @@ package fr.acinq.eclair.channel.states.b
import akka.actor.{ActorRef, Props}
import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.bitcoin.BinaryData
import fr.acinq.eclair.TestBitcoinClient
import fr.acinq.eclair.{TestBitcoinClient, TestConstants}
import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.channel._
@ -31,6 +31,8 @@ class WaitForFundingSignedStateSpec extends StateSpecBaseClass {
val paymentHandler = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, paymentHandler.ref, Alice.channelParams, "B"))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, paymentHandler.ref, Bob.channelParams, "A"))
alice ! INPUT_INIT_FUNDER(TestConstants.anchorAmount, 0)
bob ! INPUT_INIT_FUNDEE()
within(30 seconds) {
alice2bob.expectMsgType[OpenChannel]
alice2bob.forward(bob)
@ -49,9 +51,9 @@ class WaitForFundingSignedStateSpec extends StateSpecBaseClass {
within(30 seconds) {
bob2alice.expectMsgType[FundingSigned]
bob2alice.forward(alice)
awaitCond(alice.stateName == WAIT_FOR_FUNDING_SIGNED)
alice2blockchain.expectMsgType[WatchConfirmed]
awaitCond(alice.stateName == WAIT_FOR_FUNDING_LOCKED_INTERNAL)
alice2blockchain.expectMsgType[WatchSpent]
alice2blockchain.expectMsgType[WatchConfirmed]
alice2blockchain.expectMsgType[Publish]
}
}

View File

@ -1,8 +1,8 @@
package fr.acinq.eclair.channel.states.d
package fr.acinq.eclair.channel.states.c
import akka.actor.{ActorRef, Props}
import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.eclair.TestBitcoinClient
import fr.acinq.eclair.{TestBitcoinClient, TestConstants}
import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.channel._
@ -17,9 +17,9 @@ import scala.concurrent.duration._
* Created by PM on 05/07/2016.
*/
@RunWith(classOf[JUnitRunner])
class OpenWaitForCompleteOurAnchorStateSpec extends StateSpecBaseClass {
class WaitForFundingLockedInternalStateSpec extends StateSpecBaseClass {
type FixtureParam = Tuple5[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef]
type FixtureParam = Tuple6[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef]
override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe()
@ -30,6 +30,8 @@ class OpenWaitForCompleteOurAnchorStateSpec extends StateSpecBaseClass {
val paymentHandler = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, paymentHandler.ref, Alice.channelParams, "B"))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, paymentHandler.ref, Bob.channelParams, "A"))
alice ! INPUT_INIT_FUNDER(TestConstants.anchorAmount, 0)
bob ! INPUT_INIT_FUNDEE()
within(30 seconds) {
alice2bob.expectMsgType[OpenChannel]
alice2bob.forward(bob)
@ -41,43 +43,55 @@ class OpenWaitForCompleteOurAnchorStateSpec extends StateSpecBaseClass {
alice2bob.forward(bob)
bob2alice.expectMsgType[FundingSigned]
bob2alice.forward(alice)
alice2blockchain.expectMsgType[WatchConfirmed]
alice2blockchain.forward(blockchainA)
alice2blockchain.expectMsgType[WatchSpent]
alice2blockchain.forward(blockchainA)
alice2blockchain.expectMsgType[Publish]
alice2blockchain.forward(blockchainA)
alice2bob.expectMsgType[FundingLocked]
alice2bob.forward(bob)
bob ! BITCOIN_FUNDING_DEPTHOK
alice2blockchain.expectMsgType[WatchLost]
alice2blockchain.forward(blockchainA)
awaitCond(alice.stateName == WAIT_FOR_FUNDING_LOCKED)
}
test((alice, alice2bob, bob2alice, alice2blockchain, blockchainA))
}
test("recv FundingLocked") { case (alice, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
bob2alice.expectMsgType[FundingLocked]
bob2alice.forward(alice)
awaitCond(alice.stateName == NORMAL)
}
}
test("recv CMD_CLOSE") { case (alice, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val tx = alice.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.publishableTx
alice ! CMD_CLOSE(None)
awaitCond(alice.stateName == CLOSING)
alice2blockchain.expectMsg(Publish(tx))
alice2blockchain.expectMsgType[WatchConfirmed]
alice2blockchain.expectMsgType[Publish]
awaitCond(alice.stateName == WAIT_FOR_FUNDING_LOCKED_INTERNAL)
}
test((alice, bob, alice2bob, bob2alice, alice2blockchain, blockchainA))
}
test("recv FundingLocked") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
// make bob send a FundingLocked msg
bob ! BITCOIN_FUNDING_DEPTHOK
val msg = bob2alice.expectMsgType[FundingLocked]
bob2alice.forward(alice)
awaitCond(alice.stateData.asInstanceOf[DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL].deferred == Some(msg))
awaitCond(alice.stateName == WAIT_FOR_FUNDING_LOCKED_INTERNAL)
}
}
test("recv BITCOIN_ANCHOR_SPENT") { case (alice, alice2bob, bob2alice, alice2blockchain, _) =>
test("recv BITCOIN_FUNDING_DEPTHOK") { case (alice, _, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val tx = alice.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.publishableTx
alice ! BITCOIN_FUNDING_DEPTHOK
awaitCond(alice.stateName == WAIT_FOR_FUNDING_LOCKED)
alice2blockchain.expectMsgType[WatchLost]
alice2bob.expectMsgType[FundingLocked]
}
}
test("recv BITCOIN_FUNDING_TIMEOUT") { case (alice, _, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
alice ! BITCOIN_FUNDING_TIMEOUT
alice2bob.expectMsgType[Error]
awaitCond(alice.stateName == CLOSED)
}
}
test("recv BITCOIN_FUNDING_SPENT (remote commit)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
// bob publishes his commitment tx
val tx = bob.stateData.asInstanceOf[DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL].commitments.localCommit.publishableTx
alice ! (BITCOIN_FUNDING_SPENT, tx)
alice2blockchain.expectMsgType[WatchConfirmed]
awaitCond(alice.stateName == CLOSING)
}
}
test("recv BITCOIN_FUNDING_SPENT (other commit)") { case (alice, _, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val tx = alice.stateData.asInstanceOf[DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL].commitments.localCommit.publishableTx
alice ! (BITCOIN_FUNDING_SPENT, null)
alice2bob.expectMsgType[Error]
alice2blockchain.expectMsg(Publish(tx))
@ -85,10 +99,20 @@ class OpenWaitForCompleteOurAnchorStateSpec extends StateSpecBaseClass {
}
}
test("recv error") { case (alice, alice2bob, bob2alice, alice2blockchain, _) =>
test("recv Error") { case (alice, _, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val tx = alice.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.publishableTx
alice ! Error(0, "oops".getBytes())
val tx = alice.stateData.asInstanceOf[DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL].commitments.localCommit.publishableTx
alice ! Error(0, "oops".getBytes)
awaitCond(alice.stateName == CLOSING)
alice2blockchain.expectMsg(Publish(tx))
alice2blockchain.expectMsgType[WatchConfirmed]
}
}
test("recv CMD_CLOSE") { case (alice, _, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val tx = alice.stateData.asInstanceOf[DATA_WAIT_FOR_FUNDING_LOCKED_INTERNAL].commitments.localCommit.publishableTx
alice ! CMD_CLOSE(None)
awaitCond(alice.stateName == CLOSING)
alice2blockchain.expectMsg(Publish(tx))
alice2blockchain.expectMsgType[WatchConfirmed]

View File

@ -2,7 +2,7 @@ package fr.acinq.eclair.channel.states.c
import akka.actor.{ActorRef, Props}
import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.eclair.TestBitcoinClient
import fr.acinq.eclair.{TestBitcoinClient, TestConstants}
import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.channel._
@ -19,7 +19,7 @@ import scala.concurrent.duration._
@RunWith(classOf[JUnitRunner])
class WaitForFundingLockedStateSpec extends StateSpecBaseClass {
type FixtureParam = Tuple5[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef]
type FixtureParam = Tuple6[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef]
override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe()
@ -30,6 +30,8 @@ class WaitForFundingLockedStateSpec extends StateSpecBaseClass {
val paymentHandler = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, paymentHandler.ref, Alice.channelParams, "B"))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, paymentHandler.ref, Bob.channelParams, "A"))
alice ! INPUT_INIT_FUNDER(TestConstants.anchorAmount, 0)
bob ! INPUT_INIT_FUNDEE()
within(30 seconds) {
alice2bob.expectMsgType[OpenChannel]
alice2bob.forward(bob)
@ -41,47 +43,43 @@ class WaitForFundingLockedStateSpec extends StateSpecBaseClass {
alice2bob.forward(bob)
bob2alice.expectMsgType[FundingSigned]
bob2alice.forward(alice)
val watch = alice2blockchain.expectMsgType[WatchConfirmed]
alice2blockchain.send(blockchainA, watch.copy(channel = system.deadLetters)) // so that we can control when BITCOIN_ANCHOR_DEPTHOK arrives
alice2blockchain.expectMsgType[WatchSpent]
alice2blockchain.forward(blockchainA)
alice2blockchain.expectMsgType[WatchConfirmed]
alice2blockchain.expectMsgType[Publish]
alice2blockchain.forward(blockchainA)
bob ! BITCOIN_FUNDING_DEPTHOK
awaitCond(alice.stateName == WAIT_FOR_FUNDING_LOCKED)
}
test((alice, alice2bob, bob2alice, alice2blockchain, blockchainA))
}
test("recv FundingLocked") { case (alice, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val msg = bob2alice.expectMsgType[FundingLocked]
bob2alice.forward(alice)
awaitCond(alice.stateData.asInstanceOf[DATA_WAIT_FOR_FUNDING_LOCKED].deferred == Some(msg))
awaitCond(alice.stateName == WAIT_FOR_FUNDING_LOCKED)
}
}
test("recv BITCOIN_ANCHOR_DEPTHOK") { case (alice, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
bob2blockchain.expectMsgType[WatchSpent]
bob2blockchain.expectMsgType[WatchConfirmed]
alice ! BITCOIN_FUNDING_DEPTHOK
awaitCond(alice.stateName == WAIT_FOR_FUNDING_LOCKED)
bob ! BITCOIN_FUNDING_DEPTHOK
alice2blockchain.expectMsgType[WatchLost]
bob2blockchain.expectMsgType[WatchLost]
alice2bob.expectMsgType[FundingLocked]
awaitCond(alice.stateName == WAIT_FOR_FUNDING_LOCKED)
awaitCond(bob.stateName == WAIT_FOR_FUNDING_LOCKED)
}
test((alice, bob, alice2bob, bob2alice, alice2blockchain, blockchainA))
}
test("recv FundingLocked") { case (alice, _, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
bob2alice.expectMsgType[FundingLocked]
bob2alice.forward(alice)
awaitCond(alice.stateName == NORMAL)
}
}
test("recv BITCOIN_ANCHOR_TIMEOUT") { case (alice, alice2bob, bob2alice, alice2blockchain, _) =>
test("recv BITCOIN_FUNDING_SPENT (remote commit)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
alice ! BITCOIN_FUNDING_TIMEOUT
alice2bob.expectMsgType[Error]
awaitCond(alice.stateName == CLOSED)
// bob publishes his commitment tx
val tx = bob.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.publishableTx
alice ! (BITCOIN_FUNDING_SPENT, tx)
alice2blockchain.expectMsgType[WatchConfirmed]
awaitCond(alice.stateName == CLOSING)
}
}
test("recv BITCOIN_ANCHOR_SPENT") { case (alice, alice2bob, bob2alice, alice2blockchain, _) =>
test("recv BITCOIN_FUNDING_SPENT (other commit)") { case (alice, _, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val tx = alice.stateData.asInstanceOf[DATA_WAIT_FOR_FUNDING_LOCKED].commitments.localCommit.publishableTx
val tx = alice.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.publishableTx
alice ! (BITCOIN_FUNDING_SPENT, null)
alice2bob.expectMsgType[Error]
alice2blockchain.expectMsg(Publish(tx))
@ -89,9 +87,9 @@ class WaitForFundingLockedStateSpec extends StateSpecBaseClass {
}
}
test("recv error") { case (alice, alice2bob, bob2alice, alice2blockchain, _) =>
test("recv Error") { case (alice, _, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val tx = alice.stateData.asInstanceOf[DATA_WAIT_FOR_FUNDING_LOCKED].commitments.localCommit.publishableTx
val tx = alice.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.publishableTx
alice ! Error(0, "oops".getBytes)
awaitCond(alice.stateName == CLOSING)
alice2blockchain.expectMsg(Publish(tx))
@ -99,9 +97,9 @@ class WaitForFundingLockedStateSpec extends StateSpecBaseClass {
}
}
test("recv CMD_CLOSE") { case (alice, alice2bob, bob2alice, alice2blockchain, _) =>
test("recv CMD_CLOSE") { case (alice, _, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val tx = alice.stateData.asInstanceOf[DATA_WAIT_FOR_FUNDING_LOCKED].commitments.localCommit.publishableTx
val tx = alice.stateData.asInstanceOf[DATA_NORMAL].commitments.localCommit.publishableTx
alice ! CMD_CLOSE(None)
awaitCond(alice.stateName == CLOSING)
alice2blockchain.expectMsg(Publish(tx))

View File

@ -593,7 +593,7 @@ class NormalStateSpec extends StateSpecBaseClass with StateTestsHelperMethods {
}
}
test("recv BITCOIN_ANCHOR_SPENT (their commit w/ htlc)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, bob2blockchain) =>
test("recv BITCOIN_FUNDING_SPENT (their commit w/ htlc)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, bob2blockchain) =>
within(30 seconds) {
val sender = TestProbe()
@ -647,7 +647,7 @@ class NormalStateSpec extends StateSpecBaseClass with StateTestsHelperMethods {
}
}
test("recv BITCOIN_ANCHOR_SPENT (revoked commit)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
test("recv BITCOIN_FUNDING_SPENT (revoked commit)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val sender = TestProbe()
@ -699,7 +699,7 @@ class NormalStateSpec extends StateSpecBaseClass with StateTestsHelperMethods {
}
}
test("recv error") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
test("recv Error") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val (r1, htlc1) = addHtlc(300000000, alice, bob, alice2bob, bob2alice)
// id 1

View File

@ -378,7 +378,7 @@ class ShutdownStateSpec extends StateSpecBaseClass with StateTestsHelperMethods
}
}
test("recv BITCOIN_ANCHOR_SPENT (their commit)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
test("recv BITCOIN_FUNDING_SPENT (their commit)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
// bob publishes his current commit tx, which contains two pending htlcs alice->bob
val bobCommitTx = bob.stateData.asInstanceOf[DATA_SHUTDOWN].commitments.localCommit.publishableTx
@ -402,7 +402,7 @@ class ShutdownStateSpec extends StateSpecBaseClass with StateTestsHelperMethods
}
}
test("recv BITCOIN_ANCHOR_SPENT (revoked tx)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
test("recv BITCOIN_FUNDING_SPENT (revoked tx)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val revokedTx = bob.stateData.asInstanceOf[DATA_SHUTDOWN].commitments.localCommit.publishableTx
@ -428,7 +428,7 @@ class ShutdownStateSpec extends StateSpecBaseClass with StateTestsHelperMethods
}
}
test("recv error") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
test("recv Error") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val aliceCommitTx = alice.stateData.asInstanceOf[DATA_SHUTDOWN].commitments.localCommit.publishableTx
alice ! Error(0, "oops".getBytes)

View File

@ -139,7 +139,7 @@ class NegotiatingStateSpec extends StateSpecBaseClass {
}
}
test("recv BITCOIN_ANCHOR_SPENT (counterparty's mutual close)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, bob2blockchain) =>
test("recv BITCOIN_FUNDING_SPENT (counterparty's mutual close)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, bob2blockchain) =>
within(30 seconds) {
var aliceCloseFee, bobCloseFee = 0L
do {
@ -151,7 +151,7 @@ class NegotiatingStateSpec extends StateSpecBaseClass {
}
} while (aliceCloseFee != bobCloseFee)
// at this point alice and bob have converged on closing fees, but alice has not yet received the final signature whereas bob has
// bob publishes the mutual close and alice is notified that the anchor has been spent
// bob publishes the mutual close and alice is notified that the funding tx has been spent
// actual test starts here
assert(alice.stateName == NEGOTIATING)
val mutualCloseTx = bob2blockchain.expectMsgType[Publish].tx
@ -162,7 +162,7 @@ class NegotiatingStateSpec extends StateSpecBaseClass {
}
}
test("recv error") { case (alice, _, alice2bob, bob2alice, alice2blockchain, _) =>
test("recv Error") { case (alice, _, alice2bob, bob2alice, alice2blockchain, _) =>
within(30 seconds) {
val tx = alice.stateData.asInstanceOf[DATA_NEGOTIATING].commitments.localCommit.publishableTx
alice ! Error(0, "oops".getBytes())

View File

@ -104,7 +104,7 @@ class ClosingStateSpec extends StateSpecBaseClass with StateTestsHelperMethods {
}
}
test("recv BITCOIN_ANCHOR_SPENT (our commit)") { case (_, _, _, _, _, _, _) =>
test("recv BITCOIN_FUNDING_SPENT (our commit)") { case (_, _, _, _, _, _, _) =>
within(30 seconds) {
// this test needs a specific intialization because we need to have published our own commitment tx (that's why ignored fixture args)
// to do that alice will receive an error packet when in NORMAL state, which will make her publish her commit tx and then reach CLOSING state
@ -219,7 +219,7 @@ class ClosingStateSpec extends StateSpecBaseClass with StateTestsHelperMethods {
}
}
test("recv BITCOIN_ANCHOR_SPENT (their commit)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _, bobCommitTxes) =>
test("recv BITCOIN_FUNDING_SPENT (their commit)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _, bobCommitTxes) =>
within(30 seconds) {
val initialState = alice.stateData.asInstanceOf[DATA_CLOSING]
// bob publishes his last current commit tx, the one it had when entering NEGOTIATING state
@ -249,7 +249,7 @@ class ClosingStateSpec extends StateSpecBaseClass with StateTestsHelperMethods {
}
}
test("recv BITCOIN_ANCHOR_SPENT (one revoked tx)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _, bobCommitTxes) =>
test("recv BITCOIN_FUNDING_SPENT (one revoked tx)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _, bobCommitTxes) =>
within(30 seconds) {
val initialState = alice.stateData.asInstanceOf[DATA_CLOSING]
// bob publishes one of his revoked txes
@ -264,7 +264,7 @@ class ClosingStateSpec extends StateSpecBaseClass with StateTestsHelperMethods {
}
}
test("recv BITCOIN_ANCHOR_SPENT (multiple revoked tx)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _, bobCommitTxes) =>
test("recv BITCOIN_FUNDING_SPENT (multiple revoked tx)") { case (alice, bob, alice2bob, bob2alice, alice2blockchain, _, bobCommitTxes) =>
within(30 seconds) {
// bob publishes multiple revoked txes (last one isn't revoked)
for (bobRevokedTx <- bobCommitTxes.dropRight(1)) {

View File

@ -218,7 +218,7 @@ object InteroperabilitySpec {
/**
*
* @return a funding address that can be used to connect to another node
* @return a funding tx address that can be used to connect to another node
*/
def fund: String = {
val raw = s"$path newaddr" !!
@ -232,7 +232,7 @@ object InteroperabilitySpec {
*
* @param host node address
* @param port node port
* @param tx transaction that sends money to a funding address generated with the "fund" method
* @param tx transaction that sends money to a funding tx address generated with the "fund" method
*/
def connect(host: String, port: Int, tx: String): Unit = {
assert(s"$path connect $host $port $tx".! == 0)

View File

@ -82,7 +82,7 @@ class Bolt3Spec extends FunSuite {
)
val redeemScript: BinaryData = Bolt3.fundingScript(localPubKey, remotePubKey)
println(s"size of funding script: ${redeemScript.length}")
println(s"size of funding tx script: ${redeemScript.length}")
val localSig: BinaryData = Transaction.signInput(tx, 0, redeemScript, SIGHASH_ALL, fundingTx.txOut(fundingPos).amount, SigVersion.SIGVERSION_WITNESS_V0, localPrivKey)
println(s"local sig size: ${localSig.length}")
val remoteSig: BinaryData = Transaction.signInput(tx, 0, redeemScript, SIGHASH_ALL, fundingTx.txOut(fundingPos).amount, SigVersion.SIGVERSION_WITNESS_V0, remotePrivKey)