Skip to content

Commit

Permalink
Gradle: Add Regtest Setup Tasks
Browse files Browse the repository at this point in the history
The custom Gradle Tasks will help developers set up their Bitcoin Core/
Elements Core Regtest environment. These tasks set up an isolated
Bitcoin Core/Elements Core regtest instance, create a wallet, and
premine the initial regtest blocks/pegin BTC to L-BTC.

The :desktop:runWithBitcoindRegtestWallet and
:desktop:runWithElementsdRegtestWallet Gradle Tasks set up a regtest
instance and automatically connect Bisq to it.

See: docs/wallet-regtest-setup.md
  • Loading branch information
alvasw committed Mar 15, 2022
1 parent 3334d5f commit 6c99f7f
Show file tree
Hide file tree
Showing 22 changed files with 986 additions and 0 deletions.
4 changes: 4 additions & 0 deletions build.gradle
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import bisq.gradle.BisqPlugin

plugins {
id 'java'
}

apply plugin: BisqPlugin

group 'bisq'

repositories {
Expand Down
1 change: 1 addition & 0 deletions buildSrc/build.gradle
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
plugins {
id "org.gradle.kotlin.kotlin-dsl" version "2.1.7"
id 'com.google.protobuf' version '0.8.16'
id 'signing'
id 'maven-publish'
Expand Down
32 changes: 32 additions & 0 deletions buildSrc/src/main/kotlin/bisq/gradle/BisqPlugin.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package bisq.gradle

import bisq.gradle.bitcoind.BitcoindRegtestTasks
import bisq.gradle.elementsd.ElementsdRegtestTasks
import org.gradle.api.Plugin
import org.gradle.api.Project
import java.io.File


class BisqPlugin : Plugin<Project> {
override fun apply(project: Project) {
val regtestRootDataDir = project.buildDir.resolve("regtest")
regtestRootDataDir.mkdirs()

registerBitcoindRegtestTasks(project, regtestRootDataDir)
registerElementsdRegtestTasks(project, regtestRootDataDir)
}

private fun registerBitcoindRegtestTasks(project: Project, regtestRootDataDir: File) {
val bitcoindDataDir: File = regtestRootDataDir.resolve("bitcoind_regtest")
val bitcoindRegtestTasks = BitcoindRegtestTasks(project, bitcoindDataDir)
bitcoindRegtestTasks.registerTasks()
}

private fun registerElementsdRegtestTasks(project: Project, regtestRootDataDir: File) {
val elementsdDataDir: File = regtestRootDataDir.resolve("elementsd_regtest")
val elementsdRegtestTasks = ElementsdRegtestTasks(project, elementsdDataDir)
elementsdRegtestTasks.registerTasks()
}


}
15 changes: 15 additions & 0 deletions buildSrc/src/main/kotlin/bisq/gradle/Network.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
package bisq.gradle

import java.io.IOException
import java.net.ServerSocket

object Network {
fun isPortFree(port: Int): Boolean =
try {
val server = ServerSocket(port)
server.close()
true
} catch (e: IOException) {
false
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package bisq.gradle.bitcoind

import bisq.gradle.tasks.bitcoind.BitcoindStopTask
import bisq.gradle.tasks.bitcoind.StartBitcoinQtTask
import org.gradle.api.Project
import org.gradle.api.tasks.Delete
import org.gradle.api.tasks.TaskContainer
import org.gradle.api.tasks.TaskProvider
import org.gradle.kotlin.dsl.register
import java.io.File

class BitcoindProcessTasks(
project: Project,
private val bitcoindDataDir: File,
private val taskNameSuffix: String = ""
) {
private val tasks: TaskContainer = project.tasks

lateinit var startBitcoinQtTask: TaskProvider<StartBitcoinQtTask>
lateinit var stopBitcoindTask: TaskProvider<BitcoindStopTask>

fun registerTasks() {
startBitcoinQtTask = registerBitcoindStartTask()
stopBitcoindTask = registerBitcoindStopTask()
registerCleanTask(stopBitcoindTask)
}

private fun registerBitcoindStartTask(): TaskProvider<StartBitcoinQtTask> =
tasks.register<StartBitcoinQtTask>("bitcoindStart$taskNameSuffix") {
dataDir.set(bitcoindDataDir)
}

private fun registerBitcoindStopTask(): TaskProvider<BitcoindStopTask> =
tasks.register<BitcoindStopTask>("bitcoindStop$taskNameSuffix")

private fun registerCleanTask(stopBitcoindTask: TaskProvider<BitcoindStopTask>): TaskProvider<Delete> =
tasks.register<Delete>("cleanBitcoindRegtest$taskNameSuffix") {
dependsOn(stopBitcoindTask)
delete = setOf(bitcoindDataDir.absolutePath)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
package bisq.gradle.bitcoind

import bisq.gradle.tasks.ApplicationRunTaskFactory
import bisq.gradle.tasks.bitcoind.StartBitcoinQtTask
import org.gradle.api.Project
import org.gradle.api.tasks.TaskProvider
import java.io.File

class BitcoindRegtestTasks(private val project: Project, dataDir: File) {

private val bitcoindDataDir: File = dataDir.resolve("bitcoind")
private val bisqDataDir: File = dataDir.resolve("bisq")

fun registerTasks() {
bisqDataDir.resolve("wallets").mkdirs()

val bitcoindProcessTasks = BitcoindProcessTasks(project, bitcoindDataDir)
bitcoindProcessTasks.registerTasks()

val bitcoindWalletCreationTasks: BitcoindWalletCreationTasks =
registerWalletTasks(bitcoindProcessTasks.startBitcoinQtTask)

ApplicationRunTaskFactory.registerDesktopRegtestRunTask(
project = project,
taskName = "runWithBitcoindRegtestWallet",
description = "Run Bisq with Bitcoin Core Wallet (Regtest)",
cmdLineArgs = listOf("--regtest-bitcoind", "--data-dir=${bisqDataDir.absolutePath}"),
dependentTask = bitcoindWalletCreationTasks.mineInitialRegtestBlocksTask
)
}

private fun registerWalletTasks(
startBitcoinQtTask: TaskProvider<StartBitcoinQtTask>
): BitcoindWalletCreationTasks {
val bitcoindWalletCreationTasks = BitcoindWalletCreationTasks(
project = project,
bisqDataDir = bisqDataDir
)
bitcoindWalletCreationTasks.registerTasks(startBitcoinQtTask)
return bitcoindWalletCreationTasks
}
}
25 changes: 25 additions & 0 deletions buildSrc/src/main/kotlin/bisq/gradle/bitcoind/BitcoindRpcClient.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package bisq.gradle.bitcoind

object BitcoindRpcClient {
private val cmdArgs = listOf(
"bitcoin-cli",
"-regtest",
"-rpcwait",
"-rpcuser=bisq",
"-rpcpassword=bisq"
)

fun daemonRpcCall(args: List<String>): String {
val process = ProcessBuilder(cmdArgs + args)
.start()
process.waitFor()

return process.inputStream
.bufferedReader()
.readText()
}

fun walletRpcCall(walletPath: String, args: List<String>): String {
return daemonRpcCall(listOf("-rpcwallet=$walletPath") + args)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package bisq.gradle.bitcoind

import bisq.gradle.tasks.bitcoind.BitcoindCreateOrLoadWalletTask
import bisq.gradle.tasks.bitcoind.BitcoindMineToWallet
import bisq.gradle.tasks.bitcoind.StartBitcoinQtTask
import org.gradle.api.Project
import org.gradle.api.tasks.TaskContainer
import org.gradle.api.tasks.TaskProvider
import org.gradle.kotlin.dsl.register
import java.io.File


class BitcoindWalletCreationTasks(
project: Project,
bisqDataDir: File,
private val taskNameSuffix: String = ""
) {

private val tasks: TaskContainer = project.tasks
val walletDirectory: File = bisqDataDir.resolve("wallets/bitcoind")

private lateinit var createWalletTask: TaskProvider<BitcoindCreateOrLoadWalletTask>
lateinit var mineInitialRegtestBlocksTask: TaskProvider<BitcoindMineToWallet>

fun registerTasks(startBitcoinQtTask: TaskProvider<StartBitcoinQtTask>) {
createWalletTask = registerCreateMinerWalletTask(startBitcoinQtTask)
mineInitialRegtestBlocksTask = registerMineInitialRegtestBlocksTask()
}

private fun registerCreateMinerWalletTask(startBitcoinQtTask: TaskProvider<StartBitcoinQtTask>):
TaskProvider<BitcoindCreateOrLoadWalletTask> =
tasks.register<BitcoindCreateOrLoadWalletTask>("bitcoindCreateMinerWallet$taskNameSuffix") {
dependsOn(startBitcoinQtTask)
walletDirectory.set(this@BitcoindWalletCreationTasks.walletDirectory)
}

private fun registerMineInitialRegtestBlocksTask(): TaskProvider<BitcoindMineToWallet> =
tasks.register<BitcoindMineToWallet>("bitcoindMineInitialRegtestBlocks$taskNameSuffix") {
dependsOn(createWalletTask)
onlyIf { getBlockCount() == 0 }

walletDirectory.set(this@BitcoindWalletCreationTasks.walletDirectory)
numberOfBlocks.set(101)
}

private fun getBlockCount(): Int {
val blockCount = BitcoindRpcClient.daemonRpcCall(listOf("getblockcount")).trim()
return blockCount.toInt()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
package bisq.gradle.elementsd

import bisq.gradle.bitcoind.BitcoindProcessTasks
import bisq.gradle.tasks.bitcoind.BitcoindMineToWallet
import bisq.gradle.tasks.elementsd.ElementsdStopTask
import bisq.gradle.tasks.elementsd.StartElementsQtTask
import org.gradle.api.Project
import org.gradle.api.tasks.Delete
import org.gradle.api.tasks.TaskContainer
import org.gradle.api.tasks.TaskProvider
import org.gradle.kotlin.dsl.register
import java.io.File

class ElementsdProcessTasks(
project: Project,
private val elementsdDataDir: File
) {

private val tasks: TaskContainer = project.tasks

lateinit var elementsdStartTask: TaskProvider<StartElementsQtTask>
private lateinit var elementsdStopTask: TaskProvider<ElementsdStopTask>

fun registerTasks(
bitcoindProcessTasks: BitcoindProcessTasks,
mineInitialRegtestBlocksTask: TaskProvider<BitcoindMineToWallet>
) {
elementsdStartTask = registerElementsdStartTask(mineInitialRegtestBlocksTask)

elementsdStopTask = registerElementsdStopTask()
bitcoindProcessTasks.stopBitcoindTask.configure { dependsOn(elementsdStopTask) }

registerCleanTask()
}

private fun registerElementsdStartTask(mineInitialRegtestBlocksTask: TaskProvider<BitcoindMineToWallet>):
TaskProvider<StartElementsQtTask> =
tasks.register<StartElementsQtTask>("elementsdStart") {
dependsOn(mineInitialRegtestBlocksTask)
dataDir.set(elementsdDataDir)
}

private fun registerElementsdStopTask(): TaskProvider<ElementsdStopTask> =
tasks.register<ElementsdStopTask>("elementsdStop")

private fun registerCleanTask(): TaskProvider<Delete> =
tasks.register<Delete>("cleanElementsdRegtest") {
dependsOn(elementsdStopTask)
delete = setOf(elementsdDataDir.absolutePath)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
package bisq.gradle.elementsd

import bisq.gradle.bitcoind.BitcoindProcessTasks
import bisq.gradle.bitcoind.BitcoindWalletCreationTasks
import bisq.gradle.tasks.ApplicationRunTaskFactory
import org.gradle.api.Project
import java.io.File

class ElementsdRegtestTasks(private val project: Project, dataDir: File) {

private val bitcoindDataDir: File = dataDir.resolve("bitcoind")
private val elementsdDataDir: File = dataDir.resolve("elementsd")
private val bisqDataDir: File = dataDir.resolve("bisq")

private lateinit var bitcoindProcessTasks: BitcoindProcessTasks
private lateinit var bitcoindWalletCreationTasks: BitcoindWalletCreationTasks

private lateinit var elementsdWalletCreationTasks: ElementsdWalletCreationTasks

fun registerTasks() {
bisqDataDir.resolve("wallets").mkdirs()

registerBitcoindTasks()
registerElementsdTasks()

ApplicationRunTaskFactory.registerDesktopRegtestRunTask(
project = project,
taskName = "runWithElementsdRegtestWallet",
description = "Run Bisq with Elements Core Wallet (Regtest)",
cmdLineArgs = listOf("--regtest-elementsd", "--data-dir=${bisqDataDir.absolutePath}"),
dependentTask = elementsdWalletCreationTasks.peginTask
)
}

private fun registerBitcoindTasks() {
bitcoindProcessTasks = BitcoindProcessTasks(project, bitcoindDataDir, taskNameSuffix = "ForElementsRegtest")
bitcoindProcessTasks.registerTasks()

bitcoindWalletCreationTasks = BitcoindWalletCreationTasks(
project = project,
bisqDataDir = bisqDataDir,
taskNameSuffix = "ForElementsRegtest"
)
bitcoindWalletCreationTasks.registerTasks(bitcoindProcessTasks.startBitcoinQtTask)
}

private fun registerElementsdTasks() {
val elementsdProcessTasks =
ElementsdProcessTasks(project, elementsdDataDir)
elementsdProcessTasks.registerTasks(
bitcoindProcessTasks,
bitcoindWalletCreationTasks.mineInitialRegtestBlocksTask
)

elementsdWalletCreationTasks = ElementsdWalletCreationTasks(
project = project,
bisqDataDir = bisqDataDir,
)
elementsdWalletCreationTasks.registerTasks(
elementsdProcessTasks.elementsdStartTask,
bitcoindWalletCreationTasks.walletDirectory
)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
package bisq.gradle.elementsd

object ElementsdRpcClient {
private val cmdArgs = listOf(
"elements-cli",
"-rpcwait",
"-chain=elementsregtest",

"-rpcuser=bisq",
"-rpcpassword=bisq"
)

fun daemonRpcCall(args: List<String>): String {
val process = ProcessBuilder(cmdArgs + args)
.start()
process.waitFor()

return process.inputStream
.bufferedReader()
.readText()
}

fun walletRpcCall(walletPath: String, args: List<String>): String {
return daemonRpcCall(listOf("-rpcwallet=$walletPath") + args)
}
}

0 comments on commit 6c99f7f

Please sign in to comment.