Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

bitcoind: Use project bitcoind in tests #2760

Merged
merged 11 commits into from
Sep 4, 2024
Original file line number Diff line number Diff line change
Expand Up @@ -38,20 +38,16 @@ public BitcoindDaemon(JsonRpcClient rpcClient) {
}

public void createOrLoadWallet(String walletName, Optional<String> passphrase) {
createOrLoadWallet(walletName, passphrase, true, false, false);
}

public void createOrLoadLegacyWallet(String walletName, Optional<String> passphrase) {
createOrLoadWallet(walletName, passphrase, false, false, false);
createOrLoadWallet(walletName, passphrase, false, false);
}

public void createOrLoadWatchOnlyWallet(String walletName) {
createOrLoadWallet(walletName, Optional.empty(), true, true, true);
createOrLoadWallet(walletName, Optional.empty(), true, true);
}

private void createOrLoadWallet(String walletName, Optional<String> passphrase, boolean descriptors, boolean disablePrivateKeys, boolean blank) {
private void createOrLoadWallet(String walletName, Optional<String> passphrase, boolean disablePrivateKeys, boolean blank) {
try {
createWallet(walletName, passphrase.orElse(""), descriptors, disablePrivateKeys, blank);
createWallet(walletName, passphrase.orElse(""), disablePrivateKeys, blank);
} catch (RpcCallFailureException e) {
if (doesWalletExist(e)) {
List<String> loadedWallets = listWallets();
Expand Down Expand Up @@ -117,7 +113,11 @@ private static List<String> listWalletsWithRpcClient(JsonRpcClient rpcClient) {
}

public String sendRawTransaction(String hexString) {
var request = new BitcoindSendRawTransactionRpcCall.Request(hexString);
return sendRawTransaction(hexString, null);
}

public String sendRawTransaction(String hexString, String maxBurnAmount) {
var request = new BitcoindSendRawTransactionRpcCall.Request(hexString, maxBurnAmount);
var rpcCall = new BitcoindSendRawTransactionRpcCall(request);
return rpcClient.call(rpcCall).getResult();
}
Expand Down Expand Up @@ -147,10 +147,9 @@ private boolean doesWalletExist(RpcCallFailureException e) {
return e.getMessage().contains("Database already exists.");
}

private void createWallet(String walletName, String passphrase, boolean descriptors, boolean disablePrivateKeys, boolean blank) {
private void createWallet(String walletName, String passphrase, boolean disablePrivateKeys, boolean blank) {
var request = BitcoindCreateWalletRpcCall.Request.builder()
.walletName(walletName)
.descriptors(descriptors)
.disablePrivateKeys(disablePrivateKeys)
.blank(blank)
.passphrase(passphrase)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,6 @@ public static class Request {
private String passphrase;
@Json(name = "avoid_reuse")
private Boolean avoidReuse;
private boolean descriptors;
}

public BitcoindCreateWalletRpcCall(Request request) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,9 +32,12 @@ public class BitcoindSendRawTransactionRpcCall extends DaemonRpcCall<BitcoindSen
public static final class Request {
@Json(name = "hexstring")
private final String hexString;
@Json(name = "maxburnamount")
private final String maxBurnAmount;

public Request(String hexString) {
public Request(String hexString, String maxBurnAmount) {
this.hexString = hexString;
this.maxBurnAmount = maxBurnAmount;
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package bisq.wallets.bitcoind.rpc.responses;

import com.squareup.moshi.Json;
import lombok.Getter;

import java.util.List;
Expand All @@ -29,4 +30,6 @@ public class BitcoindDescriptor {
private boolean internal;
private List<Integer> range;
private Integer next;
@Json(name = "next_index")
private Integer nextIndex;
}
Original file line number Diff line number Diff line change
Expand Up @@ -27,5 +27,7 @@ public static class Result {
private BitcoindGetMineBalancesResponse mine;
@Json(name = "watchonly")
private BitcoindGetMineBalancesResponse watchOnly;
@Json(name = "lastprocessedblock")
private BitcoindGetLastProcessedBlockBalancesResponse lastProcessedBlock;
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package bisq.wallets.bitcoind.rpc.responses;

import lombok.Getter;

@Getter
public class BitcoindGetLastProcessedBlockBalancesResponse {
private String hash;
long height;
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public class BitcoindListTransactionsResponse extends JsonRpcResponse<List<Bitco
public static class Entry implements TransactionInfo {
private boolean involvesWatchonly;
private String address;
@Json(name = "parent_descs")
private List<String> parentDescs;
private String category;
private double amount;
private String label;
Expand All @@ -46,6 +48,8 @@ public static class Entry implements TransactionInfo {
private int blocktime;
@Json(name = "txid")
private String txId;
@Json(name = "wtxid")
private String wtxId;
private String[] walletconflicts;
private int time;
private int timereceived;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,5 +26,6 @@ public class BitcoindWalletProcessPsbtResponse extends JsonRpcResponse<BitcoindW
public static class Result {
private String psbt;
private boolean complete;
private String hex;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -20,13 +20,16 @@
import bisq.wallets.json_rpc.JsonRpcResponse;
import lombok.Getter;

import java.util.Collections;
import java.util.List;

public class BitcoindWarningResponse extends JsonRpcResponse<BitcoindWarningResponse.Result> {
@Getter
public static class Result {
protected String warning;
protected List<String> warnings = Collections.emptyList();

public boolean hasWarning() {
return !warning.isEmpty();
return !warnings.isEmpty();
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@ public class ElementsdRegtestProcess extends BitcoindRegtestProcess {
private final ElementsdConfig elementsdConfig;

public ElementsdRegtestProcess(ElementsdConfig elementsdConfig, Path dataDir) {
super(elementsdConfig.elementsdRpcConfig(), dataDir);
super(null, elementsdConfig.elementsdRpcConfig(), dataDir);
this.elementsdConfig = elementsdConfig;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public ElementsdDaemon(JsonRpcClient rpcClient) {
}

public void createOrLoadWallet(String walletName, Optional<String> passphrase) {
bitcoindDaemon.createOrLoadLegacyWallet(walletName, passphrase);
throw new UnsupportedOperationException("Bitcoin Core 25.0 removed legacy wallet support.");
}

public ElementsdDecodeRawTransactionResponse decodeRawTransaction(String txInHex) {
Expand Down
13 changes: 13 additions & 0 deletions wallets/regtest/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,5 +1,18 @@
plugins {
id("bisq.java-library")
id("bisq.gradle.bitcoin_core.BitcoinCorePlugin")
}

bitcoin_core {
version.set("27.1")
}

sourceSets {
main {
resources {
srcDir(layout.buildDirectory.file("generated/src/main/resources"))
}
}
}

dependencies {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,12 +38,14 @@
@Slf4j
public class BitcoindRegtestProcess extends DaemonProcess {

private final Path binaryPath;
@Getter
protected final RpcConfig rpcConfig;
private final BitcoindDaemon bitcoindDaemon;

public BitcoindRegtestProcess(RpcConfig rpcConfig, Path dataDir) {
public BitcoindRegtestProcess(Path binaryPath, RpcConfig rpcConfig, Path dataDir) {
super(dataDir);
this.binaryPath = binaryPath;
this.rpcConfig = rpcConfig;
JsonRpcClient rpcClient = RpcClientFactory.createDaemonRpcClient(rpcConfig);
bitcoindDaemon = new BitcoindDaemon(rpcClient);
Expand All @@ -53,7 +55,7 @@ public BitcoindRegtestProcess(RpcConfig rpcConfig, Path dataDir) {
public ProcessConfig createProcessConfig() {
int zmqPort = NetworkUtils.findFreeSystemPort();
return ProcessConfig.builder()
.name("bitcoind")
.name(binaryPath.toAbsolutePath().toString())
.args(List.of(
"-regtest",
"-datadir=" + dataDir.toAbsolutePath(),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@

package bisq.wallets.regtest.bitcoind;

import bisq.common.platform.OS;
import bisq.common.util.NetworkUtils;
import bisq.wallets.bitcoind.rpc.BitcoindDaemon;
import bisq.wallets.bitcoind.rpc.BitcoindWallet;
Expand All @@ -27,7 +28,10 @@
import bisq.wallets.regtest.process.MultiProcessCoordinator;
import lombok.Getter;

import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;
import java.util.Objects;
Expand Down Expand Up @@ -65,7 +69,7 @@ public List<String> mineOneBlock() throws InterruptedException {
return mineBlocks(1);
}

public List<String> mineBlocks(int numberOfBlocks) throws InterruptedException {
public List<String> mineBlocks(int numberOfBlocks) {
return remoteBitcoind.mineBlocks(numberOfBlocks);
}

Expand Down Expand Up @@ -101,9 +105,13 @@ private RpcConfig createRpcConfig() {
return createRpcConfig("127.0.0.1", port);
}

private BitcoindRegtestProcess createBitcoindProcess() {
private BitcoindRegtestProcess createBitcoindProcess() throws IOException {
Path bitcoindBinaryDir = tmpDirPath.resolve("bitcoind_binary");
Path bitcoindPath = installBitcoind(bitcoindBinaryDir);

Path bitcoindDataDir = tmpDirPath.resolve("bitcoind_data_dir");
return new BitcoindRegtestProcess(
bitcoindPath,
rpcConfig,
bitcoindDataDir
);
Expand All @@ -124,4 +132,40 @@ public BitcoindWallet getMinerWallet() {
public ZmqListeners getZmqListeners() {
return remoteBitcoind.getZmqListeners();
}

private Path installBitcoind(Path bitcoindBinaryDir) throws IOException {
File bitcoindBinaryDirFile = bitcoindBinaryDir.toFile();
boolean isSuccess = bitcoindBinaryDirFile.mkdirs();
if (!isSuccess) {
throw new IllegalStateException("Couldn't create " + bitcoindBinaryDir.toAbsolutePath() + " for " +
"bitcoind installation.");
}

InputStream inputStream = getClass()
.getClassLoader()
.getResourceAsStream("bitcoind");

if (inputStream == null) {
throw new IllegalStateException("Can't read bitcoind binary from resources.");
}

Path bitcoindPath = bitcoindBinaryDir.resolve("bitcoind");
try (inputStream) {
Files.copy(inputStream, bitcoindPath);

boolean endOfStreamReached = inputStream.available() == 0;
if (!endOfStreamReached) {
throw new IllegalStateException("Couldn't extract bitcoind binary.");
}

if (OS.isLinux() || OS.isMacOs()) {
isSuccess = bitcoindPath.toFile().setExecutable(true);
if (!isSuccess) {
throw new IllegalStateException("Couldn't set executable bit on bitcoind binary.");
}
}

return bitcoindPath;
}
}
}
Loading