mirror of
https://github.com/ACINQ/eclair.git
synced 2025-02-23 14:40:34 +01:00
Merge branch 'master' into wip-akkahttp
This commit is contained in:
commit
c63c71db11
9 changed files with 95 additions and 49 deletions
|
@ -56,10 +56,11 @@ eclair.bitcoind.rpcpassword (default: bar)
|
|||
## Status
|
||||
- [X] Network
|
||||
- [ ] Routing
|
||||
- [X] Channel state machine
|
||||
- [X] Channel protocol
|
||||
- [X] HTLC Scripts
|
||||
- [ ] Unilateral close handling
|
||||
- [ ] Relaying Payment
|
||||
- [ ] Fee management
|
||||
- [X] Blockchain watcher
|
||||
- [ ] Storing states in a database
|
||||
|
||||
|
|
|
@ -27,6 +27,9 @@ object Boot extends App with Logging {
|
|||
implicit val formats = org.json4s.DefaultFormats
|
||||
implicit val ec = ExecutionContext.Implicits.global
|
||||
|
||||
logger.info(s"hello!")
|
||||
logger.info(s"nodeid=${Globals.node_id.pub}")
|
||||
|
||||
val config = ConfigFactory.load()
|
||||
val chain = Await.result(bitcoin_client.invoke("getblockchaininfo").map(json => (json \ "chain").extract[String]), 10 seconds)
|
||||
assert(chain == "testnet" || chain == "regtest", "you should be on testnet or regtest")
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
package fr.acinq.eclair
|
||||
|
||||
import com.typesafe.config.ConfigFactory
|
||||
import fr.acinq.bitcoin.{BitcoinJsonRPCClient, Base58Check}
|
||||
import fr.acinq.bitcoin.{Crypto, BitcoinJsonRPCClient}
|
||||
import fr.acinq.eclair.channel.OurChannelParams
|
||||
import fr.acinq.eclair.crypto.LightningCrypto._
|
||||
import fr.acinq.eclair.crypto.LightningCrypto
|
||||
import lightning.locktime
|
||||
import lightning.locktime.Locktime.Seconds
|
||||
|
||||
|
@ -13,9 +13,10 @@ import lightning.locktime.Locktime.Seconds
|
|||
*/
|
||||
object Globals {
|
||||
val config = ConfigFactory.load()
|
||||
val node_id = KeyPair("0277863c1e40a2d4934ccf18e6679ea949d36bb0d1333fb098e99180df60d0195a","0623a602c7b0c96df445b999de31ca31682f0117ca2bf2fb149b9e09287d5d47")
|
||||
val commit_priv = Base58Check.decode("cQPmcNr6pwBQPyGfab3SksE9nTCtx9ism9T4dkS9dETNU2KKtJHk")._2
|
||||
val final_priv = Base58Check.decode("cUrAtLtV7GGddqdkhUxnbZVDWGJBTducpPoon3eKp9Vnr1zxs6BG")._2
|
||||
|
||||
val node_id = LightningCrypto.randomKeyPair()
|
||||
val commit_priv = Crypto.sha256(node_id.priv) // TODO : just for testing
|
||||
val final_priv = Crypto.sha256(commit_priv) // TODO : just for testing
|
||||
|
||||
val default_locktime = locktime(Seconds(86400))
|
||||
val default_mindepth = 3
|
||||
|
|
|
@ -26,7 +26,6 @@ class PollingWatcher(client: BitcoinJsonRPCClient)(implicit ec: ExecutionContext
|
|||
override def receive: Receive = ???
|
||||
|
||||
def watching(watches: Map[Watch, Cancellable]): Receive = {
|
||||
case w: WatchConfirmedBasedOnOutputs => log.warning(s"ignoring $w (not implemented)")
|
||||
|
||||
case w: WatchLost => log.warning(s"ignoring $w (not implemented)")
|
||||
|
||||
|
|
|
@ -12,7 +12,6 @@ import fr.acinq.eclair.channel.BlockchainEvent
|
|||
|
||||
trait Watch
|
||||
final case class WatchConfirmed(channel: ActorRef, txId: BinaryData, minDepth: Int, event: BlockchainEvent) extends Watch
|
||||
final case class WatchConfirmedBasedOnOutputs(channel: ActorRef, txIdSpent: BinaryData, txOut: Seq[TxOut], minDepth: Int, event: BlockchainEvent) extends Watch
|
||||
final case class WatchSpent(channel: ActorRef, txId: BinaryData, outputIndex: Int, minDepth: Int, event: BlockchainEvent) extends Watch
|
||||
final case class WatchLost(channel: ActorRef, txId: BinaryData, minDepth: Int, event: BlockchainEvent) extends Watch // notify me if confirmation number gets below minDepth
|
||||
|
||||
|
|
|
@ -734,7 +734,6 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
|
|||
goto(CLOSING) using DATA_CLOSING(d.ourParams, d.theirParams, d.shaChain, d.commitment, ourCommitPublished = Some(d.commitment.tx))
|
||||
case true =>
|
||||
them ! close_channel_ack()
|
||||
blockchain ! WatchConfirmed(self, signedFinalTx.txid, d.ourParams.minDepth, BITCOIN_CLOSE_DONE)
|
||||
blockchain ! Publish(signedFinalTx)
|
||||
goto(CLOSING) using DATA_CLOSING(d.ourParams, d.theirParams, d.shaChain, d.commitment, mutualClosePublished = Some(signedFinalTx))
|
||||
}
|
||||
|
@ -742,7 +741,8 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
|
|||
case Event((BITCOIN_ANCHOR_SPENT, tx: Transaction), d: CurrentCommitment) if (isMutualClose(tx, d.ourParams, d.theirParams, d.commitment)) =>
|
||||
// it is possible that we received this before the close_channel_complete, we may still receive the latter
|
||||
log.info(s"mutual close detected: $tx")
|
||||
stay
|
||||
blockchain ! WatchConfirmed(self, tx.txid, d.ourParams.minDepth, BITCOIN_CLOSE_DONE)
|
||||
goto(CLOSING) using DATA_CLOSING(d.ourParams, d.theirParams, d.shaChain, d.commitment, mutualClosePublished = Some(tx))
|
||||
|
||||
case Event((BITCOIN_ANCHOR_SPENT, tx: Transaction), d: CurrentCommitment) if (isTheirCommit(tx, d.ourParams, d.theirParams, d.commitment)) =>
|
||||
them ! handle_theircommit(tx, d.ourParams, d.theirParams, d.shaChain, d.commitment)
|
||||
|
@ -754,8 +754,6 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
|
|||
|
||||
case Event((BITCOIN_ANCHOR_SPENT, _), _) =>
|
||||
goto(ERR_INFORMATION_LEAK)
|
||||
|
||||
case Event(BITCOIN_CLOSE_DONE, _) => goto(CLOSED)
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -768,7 +766,8 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
|
|||
case Event((BITCOIN_ANCHOR_SPENT, tx: Transaction), d: CurrentCommitment) if (isMutualClose(tx, d.ourParams, d.theirParams, d.commitment)) =>
|
||||
// it is possible that we received this before the close_channel_ack, we may still receive the latter
|
||||
log.info(s"mutual close detected: $tx")
|
||||
stay
|
||||
blockchain ! WatchConfirmed(self, tx.txid, d.ourParams.minDepth, BITCOIN_CLOSE_DONE)
|
||||
goto(CLOSING) using DATA_CLOSING(d.ourParams, d.theirParams, d.shaChain, d.commitment, mutualClosePublished = Some(tx))
|
||||
|
||||
case Event((BITCOIN_ANCHOR_SPENT, tx: Transaction), d: CurrentCommitment) if (isTheirCommit(tx, d.ourParams, d.theirParams, d.commitment)) =>
|
||||
them ! handle_theircommit(tx, d.ourParams, d.theirParams, d.shaChain, d.commitment)
|
||||
|
@ -781,8 +780,6 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
|
|||
case Event((BITCOIN_ANCHOR_SPENT, _), _) =>
|
||||
goto(ERR_INFORMATION_LEAK)
|
||||
|
||||
case Event(BITCOIN_CLOSE_DONE, _) => goto(CLOSED)
|
||||
|
||||
case Event(pkt: error, d: DATA_WAIT_FOR_CLOSE_ACK) =>
|
||||
// no-op, because at this point we have already published the mutual close tx on the blockchain
|
||||
goto(CLOSING) using DATA_CLOSING(d.ourParams, d.theirParams, d.shaChain, d.commitment, mutualClosePublished = Some(d.mutualCloseTx))
|
||||
|
@ -796,6 +793,7 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
|
|||
|
||||
case Event((BITCOIN_ANCHOR_SPENT, tx: Transaction), d@DATA_CLOSING(ourParams, theirParams, _, commitment, _, _, _, _)) if (isMutualClose(tx, ourParams, theirParams, commitment)) =>
|
||||
log.info(s"mutual close detected: $tx")
|
||||
blockchain ! WatchConfirmed(self, tx.txid, ourParams.minDepth, BITCOIN_CLOSE_DONE)
|
||||
// wait for BITCOIN_CLOSE_DONE
|
||||
// should we override the previous tx? (which may be different because of malleability)
|
||||
stay using d.copy(mutualClosePublished = Some(tx))
|
||||
|
@ -838,6 +836,10 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
|
|||
case Event(BITCOIN_SPEND_THEIRS_DONE, _) => goto(CLOSED)
|
||||
|
||||
case Event(BITCOIN_STEAL_DONE, _) => goto(CLOSED)
|
||||
|
||||
case Event(p: close_channel_complete, _) => stay // if bitcoin network is faster than lightning network (very unlikely to happen)
|
||||
|
||||
case Event(p: close_channel_ack, _) => stay // if bitcoin network is faster than lightning network (very unlikely to happen)
|
||||
}
|
||||
|
||||
when(CLOSED) {
|
||||
|
@ -922,8 +924,6 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
|
|||
val finalTx = makeFinalTx(commitment.tx.txIn, ourFinalPubKey, theirParams.finalPubKey, closingState)
|
||||
val ourSig = bin2signature(Transaction.signInput(finalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
val anchorTxId = commitment.tx.txIn(0).outPoint.txid // commit tx only has 1 input, which is the anchor
|
||||
// we need to watch for BITCOIN_CLOSE_DONE with what we have here, because they may never answer with the fully signed closing tx and still publish it
|
||||
blockchain ! WatchConfirmedBasedOnOutputs(self, anchorTxId, finalTx.txOut, ourParams.minDepth, BITCOIN_CLOSE_DONE)
|
||||
close_channel(ourSig, cmd.fee)
|
||||
}
|
||||
|
||||
|
@ -932,7 +932,6 @@ class Channel(val them: ActorRef, val blockchain: ActorRef, val params: OurChann
|
|||
val finalTx = makeFinalTx(commitment.tx.txIn, ourFinalPubKey, theirParams.finalPubKey, closingState)
|
||||
val ourSig = Transaction.signInput(finalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey)
|
||||
val signedFinalTx = finalTx.updateSigScript(0, sigScript2of2(pkt.sig, ourSig, theirParams.commitPubKey, ourCommitPubKey))
|
||||
blockchain ! WatchConfirmed(self, signedFinalTx.txid, ourParams.minDepth, BITCOIN_CLOSE_DONE)
|
||||
blockchain ! Publish(signedFinalTx)
|
||||
(signedFinalTx, close_channel_complete(ourSig))
|
||||
}
|
||||
|
|
|
@ -68,7 +68,7 @@ class AuthHandler(them: ActorRef, blockchain: ActorRef, our_params: OurChannelPa
|
|||
stay using s.copy(totlen_in = new_totlen_in, acc_in = rest)
|
||||
|
||||
case Event(pkt(Auth(auth)), s: SessionData) =>
|
||||
log.info(s"their_nodeid: ${BinaryData(auth.nodeId.key.toByteArray)}")
|
||||
log.info(s"their_nodeid=${BinaryData(auth.nodeId.key.toByteArray)}")
|
||||
assert(Crypto.verifySignature(Crypto.hash256(session_key.pub), signature2bin(auth.sessionSig), pubkey2bin(auth.nodeId)), "auth failed")
|
||||
val channel = context.actorOf(Channel.props(self, blockchain, our_params), name = "channel")
|
||||
goto(IO_NORMAL) using Normal(channel, s)
|
||||
|
|
|
@ -3,7 +3,7 @@ package fr.acinq.eclair.channel
|
|||
import fr.acinq.bitcoin._
|
||||
import fr.acinq.eclair._
|
||||
import fr.acinq.eclair.channel.Scripts._
|
||||
import fr.acinq.eclair.blockchain.{Publish, WatchConfirmed, WatchConfirmedBasedOnOutputs}
|
||||
import fr.acinq.eclair.blockchain.{Publish, WatchConfirmed}
|
||||
import lightning._
|
||||
import org.junit.runner.RunWith
|
||||
import org.scalatest.Ignore
|
||||
|
@ -58,18 +58,18 @@ class ChannelOpenSpec extends TestHelper() {
|
|||
"handle CMD_CLOSE in OPEN_WAITING_THEIRANCHOR" in {
|
||||
val (node, ChannelDesc(Some(ourParams), Some(theirParams), Some(Commitment(_, ourCommitTx, state, _)))) = reachState_NOANCHOR(OPEN_WAITING_THEIRANCHOR)
|
||||
node ! CMD_CLOSE(0)
|
||||
expectMsgClass(classOf[WatchConfirmedBasedOnOutputs])
|
||||
expectMsgClass(classOf[close_channel])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(WAIT_FOR_CLOSE_COMPLETE)
|
||||
// the only difference between their final tx and ours is the order of the outputs, because state is symmetric
|
||||
val closingState = state.reverse.adjust_fees(Globals.closing_fee * 1000, ourParams.anchorAmount.isDefined)
|
||||
val theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(theirFinalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
val finalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(finalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
node ! close_channel_complete(ourFinalSigForThem)
|
||||
expectMsgClass(classOf[close_channel_ack])
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
expectMsgClass(classOf[Publish])
|
||||
node ! (BITCOIN_ANCHOR_SPENT, finalTx)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(CLOSING)
|
||||
node ! BITCOIN_CLOSE_DONE
|
||||
|
@ -77,21 +77,41 @@ class ChannelOpenSpec extends TestHelper() {
|
|||
expectMsg(CLOSED)
|
||||
}
|
||||
|
||||
"handle CMD_CLOSE in OPEN_WAITING_THEIRANCHOR (closing tx received early)" in {
|
||||
val (node, ChannelDesc(Some(ourParams), Some(theirParams), Some(Commitment(_, ourCommitTx, state, _)))) = reachState_NOANCHOR(OPEN_WAITING_THEIRANCHOR)
|
||||
node ! CMD_CLOSE(0)
|
||||
expectMsgClass(classOf[close_channel])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(WAIT_FOR_CLOSE_COMPLETE)
|
||||
// the only difference between their final tx and ours is the order of the outputs, because state is symmetric
|
||||
val closingState = state.reverse.adjust_fees(Globals.closing_fee * 1000, ourParams.anchorAmount.isDefined)
|
||||
val finalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(finalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
node ! (BITCOIN_ANCHOR_SPENT, finalTx)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(CLOSING)
|
||||
node ! close_channel_complete(ourFinalSigForThem)
|
||||
node ! BITCOIN_CLOSE_DONE
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(CLOSED)
|
||||
}
|
||||
|
||||
"handle CMD_CLOSE in OPEN_WAITING_OURANCHOR" in {
|
||||
val (node, ChannelDesc(Some(ourParams), Some(theirParams), Some(Commitment(_, ourCommitTx, state, _)))) = reachState_WITHANCHOR(OPEN_WAITING_OURANCHOR)
|
||||
node ! CMD_CLOSE(0)
|
||||
expectMsgClass(classOf[WatchConfirmedBasedOnOutputs])
|
||||
expectMsgClass(classOf[close_channel])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(WAIT_FOR_CLOSE_COMPLETE)
|
||||
// the only difference between their final tx and ours is the order of the outputs, because state is symmetric
|
||||
val closingState = state.reverse.adjust_fees(Globals.closing_fee * 1000, ourParams.anchorAmount.isDefined)
|
||||
val theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(theirFinalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
val finalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(finalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
node ! close_channel_complete(ourFinalSigForThem)
|
||||
expectMsgClass(classOf[close_channel_ack])
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
expectMsgClass(classOf[Publish])
|
||||
node ! (BITCOIN_ANCHOR_SPENT, finalTx)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(CLOSING)
|
||||
node ! BITCOIN_CLOSE_DONE
|
||||
|
@ -102,18 +122,18 @@ class ChannelOpenSpec extends TestHelper() {
|
|||
"handle CMD_CLOSE in OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR" in {
|
||||
val (node, ChannelDesc(Some(ourParams), Some(theirParams), Some(Commitment(_, ourCommitTx, state, _)))) = reachState_NOANCHOR(OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR)
|
||||
node ! CMD_CLOSE(0)
|
||||
expectMsgClass(classOf[WatchConfirmedBasedOnOutputs])
|
||||
expectMsgClass(classOf[close_channel])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(WAIT_FOR_CLOSE_COMPLETE)
|
||||
// the only difference between their final tx and ours is the order of the outputs, because state is symmetric
|
||||
val closingState = state.reverse.adjust_fees(Globals.closing_fee * 1000, ourParams.anchorAmount.isDefined)
|
||||
val theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(theirFinalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
val finalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(finalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
node ! close_channel_complete(ourFinalSigForThem)
|
||||
expectMsgClass(classOf[close_channel_ack])
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
expectMsgClass(classOf[Publish])
|
||||
node ! (BITCOIN_ANCHOR_SPENT, finalTx)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(CLOSING)
|
||||
node ! BITCOIN_CLOSE_DONE
|
||||
|
@ -124,18 +144,18 @@ class ChannelOpenSpec extends TestHelper() {
|
|||
"handle CMD_CLOSE in OPEN_WAIT_FOR_COMPLETE_OURANCHOR" in {
|
||||
val (node, ChannelDesc(Some(ourParams), Some(theirParams), Some(Commitment(_, ourCommitTx, state, _)))) = reachState_WITHANCHOR(OPEN_WAIT_FOR_COMPLETE_OURANCHOR)
|
||||
node ! CMD_CLOSE(0)
|
||||
expectMsgClass(classOf[WatchConfirmedBasedOnOutputs])
|
||||
expectMsgClass(classOf[close_channel])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(WAIT_FOR_CLOSE_COMPLETE)
|
||||
// the only difference between their final tx and ours is the order of the outputs, because state is symmetric
|
||||
val closingState = state.reverse.adjust_fees(Globals.closing_fee * 1000, ourParams.anchorAmount.isDefined)
|
||||
val theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(theirFinalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
val finalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(finalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
node ! close_channel_complete(ourFinalSigForThem)
|
||||
expectMsgClass(classOf[close_channel_ack])
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
expectMsgClass(classOf[Publish])
|
||||
node ! (BITCOIN_ANCHOR_SPENT, finalTx)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(CLOSING)
|
||||
node ! BITCOIN_CLOSE_DONE
|
||||
|
@ -147,15 +167,37 @@ class ChannelOpenSpec extends TestHelper() {
|
|||
val (node, ChannelDesc(Some(ourParams), Some(theirParams), Some(Commitment(_, ourCommitTx, state, _)))) = reachState_NOANCHOR(OPEN_WAITING_THEIRANCHOR)
|
||||
// the only difference between their final tx and ours is the order of the outputs, because state is symmetric
|
||||
val closingState = state.reverse.adjust_fees(Globals.closing_fee * 1000, ourParams.anchorAmount.isDefined)
|
||||
val theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(theirFinalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
val finalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(finalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
node ! close_channel(ourFinalSigForThem, 0)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
expectMsgClass(classOf[Publish])
|
||||
expectMsgClass(classOf[close_channel_complete])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(WAIT_FOR_CLOSE_ACK)
|
||||
node ! close_channel_ack()
|
||||
node ! (BITCOIN_ANCHOR_SPENT, finalTx) // TODO: this event could be sent before the close_channel_ack
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(CLOSING)
|
||||
node ! BITCOIN_CLOSE_DONE
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(CLOSED)
|
||||
}
|
||||
|
||||
"handle PKT_CLOSE in OPEN_WAITING_THEIRANCHOR (closing tx received early)" in {
|
||||
val (node, ChannelDesc(Some(ourParams), Some(theirParams), Some(Commitment(_, ourCommitTx, state, _)))) = reachState_NOANCHOR(OPEN_WAITING_THEIRANCHOR)
|
||||
// the only difference between their final tx and ours is the order of the outputs, because state is symmetric
|
||||
val closingState = state.reverse.adjust_fees(Globals.closing_fee * 1000, ourParams.anchorAmount.isDefined)
|
||||
val finalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(finalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
node ! close_channel(ourFinalSigForThem, 0)
|
||||
expectMsgClass(classOf[Publish])
|
||||
expectMsgClass(classOf[close_channel_complete])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(WAIT_FOR_CLOSE_ACK)
|
||||
node ! (BITCOIN_ANCHOR_SPENT, finalTx)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
node ! close_channel_ack()
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(CLOSING)
|
||||
node ! BITCOIN_CLOSE_DONE
|
||||
|
@ -167,15 +209,16 @@ class ChannelOpenSpec extends TestHelper() {
|
|||
val (node, ChannelDesc(Some(ourParams), Some(theirParams), Some(Commitment(_, ourCommitTx, state, _)))) = reachState_WITHANCHOR(OPEN_WAITING_OURANCHOR)
|
||||
// the only difference between their final tx and ours is the order of the outputs, because state is symmetric
|
||||
val closingState = state.reverse.adjust_fees(Globals.closing_fee * 1000, ourParams.anchorAmount.isDefined)
|
||||
val theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(theirFinalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
val finalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(finalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
node ! close_channel(ourFinalSigForThem, 0)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
expectMsgClass(classOf[Publish])
|
||||
expectMsgClass(classOf[close_channel_complete])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(WAIT_FOR_CLOSE_ACK)
|
||||
node ! close_channel_ack()
|
||||
node ! (BITCOIN_ANCHOR_SPENT, finalTx)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(CLOSING)
|
||||
node ! BITCOIN_CLOSE_DONE
|
||||
|
@ -187,15 +230,16 @@ class ChannelOpenSpec extends TestHelper() {
|
|||
val (node, ChannelDesc(Some(ourParams), Some(theirParams), Some(Commitment(_, ourCommitTx, state, _)))) = reachState_NOANCHOR(OPEN_WAIT_FOR_COMPLETE_THEIRANCHOR)
|
||||
// the only difference between their final tx and ours is the order of the outputs, because state is symmetric
|
||||
val closingState = state.reverse.adjust_fees(Globals.closing_fee * 1000, ourParams.anchorAmount.isDefined)
|
||||
val theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(theirFinalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
val finalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(finalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
node ! close_channel(ourFinalSigForThem, 0)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
expectMsgClass(classOf[Publish])
|
||||
expectMsgClass(classOf[close_channel_complete])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(WAIT_FOR_CLOSE_ACK)
|
||||
node ! close_channel_ack()
|
||||
node ! (BITCOIN_ANCHOR_SPENT, finalTx)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(CLOSING)
|
||||
node ! BITCOIN_CLOSE_DONE
|
||||
|
@ -207,15 +251,16 @@ class ChannelOpenSpec extends TestHelper() {
|
|||
val (node, ChannelDesc(Some(ourParams), Some(theirParams), Some(Commitment(_, ourCommitTx, state, _)))) = reachState_WITHANCHOR(OPEN_WAIT_FOR_COMPLETE_OURANCHOR)
|
||||
// the only difference between their final tx and ours is the order of the outputs, because state is symmetric
|
||||
val closingState = state.reverse.adjust_fees(Globals.closing_fee * 1000, ourParams.anchorAmount.isDefined)
|
||||
val theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(theirFinalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
val finalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, closingState)
|
||||
val ourFinalSigForThem = bin2signature(Transaction.signInput(finalTx, 0, multiSig2of2(ourCommitPubKey, theirParams.commitPubKey), SIGHASH_ALL, ourParams.commitPrivKey))
|
||||
node ! close_channel(ourFinalSigForThem, 0)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
expectMsgClass(classOf[Publish])
|
||||
expectMsgClass(classOf[close_channel_complete])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(WAIT_FOR_CLOSE_ACK)
|
||||
node ! close_channel_ack()
|
||||
node ! (BITCOIN_ANCHOR_SPENT, finalTx)
|
||||
expectMsgClass(classOf[WatchConfirmed])
|
||||
node ! CMD_GETSTATE
|
||||
expectMsg(CLOSING)
|
||||
node ! BITCOIN_CLOSE_DONE
|
||||
|
|
|
@ -40,7 +40,6 @@ class ChannelSpec extends TestKit(ActorSystem("TestSystem")) with WordSpecLike w
|
|||
case m: WatchConfirmed => true
|
||||
case m: WatchSpent => true
|
||||
case m: WatchLost => true
|
||||
case m: WatchConfirmedBasedOnOutputs => true
|
||||
}
|
||||
val pipe = system.actorOf(Props[ChannelSpec.Pipe])
|
||||
val alice = system.actorOf(Channel.props(pipe, blockchain.ref, Alice.channelParams), "Alice")
|
||||
|
|
Loading…
Add table
Reference in a new issue