diff --git a/bench/src/main/scala/org/bitcoins/bench/eclair/EclairBench.scala b/bench/src/main/scala/org/bitcoins/bench/eclair/EclairBench.scala index 82aa347909..0d2f5b5cbe 100644 --- a/bench/src/main/scala/org/bitcoins/bench/eclair/EclairBench.scala +++ b/bench/src/main/scala/org/bitcoins/bench/eclair/EclairBench.scala @@ -21,28 +21,47 @@ object EclairBench extends App with EclairRpcTestUtil { implicit val system = ActorSystem() import system.dispatcher - val networkSize = 1 - val paymentCount = 10 - val channelAmount = 10000000000L.msats - val outputFileName = "test.csv" + // put compiled test jar files into binaries/eclair/${version} directory - // release - val EclairVersion = Option.empty[String] - val EclairCommit = Option.empty[String] + // None means current release + val TestEclairVersion = Option.empty[String] + val TestEclairCommit = Option.empty[String] + // val TestEclairVersion = Option("0.3.3-SNAPSHOT") + // val TestEclairCommit = Option("84825ff") + val SenderEclairVersion = Option.empty[String] + val SenderEclairCommit = Option.empty[String] - // psql - // compiled binary can be found here: - // https://s3-us-west-1.amazonaws.com/suredbits.com/eclair/eclair-node-0.3.3-SNAPSHOT-949f1ec-psql.jar - // put it into binaries/eclair/0.3.3-SNAPSHOT directory -// val EclairVersion = Option("0.3.3-SNAPSHOT") -// val EclairCommit = Option("949f1ec-psql") + val NetworkSize = 10 + val PaymentCount = 2000 + val ChannelAmount = 10000000000L.msats + val PaymentAmount = 10.msats + val OutputFileName = "test.csv" + val LogbackXml = None // Some("~/logback.xml") // don't forget to recreate `eclair` Postgres database before starting a new test EclairRpcTestUtil.customConfigMap = Map( - "eclair.db.driver" -> "psql" + "eclair.db.driver" -> "psql", +// "eclair.db.psql.pool.max-size" -> 12, + "eclair.db.psql.lock-type" -> "none" +// "eclair.db.psql.lock-type" -> "optimistic" +// "eclair.db.psql.lock-type" -> "exclusive" ) - def sendPayments(network: Network, amount: MilliSatoshis, count: Int)( + object Progress { + private var count = 0 + private var percentage = 0 + + def inc(): Unit = synchronized { + count += 1 + val newPercentage = count * 100 / (NetworkSize * PaymentCount) + if (newPercentage % 10 == 0 && newPercentage != percentage) { + percentage = newPercentage + print(s"$percentage% ") + } + } + } + + def sendPayments(network: EclairNetwork, amount: MilliSatoshis, count: Int)( implicit ec: ExecutionContext): Future[Vector[PaymentId]] = for { testNodeInfo <- network.testEclairNode.getInfo @@ -64,25 +83,26 @@ object EclairBench extends App with EclairRpcTestUtil { None) } yield { logPaymentId(paymentHash, id) + Progress.inc() acc :+ id } } }) } yield paymentIds.flatten - def runTests(network: Network): Future[Vector[PaymentLogEntry]] = { + def runTests(network: EclairNetwork): Future[Vector[PaymentLogEntry]] = { println("Setting up the test network") for { _ <- network.testEclairNode.connectToWebSocket(logEvent) _ = println( - s"Set up ${networkSize} nodes, that will send $paymentCount paments to the test node each") + s"Set up ${NetworkSize} nodes, that will send $PaymentCount payments to the test node each") _ = println( s"Test node data directory: ${network.testEclairNode.instance.authCredentials.datadir .getOrElse("")}") _ = println("Testing...") - _ <- sendPayments(network, 1000.msats, paymentCount) + _ <- sendPayments(network, PaymentAmount, PaymentCount) _ <- TestAsyncUtil.retryUntilSatisfied( - condition = paymentLog.size() == networkSize * paymentCount, + condition = paymentLog.size() == NetworkSize * PaymentCount, duration = 1.second, maxTries = 100) _ <- TestAsyncUtil @@ -90,7 +110,7 @@ object EclairBench extends App with EclairRpcTestUtil { paymentLog.values().asScala.forall(_.completed), duration = 1.second, maxTries = 100) - _ = println("Done!") + _ = println("\nDone!") } yield { paymentLog .values() @@ -101,10 +121,13 @@ object EclairBench extends App with EclairRpcTestUtil { } val res: Future[Unit] = for { - network <- Network.start(EclairVersion, - EclairCommit, - networkSize, - channelAmount) + network <- EclairNetwork.start(TestEclairVersion, + TestEclairCommit, + SenderEclairVersion, + SenderEclairCommit, + NetworkSize, + ChannelAmount, + LogbackXml) log <- runTests(network).recoverWith { case e: Throwable => e.printStackTrace() @@ -122,7 +145,7 @@ object EclairBench extends App with EclairRpcTestUtil { case (x, i) => s"${x.paymentSentAt - first.paymentSentAt},${i + 1},${x.toCSV}" } - val outputFile = new File(outputFileName) + val outputFile = new File(OutputFileName) Files.write(outputFile.toPath, csv.asJava, StandardOpenOption.CREATE, diff --git a/eclair-rpc/src/main/scala/org/bitcoins/eclair/rpc/client/EclairRpcClient.scala b/eclair-rpc/src/main/scala/org/bitcoins/eclair/rpc/client/EclairRpcClient.scala index f51e5f7455..b0ba9e6755 100644 --- a/eclair-rpc/src/main/scala/org/bitcoins/eclair/rpc/client/EclairRpcClient.scala +++ b/eclair-rpc/src/main/scala/org/bitcoins/eclair/rpc/client/EclairRpcClient.scala @@ -704,10 +704,13 @@ class EclairRpcClient(val instance: EclairInstance, binary: Option[File] = None) require(instance.authCredentials.datadir.isDefined, s"A datadir needs to be provided to start eclair") - if (process.isEmpty) { - val p = Process( - s"java -jar -Declair.datadir=${instance.authCredentials.datadir.get} $pathToEclairJar &") + val logback = instance.logbackXmlPath + .map(path => s"-Dlogback.configurationFile=$path") + .getOrElse("") + val cmd = + s"java -jar -Declair.datadir=${instance.authCredentials.datadir.get} $logback $pathToEclairJar &" + val p = Process(cmd) val result = p.run() logger.debug( s"Starting eclair with datadir ${instance.authCredentials.datadir.get}") diff --git a/eclair-rpc/src/main/scala/org/bitcoins/eclair/rpc/config/EclairInstance.scala b/eclair-rpc/src/main/scala/org/bitcoins/eclair/rpc/config/EclairInstance.scala index b722a6df61..b0152ec61f 100644 --- a/eclair-rpc/src/main/scala/org/bitcoins/eclair/rpc/config/EclairInstance.scala +++ b/eclair-rpc/src/main/scala/org/bitcoins/eclair/rpc/config/EclairInstance.scala @@ -15,6 +15,7 @@ sealed trait EclairInstance { def uri: URI def rpcUri: URI def authCredentials: EclairAuthCredentials + def logbackXmlPath: Option[String] } /** @@ -29,57 +30,67 @@ object EclairInstance { network: NetworkParameters, uri: URI, rpcUri: URI, - authCredentials: EclairAuthCredentials) + authCredentials: EclairAuthCredentials, + logbackXmlPath: Option[String]) extends EclairInstance def apply( network: NetworkParameters, uri: URI, rpcUri: URI, - authCredentials: EclairAuthCredentials): EclairInstance = { - EclairInstanceImpl(network, uri, rpcUri, authCredentials) + authCredentials: EclairAuthCredentials, + logbackXmlPath: Option[String]): EclairInstance = { + EclairInstanceImpl(network, uri, rpcUri, authCredentials, logbackXmlPath) } private val DEFAULT_DATADIR = Paths.get(Properties.userHome, ".eclair") private val DEFAULT_CONF_FILE = DEFAULT_DATADIR.resolve("eclair.conf") - def fromDatadir(datadir: File = DEFAULT_DATADIR.toFile): EclairInstance = { + def fromDatadir( + datadir: File = DEFAULT_DATADIR.toFile, + logbackXml: Option[String]): EclairInstance = { require(datadir.exists, s"${datadir.getPath} does not exist!") require(datadir.isDirectory, s"${datadir.getPath} is not a directory!") val eclairConf = new File(datadir.getAbsolutePath + "/eclair.conf") - fromConfigFile(eclairConf) + fromConfigFile(eclairConf, logbackXml) } - def fromConfigFile(file: File = DEFAULT_CONF_FILE.toFile): EclairInstance = { + def fromConfigFile( + file: File = DEFAULT_CONF_FILE.toFile, + logbackXml: Option[String]): EclairInstance = { require(file.exists, s"${file.getPath} does not exist!") require(file.isFile, s"${file.getPath} is not a file!") val config = ConfigFactory.parseFile(file) - fromConfig(config, file.getParentFile) + fromConfig(config, file.getParentFile, logbackXml) } /** * $fromConfigDoc */ - def fromConfig(config: Config, datadir: File): EclairInstance = { - fromConfig(config, Some(datadir)) + def fromConfig( + config: Config, + datadir: File, + logbackXml: Option[String]): EclairInstance = { + fromConfig(config, Some(datadir), logbackXml) } /** * $fromConfigDoc */ def fromConfig(config: Config): EclairInstance = { - fromConfig(config, None) + fromConfig(config, None, None) } private def fromConfig( config: Config, - datadir: Option[File]): EclairInstance = { + datadir: Option[File], + logbackXml: Option[String]): EclairInstance = { val chain = ConfigUtil.getStringOrElse(config, "eclair.chain", "testnet") // default conf: https://github.com/ACINQ/eclair/blob/master/eclair-core/src/main/resources/reference.conf @@ -116,7 +127,8 @@ object EclairInstance { val instance = EclairInstance(network = np, uri = uri, rpcUri = rpcUri, - authCredentials = eclairAuth) + authCredentials = eclairAuth, + logbackXml) instance } diff --git a/testkit/src/main/scala/org/bitcoins/testkit/eclair/rpc/EclairRpcTestUtil.scala b/testkit/src/main/scala/org/bitcoins/testkit/eclair/rpc/EclairRpcTestUtil.scala index eaf5b01b8d..979385266f 100644 --- a/testkit/src/main/scala/org/bitcoins/testkit/eclair/rpc/EclairRpcTestUtil.scala +++ b/testkit/src/main/scala/org/bitcoins/testkit/eclair/rpc/EclairRpcTestUtil.scala @@ -163,25 +163,32 @@ trait EclairRpcTestUtil extends BitcoinSLogger { } /** Assumes bitcoind is running already and you have specified correct bindings in eclair.conf */ - def cannonicalEclairInstance(): EclairInstance = { + def cannonicalEclairInstance( + logbackXml: Option[String] = None): EclairInstance = { val datadir = cannonicalDatadir - eclairInstance(datadir) + eclairInstance(datadir, logbackXml) } - def eclairInstance(datadir: File): EclairInstance = { - val instance = EclairInstance.fromDatadir(datadir) + def eclairInstance( + datadir: File, + logbackXml: Option[String]): EclairInstance = { + val instance = EclairInstance.fromDatadir(datadir, logbackXml) instance } /** Starts the given bitcoind instance and then starts the eclair instance */ - def eclairInstance(bitcoindRpc: BitcoindRpcClient): EclairInstance = { + def eclairInstance( + bitcoindRpc: BitcoindRpcClient, + logbackXml: Option[String] = None): EclairInstance = { val datadir = eclairDataDir(bitcoindRpc, false) - eclairInstance(datadir) + eclairInstance(datadir, logbackXml) } - def randomEclairInstance(bitcoindRpc: BitcoindRpcClient): EclairInstance = { + def randomEclairInstance( + bitcoindRpc: BitcoindRpcClient, + logbackXml: Option[String] = None): EclairInstance = { val datadir = eclairDataDir(bitcoindRpc, false) - eclairInstance(datadir) + eclairInstance(datadir, logbackXml) } def randomEclairClient( @@ -699,7 +706,7 @@ trait EclairRpcTestUtil extends BitcoinSLogger { shutdownF } - case class Network( + case class EclairNetwork( bitcoind: BitcoindRpcClient, testEclairNode: EclairRpcClient, networkEclairNodes: Vector[EclairRpcClient], @@ -713,31 +720,36 @@ trait EclairRpcTestUtil extends BitcoinSLogger { } yield () } - object Network { + object EclairNetwork { def start( - eclairVersion: Option[String], - eclairCommit: Option[String], + testEclairVersion: Option[String], + testEclairCommit: Option[String], + senderEclairVersion: Option[String], + senderEclairCommit: Option[String], networkSize: Int, - channelAmount: MilliSatoshis)( - implicit system: ActorSystem): Future[Network] = { + channelAmount: MilliSatoshis, + logbackXml: Option[String])( + implicit system: ActorSystem): Future[EclairNetwork] = { import system.dispatcher for { bitcoind <- startedBitcoindRpcClient() - testEclairInstance = EclairRpcTestUtil.eclairInstance(bitcoind) + testEclairInstance = EclairRpcTestUtil.eclairInstance(bitcoind, + logbackXml = + logbackXml) testEclairNode = new EclairRpcClient( testEclairInstance, - binary(eclairVersion, eclairCommit)) + binary(testEclairVersion, testEclairCommit)) _ <- testEclairNode.start() _ <- awaitEclairInSync(testEclairNode, bitcoind) networkEclairInstances = 1 .to(networkSize) .toVector - .map(_ => EclairRpcTestUtil.eclairInstance(bitcoind)) + .map(_ => + EclairRpcTestUtil.eclairInstance(bitcoind, logbackXml = logbackXml)) networkEclairNodes = networkEclairInstances.map( new EclairRpcClient(_, - binary(Some(EclairRpcClient.version), - Some(EclairRpcClient.commit)))) + binary(senderEclairVersion, senderEclairCommit))) _ <- Future.sequence(networkEclairNodes.map(_.start())) _ <- Future.sequence( networkEclairNodes.map(awaitEclairInSync(_, bitcoind))) @@ -756,7 +768,10 @@ trait EclairRpcTestUtil extends BitcoinSLogger { } _ <- Future.sequence( channelIds.map(awaitChannelOpened(testEclairNode, _))) - } yield Network(bitcoind, testEclairNode, networkEclairNodes, channelIds) + } yield EclairNetwork(bitcoind, + testEclairNode, + networkEclairNodes, + channelIds) } }