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

added tests for state WAIT_FOR_FUNDING_PARENT

This commit is contained in:
pm47 2017-04-10 16:52:33 +02:00 committed by Pierre-Marie Padiou
parent 9a2bdb31a1
commit e2350ca8b1
4 changed files with 80 additions and 9 deletions

View File

@ -221,7 +221,7 @@ class Channel(val nodeParams: NodeParams, remoteNodeId: PublicKey, blockchain: A
log.info(s"publishing parent tx: txid=${parentTx.txid} tx=${Transaction.write(parentTx)}")
// we use a small delay so that we are sure Publish doesn't race with WatchSpent (which is ok but generates unnecessary warnings)
context.system.scheduler.scheduleOnce(100 milliseconds, blockchain, PublishAsap(parentTx))
goto(WAIT_FOR_FUNDING_PARENT) using DATA_WAIT_FOR_FUNDING_PARENT(fundingResponse, parentTx :: Nil, data)
goto(WAIT_FOR_FUNDING_PARENT) using DATA_WAIT_FOR_FUNDING_PARENT(fundingResponse, Set(parentTx), data)
case Event(CMD_CLOSE(_), _) => goto(CLOSED)
@ -231,7 +231,6 @@ class Channel(val nodeParams: NodeParams, remoteNodeId: PublicKey, blockchain: A
})
when(WAIT_FOR_FUNDING_PARENT)(handleExceptions {
case Event(WatchEventSpent(BITCOIN_INPUT_SPENT(parentTx), spendingTx), DATA_WAIT_FOR_FUNDING_PARENT(fundingResponse, parentCandidates, data)) =>
if (parentTx.txid != spendingTx.txid) {
// an input of our parent tx was spent by a tx that we're not aware of (i.e. a malleated version of our parent tx)
@ -239,7 +238,7 @@ class Channel(val nodeParams: NodeParams, remoteNodeId: PublicKey, blockchain: A
log.warning(s"parent tx has been malleated: originalParentTxid=${parentTx.txid} malleated=${spendingTx.txid}")
}
blockchain ! WatchConfirmed(self, spendingTx.txid, minDepth = 1, BITCOIN_TX_CONFIRMED(spendingTx))
stay using DATA_WAIT_FOR_FUNDING_PARENT(fundingResponse, spendingTx +: parentCandidates, data)
stay using DATA_WAIT_FOR_FUNDING_PARENT(fundingResponse, parentCandidates + spendingTx, data)
case Event(WatchEventConfirmed(BITCOIN_TX_CONFIRMED(tx), _, _), DATA_WAIT_FOR_FUNDING_PARENT(fundingResponse, _, data)) =>
// a potential parent for our funding tx has been confirmed, let's update our funding tx
@ -265,6 +264,12 @@ class Channel(val nodeParams: NodeParams, remoteNodeId: PublicKey, blockchain: A
log.warning(s"confirmed tx ${tx.txid} is not an input to our funding tx")
stay()
}
case Event(CMD_CLOSE(_), _) => goto(CLOSED)
case Event(e: Error, _) => handleRemoteErrorNoCommitments(e)
case Event(INPUT_DISCONNECTED, _) => goto(CLOSED)
})
when(WAIT_FOR_FUNDING_CREATED)(handleExceptions {

View File

@ -133,7 +133,7 @@ case class RevokedCommitPublished(commitTx: Transaction, claimMainOutputTx: Opti
final case class DATA_WAIT_FOR_OPEN_CHANNEL(initFundee: INPUT_INIT_FUNDEE) extends Data
final case class DATA_WAIT_FOR_ACCEPT_CHANNEL(initFunder: INPUT_INIT_FUNDER, lastSent: OpenChannel) extends Data
final case class DATA_WAIT_FOR_FUNDING_INTERNAL(temporaryChannelId: BinaryData, localParams: LocalParams, remoteParams: RemoteParams, fundingSatoshis: Long, pushMsat: Long, initialFeeratePerKw: Long, remoteFirstPerCommitmentPoint: Point, lastSent: OpenChannel) extends Data
final case class DATA_WAIT_FOR_FUNDING_PARENT(fundingResponse: MakeFundingTxResponse, parentCandidates: Seq[Transaction], data: DATA_WAIT_FOR_FUNDING_INTERNAL) extends Data
final case class DATA_WAIT_FOR_FUNDING_PARENT(fundingResponse: MakeFundingTxResponse, parentCandidates: Set[Transaction], data: DATA_WAIT_FOR_FUNDING_INTERNAL) extends Data
final case class DATA_WAIT_FOR_FUNDING_CREATED(temporaryChannelId: BinaryData, localParams: LocalParams, remoteParams: RemoteParams, fundingSatoshis: Long, pushMsat: Long, initialFeeratePerKw: Long, remoteFirstPerCommitmentPoint: Point, lastSent: AcceptChannel) extends Data
final case class DATA_WAIT_FOR_FUNDING_SIGNED(channelId: BinaryData, localParams: LocalParams, remoteParams: RemoteParams, fundingTx: Transaction, localSpec: CommitmentSpec, localCommitTx: CommitTx, remoteCommit: RemoteCommit, lastSent: FundingCreated) extends Data
final case class DATA_WAIT_FOR_FUNDING_CONFIRMED(commitments: Commitments, deferred: Option[FundingLocked], lastSent: Either[FundingCreated, FundingSigned]) extends Data with HasCommitments

View File

@ -45,11 +45,7 @@ class WaitForFundingCreatedInternalStateSpec extends TestkitBaseClass with State
alice ! dummyFundingTx
val w = alice2blockchain.expectMsgType[WatchSpent]
alice2blockchain.expectMsgType[PublishAsap]
alice ! WatchEventSpent(w.event, dummyFundingTx.parentTx)
alice2blockchain.expectMsgType[WatchConfirmed]
alice ! WatchEventConfirmed(BITCOIN_TX_CONFIRMED(dummyFundingTx.parentTx), 400000, 42)
awaitCond(alice.stateName == WAIT_FOR_FUNDING_SIGNED)
alice2bob.expectMsgType[FundingCreated]
awaitCond(alice.stateName == WAIT_FOR_FUNDING_PARENT)
}
}

View File

@ -0,0 +1,70 @@
package fr.acinq.eclair.channel.states.b
import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.bitcoin.Transaction
import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.channel._
import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.wire._
import fr.acinq.eclair.{TestBitcoinClient, TestConstants, TestkitBaseClass}
import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner
import scala.concurrent.duration._
/**
* Created by PM on 05/07/2016.
*/
@RunWith(classOf[JUnitRunner])
class WaitForFundingParentStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple5[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, Transaction]
override def withFixture(test: OneArgTest) = {
val setup = init()
import setup._
val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures)
val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures)
within(30 seconds) {
alice ! INPUT_INIT_FUNDER("00" * 32, TestConstants.fundingSatoshis, TestConstants.pushMsat, TestConstants.feeratePerKw, Alice.channelParams, alice2bob.ref, bobInit)
bob ! INPUT_INIT_FUNDEE("00" * 32, Bob.channelParams, bob2alice.ref, aliceInit)
alice2bob.expectMsgType[OpenChannel]
alice2bob.forward(bob)
bob2alice.expectMsgType[AcceptChannel]
bob2alice.forward(alice)
val makeFundingTx = alice2blockchain.expectMsgType[MakeFundingTx]
val dummyFundingTx = TestBitcoinClient.makeDummyFundingTx(makeFundingTx)
alice ! dummyFundingTx
alice2blockchain.expectMsgType[WatchSpent]
alice2blockchain.expectMsgType[PublishAsap]
awaitCond(alice.stateName == WAIT_FOR_FUNDING_PARENT)
test((alice, alice2bob, bob2alice, alice2blockchain, dummyFundingTx.parentTx))
}
}
test("recv BITCOIN_INPUT_SPENT and then BITCOIN_TX_CONFIRMED") { case (alice, alice2bob, _, alice2blockchain, parentTx) =>
within(30 seconds) {
alice ! WatchEventSpent(BITCOIN_INPUT_SPENT(parentTx), parentTx)
alice2blockchain.expectMsgType[WatchConfirmed]
alice ! WatchEventConfirmed(BITCOIN_TX_CONFIRMED(parentTx), 400000, 42)
alice2bob.expectMsgType[FundingCreated]
awaitCond(alice.stateName == WAIT_FOR_FUNDING_SIGNED)
}
}
test("recv Error") { case (bob, alice2bob, bob2alice, _, _) =>
within(30 seconds) {
bob ! Error("00" * 32, "oops".getBytes)
awaitCond(bob.stateName == CLOSED)
}
}
test("recv CMD_CLOSE") { case (alice, alice2bob, bob2alice, _, _) =>
within(30 seconds) {
alice ! CMD_CLOSE(None)
awaitCond(alice.stateName == CLOSED)
}
}
}