From 5b86675065f53d89f770e02cddd78b52c41341e6 Mon Sep 17 00:00:00 2001 From: sstone Date: Sun, 14 Feb 2016 20:01:09 +0100 Subject: [PATCH] fix tests --- .../eclair/blockchain/PollingWatcher.scala | 21 ++++++++++++-- .../fr/acinq/eclair/blockchain/Types.scala | 2 +- .../fr/acinq/eclair/channel/Anchor.scala | 16 ---------- .../fr/acinq/eclair/channel/Channel.scala | 2 +- .../eclair/channel/ChannelOpenSpec.scala | 29 ++++++++++++------- .../fr/acinq/eclair/channel/TestHelper.scala | 11 +++++-- 6 files changed, 49 insertions(+), 32 deletions(-) diff --git a/eclair-demo/src/main/scala/fr/acinq/eclair/blockchain/PollingWatcher.scala b/eclair-demo/src/main/scala/fr/acinq/eclair/blockchain/PollingWatcher.scala index 10cd58c2a..20abe1285 100644 --- a/eclair-demo/src/main/scala/fr/acinq/eclair/blockchain/PollingWatcher.scala +++ b/eclair-demo/src/main/scala/fr/acinq/eclair/blockchain/PollingWatcher.scala @@ -2,8 +2,10 @@ package fr.acinq.eclair.blockchain import akka.actor.{Cancellable, Actor, ActorLogging} -import fr.acinq.bitcoin.{BinaryData, Transaction, JsonRPCError, BitcoinJsonRPCClient} -import fr.acinq.eclair.channel.BITCOIN_ANCHOR_SPENT +import akka.pattern.pipe +import fr.acinq.bitcoin._ +import fr.acinq.eclair.channel +import fr.acinq.eclair.channel.{Scripts, BITCOIN_ANCHOR_SPENT} import grizzled.slf4j.Logging import org.bouncycastle.util.encoders.Hex import org.json4s.JsonAST._ @@ -61,6 +63,9 @@ class PollingWatcher(client: BitcoinJsonRPCClient)(implicit ec: ExecutionContext PollingWatcher.publishTransaction(client, tx).onFailure { case t: Throwable => log.error(t, s"cannot publish tx ${Hex.toHexString(Transaction.write(tx))}") } + + case MakeAnchor(ourCommitPub, theirCommitPub, amount) => + PollingWatcher.makeAnchorTx(client, ourCommitPub, theirCommitPub, amount).pipeTo(sender) } } @@ -152,6 +157,18 @@ object PollingWatcher extends Logging { tx = txs.find(tx => tx.txIn.exists(input => input.outPoint.txid == txid && input.outPoint.index == outputIndex)).getOrElse(throw new RuntimeException("tx not found!")) } yield tx } + + def makeAnchorTx(bitcoind: BitcoinJsonRPCClient, ourCommitPub: BinaryData, theirCommitPub: BinaryData, amount: Long)(implicit ec: ExecutionContext): Future[(Transaction, Int)] = { + val anchorOutputScript = channel.Scripts.anchorPubkeyScript(ourCommitPub, theirCommitPub) + val tx = Transaction(version = 1, txIn = Seq.empty[TxIn], txOut = TxOut(amount, anchorOutputScript) :: Nil, lockTime = 0) + val future = for { + FundTransactionResponse(tx1, changepos, fee) <- PollingWatcher.fundTransaction(bitcoind, tx) + SignTransactionResponse(anchorTx, true) <- PollingWatcher.signTransaction(bitcoind, tx1) + Some(pos) = Scripts.findPublicKeyScriptIndex(anchorTx, anchorOutputScript) + } yield (anchorTx, pos) + + future + } } object MyTest extends App { diff --git a/eclair-demo/src/main/scala/fr/acinq/eclair/blockchain/Types.scala b/eclair-demo/src/main/scala/fr/acinq/eclair/blockchain/Types.scala index 6d7e3f433..51761d948 100644 --- a/eclair-demo/src/main/scala/fr/acinq/eclair/blockchain/Types.scala +++ b/eclair-demo/src/main/scala/fr/acinq/eclair/blockchain/Types.scala @@ -17,5 +17,5 @@ final case class WatchSpent(channel: ActorRef, txId: BinaryData, outputIndex: In final case class WatchLost(channel: ActorRef, txId: BinaryData, minDepth: Int, event: BlockchainEvent) extends Watch // notify me if confirmation number gets below minDepth final case class Publish(tx: Transaction) - +final case class MakeAnchor(ourCommitPub: BinaryData, theirCommitPub: BinaryData, amount: Long) // @formatter:on diff --git a/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Anchor.scala b/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Anchor.scala index c6c73135c..9cbe74eed 100644 --- a/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Anchor.scala +++ b/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Anchor.scala @@ -10,23 +10,7 @@ import org.bouncycastle.util.encoders.Hex import scala.concurrent.{Future, ExecutionContext, Await} import scala.concurrent.duration._ -/** - * Created by fabrice on 03/02/16. - */ object Anchor extends App { - - def makeAnchorTx(bitcoind: BitcoinJsonRPCClient, ourCommitPub: BinaryData, theirCommitPub: BinaryData, amount: Long)(implicit ec: ExecutionContext): Future[(Transaction, Int)] = { - val anchorOutputScript = channel.Scripts.anchorPubkeyScript(ourCommitPub, theirCommitPub) - val tx = Transaction(version = 1, txIn = Seq.empty[TxIn], txOut = TxOut(amount, anchorOutputScript) :: Nil, lockTime = 0) - val future = for { - FundTransactionResponse(tx1, changepos, fee) <- PollingWatcher.fundTransaction(bitcoind, tx) - SignTransactionResponse(anchorTx, true) <- PollingWatcher.signTransaction(bitcoind, tx1) - Some(pos) = Scripts.findPublicKeyScriptIndex(anchorTx, anchorOutputScript) - } yield (anchorTx, pos) - - future - } - import scala.concurrent.ExecutionContext.Implicits.global object Alice { diff --git a/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Channel.scala b/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Channel.scala index f45feec8f..0bef79f85 100644 --- a/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Channel.scala +++ b/eclair-demo/src/main/scala/fr/acinq/eclair/channel/Channel.scala @@ -252,7 +252,7 @@ class Channel(val blockchain: ActorRef, val params: OurChannelParams) extends Lo case Event(open_channel(delay, theirRevocationHash, commitKey, finalKey, WONT_CREATE_ANCHOR, minDepth, commitmentFee), DATA_OPEN_WAIT_FOR_OPEN(ourParams)) => val theirParams = TheirChannelParams(delay, commitKey, finalKey, minDepth, commitmentFee) log.debug(s"their params: $theirParams") - Anchor.makeAnchorTx(Globals.bitcoin_client, ourCommitPubKey, theirParams.commitPubKey, ourParams.anchorAmount.get).pipeTo(self) + blockchain ! MakeAnchor(ourCommitPubKey, theirParams.commitPubKey, ourParams.anchorAmount.get) stay using DATA_OPEN_WITH_ANCHOR_WAIT_FOR_ANCHOR(ourParams, theirParams, theirRevocationHash) case Event((anchorTx: Transaction, anchorOutputIndex: Int), DATA_OPEN_WITH_ANCHOR_WAIT_FOR_ANCHOR(ourParams, theirParams, theirRevocationHash)) => diff --git a/eclair-demo/src/test/scala/fr/acinq/eclair/channel/ChannelOpenSpec.scala b/eclair-demo/src/test/scala/fr/acinq/eclair/channel/ChannelOpenSpec.scala index ef2b396e4..e98e47478 100644 --- a/eclair-demo/src/test/scala/fr/acinq/eclair/channel/ChannelOpenSpec.scala +++ b/eclair-demo/src/test/scala/fr/acinq/eclair/channel/ChannelOpenSpec.scala @@ -6,8 +6,11 @@ import fr.acinq.eclair.channel.Scripts._ import fr.acinq.eclair.blockchain.{Publish, WatchConfirmed, WatchConfirmedBasedOnOutputs} import lightning._ import org.junit.runner.RunWith +import org.scalatest.Ignore import org.scalatest.junit.JUnitRunner +import scala.concurrent.duration._ + /** * Created by PM on 02/09/2015. */ @@ -60,7 +63,8 @@ class ChannelOpenSpec extends TestHelper() { 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 theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, state.reverse) + 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)) node ! close_channel_complete(ourFinalSigForThem) expectMsgClass(classOf[close_channel_ack]) @@ -81,7 +85,8 @@ class ChannelOpenSpec extends TestHelper() { 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 theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, state.reverse) + 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)) node ! close_channel_complete(ourFinalSigForThem) expectMsgClass(classOf[close_channel_ack]) @@ -102,7 +107,8 @@ class ChannelOpenSpec extends TestHelper() { 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 theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, state.reverse) + 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)) node ! close_channel_complete(ourFinalSigForThem) expectMsgClass(classOf[close_channel_ack]) @@ -123,7 +129,8 @@ class ChannelOpenSpec extends TestHelper() { 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 theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, state.reverse) + 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)) node ! close_channel_complete(ourFinalSigForThem) expectMsgClass(classOf[close_channel_ack]) @@ -139,7 +146,8 @@ class ChannelOpenSpec extends TestHelper() { "handle PKT_CLOSE in OPEN_WAITING_THEIRANCHOR" 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 theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, state.reverse) + 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)) node ! close_channel(ourFinalSigForThem, 0) expectMsgClass(classOf[WatchConfirmed]) @@ -158,7 +166,8 @@ class ChannelOpenSpec extends TestHelper() { "handle PKT_CLOSE in OPEN_WAITING_OURANCHOR" in { 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 theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, state.reverse) + 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)) node ! close_channel(ourFinalSigForThem, 0) expectMsgClass(classOf[WatchConfirmed]) @@ -177,7 +186,8 @@ class ChannelOpenSpec extends TestHelper() { "handle PKT_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) // the only difference between their final tx and ours is the order of the outputs, because state is symmetric - val theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, state.reverse) + 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)) node ! close_channel(ourFinalSigForThem, 0) expectMsgClass(classOf[WatchConfirmed]) @@ -196,7 +206,8 @@ class ChannelOpenSpec extends TestHelper() { "handle PKT_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) // the only difference between their final tx and ours is the order of the outputs, because state is symmetric - val theirFinalTx = makeFinalTx(ourCommitTx.txIn, theirParams.finalPubKey, ourFinalPubKey, state.reverse) + 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)) node ! close_channel(ourFinalSigForThem, 0) expectMsgClass(classOf[WatchConfirmed]) @@ -211,7 +222,5 @@ class ChannelOpenSpec extends TestHelper() { node ! CMD_GETSTATE expectMsg(CLOSED) } - } - } diff --git a/eclair-demo/src/test/scala/fr/acinq/eclair/channel/TestHelper.scala b/eclair-demo/src/test/scala/fr/acinq/eclair/channel/TestHelper.scala index 6acd6865b..6934872f0 100644 --- a/eclair-demo/src/test/scala/fr/acinq/eclair/channel/TestHelper.scala +++ b/eclair-demo/src/test/scala/fr/acinq/eclair/channel/TestHelper.scala @@ -5,7 +5,7 @@ import akka.testkit.{ImplicitSender, TestKit} import com.google.protobuf.ByteString import fr.acinq.bitcoin._ import fr.acinq.eclair._ -import fr.acinq.eclair.blockchain.{Publish, WatchConfirmed, WatchLost, WatchSpent} +import fr.acinq.eclair.blockchain._ import fr.acinq.eclair.crypto.ShaChain import fr.acinq.eclair.channel.Scripts._ import lightning._ @@ -56,7 +56,7 @@ abstract class TestHelper(_system: ActorSystem) extends TestKit(_system) with Im val ourRevocationHash = Crypto.sha256(ShaChain.shaChainFromSeed(ourParams.shaSeed, 0)) node ! CMD_GETSTATE // node is in OPEN_WAIT_FOR_OPEN_NOANCHOR if (expectMsgClass(classOf[State]) == targetState) return (node, channelDesc) - channelDesc = channelDesc.copy(ourParams = Some(ourParams)) + channelDesc = channelDesc.copy(ourParams = Some(ourParams.copy(anchorAmount = None))) node ! open_channel(ourParams.delay, ourRevocationHash, ourCommitPubKey, ourFinalPubKey, WILL_CREATE_ANCHOR, Some(ourParams.minDepth), ourParams.commitmentFee) val (anchorTx, anchorOutputIndex) = makeAnchorTx(ourCommitPubKey, theirParams.commitPubKey, anchorAmount, previousTxOutput, signData) // we fund the channel with the anchor tx, so the money is ours @@ -99,6 +99,13 @@ abstract class TestHelper(_system: ActorSystem) extends TestKit(_system) with Im if (expectMsgClass(classOf[State]) == targetState) return (node, channelDesc) channelDesc = channelDesc.copy(ourParams = Some(ourParams)) node ! open_channel(ourParams.delay, ourRevocationHash, ourCommitPubKey, ourFinalPubKey, WONT_CREATE_ANCHOR, Some(ourParams.minDepth), ourParams.commitmentFee) + val MakeAnchor(_, _, amount) = expectMsgClass(classOf[MakeAnchor]) + val anchorTx = Transaction(version = 1, + txIn = Seq.empty[TxIn], + txOut = TxOut(amount, Scripts.anchorPubkeyScript(ourCommitPubKey, theirParams.commitPubKey)) :: Nil, + lockTime = 0 + ) + node ! (anchorTx, 0) val their_open_anchor = expectMsgClass(classOf[open_anchor]) // we fund the channel with the anchor tx, so the money is ours val state = ChannelState(them = ChannelOneSide(their_open_anchor.amount * 1000 - ourParams.commitmentFee * 1000, ourParams.commitmentFee * 1000, Seq()), us = ChannelOneSide(0, 0, Seq()))