1
0
mirror of https://github.com/ACINQ/eclair.git synced 2024-11-20 02:27:32 +01:00

Merge branch 'wip-bolts' into wip-persist3

This commit is contained in:
sstone 2017-02-27 16:35:01 +01:00
commit 817704f5da
33 changed files with 308 additions and 326 deletions

View File

@ -47,7 +47,8 @@ object Boot extends App with Logging {
class Setup() extends Logging { class Setup() extends Logging {
logger.info(s"hello!") logger.info(s"hello!")
logger.info(s"nodeid=${Globals.Node.publicKey.toBin} alias=${Globals.Node.alias}") val nodeParams = NodeParams.loadFromConfiguration()
logger.info(s"nodeid=${nodeParams.privateKey.publicKey.toBin} alias=${nodeParams.alias}")
val config = ConfigFactory.load() val config = ConfigFactory.load()
implicit lazy val system = ActorSystem() implicit lazy val system = ActorSystem()
@ -103,11 +104,11 @@ class Setup() extends Logging {
case "noop" => system.actorOf(Props[NoopPaymentHandler], name = "payment-handler") case "noop" => system.actorOf(Props[NoopPaymentHandler], name = "payment-handler")
} }
val register = system.actorOf(Props(new Register), name = "register") val register = system.actorOf(Props(new Register), name = "register")
val relayer = system.actorOf(Relayer.props(Globals.Node.privateKey, paymentHandler), name = "relayer") val relayer = system.actorOf(Relayer.props(nodeParams.privateKey, paymentHandler), name = "relayer")
val router = system.actorOf(Router.props(watcher, db), name = "router") val router = system.actorOf(Router.props(watcher, db), name = "router")
val paymentInitiator = system.actorOf(PaymentInitiator.props(Globals.Node.publicKey, router), "payment-initiator") val switchboard = system.actorOf(Switchboard.props(nodeParams, watcher, router, relayer, finalScriptPubKey, db), name = "switchboard")
val switchboard = system.actorOf(Switchboard.props(watcher, router, relayer, finalScriptPubKey, db), name = "switchboard") val paymentInitiator = system.actorOf(PaymentInitiator.props(nodeParams.privateKey.publicKey, router), "payment-initiator")
val server = system.actorOf(Server.props(switchboard, new InetSocketAddress(config.getString("eclair.server.host"), config.getInt("eclair.server.port"))), "server") val server = system.actorOf(Server.props(nodeParams, switchboard, new InetSocketAddress(config.getString("eclair.server.host"), config.getInt("eclair.server.port"))), "server")
val _setup = this val _setup = this
val api = new Service { val api = new Service {

View File

@ -1,50 +1,12 @@
package fr.acinq.eclair package fr.acinq.eclair
import java.net.InetSocketAddress
import java.util.concurrent.atomic.AtomicLong import java.util.concurrent.atomic.AtomicLong
import com.typesafe.config.ConfigFactory
import fr.acinq.bitcoin.{BinaryData, DeterministicWallet}
import fr.acinq.eclair.router.Router
import scala.compat.Platform
import scala.concurrent.duration._
/** /**
* Created by PM on 25/01/2016. * Created by PM on 25/01/2016.
*/ */
object Globals { object Globals {
val config = ConfigFactory.load().getConfig("eclair")
object Node {
val seed: BinaryData = config.getString("node.seed")
val master = DeterministicWallet.generate(seed)
val extendedPrivateKey = DeterministicWallet.derivePrivateKey(master, DeterministicWallet.hardened(46) :: DeterministicWallet.hardened(0) :: Nil)
val privateKey = extendedPrivateKey.privateKey
val extendedPublicKey = DeterministicWallet.publicKey(extendedPrivateKey)
val publicKey = extendedPublicKey.publicKey
val id = publicKey.toBin.toString()
val alias = config.getString("node.alias").take(32)
val color: (Byte, Byte, Byte) = (config.getInt("node.color.r").toByte, config.getInt("node.color.g").toByte, config.getInt("node.color.b").toByte)
val address = new InetSocketAddress(config.getString("server.host"), config.getInt("server.port"))
}
val global_features = BinaryData("")
val local_features = BinaryData("05") // channels_public and initial_routing_sync
val expiry_delta_blocks = config.getInt("expiry-delta-blocks")
val htlc_minimum_msat = config.getInt("htlc-minimum-msat")
val delay_blocks = config.getInt("delay-blocks")
val mindepth_blocks = config.getInt("mindepth-blocks")
val feeratePerKw = 10000
val fee_base_msat = config.getInt("fee-base-msat")
val fee_proportional_millionth = config.getInt("fee-proportional-millionth")
val default_anchor_amount = 1000000
// channel reserve can't be more than 5% of the funding amount (recommended: 1%)
val max_reserve_to_funding_ratio = 0.05
/** /**
* This counter holds the current blockchain height. * This counter holds the current blockchain height.
@ -53,3 +15,5 @@ object Globals {
*/ */
val blockCount = new AtomicLong(0) val blockCount = new AtomicLong(0)
} }

View File

@ -0,0 +1,64 @@
package fr.acinq.eclair
import java.net.InetSocketAddress
import com.typesafe.config.ConfigFactory
import fr.acinq.bitcoin.{BinaryData, DeterministicWallet}
import fr.acinq.bitcoin.Crypto.PrivateKey
import fr.acinq.bitcoin.DeterministicWallet.ExtendedPrivateKey
/**
* Created by PM on 26/02/2017.
*/
case class NodeParams(extendedPrivateKey: ExtendedPrivateKey,
privateKey: PrivateKey,
alias: String,
color: (Byte, Byte, Byte),
address: InetSocketAddress,
globalFeatures: BinaryData,
localFeatures: BinaryData,
dustLimitSatoshis: Long,
maxHtlcValueInFlightMsat: Long,
maxAcceptedHtlcs: Int,
expiryDeltaBlocks: Int,
htlcMinimumMsat: Int,
delayBlocks: Int,
minDepthBlocks: Int,
feeratePerKw: Int,
feeBaseMsat: Int,
feeProportionalMillionth: Int,
reserveToFundingRatio: Double,
maxReserveToFundingRatio: Double)
object NodeParams {
def loadFromConfiguration(): NodeParams = {
val config = ConfigFactory.load().getConfig("eclair")
val seed: BinaryData = config.getString("node.seed")
val master = DeterministicWallet.generate(seed)
val extendedPrivateKey = DeterministicWallet.derivePrivateKey(master, DeterministicWallet.hardened(46) :: DeterministicWallet.hardened(0) :: Nil)
NodeParams(
extendedPrivateKey = extendedPrivateKey,
privateKey = extendedPrivateKey.privateKey,
alias = config.getString("node.alias").take(32),
color = (config.getInt("node.color.r").toByte, config.getInt("node.color.g").toByte, config.getInt("node.color.b").toByte),
address = new InetSocketAddress(config.getString("server.host"), config.getInt("server.port")),
globalFeatures = BinaryData(""),
localFeatures = BinaryData("05"), // channels_public and initial_routing_sync
dustLimitSatoshis = 542,
maxHtlcValueInFlightMsat = Long.MaxValue,
maxAcceptedHtlcs = 100,
expiryDeltaBlocks = config.getInt("expiry-delta-blocks"),
htlcMinimumMsat = config.getInt("htlc-minimum-msat"),
delayBlocks = config.getInt("delay-blocks"),
minDepthBlocks = config.getInt("mindepth-blocks"),
feeratePerKw = 10000,
feeBaseMsat = config.getInt("fee-base-msat"),
feeProportionalMillionth = config.getInt("fee-proportional-millionth"),
reserveToFundingRatio = 0.01, // recommended by BOLT #2
maxReserveToFundingRatio = 0.05 // channel reserve can't be more than 5% of the funding amount (recommended: 1%)
)
}
}

View File

@ -27,7 +27,7 @@ case class ChannelRecord(id: Long, state: ChannelState)
*/ */
object Channel { object Channel {
def props(remote: ActorRef, blockchain: ActorRef, router: ActorRef, relayer: ActorRef, db: SimpleDb) = Props(new Channel(remote, blockchain, router, relayer, db)) def props(nodeParams: NodeParams, remote: ActorRef, blockchain: ActorRef, router: ActorRef, relayer: ActorRef, db: SimpleDb) = Props(new Channel(nodeParams, remote, blockchain, router, relayer, db))
def makeChannelDb(db: SimpleDb): SimpleTypedDb[Long, ChannelRecord] = { def makeChannelDb(db: SimpleDb): SimpleTypedDb[Long, ChannelRecord] = {
def channelid2String(id: Long) = s"channel-$id" def channelid2String(id: Long) = s"channel-$id"
@ -47,7 +47,7 @@ object Channel {
} }
} }
class Channel(val r: ActorRef, val blockchain: ActorRef, router: ActorRef, relayer: ActorRef, db: SimpleDb)(implicit ec: ExecutionContext = ExecutionContext.Implicits.global) extends LoggingFSM[State, Data] { class Channel(nodeParams: NodeParams, val r: ActorRef, val blockchain: ActorRef, router: ActorRef, relayer: ActorRef, db: SimpleDb)(implicit ec: ExecutionContext = ExecutionContext.Implicits.global) extends LoggingFSM[State, Data] {
import Channel._ import Channel._
@ -141,7 +141,7 @@ class Channel(val r: ActorRef, val blockchain: ActorRef, router: ActorRef, relay
when(WAIT_FOR_OPEN_CHANNEL)(handleExceptions { when(WAIT_FOR_OPEN_CHANNEL)(handleExceptions {
case Event(open: OpenChannel, DATA_WAIT_FOR_OPEN_CHANNEL(INPUT_INIT_FUNDEE(_, _, localParams, remoteInit))) => case Event(open: OpenChannel, DATA_WAIT_FOR_OPEN_CHANNEL(INPUT_INIT_FUNDEE(_, _, localParams, remoteInit))) =>
Try(Funding.validateParams(open.channelReserveSatoshis, open.fundingSatoshis)) match { Try(Funding.validateParams(nodeParams, open.channelReserveSatoshis, open.fundingSatoshis)) match {
case Failure(t) => case Failure(t) =>
log.warning(t.getMessage) log.warning(t.getMessage)
remote ! Error(open.temporaryChannelId, t.getMessage.getBytes) remote ! Error(open.temporaryChannelId, t.getMessage.getBytes)
@ -149,7 +149,7 @@ class Channel(val r: ActorRef, val blockchain: ActorRef, router: ActorRef, relay
case Success(_) => case Success(_) =>
context.system.eventStream.publish(ChannelCreated(open.temporaryChannelId, context.parent, self, localParams, remoteNodeId)) context.system.eventStream.publish(ChannelCreated(open.temporaryChannelId, context.parent, self, localParams, remoteNodeId))
// TODO: maybe also check uniqueness of temporary channel id // TODO: maybe also check uniqueness of temporary channel id
val minimumDepth = Globals.mindepth_blocks val minimumDepth = nodeParams.minDepthBlocks
val firstPerCommitmentPoint = Generators.perCommitPoint(localParams.shaSeed, 0) val firstPerCommitmentPoint = Generators.perCommitPoint(localParams.shaSeed, 0)
val accept = AcceptChannel(temporaryChannelId = open.temporaryChannelId, val accept = AcceptChannel(temporaryChannelId = open.temporaryChannelId,
dustLimitSatoshis = localParams.dustLimitSatoshis, dustLimitSatoshis = localParams.dustLimitSatoshis,
@ -195,7 +195,7 @@ class Channel(val r: ActorRef, val blockchain: ActorRef, router: ActorRef, relay
when(WAIT_FOR_ACCEPT_CHANNEL)(handleExceptions { when(WAIT_FOR_ACCEPT_CHANNEL)(handleExceptions {
case Event(accept: AcceptChannel, DATA_WAIT_FOR_ACCEPT_CHANNEL(INPUT_INIT_FUNDER(_, temporaryChannelId, fundingSatoshis, pushMsat, localParams, remoteInit), open)) => case Event(accept: AcceptChannel, DATA_WAIT_FOR_ACCEPT_CHANNEL(INPUT_INIT_FUNDER(_, temporaryChannelId, fundingSatoshis, pushMsat, localParams, remoteInit), open)) =>
Try(Funding.validateParams(accept.channelReserveSatoshis, fundingSatoshis)) match { Try(Funding.validateParams(nodeParams, accept.channelReserveSatoshis, fundingSatoshis)) match {
case Failure(t) => case Failure(t) =>
log.warning(t.getMessage) log.warning(t.getMessage)
remote ! Error(temporaryChannelId, t.getMessage.getBytes) remote ! Error(temporaryChannelId, t.getMessage.getBytes)
@ -375,7 +375,7 @@ class Channel(val r: ActorRef, val blockchain: ActorRef, router: ActorRef, relay
// this clock will be used to detect htlc timeouts // this clock will be used to detect htlc timeouts
context.system.eventStream.subscribe(self, classOf[CurrentBlockCount]) context.system.eventStream.subscribe(self, classOf[CurrentBlockCount])
if (Funding.announceChannel(params.localParams.localFeatures, params.remoteParams.localFeatures)) { if (Funding.announceChannel(params.localParams.localFeatures, params.remoteParams.localFeatures)) {
val (localNodeSig, localBitcoinSig) = Announcements.signChannelAnnouncement(d.channelId, Globals.Node.privateKey, remoteNodeId, d.params.localParams.fundingPrivKey, d.params.remoteParams.fundingPubKey) val (localNodeSig, localBitcoinSig) = Announcements.signChannelAnnouncement(d.channelId, nodeParams.privateKey, remoteNodeId, d.params.localParams.fundingPrivKey, d.params.remoteParams.fundingPubKey)
val annSignatures = AnnouncementSignatures(d.channelId, localNodeSig, localBitcoinSig) val annSignatures = AnnouncementSignatures(d.channelId, localNodeSig, localBitcoinSig)
// FD remote ! annSignatures // FD remote ! annSignatures
goto(WAIT_FOR_ANN_SIGNATURES) using DATA_WAIT_FOR_ANN_SIGNATURES(params, commitments.copy(remoteNextCommitInfo = Right(nextPerCommitmentPoint)).addToUnackedMessages(annSignatures), annSignatures) goto(WAIT_FOR_ANN_SIGNATURES) using DATA_WAIT_FOR_ANN_SIGNATURES(params, commitments.copy(remoteNextCommitInfo = Right(nextPerCommitmentPoint)).addToUnackedMessages(annSignatures), annSignatures)
@ -396,10 +396,10 @@ class Channel(val r: ActorRef, val blockchain: ActorRef, router: ActorRef, relay
when(WAIT_FOR_ANN_SIGNATURES)(handleExceptions { when(WAIT_FOR_ANN_SIGNATURES)(handleExceptions {
case Event(AnnouncementSignatures(_, remoteNodeSig, remoteBitcoinSig), d@DATA_WAIT_FOR_ANN_SIGNATURES(params, commitments, _)) => case Event(AnnouncementSignatures(_, remoteNodeSig, remoteBitcoinSig), d@DATA_WAIT_FOR_ANN_SIGNATURES(params, commitments, _)) =>
log.info(s"announcing channel ${d.channelId} on the network") log.info(s"announcing channel ${d.channelId} on the network")
val (localNodeSig, localBitcoinSig) = Announcements.signChannelAnnouncement(d.channelId, Globals.Node.privateKey, remoteNodeId, d.params.localParams.fundingPrivKey, d.params.remoteParams.fundingPubKey) val (localNodeSig, localBitcoinSig) = Announcements.signChannelAnnouncement(d.channelId, nodeParams.privateKey, remoteNodeId, d.params.localParams.fundingPrivKey, d.params.remoteParams.fundingPubKey)
val channelAnn = Announcements.makeChannelAnnouncement(d.channelId, Globals.Node.publicKey, remoteNodeId, d.params.localParams.fundingPrivKey.publicKey, d.params.remoteParams.fundingPubKey, localNodeSig, remoteNodeSig, localBitcoinSig, remoteBitcoinSig) val channelAnn = Announcements.makeChannelAnnouncement(d.channelId, nodeParams.privateKey.publicKey, remoteNodeId, d.params.localParams.fundingPrivKey.publicKey, d.params.remoteParams.fundingPubKey, localNodeSig, remoteNodeSig, localBitcoinSig, remoteBitcoinSig)
val nodeAnn = Announcements.makeNodeAnnouncement(Globals.Node.privateKey, Globals.Node.alias, Globals.Node.color, Globals.Node.address :: Nil, Platform.currentTime / 1000) val nodeAnn = Announcements.makeNodeAnnouncement(nodeParams.privateKey, nodeParams.alias, nodeParams.color, nodeParams.address :: Nil, Platform.currentTime / 1000)
val channelUpdate = Announcements.makeChannelUpdate(Globals.Node.privateKey, remoteNodeId, d.commitments.channelId, Globals.expiry_delta_blocks, Globals.htlc_minimum_msat, Globals.fee_base_msat, Globals.fee_proportional_millionth, Platform.currentTime / 1000) val channelUpdate = Announcements.makeChannelUpdate(nodeParams.privateKey, remoteNodeId, d.commitments.channelId, nodeParams.expiryDeltaBlocks, nodeParams.htlcMinimumMsat, nodeParams.feeBaseMsat, nodeParams.feeProportionalMillionth, Platform.currentTime / 1000)
router ! channelAnn router ! channelAnn
router ! nodeAnn router ! nodeAnn
router ! channelUpdate router ! channelUpdate
@ -850,7 +850,7 @@ class Channel(val r: ActorRef, val blockchain: ActorRef, router: ActorRef, relay
remote = r remote = r
// this is a brand new channel // this is a brand new channel
if (Funding.announceChannel(d.params.localParams.localFeatures, d.params.remoteParams.localFeatures)) { if (Funding.announceChannel(d.params.localParams.localFeatures, d.params.remoteParams.localFeatures)) {
val (localNodeSig, localBitcoinSig) = Announcements.signChannelAnnouncement(d.channelId, Globals.Node.privateKey, remoteNodeId, d.params.localParams.fundingPrivKey, d.params.remoteParams.fundingPubKey) val (localNodeSig, localBitcoinSig) = Announcements.signChannelAnnouncement(d.channelId, nodeParams.privateKey, remoteNodeId, d.params.localParams.fundingPrivKey, d.params.remoteParams.fundingPubKey)
val annSignatures = AnnouncementSignatures(d.channelId, localNodeSig, localBitcoinSig) val annSignatures = AnnouncementSignatures(d.channelId, localNodeSig, localBitcoinSig)
remote ! annSignatures remote ! annSignatures
} else { } else {

View File

@ -4,7 +4,7 @@ import fr.acinq.bitcoin.Crypto.{Point, PublicKey, Scalar, sha256}
import fr.acinq.bitcoin.Script._ import fr.acinq.bitcoin.Script._
import fr.acinq.bitcoin.{OutPoint, _} import fr.acinq.bitcoin.{OutPoint, _}
import fr.acinq.eclair.Features.Unset import fr.acinq.eclair.Features.Unset
import fr.acinq.eclair.{Features, Globals} import fr.acinq.eclair.{Features, Globals, NodeParams}
import fr.acinq.eclair.crypto.Generators import fr.acinq.eclair.crypto.Generators
import fr.acinq.eclair.transactions.Scripts._ import fr.acinq.eclair.transactions.Scripts._
import fr.acinq.eclair.transactions.Transactions._ import fr.acinq.eclair.transactions.Transactions._
@ -22,9 +22,9 @@ object Helpers {
object Funding { object Funding {
def validateParams(channelReserveSatoshis: Long, fundingSatoshis: Long): Unit = { def validateParams(nodeParams: NodeParams, channelReserveSatoshis: Long, fundingSatoshis: Long): Unit = {
val reserveToFundingRatio = channelReserveSatoshis.toDouble / fundingSatoshis val reserveToFundingRatio = channelReserveSatoshis.toDouble / fundingSatoshis
require(reserveToFundingRatio <= Globals.max_reserve_to_funding_ratio, s"channelReserveSatoshis too high: ratio=$reserveToFundingRatio max=${Globals.max_reserve_to_funding_ratio}") require(reserveToFundingRatio <= nodeParams.maxReserveToFundingRatio, s"channelReserveSatoshis too high: ratio=$reserveToFundingRatio max=${nodeParams.maxReserveToFundingRatio}")
} }
def makeFundingInputInfo(fundingTxId: BinaryData, fundingTxOutputIndex: Int, fundingSatoshis: Satoshi, fundingPubkey1: PublicKey, fundingPubkey2: PublicKey): InputInfo = { def makeFundingInputInfo(fundingTxId: BinaryData, fundingTxOutputIndex: Int, fundingSatoshis: Satoshi, fundingPubkey1: PublicKey, fundingPubkey2: PublicKey): InputInfo = {

View File

@ -27,7 +27,7 @@ class GUIUpdater(primaryStage: Stage, mainController: MainController, setup: Set
} }
val graph = new SimpleGraph[BinaryData, NamedEdge](classOf[NamedEdge]) val graph = new SimpleGraph[BinaryData, NamedEdge](classOf[NamedEdge])
graph.addVertex(Globals.Node.publicKey) graph.addVertex(setup.nodeParams.privateKey.publicKey)
def receive: Receive = main(Map()) def receive: Receive = main(Map())

View File

@ -65,7 +65,7 @@ class Handlers(setup: Setup) extends Logging {
(paymentHandler ? 'genh).mapTo[BinaryData].map { h => (paymentHandler ? 'genh).mapTo[BinaryData].map { h =>
Platform.runLater(new Runnable() { Platform.runLater(new Runnable() {
override def run = { override def run = {
textarea.setText(s"${Globals.Node.id}:$amountMsat:${h.toString()}") textarea.setText(s"${setup.nodeParams.privateKey.publicKey}:$amountMsat:${h.toString()}")
textarea.requestFocus textarea.requestFocus
textarea.selectAll textarea.selectAll
} }

View File

@ -89,7 +89,7 @@ class MainController(val handlers: Handlers, val stage: Stage, val setup: Setup,
initNotifs initNotifs
// init status bar // init status bar
labelNodeId.setText(s"${Globals.Node.id}") labelNodeId.setText(s"${setup.nodeParams.privateKey.publicKey}")
labelApi.setText(s"${setup.config.getInt("eclair.api.port")}") labelApi.setText(s"${setup.config.getInt("eclair.api.port")}")
labelServer.setText(s"${setup.config.getInt("eclair.server.port")}") labelServer.setText(s"${setup.config.getInt("eclair.server.port")}")
bitcoinVersion.setText(s"v${setup.bitcoinVersion}") bitcoinVersion.setText(s"v${setup.bitcoinVersion}")
@ -98,8 +98,8 @@ class MainController(val handlers: Handlers, val stage: Stage, val setup: Setup,
// init context // init context
contextMenu = ContextMenuUtils.buildCopyContext(List( contextMenu = ContextMenuUtils.buildCopyContext(List(
new CopyAction("Copy Pubkey", Globals.Node.id), new CopyAction("Copy Pubkey", s"${setup.nodeParams.privateKey.publicKey}"),
new CopyAction("Copy URI", s"${Globals.Node.id}@${Globals.Node.address.getHostString}:${Globals.Node.address.getPort}" ))) new CopyAction("Copy URI", s"${setup.nodeParams.privateKey.publicKey}@${setup.nodeParams.address.getHostString}:${setup.nodeParams.address.getPort}" )))
// init channels tab // init channels tab
if (channelBox.getChildren.size() > 0) { if (channelBox.getChildren.size() > 0) {

View File

@ -5,7 +5,7 @@ import java.net.InetSocketAddress
import akka.actor.{Props, _} import akka.actor.{Props, _}
import akka.io.{IO, Tcp} import akka.io.{IO, Tcp}
import fr.acinq.bitcoin.Crypto.PublicKey import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.eclair.Globals import fr.acinq.eclair.{Globals, NodeParams}
import fr.acinq.eclair.crypto.Noise.KeyPair import fr.acinq.eclair.crypto.Noise.KeyPair
import fr.acinq.eclair.crypto.TransportHandler import fr.acinq.eclair.crypto.TransportHandler
import fr.acinq.eclair.crypto.TransportHandler.HandshakeCompleted import fr.acinq.eclair.crypto.TransportHandler.HandshakeCompleted
@ -14,7 +14,7 @@ import fr.acinq.eclair.wire.LightningMessage
/** /**
* Created by PM on 27/10/2015. * Created by PM on 27/10/2015.
*/ */
class Client(switchboard: ActorRef, address: InetSocketAddress, remoteNodeId: PublicKey, origin: ActorRef) extends Actor with ActorLogging { class Client(nodeParams: NodeParams, switchboard: ActorRef, address: InetSocketAddress, remoteNodeId: PublicKey, origin: ActorRef) extends Actor with ActorLogging {
import Tcp._ import Tcp._
import context.system import context.system
@ -31,7 +31,7 @@ class Client(switchboard: ActorRef, address: InetSocketAddress, remoteNodeId: Pu
val connection = sender val connection = sender
val transport = context.actorOf(Props( val transport = context.actorOf(Props(
new TransportHandler[LightningMessage]( new TransportHandler[LightningMessage](
KeyPair(Globals.Node.publicKey.toBin, Globals.Node.privateKey.toBin), KeyPair(nodeParams.privateKey.publicKey.toBin, nodeParams.privateKey.toBin),
Some(remoteNodeId), Some(remoteNodeId),
connection = connection, connection = connection,
serializer = LightningMessageSerializer))) serializer = LightningMessageSerializer)))
@ -53,6 +53,6 @@ class Client(switchboard: ActorRef, address: InetSocketAddress, remoteNodeId: Pu
object Client extends App { object Client extends App {
def props(switchboard: ActorRef, address: InetSocketAddress, remoteNodeId: PublicKey, origin: ActorRef): Props = Props(classOf[Client], switchboard, address, remoteNodeId, origin) def props(nodeParams: NodeParams, switchboard: ActorRef, address: InetSocketAddress, remoteNodeId: PublicKey, origin: ActorRef): Props = Props(new Client(nodeParams, switchboard, address, remoteNodeId, origin))
} }

View File

@ -4,14 +4,14 @@ import java.net.InetSocketAddress
import akka.actor.{ActorRef, LoggingFSM, PoisonPill, Props, Terminated} import akka.actor.{ActorRef, LoggingFSM, PoisonPill, Props, Terminated}
import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey} import fr.acinq.bitcoin.Crypto.{PrivateKey, PublicKey}
import fr.acinq.bitcoin.{BinaryData, DeterministicWallet} import fr.acinq.bitcoin.{BinaryData, Crypto, DeterministicWallet}
import fr.acinq.eclair.channel._ import fr.acinq.eclair.channel._
import fr.acinq.eclair.crypto.TransportHandler.{HandshakeCompleted, Listener, Serializer} import fr.acinq.eclair.crypto.TransportHandler.{HandshakeCompleted, Listener, Serializer}
import fr.acinq.eclair.db.{JavaSerializer, SimpleDb, SimpleTypedDb} import fr.acinq.eclair.db.{JavaSerializer, SimpleDb, SimpleTypedDb}
import fr.acinq.eclair.io.Switchboard.{NewChannel, NewConnection} import fr.acinq.eclair.io.Switchboard.{NewChannel, NewConnection}
import fr.acinq.eclair.router.SendRoutingState import fr.acinq.eclair.router.SendRoutingState
import fr.acinq.eclair.wire._ import fr.acinq.eclair.wire._
import fr.acinq.eclair.{Features, Globals} import fr.acinq.eclair.{Features, Globals, NodeParams}
import scala.compat.Platform import scala.compat.Platform
@ -42,7 +42,7 @@ case class PeerRecord(id: PublicKey, address: Option[InetSocketAddress])
/** /**
* Created by PM on 26/08/2016. * Created by PM on 26/08/2016.
*/ */
class Peer(remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress], watcher: ActorRef, router: ActorRef, relayer: ActorRef, defaultFinalScriptPubKey: BinaryData, db: SimpleDb) extends LoggingFSM[State, Data] { class Peer(nodeParams: NodeParams, remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress], watcher: ActorRef, router: ActorRef, relayer: ActorRef, defaultFinalScriptPubKey: BinaryData, db: SimpleDb) extends LoggingFSM[State, Data] {
import Peer._ import Peer._
@ -56,7 +56,7 @@ class Peer(remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress], watc
stay stay
case Event(c: ChannelRecord, d@DisconnectedData(offlineChannels)) => case Event(c: ChannelRecord, d@DisconnectedData(offlineChannels)) =>
val (channel, _) = createChannel(null, c.id, false, db) val (channel, _) = createChannel(nodeParams, null, c.id, false, 0, db) // TODO: fixme using a dedicated restore message
channel ! INPUT_RESTORED(c.id, c.state) channel ! INPUT_RESTORED(c.id, c.state)
stay using d.copy(offlineChannels = offlineChannels :+ HotChannel(c.id, channel)) stay using d.copy(offlineChannels = offlineChannels :+ HotChannel(c.id, channel))
@ -71,7 +71,7 @@ class Peer(remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress], watc
log.info(s"registering as a listener to $transport") log.info(s"registering as a listener to $transport")
transport ! Listener(self) transport ! Listener(self)
context watch transport context watch transport
transport ! Init(globalFeatures = Globals.global_features, localFeatures = Globals.local_features) transport ! Init(globalFeatures = nodeParams.globalFeatures, localFeatures = nodeParams.localFeatures)
goto(INITIALIZING) using InitializingData(transport, channels) goto(INITIALIZING) using InitializingData(transport, channels)
} }
@ -82,7 +82,7 @@ class Peer(remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress], watc
case Event(remoteInit: Init, InitializingData(transport, offlineChannels)) => case Event(remoteInit: Init, InitializingData(transport, offlineChannels)) =>
import fr.acinq.eclair.Features._ import fr.acinq.eclair.Features._
log.info(s"$remoteNodeId has features: channelPublic=${channelPublic(remoteInit.localFeatures)} initialRoutingSync=${initialRoutingSync(remoteInit.localFeatures)}") log.info(s"$remoteNodeId has features: channelPublic=${channelPublic(remoteInit.localFeatures)} initialRoutingSync=${initialRoutingSync(remoteInit.localFeatures)}")
if (Features.areFeaturesCompatible(Globals.local_features, remoteInit.localFeatures)) { if (Features.areFeaturesCompatible(nodeParams.localFeatures, remoteInit.localFeatures)) {
if (Features.initialRoutingSync(remoteInit.localFeatures) != Unset) { if (Features.initialRoutingSync(remoteInit.localFeatures) != Unset) {
router ! SendRoutingState(transport) router ! SendRoutingState(transport)
} }
@ -111,7 +111,7 @@ class Peer(remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress], watc
case Event(c: NewChannel, d@ConnectedData(transport, remoteInit, channels)) => case Event(c: NewChannel, d@ConnectedData(transport, remoteInit, channels)) =>
log.info(s"requesting a new channel to $remoteNodeId with fundingSatoshis=${c.fundingSatoshis} and pushMsat=${c.pushMsat}") log.info(s"requesting a new channel to $remoteNodeId with fundingSatoshis=${c.fundingSatoshis} and pushMsat=${c.pushMsat}")
val temporaryChannelId = Platform.currentTime val temporaryChannelId = Platform.currentTime
val (channel, localParams) = createChannel(transport, temporaryChannelId, funder = true, db) val (channel, localParams) = createChannel(nodeParams, transport, temporaryChannelId, funder = true, c.fundingSatoshis.toLong, db)
channel ! INPUT_INIT_FUNDER(remoteNodeId, temporaryChannelId, c.fundingSatoshis.amount, c.pushMsat.amount, localParams, remoteInit) channel ! INPUT_INIT_FUNDER(remoteNodeId, temporaryChannelId, c.fundingSatoshis.amount, c.pushMsat.amount, localParams, remoteInit)
stay using d.copy(channels = channels + (temporaryChannelId -> channel)) stay using d.copy(channels = channels + (temporaryChannelId -> channel))
@ -135,7 +135,7 @@ class Peer(remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress], watc
case Event(msg: OpenChannel, d@ConnectedData(transport, remoteInit, channels)) => case Event(msg: OpenChannel, d@ConnectedData(transport, remoteInit, channels)) =>
log.info(s"accepting a new channel to $remoteNodeId") log.info(s"accepting a new channel to $remoteNodeId")
val temporaryChannelId = msg.temporaryChannelId val temporaryChannelId = msg.temporaryChannelId
val (channel, localParams) = createChannel(transport, temporaryChannelId, funder = false, db) val (channel, localParams) = createChannel(nodeParams, transport, temporaryChannelId, funder = false, fundingSatoshis = msg.fundingSatoshis, db)
channel ! INPUT_INIT_FUNDEE(remoteNodeId, temporaryChannelId, localParams, remoteInit) channel ! INPUT_INIT_FUNDEE(remoteNodeId, temporaryChannelId, localParams, remoteInit)
channel ! msg channel ! msg
stay using d.copy(channels = channels + (temporaryChannelId -> channel)) stay using d.copy(channels = channels + (temporaryChannelId -> channel))
@ -163,9 +163,9 @@ class Peer(remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress], watc
stay using d.copy(channels = channels - channelId) stay using d.copy(channels = channels - channelId)
} }
def createChannel(transport: ActorRef, temporaryChannelId: Long, funder: Boolean, db: SimpleDb): (ActorRef, LocalParams) = { def createChannel(nodeParams: NodeParams, transport: ActorRef, temporaryChannelId: Long, funder: Boolean, fundingSatoshis: Long, db: SimpleDb): (ActorRef, LocalParams) = {
val localParams = makeChannelParams(temporaryChannelId, defaultFinalScriptPubKey, funder) val localParams = makeChannelParams(nodeParams, temporaryChannelId, defaultFinalScriptPubKey, funder, fundingSatoshis)
val channel = context.actorOf(Channel.props(transport, watcher, router, relayer, db), s"channel-$temporaryChannelId") val channel = context.actorOf(Channel.props(nodeParams, transport, watcher, router, relayer, db), s"channel-$temporaryChannelId")
context watch channel context watch channel
(channel, localParams) (channel, localParams)
} }
@ -174,28 +174,28 @@ class Peer(remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress], watc
object Peer { object Peer {
def props(remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress], watcher: ActorRef, router: ActorRef, relayer: ActorRef, defaultFinalScriptPubKey: BinaryData, db: SimpleDb) = Props(classOf[Peer], remoteNodeId, address_opt, watcher, router, relayer, defaultFinalScriptPubKey, db) def props(nodeParams: NodeParams, remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress], watcher: ActorRef, router: ActorRef, relayer: ActorRef, defaultFinalScriptPubKey: BinaryData, db: SimpleDb) = Props(new Peer(nodeParams, remoteNodeId, address_opt, watcher, router, relayer, defaultFinalScriptPubKey, db))
def generateKey(keyPath: Seq[Long]): PrivateKey = DeterministicWallet.derivePrivateKey(Globals.Node.extendedPrivateKey, keyPath).privateKey def generateKey(nodeParams: NodeParams, keyPath: Seq[Long]): PrivateKey = DeterministicWallet.derivePrivateKey(nodeParams.extendedPrivateKey, keyPath).privateKey
def makeChannelParams(keyIndex: Long, defaultFinalScriptPubKey: BinaryData, isFunder: Boolean): LocalParams = def makeChannelParams(nodeParams: NodeParams, keyIndex: Long, defaultFinalScriptPubKey: BinaryData, isFunder: Boolean, fundingSatoshis: Long): LocalParams =
LocalParams( LocalParams(
dustLimitSatoshis = 542, dustLimitSatoshis = nodeParams.dustLimitSatoshis,
maxHtlcValueInFlightMsat = Long.MaxValue, maxHtlcValueInFlightMsat = nodeParams.maxHtlcValueInFlightMsat,
channelReserveSatoshis = 0, channelReserveSatoshis = (nodeParams.reserveToFundingRatio * fundingSatoshis).toLong,
htlcMinimumMsat = 0, htlcMinimumMsat = nodeParams.htlcMinimumMsat,
feeratePerKw = Globals.feeratePerKw, feeratePerKw = nodeParams.feeratePerKw,
toSelfDelay = Globals.delay_blocks, toSelfDelay = nodeParams.delayBlocks,
maxAcceptedHtlcs = 100, maxAcceptedHtlcs = nodeParams.maxAcceptedHtlcs,
fundingPrivKey = generateKey(keyIndex :: 0L :: Nil), fundingPrivKey = generateKey(nodeParams, keyIndex :: 0L :: Nil),
revocationSecret = generateKey(keyIndex :: 1L :: Nil), revocationSecret = generateKey(nodeParams, keyIndex :: 1L :: Nil),
paymentKey = generateKey(keyIndex :: 2L :: Nil), paymentKey = generateKey(nodeParams, keyIndex :: 2L :: Nil),
delayedPaymentKey = generateKey(keyIndex :: 3L :: Nil), delayedPaymentKey = generateKey(nodeParams, keyIndex :: 3L :: Nil),
defaultFinalScriptPubKey = defaultFinalScriptPubKey, defaultFinalScriptPubKey = defaultFinalScriptPubKey,
shaSeed = Globals.Node.seed, shaSeed = Crypto.sha256(generateKey(nodeParams, keyIndex :: 4L :: Nil).toBin), // TODO: check that
isFunder = isFunder, isFunder = isFunder,
globalFeatures = Globals.global_features, globalFeatures = nodeParams.globalFeatures,
localFeatures = Globals.local_features localFeatures = nodeParams.localFeatures
) )
def makePeerDb(db: SimpleDb): SimpleTypedDb[PublicKey, PeerRecord] = { def makePeerDb(db: SimpleDb): SimpleTypedDb[PublicKey, PeerRecord] = {

View File

@ -8,12 +8,12 @@ import fr.acinq.eclair.crypto.Noise.KeyPair
import fr.acinq.eclair.crypto.TransportHandler import fr.acinq.eclair.crypto.TransportHandler
import fr.acinq.eclair.crypto.TransportHandler.HandshakeCompleted import fr.acinq.eclair.crypto.TransportHandler.HandshakeCompleted
import fr.acinq.eclair.wire.LightningMessage import fr.acinq.eclair.wire.LightningMessage
import fr.acinq.eclair.{Globals, TCPBindError} import fr.acinq.eclair.{Globals, NodeParams, TCPBindError}
/** /**
* Created by PM on 27/10/2015. * Created by PM on 27/10/2015.
*/ */
class Server(switchboard: ActorRef, address: InetSocketAddress) extends Actor with ActorLogging { class Server(nodeParams: NodeParams, switchboard: ActorRef, address: InetSocketAddress) extends Actor with ActorLogging {
import Tcp._ import Tcp._
import context.system import context.system
@ -35,7 +35,7 @@ class Server(switchboard: ActorRef, address: InetSocketAddress) extends Actor wi
val connection = sender val connection = sender
val transport = context.actorOf(Props( val transport = context.actorOf(Props(
new TransportHandler[LightningMessage]( new TransportHandler[LightningMessage](
KeyPair(Globals.Node.publicKey.toBin, Globals.Node.privateKey.toBin), KeyPair(nodeParams.privateKey.publicKey.toBin, nodeParams.privateKey.toBin),
None, None,
connection = connection, connection = connection,
serializer = LightningMessageSerializer))) serializer = LightningMessageSerializer)))
@ -49,7 +49,7 @@ class Server(switchboard: ActorRef, address: InetSocketAddress) extends Actor wi
object Server { object Server {
def props(switchboard: ActorRef, address: InetSocketAddress): Props = Props(classOf[Server], switchboard, address) def props(nodeParams: NodeParams, switchboard: ActorRef, address: InetSocketAddress): Props = Props(new Server(nodeParams, switchboard, address))
} }

View File

@ -5,8 +5,8 @@ import java.net.InetSocketAddress
import akka.actor.{Actor, ActorLogging, ActorRef, Props, Status, Terminated} import akka.actor.{Actor, ActorLogging, ActorRef, Props, Status, Terminated}
import fr.acinq.bitcoin.Crypto.PublicKey import fr.acinq.bitcoin.Crypto.PublicKey
import fr.acinq.bitcoin.{BinaryData, MilliSatoshi, Satoshi, ScriptElt} import fr.acinq.bitcoin.{BinaryData, MilliSatoshi, Satoshi, ScriptElt}
import fr.acinq.eclair.Globals
import fr.acinq.eclair.channel.ChannelRecord import fr.acinq.eclair.channel.ChannelRecord
import fr.acinq.eclair.{Globals, NodeParams}
import fr.acinq.eclair.crypto.TransportHandler.HandshakeCompleted import fr.acinq.eclair.crypto.TransportHandler.HandshakeCompleted
import fr.acinq.eclair.db.{ChannelState, SimpleDb} import fr.acinq.eclair.db.{ChannelState, SimpleDb}
@ -14,9 +14,10 @@ import fr.acinq.eclair.db.{ChannelState, SimpleDb}
* Ties network connections to peers. * Ties network connections to peers.
* Created by PM on 14/02/2017. * Created by PM on 14/02/2017.
*/ */
class Switchboard(watcher: ActorRef, router: ActorRef, relayer: ActorRef, defaultFinalScriptPubKey: BinaryData, db: SimpleDb) extends Actor with ActorLogging { class Switchboard(nodeParams: NodeParams, watcher: ActorRef, router: ActorRef, relayer: ActorRef, defaultFinalScriptPubKey: BinaryData, db: SimpleDb) extends Actor with ActorLogging {
import Switchboard._ import Switchboard._
val peerDb = Peer.makePeerDb(db) val peerDb = Peer.makePeerDb(db)
def receive: Receive = main(Map(), Map()) def receive: Receive = main(Map(), Map())
@ -35,8 +36,7 @@ class Switchboard(watcher: ActorRef, router: ActorRef, relayer: ActorRef, defaul
case channelRecord: ChannelRecord => peers(channelRecord.state.remotePubKey) forward channelRecord case channelRecord: ChannelRecord => peers(channelRecord.state.remotePubKey) forward channelRecord
case NewConnection(Globals.Node.publicKey, _, _) => case NewConnection(publicKey, _, _) if publicKey == nodeParams.privateKey.publicKey =>
sender ! Status.Failure(new RuntimeException("cannot open connection with oneself"))
case NewConnection(remoteNodeId, address, newChannel_opt) => case NewConnection(remoteNodeId, address, newChannel_opt) =>
val connection = connections.get(remoteNodeId) match { val connection = connections.get(remoteNodeId) match {
@ -46,8 +46,8 @@ class Switchboard(watcher: ActorRef, router: ActorRef, relayer: ActorRef, defaul
connection connection
case None => case None =>
log.info(s"connecting to $remoteNodeId @ $address") log.info(s"connecting to $remoteNodeId @ $address")
val connection = context.actorOf(Client.props(self, address, remoteNodeId, sender)) val connection = context.actorOf(Client.props(nodeParams, self, address, remoteNodeId, sender))
context watch(connection) context watch (connection)
connection connection
} }
val peer = peers.get(remoteNodeId) match { val peer = peers.get(remoteNodeId) match {
@ -74,13 +74,13 @@ class Switchboard(watcher: ActorRef, router: ActorRef, relayer: ActorRef, defaul
def createPeer(remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress]) = { def createPeer(remoteNodeId: PublicKey, address_opt: Option[InetSocketAddress]) = {
peerDb.put(remoteNodeId, PeerRecord(remoteNodeId, address_opt)) peerDb.put(remoteNodeId, PeerRecord(remoteNodeId, address_opt))
context.actorOf(Peer.props(remoteNodeId, address_opt, watcher, router, relayer, defaultFinalScriptPubKey, db), name = s"peer-$remoteNodeId") context.actorOf(Peer.props(nodeParams, remoteNodeId, address_opt, watcher, router, relayer, defaultFinalScriptPubKey, db), name = s"peer-$remoteNodeId")
} }
} }
object Switchboard { object Switchboard {
def props(watcher: ActorRef, router: ActorRef, relayer: ActorRef, defaultFinalScriptPubKey: BinaryData, db: SimpleDb) = Props(classOf[Switchboard], watcher, router, relayer, defaultFinalScriptPubKey, db) def props(nodeParams: NodeParams, watcher: ActorRef, router: ActorRef, relayer: ActorRef, defaultFinalScriptPubKey: BinaryData, db: SimpleDb) = Props(new Switchboard(nodeParams, watcher, router, relayer, defaultFinalScriptPubKey, db))
// @formatter:off // @formatter:off
case class NewChannel(fundingSatoshis: Satoshi, pushMsat: MilliSatoshi) case class NewChannel(fundingSatoshis: Satoshi, pushMsat: MilliSatoshi)

View File

@ -2,11 +2,12 @@ package fr.acinq.eclair.payment
import akka.actor.{Actor, ActorLogging, ActorRef, Props} import akka.actor.{Actor, ActorLogging, ActorRef, Props}
import fr.acinq.bitcoin.BinaryData import fr.acinq.bitcoin.BinaryData
import fr.acinq.bitcoin.Crypto.PublicKey
/** /**
* Created by PM on 29/08/2016. * Created by PM on 29/08/2016.
*/ */
class PaymentInitiator(sourceNodeId: BinaryData, router: ActorRef) extends Actor with ActorLogging { class PaymentInitiator(sourceNodeId: PublicKey, router: ActorRef) extends Actor with ActorLogging {
override def receive: Receive = { override def receive: Receive = {
case c: CreatePayment => case c: CreatePayment =>
@ -17,5 +18,5 @@ class PaymentInitiator(sourceNodeId: BinaryData, router: ActorRef) extends Actor
} }
object PaymentInitiator { object PaymentInitiator {
def props(sourceNodeId: BinaryData, router: ActorRef) = Props(classOf[PaymentInitiator], sourceNodeId, router) def props(sourceNodeId: PublicKey, router: ActorRef) = Props(classOf[PaymentInitiator], sourceNodeId, router)
} }

View File

@ -30,7 +30,7 @@ case object WAITING_FOR_PAYMENT_COMPLETE extends State
/** /**
* Created by PM on 26/08/2016. * Created by PM on 26/08/2016.
*/ */
class PaymentLifecycle(sourceNodeId: BinaryData, router: ActorRef) extends LoggingFSM[State, Data] { class PaymentLifecycle(sourceNodeId: PublicKey, router: ActorRef) extends LoggingFSM[State, Data] {
import PaymentLifecycle._ import PaymentLifecycle._
@ -76,7 +76,7 @@ class PaymentLifecycle(sourceNodeId: BinaryData, router: ActorRef) extends Loggi
object PaymentLifecycle { object PaymentLifecycle {
def props(sourceNodeId: BinaryData, router: ActorRef) = Props(classOf[PaymentLifecycle], sourceNodeId, router) def props(sourceNodeId: PublicKey, router: ActorRef) = Props(classOf[PaymentLifecycle], sourceNodeId, router)
/** /**
* *

View File

@ -1,9 +1,10 @@
package fr.acinq.eclair package fr.acinq.eclair
import fr.acinq.bitcoin.{Base58Check, Crypto, OP_0, OP_PUSHDATA, Script} import java.net.InetSocketAddress
import fr.acinq.bitcoin.Crypto.{PrivateKey, Scalar}
import fr.acinq.eclair.channel._ import fr.acinq.bitcoin.Crypto.PrivateKey
import fr.acinq.eclair.transactions.Scripts import fr.acinq.bitcoin.{BinaryData, DeterministicWallet, Script}
import fr.acinq.eclair.io.Peer
/** /**
* Created by PM on 26/04/2016. * Created by PM on 26/04/2016.
@ -13,46 +14,72 @@ object TestConstants {
val pushMsat = 200000000L val pushMsat = 200000000L
object Alice { object Alice {
val id = randomKey.publicKey val seed = BinaryData("01" * 32)
val channelParams = LocalParams( val master = DeterministicWallet.generate(seed)
val extendedPrivateKey = DeterministicWallet.derivePrivateKey(master, DeterministicWallet.hardened(46) :: DeterministicWallet.hardened(0) :: Nil)
val nodeParams = NodeParams(
extendedPrivateKey = extendedPrivateKey,
privateKey = extendedPrivateKey.privateKey,
alias = "alice",
color = (1: Byte, 2: Byte, 3: Byte),
address = new InetSocketAddress("localhost", 9731),
globalFeatures = "",
localFeatures = "00", // no announcement
dustLimitSatoshis = 542, dustLimitSatoshis = 542,
maxHtlcValueInFlightMsat = 150000000, maxHtlcValueInFlightMsat = 150000000,
channelReserveSatoshis = 10000, // Bob will need to keep that much satoshis as direct payment
htlcMinimumMsat = 0,
feeratePerKw = 10000,
toSelfDelay = 144,
maxAcceptedHtlcs = 100, maxAcceptedHtlcs = 100,
fundingPrivKey = PrivateKey(Array.fill[Byte](32)(1), compressed = true), expiryDeltaBlocks = 144,
revocationSecret = PrivateKey(Array.fill[Byte](32)(2), compressed = true), htlcMinimumMsat = 0,
paymentKey = PrivateKey(Array.fill[Byte](32)(3), compressed = true), minDepthBlocks = 3,
delayedPaymentKey = PrivateKey(Array.fill[Byte](32)(4), compressed = true), delayBlocks = 144,
feeratePerKw = 10000,
feeBaseMsat = 546000,
feeProportionalMillionth = 10,
reserveToFundingRatio = 0.01, // note: not used (overriden below)
maxReserveToFundingRatio = 0.05)
val id = nodeParams.privateKey.publicKey
val channelParams = Peer.makeChannelParams(
nodeParams = nodeParams,
keyIndex = 1,
defaultFinalScriptPubKey = Script.write(Script.pay2wpkh(PrivateKey(Array.fill[Byte](32)(5), compressed = true).publicKey)), defaultFinalScriptPubKey = Script.write(Script.pay2wpkh(PrivateKey(Array.fill[Byte](32)(5), compressed = true).publicKey)),
shaSeed = Crypto.sha256("alice-seed".getBytes()),
isFunder = true, isFunder = true,
globalFeatures = "", fundingSatoshis).copy(
localFeatures = "00" // no announcement channelReserveSatoshis = 10000 // Bob will need to keep that much satoshis as direct payment
) )
} }
object Bob { object Bob {
val id = randomKey.publicKey val seed = BinaryData("02" * 32)
val channelParams = LocalParams( val master = DeterministicWallet.generate(seed)
val extendedPrivateKey = DeterministicWallet.derivePrivateKey(master, DeterministicWallet.hardened(46) :: DeterministicWallet.hardened(0) :: Nil)
val nodeParams = NodeParams(
extendedPrivateKey = extendedPrivateKey,
privateKey = extendedPrivateKey.privateKey,
alias = "bob",
color = (4: Byte, 5: Byte, 6: Byte),
address = new InetSocketAddress("localhost", 9732),
globalFeatures = "",
localFeatures = "00", // no announcement
dustLimitSatoshis = 542, dustLimitSatoshis = 542,
maxHtlcValueInFlightMsat = Long.MaxValue, // Bob has no limit on the combined max value of in-flight htlcs maxHtlcValueInFlightMsat = Long.MaxValue, // Bob has no limit on the combined max value of in-flight htlcs
channelReserveSatoshis = 20000, // Alice will need to keep that much satoshis as direct payment
htlcMinimumMsat = 1000,
feeratePerKw = 10000,
toSelfDelay = 144,
maxAcceptedHtlcs = 30, maxAcceptedHtlcs = 30,
fundingPrivKey = PrivateKey(Array.fill[Byte](32)(11), compressed = true), expiryDeltaBlocks = 144,
revocationSecret = PrivateKey(Array.fill[Byte](32)(12), compressed = true), htlcMinimumMsat = 1000,
paymentKey = PrivateKey(Array.fill[Byte](32)(13), compressed = true), minDepthBlocks = 3,
delayedPaymentKey = PrivateKey(Array.fill[Byte](32)(14), compressed = true), delayBlocks = 144,
feeratePerKw = 10000,
feeBaseMsat = 546000,
feeProportionalMillionth = 10,
reserveToFundingRatio = 0.01, // note: not used (overriden below)
maxReserveToFundingRatio = 0.05)
val id = nodeParams.privateKey.publicKey
val channelParams = Peer.makeChannelParams(
nodeParams = nodeParams,
keyIndex = 1,
defaultFinalScriptPubKey = Script.write(Script.pay2wpkh(PrivateKey(Array.fill[Byte](32)(15), compressed = true).publicKey)), defaultFinalScriptPubKey = Script.write(Script.pay2wpkh(PrivateKey(Array.fill[Byte](32)(15), compressed = true).publicKey)),
shaSeed = Crypto.sha256("alice-seed".getBytes()),
isFunder = false, isFunder = false,
globalFeatures = "", fundingSatoshis).copy(
localFeatures = "00" // no announcement channelReserveSatoshis = 20000 // Alice will need to keep that much satoshis as direct payment
) )
} }

View File

@ -53,9 +53,10 @@ class ThroughputSpec extends FunSuite {
context.become(run(h2r - htlc.paymentHash)) context.become(run(h2r - htlc.paymentHash))
} }
}), "payment-handler") }), "payment-handler")
val relayer = system.actorOf(Relayer.props(Globals.Node.privateKey, paymentHandler)) val relayerA = system.actorOf(Relayer.props(Alice.nodeParams.privateKey, paymentHandler))
val alice = system.actorOf(Channel.props(pipe, blockchain, ???, relayer, new DummyDb()), "a") val relayerB = system.actorOf(Relayer.props(Bob.nodeParams.privateKey, paymentHandler))
val bob = system.actorOf(Channel.props(pipe, blockchain, ???, relayer, new DummyDb()), "b") val alice = system.actorOf(Channel.props(Alice.nodeParams, pipe, blockchain, ???, relayerA, new DummyDb()), "a")
val bob = system.actorOf(Channel.props(Bob.nodeParams, pipe, blockchain, ???, relayerB, new DummyDb()), "b")
val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures)
val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures)
alice ! INPUT_INIT_FUNDER(Bob.id, 0, TestConstants.fundingSatoshis, TestConstants.pushMsat, Alice.channelParams, bobInit) alice ! INPUT_INIT_FUNDER(Bob.id, 0, TestConstants.fundingSatoshis, TestConstants.pushMsat, Alice.channelParams, bobInit)

View File

@ -33,11 +33,11 @@ class FuzzySpec extends TestkitBaseClass with StateTestsHelperMethods {
val bob2blockchain = TestProbe() val bob2blockchain = TestProbe()
val paymentHandlerA = system.actorOf(Props(new LocalPaymentHandler()), name = "payment-handler-a") val paymentHandlerA = system.actorOf(Props(new LocalPaymentHandler()), name = "payment-handler-a")
val paymentHandlerB = system.actorOf(Props(new LocalPaymentHandler()), name = "payment-handler-b") val paymentHandlerB = system.actorOf(Props(new LocalPaymentHandler()), name = "payment-handler-b")
val relayerA = system.actorOf(Relayer.props(Globals.Node.privateKey, paymentHandlerA), "relayer-a") val relayerA = system.actorOf(Relayer.props(Alice.nodeParams.privateKey, paymentHandlerA), "relayer-a")
val relayerB = system.actorOf(Relayer.props(Globals.Node.privateKey, paymentHandlerB), "relayer-b") val relayerB = system.actorOf(Relayer.props(Bob.nodeParams.privateKey, paymentHandlerB), "relayer-b")
val router = TestProbe() val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(pipe, alice2blockchain.ref, router.ref, relayerA, new DummyDb())) val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(Alice.nodeParams, pipe, alice2blockchain.ref, router.ref, relayerA, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(pipe, bob2blockchain.ref, router.ref, relayerB, new DummyDb())) val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(Bob.nodeParams, pipe, bob2blockchain.ref, router.ref, relayerB, new DummyDb()))
within(30 seconds) { within(30 seconds) {
val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures)
val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures)
@ -66,7 +66,7 @@ class FuzzySpec extends TestkitBaseClass with StateTestsHelperMethods {
def buildCmdAdd(paymentHash: BinaryData) = { def buildCmdAdd(paymentHash: BinaryData) = {
val channelUpdate_ab = ChannelUpdate("00" * 64, 0, 0, "0000", cltvExpiryDelta = 4, feeBaseMsat = 642000, feeProportionalMillionths = 7, htlcMinimumMsat = 0) val channelUpdate_ab = ChannelUpdate("00" * 64, 0, 0, "0000", cltvExpiryDelta = 4, feeBaseMsat = 642000, feeProportionalMillionths = 7, htlcMinimumMsat = 0)
val hops = Hop(Globals.Node.publicKey, Globals.Node.publicKey, channelUpdate_ab) :: Nil val hops = Hop(Alice.nodeParams.privateKey.publicKey, Bob.nodeParams.privateKey.publicKey, channelUpdate_ab) :: Nil
// we don't want to be below htlcMinimumMsat // we don't want to be below htlcMinimumMsat
val amount = Random.nextInt(1000000) + 1000 val amount = Random.nextInt(1000000) + 1000
PaymentLifecycle.buildCommand(amount, paymentHash, hops, 444000) PaymentLifecycle.buildCommand(amount, paymentHash, hops, 444000)

View File

@ -1,13 +1,14 @@
package fr.acinq.eclair.channel.states package fr.acinq.eclair.channel.states
import akka.actor.ActorRef import akka.actor.{ActorRef, Props}
import akka.testkit.{TestFSMRef, TestKitBase, TestProbe} import akka.testkit.{TestFSMRef, TestKitBase, TestProbe}
import fr.acinq.bitcoin.{BinaryData, Crypto} import fr.acinq.bitcoin.{BinaryData, Crypto}
import fr.acinq.eclair.TestConstants
import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain._ import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.channel._ import fr.acinq.eclair.channel._
import fr.acinq.eclair.db.DummyDb
import fr.acinq.eclair.wire._ import fr.acinq.eclair.wire._
import fr.acinq.eclair.{TestBitcoinClient, TestConstants}
import scala.util.Random import scala.util.Random
@ -16,6 +17,31 @@ import scala.util.Random
*/ */
trait StateTestsHelperMethods extends TestKitBase { trait StateTestsHelperMethods extends TestKitBase {
case class Setup(alice: TestFSMRef[State, Data, Channel],
bob: TestFSMRef[State, Data, Channel],
alice2bob: TestProbe,
bob2alice: TestProbe,
blockchainA: ActorRef,
alice2blockchain: TestProbe,
bob2blockchain: TestProbe,
router: TestProbe,
relayer: TestProbe)
def init(): Setup = {
val alice2bob = TestProbe()
val bob2alice = TestProbe()
val alice2blockchain = TestProbe()
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val nodeParamsA = TestConstants.Alice.nodeParams
val nodeParamsB = TestConstants.Bob.nodeParams
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(nodeParamsA, alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(nodeParamsB, bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
Setup(alice, bob, alice2bob, bob2alice, blockchainA, alice2blockchain, bob2blockchain, router, relayer)
}
def reachNormal(alice: TestFSMRef[State, Data, Channel], def reachNormal(alice: TestFSMRef[State, Data, Channel],
bob: TestFSMRef[State, Data, Channel], bob: TestFSMRef[State, Data, Channel],
alice2bob: TestProbe, alice2bob: TestProbe,

View File

@ -1,13 +1,13 @@
package fr.acinq.eclair.channel.states.a package fr.acinq.eclair.channel.states.a
import akka.actor.{ActorRef, Props} import akka.actor.ActorRef
import akka.testkit.{TestFSMRef, TestProbe} import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain.PeerWatcher import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.channel.{WAIT_FOR_FUNDING_INTERNAL, _} import fr.acinq.eclair.channel.{WAIT_FOR_FUNDING_INTERNAL, _}
import fr.acinq.eclair.db.DummyDb import fr.acinq.eclair.db.DummyDb
import fr.acinq.eclair.wire.{AcceptChannel, Error, Init, OpenChannel} import fr.acinq.eclair.wire.{AcceptChannel, Error, Init, OpenChannel}
import fr.acinq.eclair.{TestBitcoinClient, TestConstants, TestkitBaseClass} import fr.acinq.eclair.{TestConstants, TestkitBaseClass}
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -17,20 +17,13 @@ import scala.concurrent.duration._
* Created by PM on 05/07/2016. * Created by PM on 05/07/2016.
*/ */
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class WaitForAcceptChannelStateSpec extends TestkitBaseClass { class WaitForAcceptChannelStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple5[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef] type FixtureParam = Tuple5[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef]
override def withFixture(test: OneArgTest) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val alice2blockchain = TestProbe()
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures)
val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures)
within(30 seconds) { within(30 seconds) {

View File

@ -4,6 +4,7 @@ import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.channel._ import fr.acinq.eclair.channel._
import fr.acinq.eclair.db.DummyDb import fr.acinq.eclair.db.DummyDb
import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.wire.{Error, Init, OpenChannel} import fr.acinq.eclair.wire.{Error, Init, OpenChannel}
import fr.acinq.eclair.{TestConstants, TestkitBaseClass} import fr.acinq.eclair.{TestConstants, TestkitBaseClass}
import org.junit.runner.RunWith import org.junit.runner.RunWith
@ -15,19 +16,13 @@ import scala.concurrent.duration._
* Created by PM on 05/07/2016. * Created by PM on 05/07/2016.
*/ */
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class WaitForOpenChannelStateSpec extends TestkitBaseClass { class WaitForOpenChannelStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple4[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe] type FixtureParam = Tuple4[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe]
override def withFixture(test: OneArgTest) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val alice2blockchain = TestProbe()
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures)
val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures)
within(30 seconds) { within(30 seconds) {

View File

@ -1,13 +1,13 @@
package fr.acinq.eclair.channel.states.b package fr.acinq.eclair.channel.states.b
import akka.actor.{ActorRef, Props} import akka.actor.ActorRef
import akka.testkit.{TestFSMRef, TestProbe} import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain.{MakeFundingTx, PeerWatcher} import fr.acinq.eclair.blockchain.MakeFundingTx
import fr.acinq.eclair.channel._ import fr.acinq.eclair.channel._
import fr.acinq.eclair.db.DummyDb import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.wire._ import fr.acinq.eclair.wire._
import fr.acinq.eclair.{TestBitcoinClient, TestConstants, TestkitBaseClass} import fr.acinq.eclair.{TestConstants, TestkitBaseClass}
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -17,20 +17,13 @@ import scala.concurrent.duration._
* Created by PM on 05/07/2016. * Created by PM on 05/07/2016.
*/ */
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class WaitForFundingCreatedInternalStateSpec extends TestkitBaseClass { class WaitForFundingCreatedInternalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple5[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef] type FixtureParam = Tuple5[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef]
override def withFixture(test: OneArgTest) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val alice2blockchain = TestProbe()
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures)
val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures)
within(30 seconds) { within(30 seconds) {

View File

@ -1,13 +1,12 @@
package fr.acinq.eclair.channel.states.b package fr.acinq.eclair.channel.states.b
import akka.actor.Props
import akka.testkit.{TestFSMRef, TestProbe} import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain.{PeerWatcher, WatchConfirmed, WatchSpent} import fr.acinq.eclair.blockchain.{MakeFundingTx, WatchConfirmed, WatchSpent}
import fr.acinq.eclair.channel._ import fr.acinq.eclair.channel._
import fr.acinq.eclair.db.DummyDb import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.wire._ import fr.acinq.eclair.wire._
import fr.acinq.eclair.{TestBitcoinClient, TestConstants, TestkitBaseClass} import fr.acinq.eclair.{TestConstants, TestkitBaseClass}
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -17,19 +16,13 @@ import scala.concurrent.duration._
* Created by PM on 05/07/2016. * Created by PM on 05/07/2016.
*/ */
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class WaitForFundingCreatedStateSpec extends TestkitBaseClass { class WaitForFundingCreatedStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple4[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe] type FixtureParam = Tuple4[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe]
override def withFixture(test: OneArgTest) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, blockchainA, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures)
val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures)
within(30 seconds) { within(30 seconds) {
@ -39,6 +32,8 @@ class WaitForFundingCreatedStateSpec extends TestkitBaseClass {
alice2bob.forward(bob) alice2bob.forward(bob)
bob2alice.expectMsgType[AcceptChannel] bob2alice.expectMsgType[AcceptChannel]
bob2alice.forward(alice) bob2alice.forward(alice)
alice2blockchain.expectMsgType[MakeFundingTx]
alice2blockchain.forward(blockchainA)
awaitCond(bob.stateName == WAIT_FOR_FUNDING_CREATED) awaitCond(bob.stateName == WAIT_FOR_FUNDING_CREATED)
} }
test((bob, alice2bob, bob2alice, bob2blockchain)) test((bob, alice2bob, bob2alice, bob2blockchain))

View File

@ -1,14 +1,14 @@
package fr.acinq.eclair.channel.states.b package fr.acinq.eclair.channel.states.b
import akka.actor.{ActorRef, Props} import akka.actor.ActorRef
import akka.testkit.{TestFSMRef, TestProbe} import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.bitcoin.BinaryData import fr.acinq.bitcoin.BinaryData
import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain._ import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.channel._ import fr.acinq.eclair.channel._
import fr.acinq.eclair.db.DummyDb import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.wire.{AcceptChannel, Error, FundingCreated, FundingSigned, Init, OpenChannel} import fr.acinq.eclair.wire.{AcceptChannel, Error, FundingCreated, FundingSigned, Init, OpenChannel}
import fr.acinq.eclair.{TestBitcoinClient, TestConstants, TestkitBaseClass} import fr.acinq.eclair.{TestConstants, TestkitBaseClass}
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -18,20 +18,13 @@ import scala.concurrent.duration._
* Created by PM on 05/07/2016. * Created by PM on 05/07/2016.
*/ */
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class WaitForFundingSignedStateSpec extends TestkitBaseClass { class WaitForFundingSignedStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple5[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef] type FixtureParam = Tuple5[TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef]
override def withFixture(test: OneArgTest) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val alice2blockchain = TestProbe()
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures)
val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures)
within(30 seconds) { within(30 seconds) {

View File

@ -1,13 +1,13 @@
package fr.acinq.eclair.channel.states.c package fr.acinq.eclair.channel.states.c
import akka.actor.{ActorRef, Props} import akka.actor.ActorRef
import akka.testkit.{TestFSMRef, TestProbe} import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain._ import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.channel._ import fr.acinq.eclair.channel._
import fr.acinq.eclair.db.DummyDb import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.wire._ import fr.acinq.eclair.wire._
import fr.acinq.eclair.{TestBitcoinClient, TestConstants, TestkitBaseClass} import fr.acinq.eclair.{TestConstants, TestkitBaseClass}
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -17,20 +17,13 @@ import scala.concurrent.duration._
* Created by PM on 05/07/2016. * Created by PM on 05/07/2016.
*/ */
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class WaitForAnnSignaturesStateSpec extends TestkitBaseClass { class WaitForAnnSignaturesStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple7[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef, TestProbe] type FixtureParam = Tuple7[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef, TestProbe]
override def withFixture(test: OneArgTest) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val alice2blockchain = TestProbe()
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val (aliceParams, bobParams) = (Alice.channelParams.copy(localFeatures = "01"), Bob.channelParams.copy(localFeatures = "01")) val (aliceParams, bobParams) = (Alice.channelParams.copy(localFeatures = "01"), Bob.channelParams.copy(localFeatures = "01"))
val aliceInit = Init(aliceParams.globalFeatures, aliceParams.localFeatures) val aliceInit = Init(aliceParams.globalFeatures, aliceParams.localFeatures)
val bobInit = Init(bobParams.globalFeatures, bobParams.localFeatures) val bobInit = Init(bobParams.globalFeatures, bobParams.localFeatures)

View File

@ -1,13 +1,13 @@
package fr.acinq.eclair.channel.states.c package fr.acinq.eclair.channel.states.c
import akka.actor.{ActorRef, Props} import akka.actor.ActorRef
import akka.testkit.{TestFSMRef, TestProbe} import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain._ import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.channel._ import fr.acinq.eclair.channel._
import fr.acinq.eclair.db.DummyDb import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.wire.{AcceptChannel, Error, FundingCreated, FundingLocked, FundingSigned, Init, OpenChannel} import fr.acinq.eclair.wire.{AcceptChannel, Error, FundingCreated, FundingLocked, FundingSigned, Init, OpenChannel}
import fr.acinq.eclair.{TestBitcoinClient, TestConstants, TestkitBaseClass} import fr.acinq.eclair.{TestConstants, TestkitBaseClass}
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -17,20 +17,13 @@ import scala.concurrent.duration._
* Created by PM on 05/07/2016. * Created by PM on 05/07/2016.
*/ */
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class WaitForFundingConfirmedStateSpec extends TestkitBaseClass { class WaitForFundingConfirmedStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple6[TestFSMRef[State, Data, Channel], 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) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val alice2blockchain = TestProbe()
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures)
val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures)
within(30 seconds) { within(30 seconds) {

View File

@ -1,13 +1,13 @@
package fr.acinq.eclair.channel.states.c package fr.acinq.eclair.channel.states.c
import akka.actor.{ActorRef, Props} import akka.actor.ActorRef
import akka.testkit.{TestFSMRef, TestProbe} import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain._ import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.channel._ import fr.acinq.eclair.channel._
import fr.acinq.eclair.db.DummyDb import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.wire._ import fr.acinq.eclair.wire._
import fr.acinq.eclair.{TestBitcoinClient, TestConstants, TestkitBaseClass} import fr.acinq.eclair.{TestConstants, TestkitBaseClass}
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.Tag import org.scalatest.Tag
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -18,20 +18,13 @@ import scala.concurrent.duration._
* Created by PM on 05/07/2016. * Created by PM on 05/07/2016.
*/ */
@RunWith(classOf[JUnitRunner]) @RunWith(classOf[JUnitRunner])
class WaitForFundingLockedStateSpec extends TestkitBaseClass { class WaitForFundingLockedStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple7[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef, TestProbe] type FixtureParam = Tuple7[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, ActorRef, TestProbe]
override def withFixture(test: OneArgTest) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val alice2blockchain = TestProbe()
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val (aliceParams, bobParams) = if (test.tags.contains("public")) { val (aliceParams, bobParams) = if (test.tags.contains("public")) {
(Alice.channelParams.copy(localFeatures = "01"), Bob.channelParams.copy(localFeatures = "01")) (Alice.channelParams.copy(localFeatures = "01"), Bob.channelParams.copy(localFeatures = "01"))
} else { } else {

View File

@ -1,19 +1,17 @@
package fr.acinq.eclair.channel.states.e package fr.acinq.eclair.channel.states.e
import akka.actor.Props
import akka.testkit.{TestFSMRef, TestProbe} import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.bitcoin.Crypto.Scalar import fr.acinq.bitcoin.Crypto.Scalar
import fr.acinq.bitcoin.{BinaryData, Crypto, Satoshi, Script, ScriptFlags, Transaction} import fr.acinq.bitcoin.{BinaryData, Crypto, Satoshi, ScriptFlags, Transaction}
import fr.acinq.eclair.TestConstants.{Alice, Bob} import fr.acinq.eclair.TestConstants.Bob
import fr.acinq.eclair.blockchain._ import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.blockchain.peer.CurrentBlockCount import fr.acinq.eclair.blockchain.peer.CurrentBlockCount
import fr.acinq.eclair.channel.states.StateTestsHelperMethods import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.channel.{Data, State, _} import fr.acinq.eclair.channel.{Data, State, _}
import fr.acinq.eclair.db.DummyDb
import fr.acinq.eclair.payment.{Bind, Local, Relayed} import fr.acinq.eclair.payment.{Bind, Local, Relayed}
import fr.acinq.eclair.transactions.{IN, OUT} import fr.acinq.eclair.transactions.{IN, OUT}
import fr.acinq.eclair.wire.{ClosingSigned, CommitSig, Error, RevokeAndAck, Shutdown, UpdateAddHtlc, UpdateFailHtlc, UpdateFulfillHtlc} import fr.acinq.eclair.wire.{ClosingSigned, CommitSig, Error, RevokeAndAck, Shutdown, UpdateAddHtlc, UpdateFailHtlc, UpdateFulfillHtlc}
import fr.acinq.eclair.{TestBitcoinClient, TestConstants, TestkitBaseClass} import fr.acinq.eclair.{TestConstants, TestkitBaseClass}
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -28,15 +26,8 @@ class NormalStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple7[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, TestProbe, TestProbe] type FixtureParam = Tuple7[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, TestProbe, TestProbe]
override def withFixture(test: OneArgTest) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val alice2blockchain = TestProbe()
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
within(30 seconds) { within(30 seconds) {
reachNormal(alice, bob, alice2bob, bob2alice, blockchainA, alice2blockchain, bob2blockchain) reachNormal(alice, bob, alice2bob, bob2alice, blockchainA, alice2blockchain, bob2blockchain)
awaitCond(alice.stateName == NORMAL) awaitCond(alice.stateName == NORMAL)

View File

@ -1,14 +1,11 @@
package fr.acinq.eclair.channel.states.e package fr.acinq.eclair.channel.states.e
import akka.actor.Props
import akka.testkit.{TestFSMRef, TestProbe} import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.bitcoin.BinaryData import fr.acinq.bitcoin.BinaryData
import fr.acinq.eclair.blockchain._ import fr.acinq.eclair.TestkitBaseClass
import fr.acinq.eclair.channel.states.StateTestsHelperMethods import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.channel.{Data, State, _} import fr.acinq.eclair.channel.{Data, State, _}
import fr.acinq.eclair.db.DummyDb
import fr.acinq.eclair.wire.{CommitSig, RevokeAndAck, UpdateAddHtlc} import fr.acinq.eclair.wire.{CommitSig, RevokeAndAck, UpdateAddHtlc}
import fr.acinq.eclair.{TestBitcoinClient, TestkitBaseClass}
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -23,15 +20,8 @@ class OfflineStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple7[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, TestProbe, TestProbe] type FixtureParam = Tuple7[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, TestProbe, TestProbe]
override def withFixture(test: OneArgTest) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val alice2blockchain = TestProbe()
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
within(30 seconds) { within(30 seconds) {
reachNormal(alice, bob, alice2bob, bob2alice, blockchainA, alice2blockchain, bob2blockchain) reachNormal(alice, bob, alice2bob, bob2alice, blockchainA, alice2blockchain, bob2blockchain)
awaitCond(alice.stateName == NORMAL) awaitCond(alice.stateName == NORMAL)

View File

@ -1,16 +1,13 @@
package fr.acinq.eclair.channel.states.f package fr.acinq.eclair.channel.states.f
import akka.actor.Props
import akka.testkit.{TestFSMRef, TestProbe} import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.bitcoin.Crypto.Scalar import fr.acinq.bitcoin.Crypto.Scalar
import fr.acinq.bitcoin.{BinaryData, Crypto, Satoshi, ScriptFlags, Transaction} import fr.acinq.bitcoin.{BinaryData, Crypto, Satoshi, ScriptFlags, Transaction}
import fr.acinq.eclair.{TestBitcoinClient, TestkitBaseClass} import fr.acinq.eclair.TestkitBaseClass
import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain._ import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.blockchain.peer.CurrentBlockCount import fr.acinq.eclair.blockchain.peer.CurrentBlockCount
import fr.acinq.eclair.channel.states.StateTestsHelperMethods import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.channel.{Data, State, _} import fr.acinq.eclair.channel.{Data, State, _}
import fr.acinq.eclair.db.DummyDb
import fr.acinq.eclair.wire.{CommitSig, Error, RevokeAndAck, Shutdown, UpdateAddHtlc, UpdateFailHtlc, UpdateFulfillHtlc} import fr.acinq.eclair.wire.{CommitSig, Error, RevokeAndAck, Shutdown, UpdateAddHtlc, UpdateFailHtlc, UpdateFulfillHtlc}
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -26,16 +23,9 @@ class ShutdownStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple6[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, TestProbe] type FixtureParam = Tuple6[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, TestProbe]
override def withFixture(test: OneArgTest) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val alice2blockchain = TestProbe() within(30 seconds) {
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
within(35 seconds) {
reachNormal(alice, bob, alice2bob, bob2alice, blockchainA, alice2blockchain, bob2blockchain) reachNormal(alice, bob, alice2bob, bob2alice, blockchainA, alice2blockchain, bob2blockchain)
val sender = TestProbe() val sender = TestProbe()
// alice sends an HTLC to bob // alice sends an HTLC to bob

View File

@ -1,13 +1,10 @@
package fr.acinq.eclair.channel.states.g package fr.acinq.eclair.channel.states.g
import akka.actor.Props
import akka.testkit.{TestFSMRef, TestProbe} import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.eclair.{TestBitcoinClient, TestkitBaseClass} import fr.acinq.eclair.TestkitBaseClass
import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain._ import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.channel.states.StateTestsHelperMethods import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.channel.{Data, State, _} import fr.acinq.eclair.channel.{Data, State, _}
import fr.acinq.eclair.db.DummyDb
import fr.acinq.eclair.wire.{ClosingSigned, Error, Shutdown} import fr.acinq.eclair.wire.{ClosingSigned, Error, Shutdown}
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -23,16 +20,9 @@ class NegotiatingStateSpec extends TestkitBaseClass with StateTestsHelperMethods
type FixtureParam = Tuple6[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, TestProbe] type FixtureParam = Tuple6[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, TestProbe]
override def withFixture(test: OneArgTest) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val alice2blockchain = TestProbe()
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
// note that alice.initialFeeRate != bob.initialFeeRate // note that alice.initialFeeRate != bob.initialFeeRate
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
within(30 seconds) { within(30 seconds) {
reachNormal(alice, bob, alice2bob, bob2alice, blockchainA, alice2blockchain, bob2blockchain) reachNormal(alice, bob, alice2bob, bob2alice, blockchainA, alice2blockchain, bob2blockchain)
val sender = TestProbe() val sender = TestProbe()

View File

@ -1,14 +1,11 @@
package fr.acinq.eclair.channel.states.h package fr.acinq.eclair.channel.states.h
import akka.actor.Props
import akka.testkit.{TestFSMRef, TestProbe} import akka.testkit.{TestFSMRef, TestProbe}
import fr.acinq.bitcoin.Transaction import fr.acinq.bitcoin.Transaction
import fr.acinq.eclair.{Globals, TestBitcoinClient, TestkitBaseClass} import fr.acinq.eclair.TestkitBaseClass
import fr.acinq.eclair.TestConstants.{Alice, Bob}
import fr.acinq.eclair.blockchain._ import fr.acinq.eclair.blockchain._
import fr.acinq.eclair.channel.states.StateTestsHelperMethods import fr.acinq.eclair.channel.states.StateTestsHelperMethods
import fr.acinq.eclair.channel.{Data, State, _} import fr.acinq.eclair.channel.{Data, State, _}
import fr.acinq.eclair.db.DummyDb
import fr.acinq.eclair.wire._ import fr.acinq.eclair.wire._
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -24,15 +21,8 @@ class ClosingStateSpec extends TestkitBaseClass with StateTestsHelperMethods {
type FixtureParam = Tuple7[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, TestProbe, List[Transaction]] type FixtureParam = Tuple7[TestFSMRef[State, Data, Channel], TestFSMRef[State, Data, Channel], TestProbe, TestProbe, TestProbe, TestProbe, List[Transaction]]
override def withFixture(test: OneArgTest) = { override def withFixture(test: OneArgTest) = {
val alice2bob = TestProbe() val setup = init()
val bob2alice = TestProbe() import setup._
val alice2blockchain = TestProbe()
val blockchainA = system.actorOf(Props(new PeerWatcher(new TestBitcoinClient())))
val bob2blockchain = TestProbe()
val relayer = TestProbe()
val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(alice2bob.ref, alice2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(bob2alice.ref, bob2blockchain.ref, router.ref, relayer.ref, new DummyDb()))
within(30 seconds) { within(30 seconds) {
reachNormal(alice, bob, alice2bob, bob2alice, blockchainA, alice2blockchain, bob2blockchain) reachNormal(alice, bob, alice2bob, bob2alice, blockchainA, alice2blockchain, bob2blockchain)

View File

@ -37,8 +37,8 @@ class RustyTestsSpec extends TestKit(ActorSystem("test")) with Matchers with fix
// we just bypass the relayer for this test // we just bypass the relayer for this test
val relayer = paymentHandler val relayer = paymentHandler
val router = TestProbe() val router = TestProbe()
val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(pipe, blockchainA, router.ref, relayer, new DummyDb())) val alice: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(Alice.nodeParams, pipe, blockchainA, router.ref, relayer, new DummyDb()))
val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(pipe, blockchainB, router.ref, relayer, new DummyDb())) val bob: TestFSMRef[State, Data, Channel] = TestFSMRef(new Channel(Bob.nodeParams, pipe, blockchainB, router.ref, relayer, new DummyDb()))
val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures) val aliceInit = Init(Alice.channelParams.globalFeatures, Alice.channelParams.localFeatures)
val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures) val bobInit = Init(Bob.channelParams.globalFeatures, Bob.channelParams.localFeatures)
// alice and bob will both have 1 000 000 sat // alice and bob will both have 1 000 000 sat

View File

@ -1,7 +1,8 @@
package fr.acinq.eclair.router package fr.acinq.eclair.router
import fr.acinq.eclair.TestConstants.Alice
import fr.acinq.eclair._
import fr.acinq.eclair.router.Announcements._ import fr.acinq.eclair.router.Announcements._
import fr.acinq.eclair.{Globals, _}
import org.junit.runner.RunWith import org.junit.runner.RunWith
import org.scalatest.FunSuite import org.scalatest.FunSuite
import org.scalatest.junit.JUnitRunner import org.scalatest.junit.JUnitRunner
@ -24,16 +25,14 @@ class AnnouncementsSpec extends FunSuite {
} }
test("create valid signed node announcement") { test("create valid signed node announcement") {
val key = randomKey val ann = makeNodeAnnouncement(Alice.nodeParams.privateKey, Alice.nodeParams.alias, Alice.nodeParams.color, Alice.nodeParams.address :: Nil, Platform.currentTime / 1000)
val ann = makeNodeAnnouncement(key, Globals.Node.alias, Globals.Node.color, Globals.Node.address :: Nil, Platform.currentTime / 1000)
assert(checkSig(ann)) assert(checkSig(ann))
assert(checkSig(ann.copy(timestamp = 153)) === false) assert(checkSig(ann.copy(timestamp = 153)) === false)
} }
test("create valid signed channel update announcement") { test("create valid signed channel update announcement") {
val key = randomKey val ann = makeChannelUpdate(Alice.nodeParams.privateKey, randomKey.publicKey, 45561, Alice.nodeParams.expiryDeltaBlocks, Alice.nodeParams.htlcMinimumMsat, Alice.nodeParams.feeBaseMsat, Alice.nodeParams.feeProportionalMillionth, Platform.currentTime / 1000)
val ann = makeChannelUpdate(key, randomKey.publicKey, 45561, Globals.expiry_delta_blocks, Globals.htlc_minimum_msat, Globals.fee_base_msat, Globals.fee_proportional_millionth, Platform.currentTime / 1000) assert(checkSig(ann, Alice.nodeParams.privateKey.publicKey))
assert(checkSig(ann, key.publicKey))
assert(checkSig(ann, randomKey.publicKey) === false) assert(checkSig(ann, randomKey.publicKey) === false)
} }