From a395d6ada21565134daf2b4f1bc9f4c20175ba0e Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Mon, 11 Sep 2023 19:07:33 +0200 Subject: [PATCH 1/5] Regtest: Implement alice, bob, and mediator start tasks --- .../gradle/regtest_plugin/RegtestPlugin.kt | 94 ++++++++++++++++--- ...{StartSeedNodeTask.kt => StartBisqTask.kt} | 2 +- 2 files changed, 81 insertions(+), 15 deletions(-) rename build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/{StartSeedNodeTask.kt => StartBisqTask.kt} (95%) diff --git a/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/RegtestPlugin.kt b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/RegtestPlugin.kt index 1ec052dbc5..9d70dc53be 100644 --- a/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/RegtestPlugin.kt +++ b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/RegtestPlugin.kt @@ -19,7 +19,7 @@ class RegtestPlugin : Plugin { blockNotifyArg.set(".localnet/bitcoind/blocknotify %s") } - val startFirstSeedNodeTask = project.tasks.register("startRegtestFirstSeednode") { + val startFirstSeedNodeTask = project.tasks.register("startRegtestFirstSeednode") { dependsOn(startBitcoindTask) startScriptFile.set(project.layout.projectDirectory.file("bisq-seednode")) @@ -31,7 +31,7 @@ class RegtestPlugin : Plugin { logFile.set(project.layout.projectDirectory.file(".localnet/seednode_1_shell.log")) } - val startSecondSeedNodeTask = project.tasks.register("startRegtestSecondSeednode") { + val startSecondSeedNodeTask = project.tasks.register("startRegtestSecondSeednode") { dependsOn(startBitcoindTask) dependsOn(startFirstSeedNodeTask) startScriptFile.set(project.layout.projectDirectory.file("bisq-seednode")) @@ -43,20 +43,86 @@ class RegtestPlugin : Plugin { workingDirectory.set(project.layout.projectDirectory) logFile.set(project.layout.projectDirectory.file(".localnet/seednode_2_shell.log")) } + + val startMediatorTask = project.tasks.register("startRegtestMediator") { + dependsOn(startFirstSeedNodeTask) + dependsOn(startSecondSeedNodeTask) + + startScriptFile.set(project.layout.projectDirectory.file("bisq-desktop")) + + arguments.set( + createBisqUserArgs(4444, ".localnet/mediator", "Mediator") + ) + + workingDirectory.set(project.layout.projectDirectory) + logFile.set(project.layout.projectDirectory.file(".localnet/mediator_shell.log")) + } + + val startAliceTask = project.tasks.register("startRegtestAlice") { + dependsOn(startFirstSeedNodeTask) + dependsOn(startSecondSeedNodeTask) + + startScriptFile.set(project.layout.projectDirectory.file("bisq-desktop")) + + val additionalArgs = listOf( + "--fullDaoNode=true", + "--rpcUser=bisqdao", + "--rpcPassword=bsq", + "--rpcBlockNotificationPort=5122", + "--genesisBlockHeight=111", + "--genesisTxId=30af0050040befd8af25068cc697e418e09c2d8ebd8d411d2240591b9ec203cf" + ) + arguments.set( + createBisqUserArgs(5555, ".localnet/alice", "Alice", additionalArgs) + ) + + workingDirectory.set(project.layout.projectDirectory) + logFile.set(project.layout.projectDirectory.file(".localnet/alice_shell.log")) + } + + project.tasks.register("startRegtest") { + dependsOn(startMediatorTask) + dependsOn(startAliceTask) + + startScriptFile.set(project.layout.projectDirectory.file("bisq-desktop")) + + arguments.set( + createBisqUserArgs(6666, ".localnet/bob", "Bob") + ) + + workingDirectory.set(project.layout.projectDirectory) + logFile.set(project.layout.projectDirectory.file(".localnet/bob_shell.log")) + } } - private fun createSeedNodeArgs(blockNotificationPort: Int, nodePort: Int, appName: String): List = listOf( - "--baseCurrencyNetwork=BTC_REGTEST", - "--useLocalhostForP2P=true", - "--useDevPrivilegeKeys=true", - "--fullDaoNode=true", + private fun createBisqUserArgs(nodePort: Int, + dataDir: String, + appName: String, + additionalArgs: List = emptyList()): List = + createBisqCommonArgs(nodePort) + + listOf( + "--appDataDir=$dataDir", + "--appName=$appName" + ) + additionalArgs - "--rpcUser=${RPC_USER}", - "--rpcPassword=${RPC_PASSWORD}", - "--rpcBlockNotificationPort=$blockNotificationPort", + private fun createSeedNodeArgs(blockNotificationPort: Int, nodePort: Int, appName: String): List = + createBisqCommonArgs(nodePort) + + listOf( + "--fullDaoNode=true", - "--nodePort=$nodePort", - "--userDataDir=.localnet", - "--appName=$appName" - ) + "--rpcUser=${RPC_USER}", + "--rpcPassword=${RPC_PASSWORD}", + "--rpcBlockNotificationPort=$blockNotificationPort", + + "--userDataDir=.localnet", + "--appName=$appName" + ) + + private fun createBisqCommonArgs(nodePort: Int): List = + listOf( + "--baseCurrencyNetwork=BTC_REGTEST", + "--useLocalhostForP2P=true", + "--useDevPrivilegeKeys=true", + "--nodePort=$nodePort" + ) } diff --git a/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartSeedNodeTask.kt b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartBisqTask.kt similarity index 95% rename from build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartSeedNodeTask.kt rename to build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartBisqTask.kt index 0f6cb95e49..861131a306 100644 --- a/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartSeedNodeTask.kt +++ b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartBisqTask.kt @@ -10,7 +10,7 @@ import org.gradle.api.tasks.InputFile import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction -abstract class StartSeedNodeTask : DefaultTask() { +abstract class StartBisqTask : DefaultTask() { @get:InputFile abstract val startScriptFile: RegularFileProperty From 0c093d509cffed1d0b35628b9081d0a1b5268eb0 Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Mon, 11 Sep 2023 19:52:05 +0200 Subject: [PATCH 2/5] Implement regtest stop tasks --- .../bisq/gradle/regtest_plugin/KillTask.kt | 18 ++++++++ .../gradle/regtest_plugin/ProcessKiller.kt | 31 +++++++++++++ .../gradle/regtest_plugin/RegtestPlugin.kt | 43 ++++++++++++++++++- .../gradle/regtest_plugin/StartBisqTask.kt | 16 ++++++- .../regtest_plugin/StartBitcoindTask.kt | 18 +++++++- 5 files changed, 123 insertions(+), 3 deletions(-) create mode 100644 build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/KillTask.kt create mode 100644 build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/ProcessKiller.kt diff --git a/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/KillTask.kt b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/KillTask.kt new file mode 100644 index 0000000000..baf7b18604 --- /dev/null +++ b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/KillTask.kt @@ -0,0 +1,18 @@ +package bisq.gradle.regtest_plugin + +import org.gradle.api.DefaultTask +import org.gradle.api.file.RegularFileProperty +import org.gradle.api.tasks.Internal +import org.gradle.api.tasks.TaskAction + +abstract class KillTask : DefaultTask() { + + @get:Internal + abstract val pidFile: RegularFileProperty + + @TaskAction + fun run() { + ProcessKiller(pidFile.asFile.get()) + .kill() + } +} diff --git a/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/ProcessKiller.kt b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/ProcessKiller.kt new file mode 100644 index 0000000000..b6505cd7af --- /dev/null +++ b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/ProcessKiller.kt @@ -0,0 +1,31 @@ +package bisq.gradle.regtest_plugin + +import java.io.File + +class ProcessKiller(private val pidFile: File) { + + companion object { + private const val SIG_INT_NUMBER = 2 + } + + fun kill() { + if (!pidFile.exists()) { + return + } + + val pid = pidFile.readText() + val processBuilder = ProcessBuilder( + "kill", + "-s", SIG_INT_NUMBER.toString(), + pid + ) + + processBuilder.redirectErrorStream(true) + processBuilder.redirectOutput(ProcessBuilder.Redirect.DISCARD) + + val process = processBuilder.start() + process.waitFor() + + + } +} diff --git a/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/RegtestPlugin.kt b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/RegtestPlugin.kt index 9d70dc53be..ca5cf7a6fa 100644 --- a/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/RegtestPlugin.kt +++ b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/RegtestPlugin.kt @@ -13,14 +13,22 @@ class RegtestPlugin : Plugin { override fun apply(project: Project) { val startBitcoindTask = project.tasks.register("startRegtestBitcoind") { + pidFile.set(project.layout.projectDirectory.file(".localnet/bitcoind.pid")) + dataDirectory.set(project.layout.projectDirectory.dir(".localnet/bitcoind")) rpcUser.set(RPC_USER) rpcPassword.set(RPC_PASSWORD) blockNotifyArg.set(".localnet/bitcoind/blocknotify %s") } + val stopBitcoindTask = project.tasks.register("stopRegtestBitcoind") { + pidFile.set(startBitcoindTask.flatMap { it.pidFile }) + } + val startFirstSeedNodeTask = project.tasks.register("startRegtestFirstSeednode") { dependsOn(startBitcoindTask) + + pidFile.set(project.layout.projectDirectory.file(".localnet/seednode_1.pid")) startScriptFile.set(project.layout.projectDirectory.file("bisq-seednode")) arguments.set( @@ -31,9 +39,15 @@ class RegtestPlugin : Plugin { logFile.set(project.layout.projectDirectory.file(".localnet/seednode_1_shell.log")) } + val stopFirstSeedNodeTask = project.tasks.register("stopRegtestFirstSeednode") { + pidFile.set(startFirstSeedNodeTask.flatMap { it.pidFile }) + } + val startSecondSeedNodeTask = project.tasks.register("startRegtestSecondSeednode") { dependsOn(startBitcoindTask) dependsOn(startFirstSeedNodeTask) + + pidFile.set(project.layout.projectDirectory.file(".localnet/seednode_2.pid")) startScriptFile.set(project.layout.projectDirectory.file("bisq-seednode")) arguments.set( @@ -44,10 +58,15 @@ class RegtestPlugin : Plugin { logFile.set(project.layout.projectDirectory.file(".localnet/seednode_2_shell.log")) } + val stopSeedNodeTask = project.tasks.register("stopRegtestSecondSeednode") { + pidFile.set(startSecondSeedNodeTask.flatMap { it.pidFile }) + } + val startMediatorTask = project.tasks.register("startRegtestMediator") { dependsOn(startFirstSeedNodeTask) dependsOn(startSecondSeedNodeTask) + pidFile.set(project.layout.projectDirectory.file(".localnet/mediator.pid")) startScriptFile.set(project.layout.projectDirectory.file("bisq-desktop")) arguments.set( @@ -58,10 +77,15 @@ class RegtestPlugin : Plugin { logFile.set(project.layout.projectDirectory.file(".localnet/mediator_shell.log")) } + val stopMediatorTask = project.tasks.register("stopRegtestMediator") { + pidFile.set(startMediatorTask.flatMap { it.pidFile }) + } + val startAliceTask = project.tasks.register("startRegtestAlice") { dependsOn(startFirstSeedNodeTask) dependsOn(startSecondSeedNodeTask) + pidFile.set(project.layout.projectDirectory.file(".localnet/alice.pid")) startScriptFile.set(project.layout.projectDirectory.file("bisq-desktop")) val additionalArgs = listOf( @@ -80,10 +104,15 @@ class RegtestPlugin : Plugin { logFile.set(project.layout.projectDirectory.file(".localnet/alice_shell.log")) } - project.tasks.register("startRegtest") { + val stopAliceTask = project.tasks.register("stopRegtestAlice") { + pidFile.set(startAliceTask.flatMap { it.pidFile }) + } + + val startBobTask = project.tasks.register("startRegtest") { dependsOn(startMediatorTask) dependsOn(startAliceTask) + pidFile.set(project.layout.projectDirectory.file(".localnet/bob.pid")) startScriptFile.set(project.layout.projectDirectory.file("bisq-desktop")) arguments.set( @@ -93,6 +122,18 @@ class RegtestPlugin : Plugin { workingDirectory.set(project.layout.projectDirectory) logFile.set(project.layout.projectDirectory.file(".localnet/bob_shell.log")) } + + project.tasks.register("stopRegtest") { + dependsOn(stopBitcoindTask) + + dependsOn(stopFirstSeedNodeTask) + dependsOn(stopSeedNodeTask) + + dependsOn(stopMediatorTask) + dependsOn(stopAliceTask) + + pidFile.set(startBobTask.flatMap { it.pidFile }) + } } private fun createBisqUserArgs(nodePort: Int, diff --git a/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartBisqTask.kt b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartBisqTask.kt index 861131a306..f2940c8408 100644 --- a/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartBisqTask.kt +++ b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartBisqTask.kt @@ -24,8 +24,17 @@ abstract class StartBisqTask : DefaultTask() { @get:Internal abstract val logFile: RegularFileProperty + @get:Internal + abstract val pidFile: RegularFileProperty + @TaskAction fun run() { + ProcessKiller(pidFile.asFile.get()) + .kill() + + // Wait until process stopped + Thread.sleep(5000) + val processBuilder = ProcessBuilder( "bash", startScriptFile.asFile.get().absolutePath, arguments.get().joinToString(" ") ) @@ -34,6 +43,11 @@ abstract class StartBisqTask : DefaultTask() { processBuilder.redirectErrorStream(true) processBuilder.redirectOutput(logFile.asFile.get()) - processBuilder.start() + val process = processBuilder.start() + val pid = process.pid() + + pidFile.asFile + .get() + .writeText(pid.toString()) } } diff --git a/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartBitcoindTask.kt b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartBitcoindTask.kt index 9aedb73fbd..0c15387359 100644 --- a/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartBitcoindTask.kt +++ b/build-logic/regtest/src/main/kotlin/bisq/gradle/regtest_plugin/StartBitcoindTask.kt @@ -2,13 +2,18 @@ package bisq.gradle.regtest_plugin import org.gradle.api.DefaultTask import org.gradle.api.file.DirectoryProperty +import org.gradle.api.file.RegularFileProperty import org.gradle.api.provider.Property import org.gradle.api.tasks.Input import org.gradle.api.tasks.InputDirectory +import org.gradle.api.tasks.Internal import org.gradle.api.tasks.TaskAction abstract class StartBitcoindTask : DefaultTask() { + @get:Internal + abstract val pidFile: RegularFileProperty + @get:InputDirectory abstract val dataDirectory: DirectoryProperty @@ -23,6 +28,12 @@ abstract class StartBitcoindTask : DefaultTask() { @TaskAction fun run() { + ProcessKiller(pidFile.asFile.get()) + .kill() + + // Wait until process stopped + Thread.sleep(5000) + val processBuilder = ProcessBuilder( "bitcoind", "-datadir=${dataDirectory.asFile.get().absolutePath}", @@ -42,6 +53,11 @@ abstract class StartBitcoindTask : DefaultTask() { processBuilder.redirectErrorStream(true) processBuilder.redirectOutput(ProcessBuilder.Redirect.DISCARD) - processBuilder.start() + val process = processBuilder.start() + val pid = process.pid() + + pidFile.asFile + .get() + .writeText(pid.toString()) } } From dbd35e3408af71dbf586c4465f0a27d25b3c9abd Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Mon, 11 Sep 2023 20:03:44 +0200 Subject: [PATCH 3/5] Makefile: Call regtest tasks --- Makefile | 29 ++++++++--------------------- 1 file changed, 8 insertions(+), 21 deletions(-) diff --git a/Makefile b/Makefile index 935fe586bf..248e01a869 100644 --- a/Makefile +++ b/Makefile @@ -147,35 +147,22 @@ localnet: .localnet # user, you'll need to manually run each of the targets listed below # commands manually in a separate terminal or as background jobs. deploy: setup - # ensure localnet is not already deployed - if screen -ls localnet | grep Detached; then false; fi - # create a new screen session named 'localnet' - screen -dmS localnet - # deploy each node in its own named screen window - for target in \ - bitcoind \ - seednode \ - seednode2 \ - alice \ - bob \ - mediator; do \ - screen -S localnet -X screen -t $$target; \ - screen -S localnet -p $$target -X stuff "make $$target\n"; \ - done; + ./gradlew :startRegtest # give bitcoind rpc server time to start sleep 5 # generate a block to ensure Bisq nodes get dao-synced make block + tail -f .localnet/bitcoind_shell.log \ + .localnet/seednode_1_shell.log \ + .localnet/seednode_2_shell.log \ + .localnet/alice_shell.log \ + .localnet/bob_shell.log \ + .localnet/mediator_shell.log # Undeploy a running localnet by killing all Bitcoin and Bisq # node processes, then killing the localnet screen session altogether undeploy: - # kill all Bitcoind and Bisq nodes running in screen windows - screen -S localnet -X at "#" stuff "^C" - # quit all screen windows which results in killing the session - screen -S localnet -X at "#" kill - # remove dead screens - screen -wipe || true + ./gradlew :stopRegtest bitcoind: .localnet bitcoind \ From 7ce4c9205630df2ab9c24b7285836860fd148609 Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Mon, 11 Sep 2023 20:05:01 +0200 Subject: [PATCH 4/5] Makefile: Remove old targets --- Makefile | 71 -------------------------------------------------------- 1 file changed, 71 deletions(-) diff --git a/Makefile b/Makefile index 248e01a869..c51f7306c9 100644 --- a/Makefile +++ b/Makefile @@ -164,77 +164,6 @@ deploy: setup undeploy: ./gradlew :stopRegtest -bitcoind: .localnet - bitcoind \ - -regtest \ - -prune=0 \ - -txindex=1 \ - -peerbloomfilters=1 \ - -server \ - -rpcuser=bisqdao \ - -rpcpassword=bsq \ - -datadir=.localnet/bitcoind \ - -blocknotify='.localnet/bitcoind/blocknotify %s' - -seednode: seednode/build - ./bisq-seednode \ - --baseCurrencyNetwork=BTC_REGTEST \ - --useLocalhostForP2P=true \ - --useDevPrivilegeKeys=true \ - --fullDaoNode=true \ - --rpcUser=bisqdao \ - --rpcPassword=bsq \ - --rpcBlockNotificationPort=5120 \ - --nodePort=2002 \ - --userDataDir=.localnet \ - --appName=seednode - -seednode2: seednode/build - ./bisq-seednode \ - --baseCurrencyNetwork=BTC_REGTEST \ - --useLocalhostForP2P=true \ - --useDevPrivilegeKeys=true \ - --fullDaoNode=true \ - --rpcUser=bisqdao \ - --rpcPassword=bsq \ - --rpcBlockNotificationPort=5121 \ - --nodePort=3002 \ - --userDataDir=.localnet \ - --appName=seednode2 - -mediator: desktop/build - ./bisq-desktop \ - --baseCurrencyNetwork=BTC_REGTEST \ - --useLocalhostForP2P=true \ - --useDevPrivilegeKeys=true \ - --nodePort=4444 \ - --appDataDir=.localnet/mediator \ - --appName=Mediator - -alice: setup - ./bisq-desktop \ - --baseCurrencyNetwork=BTC_REGTEST \ - --useLocalhostForP2P=true \ - --useDevPrivilegeKeys=true \ - --nodePort=5555 \ - --fullDaoNode=true \ - --rpcUser=bisqdao \ - --rpcPassword=bsq \ - --rpcBlockNotificationPort=5122 \ - --genesisBlockHeight=111 \ - --genesisTxId=30af0050040befd8af25068cc697e418e09c2d8ebd8d411d2240591b9ec203cf \ - --appDataDir=.localnet/alice \ - --appName=Alice - -bob: setup - ./bisq-desktop \ - --baseCurrencyNetwork=BTC_REGTEST \ - --useLocalhostForP2P=true \ - --useDevPrivilegeKeys=true \ - --nodePort=6666 \ - --appDataDir=.localnet/bob \ - --appName=Bob - # Generate a new block on your Bitcoin regtest network. Requires that # bitcoind is already running. See the `bitcoind` target above. block: From 13d37b6c86389b601b67a7a8a3a24086b2b51e53 Mon Sep 17 00:00:00 2001 From: Alva Swanson Date: Mon, 11 Sep 2023 20:06:23 +0200 Subject: [PATCH 5/5] Makefile: Don't build twice --- Makefile | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/Makefile b/Makefile index c51f7306c9..3bb4a6cb8c 100644 --- a/Makefile +++ b/Makefile @@ -100,7 +100,7 @@ # Set up everything necessary for deploying your localnet. This is the # default target. -setup: build .localnet +setup: .localnet clean: clean-build clean-localnet @@ -110,15 +110,6 @@ clean-build: clean-localnet: rm -rf .localnet ./dao-setup -# Build Bisq binaries and shell scripts used in the targets below -build: seednode/build desktop/build - -seednode/build: - ./gradlew :seednode:build - -desktop/build: - ./gradlew :desktop:build - # Unpack and customize a Bitcoin regtest node and Alice and Bob Bisq # nodes that have been preconfigured with a blockchain containing the # BSQ genesis transaction