mirror of
https://github.com/bitcoin-s/bitcoin-s.git
synced 2025-03-03 18:47:38 +01:00
some more changes
This commit is contained in:
parent
2f9d3606ca
commit
74fa1e61af
4 changed files with 113 additions and 60 deletions
|
@ -21,28 +21,47 @@ object EclairBench extends App with EclairRpcTestUtil {
|
||||||
implicit val system = ActorSystem()
|
implicit val system = ActorSystem()
|
||||||
import system.dispatcher
|
import system.dispatcher
|
||||||
|
|
||||||
val networkSize = 1
|
// put compiled test jar files into binaries/eclair/${version} directory
|
||||||
val paymentCount = 10
|
|
||||||
val channelAmount = 10000000000L.msats
|
|
||||||
val outputFileName = "test.csv"
|
|
||||||
|
|
||||||
// release
|
// None means current release
|
||||||
val EclairVersion = Option.empty[String]
|
val TestEclairVersion = Option.empty[String]
|
||||||
val EclairCommit = 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
|
val NetworkSize = 10
|
||||||
// compiled binary can be found here:
|
val PaymentCount = 2000
|
||||||
// https://s3-us-west-1.amazonaws.com/suredbits.com/eclair/eclair-node-0.3.3-SNAPSHOT-949f1ec-psql.jar
|
val ChannelAmount = 10000000000L.msats
|
||||||
// put it into binaries/eclair/0.3.3-SNAPSHOT directory
|
val PaymentAmount = 10.msats
|
||||||
// val EclairVersion = Option("0.3.3-SNAPSHOT")
|
val OutputFileName = "test.csv"
|
||||||
// val EclairCommit = Option("949f1ec-psql")
|
val LogbackXml = None // Some("~/logback.xml")
|
||||||
|
|
||||||
// don't forget to recreate `eclair` Postgres database before starting a new test
|
// don't forget to recreate `eclair` Postgres database before starting a new test
|
||||||
EclairRpcTestUtil.customConfigMap = Map(
|
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]] =
|
implicit ec: ExecutionContext): Future[Vector[PaymentId]] =
|
||||||
for {
|
for {
|
||||||
testNodeInfo <- network.testEclairNode.getInfo
|
testNodeInfo <- network.testEclairNode.getInfo
|
||||||
|
@ -64,25 +83,26 @@ object EclairBench extends App with EclairRpcTestUtil {
|
||||||
None)
|
None)
|
||||||
} yield {
|
} yield {
|
||||||
logPaymentId(paymentHash, id)
|
logPaymentId(paymentHash, id)
|
||||||
|
Progress.inc()
|
||||||
acc :+ id
|
acc :+ id
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
} yield paymentIds.flatten
|
} yield paymentIds.flatten
|
||||||
|
|
||||||
def runTests(network: Network): Future[Vector[PaymentLogEntry]] = {
|
def runTests(network: EclairNetwork): Future[Vector[PaymentLogEntry]] = {
|
||||||
println("Setting up the test network")
|
println("Setting up the test network")
|
||||||
for {
|
for {
|
||||||
_ <- network.testEclairNode.connectToWebSocket(logEvent)
|
_ <- network.testEclairNode.connectToWebSocket(logEvent)
|
||||||
_ = println(
|
_ = 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(
|
_ = println(
|
||||||
s"Test node data directory: ${network.testEclairNode.instance.authCredentials.datadir
|
s"Test node data directory: ${network.testEclairNode.instance.authCredentials.datadir
|
||||||
.getOrElse("")}")
|
.getOrElse("")}")
|
||||||
_ = println("Testing...")
|
_ = println("Testing...")
|
||||||
_ <- sendPayments(network, 1000.msats, paymentCount)
|
_ <- sendPayments(network, PaymentAmount, PaymentCount)
|
||||||
_ <- TestAsyncUtil.retryUntilSatisfied(
|
_ <- TestAsyncUtil.retryUntilSatisfied(
|
||||||
condition = paymentLog.size() == networkSize * paymentCount,
|
condition = paymentLog.size() == NetworkSize * PaymentCount,
|
||||||
duration = 1.second,
|
duration = 1.second,
|
||||||
maxTries = 100)
|
maxTries = 100)
|
||||||
_ <- TestAsyncUtil
|
_ <- TestAsyncUtil
|
||||||
|
@ -90,7 +110,7 @@ object EclairBench extends App with EclairRpcTestUtil {
|
||||||
paymentLog.values().asScala.forall(_.completed),
|
paymentLog.values().asScala.forall(_.completed),
|
||||||
duration = 1.second,
|
duration = 1.second,
|
||||||
maxTries = 100)
|
maxTries = 100)
|
||||||
_ = println("Done!")
|
_ = println("\nDone!")
|
||||||
} yield {
|
} yield {
|
||||||
paymentLog
|
paymentLog
|
||||||
.values()
|
.values()
|
||||||
|
@ -101,10 +121,13 @@ object EclairBench extends App with EclairRpcTestUtil {
|
||||||
}
|
}
|
||||||
|
|
||||||
val res: Future[Unit] = for {
|
val res: Future[Unit] = for {
|
||||||
network <- Network.start(EclairVersion,
|
network <- EclairNetwork.start(TestEclairVersion,
|
||||||
EclairCommit,
|
TestEclairCommit,
|
||||||
networkSize,
|
SenderEclairVersion,
|
||||||
channelAmount)
|
SenderEclairCommit,
|
||||||
|
NetworkSize,
|
||||||
|
ChannelAmount,
|
||||||
|
LogbackXml)
|
||||||
log <- runTests(network).recoverWith {
|
log <- runTests(network).recoverWith {
|
||||||
case e: Throwable =>
|
case e: Throwable =>
|
||||||
e.printStackTrace()
|
e.printStackTrace()
|
||||||
|
@ -122,7 +145,7 @@ object EclairBench extends App with EclairRpcTestUtil {
|
||||||
case (x, i) =>
|
case (x, i) =>
|
||||||
s"${x.paymentSentAt - first.paymentSentAt},${i + 1},${x.toCSV}"
|
s"${x.paymentSentAt - first.paymentSentAt},${i + 1},${x.toCSV}"
|
||||||
}
|
}
|
||||||
val outputFile = new File(outputFileName)
|
val outputFile = new File(OutputFileName)
|
||||||
Files.write(outputFile.toPath,
|
Files.write(outputFile.toPath,
|
||||||
csv.asJava,
|
csv.asJava,
|
||||||
StandardOpenOption.CREATE,
|
StandardOpenOption.CREATE,
|
||||||
|
|
|
@ -704,10 +704,13 @@ class EclairRpcClient(val instance: EclairInstance, binary: Option[File] = None)
|
||||||
|
|
||||||
require(instance.authCredentials.datadir.isDefined,
|
require(instance.authCredentials.datadir.isDefined,
|
||||||
s"A datadir needs to be provided to start eclair")
|
s"A datadir needs to be provided to start eclair")
|
||||||
|
|
||||||
if (process.isEmpty) {
|
if (process.isEmpty) {
|
||||||
val p = Process(
|
val logback = instance.logbackXmlPath
|
||||||
s"java -jar -Declair.datadir=${instance.authCredentials.datadir.get} $pathToEclairJar &")
|
.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()
|
val result = p.run()
|
||||||
logger.debug(
|
logger.debug(
|
||||||
s"Starting eclair with datadir ${instance.authCredentials.datadir.get}")
|
s"Starting eclair with datadir ${instance.authCredentials.datadir.get}")
|
||||||
|
|
|
@ -15,6 +15,7 @@ sealed trait EclairInstance {
|
||||||
def uri: URI
|
def uri: URI
|
||||||
def rpcUri: URI
|
def rpcUri: URI
|
||||||
def authCredentials: EclairAuthCredentials
|
def authCredentials: EclairAuthCredentials
|
||||||
|
def logbackXmlPath: Option[String]
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -29,57 +30,67 @@ object EclairInstance {
|
||||||
network: NetworkParameters,
|
network: NetworkParameters,
|
||||||
uri: URI,
|
uri: URI,
|
||||||
rpcUri: URI,
|
rpcUri: URI,
|
||||||
authCredentials: EclairAuthCredentials)
|
authCredentials: EclairAuthCredentials,
|
||||||
|
logbackXmlPath: Option[String])
|
||||||
extends EclairInstance
|
extends EclairInstance
|
||||||
|
|
||||||
def apply(
|
def apply(
|
||||||
network: NetworkParameters,
|
network: NetworkParameters,
|
||||||
uri: URI,
|
uri: URI,
|
||||||
rpcUri: URI,
|
rpcUri: URI,
|
||||||
authCredentials: EclairAuthCredentials): EclairInstance = {
|
authCredentials: EclairAuthCredentials,
|
||||||
EclairInstanceImpl(network, uri, rpcUri, authCredentials)
|
logbackXmlPath: Option[String]): EclairInstance = {
|
||||||
|
EclairInstanceImpl(network, uri, rpcUri, authCredentials, logbackXmlPath)
|
||||||
}
|
}
|
||||||
|
|
||||||
private val DEFAULT_DATADIR = Paths.get(Properties.userHome, ".eclair")
|
private val DEFAULT_DATADIR = Paths.get(Properties.userHome, ".eclair")
|
||||||
|
|
||||||
private val DEFAULT_CONF_FILE = DEFAULT_DATADIR.resolve("eclair.conf")
|
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.exists, s"${datadir.getPath} does not exist!")
|
||||||
require(datadir.isDirectory, s"${datadir.getPath} is not a directory!")
|
require(datadir.isDirectory, s"${datadir.getPath} is not a directory!")
|
||||||
|
|
||||||
val eclairConf = new File(datadir.getAbsolutePath + "/eclair.conf")
|
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.exists, s"${file.getPath} does not exist!")
|
||||||
require(file.isFile, s"${file.getPath} is not a file!")
|
require(file.isFile, s"${file.getPath} is not a file!")
|
||||||
|
|
||||||
val config = ConfigFactory.parseFile(file)
|
val config = ConfigFactory.parseFile(file)
|
||||||
|
|
||||||
fromConfig(config, file.getParentFile)
|
fromConfig(config, file.getParentFile, logbackXml)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* $fromConfigDoc
|
* $fromConfigDoc
|
||||||
*/
|
*/
|
||||||
def fromConfig(config: Config, datadir: File): EclairInstance = {
|
def fromConfig(
|
||||||
fromConfig(config, Some(datadir))
|
config: Config,
|
||||||
|
datadir: File,
|
||||||
|
logbackXml: Option[String]): EclairInstance = {
|
||||||
|
fromConfig(config, Some(datadir), logbackXml)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* $fromConfigDoc
|
* $fromConfigDoc
|
||||||
*/
|
*/
|
||||||
def fromConfig(config: Config): EclairInstance = {
|
def fromConfig(config: Config): EclairInstance = {
|
||||||
fromConfig(config, None)
|
fromConfig(config, None, None)
|
||||||
}
|
}
|
||||||
|
|
||||||
private def fromConfig(
|
private def fromConfig(
|
||||||
config: Config,
|
config: Config,
|
||||||
datadir: Option[File]): EclairInstance = {
|
datadir: Option[File],
|
||||||
|
logbackXml: Option[String]): EclairInstance = {
|
||||||
val chain = ConfigUtil.getStringOrElse(config, "eclair.chain", "testnet")
|
val chain = ConfigUtil.getStringOrElse(config, "eclair.chain", "testnet")
|
||||||
|
|
||||||
// default conf: https://github.com/ACINQ/eclair/blob/master/eclair-core/src/main/resources/reference.conf
|
// 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,
|
val instance = EclairInstance(network = np,
|
||||||
uri = uri,
|
uri = uri,
|
||||||
rpcUri = rpcUri,
|
rpcUri = rpcUri,
|
||||||
authCredentials = eclairAuth)
|
authCredentials = eclairAuth,
|
||||||
|
logbackXml)
|
||||||
|
|
||||||
instance
|
instance
|
||||||
}
|
}
|
||||||
|
|
|
@ -163,25 +163,32 @@ trait EclairRpcTestUtil extends BitcoinSLogger {
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Assumes bitcoind is running already and you have specified correct bindings in eclair.conf */
|
/** 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
|
val datadir = cannonicalDatadir
|
||||||
eclairInstance(datadir)
|
eclairInstance(datadir, logbackXml)
|
||||||
}
|
}
|
||||||
|
|
||||||
def eclairInstance(datadir: File): EclairInstance = {
|
def eclairInstance(
|
||||||
val instance = EclairInstance.fromDatadir(datadir)
|
datadir: File,
|
||||||
|
logbackXml: Option[String]): EclairInstance = {
|
||||||
|
val instance = EclairInstance.fromDatadir(datadir, logbackXml)
|
||||||
instance
|
instance
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Starts the given bitcoind instance and then starts the eclair 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)
|
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)
|
val datadir = eclairDataDir(bitcoindRpc, false)
|
||||||
eclairInstance(datadir)
|
eclairInstance(datadir, logbackXml)
|
||||||
}
|
}
|
||||||
|
|
||||||
def randomEclairClient(
|
def randomEclairClient(
|
||||||
|
@ -699,7 +706,7 @@ trait EclairRpcTestUtil extends BitcoinSLogger {
|
||||||
shutdownF
|
shutdownF
|
||||||
}
|
}
|
||||||
|
|
||||||
case class Network(
|
case class EclairNetwork(
|
||||||
bitcoind: BitcoindRpcClient,
|
bitcoind: BitcoindRpcClient,
|
||||||
testEclairNode: EclairRpcClient,
|
testEclairNode: EclairRpcClient,
|
||||||
networkEclairNodes: Vector[EclairRpcClient],
|
networkEclairNodes: Vector[EclairRpcClient],
|
||||||
|
@ -713,31 +720,36 @@ trait EclairRpcTestUtil extends BitcoinSLogger {
|
||||||
} yield ()
|
} yield ()
|
||||||
}
|
}
|
||||||
|
|
||||||
object Network {
|
object EclairNetwork {
|
||||||
|
|
||||||
def start(
|
def start(
|
||||||
eclairVersion: Option[String],
|
testEclairVersion: Option[String],
|
||||||
eclairCommit: Option[String],
|
testEclairCommit: Option[String],
|
||||||
|
senderEclairVersion: Option[String],
|
||||||
|
senderEclairCommit: Option[String],
|
||||||
networkSize: Int,
|
networkSize: Int,
|
||||||
channelAmount: MilliSatoshis)(
|
channelAmount: MilliSatoshis,
|
||||||
implicit system: ActorSystem): Future[Network] = {
|
logbackXml: Option[String])(
|
||||||
|
implicit system: ActorSystem): Future[EclairNetwork] = {
|
||||||
import system.dispatcher
|
import system.dispatcher
|
||||||
for {
|
for {
|
||||||
bitcoind <- startedBitcoindRpcClient()
|
bitcoind <- startedBitcoindRpcClient()
|
||||||
testEclairInstance = EclairRpcTestUtil.eclairInstance(bitcoind)
|
testEclairInstance = EclairRpcTestUtil.eclairInstance(bitcoind,
|
||||||
|
logbackXml =
|
||||||
|
logbackXml)
|
||||||
testEclairNode = new EclairRpcClient(
|
testEclairNode = new EclairRpcClient(
|
||||||
testEclairInstance,
|
testEclairInstance,
|
||||||
binary(eclairVersion, eclairCommit))
|
binary(testEclairVersion, testEclairCommit))
|
||||||
_ <- testEclairNode.start()
|
_ <- testEclairNode.start()
|
||||||
_ <- awaitEclairInSync(testEclairNode, bitcoind)
|
_ <- awaitEclairInSync(testEclairNode, bitcoind)
|
||||||
networkEclairInstances = 1
|
networkEclairInstances = 1
|
||||||
.to(networkSize)
|
.to(networkSize)
|
||||||
.toVector
|
.toVector
|
||||||
.map(_ => EclairRpcTestUtil.eclairInstance(bitcoind))
|
.map(_ =>
|
||||||
|
EclairRpcTestUtil.eclairInstance(bitcoind, logbackXml = logbackXml))
|
||||||
networkEclairNodes = networkEclairInstances.map(
|
networkEclairNodes = networkEclairInstances.map(
|
||||||
new EclairRpcClient(_,
|
new EclairRpcClient(_,
|
||||||
binary(Some(EclairRpcClient.version),
|
binary(senderEclairVersion, senderEclairCommit)))
|
||||||
Some(EclairRpcClient.commit))))
|
|
||||||
_ <- Future.sequence(networkEclairNodes.map(_.start()))
|
_ <- Future.sequence(networkEclairNodes.map(_.start()))
|
||||||
_ <- Future.sequence(
|
_ <- Future.sequence(
|
||||||
networkEclairNodes.map(awaitEclairInSync(_, bitcoind)))
|
networkEclairNodes.map(awaitEclairInSync(_, bitcoind)))
|
||||||
|
@ -756,7 +768,10 @@ trait EclairRpcTestUtil extends BitcoinSLogger {
|
||||||
}
|
}
|
||||||
_ <- Future.sequence(
|
_ <- Future.sequence(
|
||||||
channelIds.map(awaitChannelOpened(testEclairNode, _)))
|
channelIds.map(awaitChannelOpened(testEclairNode, _)))
|
||||||
} yield Network(bitcoind, testEclairNode, networkEclairNodes, channelIds)
|
} yield EclairNetwork(bitcoind,
|
||||||
|
testEclairNode,
|
||||||
|
networkEclairNodes,
|
||||||
|
channelIds)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Reference in a new issue