Merge branch 'haveno-dex:master' into take3
This commit is contained in:
commit
1b09fd2808
@ -17,19 +17,20 @@
|
||||
|
||||
package haveno.asset.coins;
|
||||
|
||||
import haveno.asset.Base58AddressValidator;
|
||||
import haveno.asset.BitcoinAddressValidator;
|
||||
import haveno.asset.Coin;
|
||||
import haveno.asset.NetworkParametersAdapter;
|
||||
|
||||
public class Litecoin extends Coin {
|
||||
public Litecoin() {
|
||||
super("Litecoin", "LTC", new Base58AddressValidator(new LitecoinMainNetParams()), Network.MAINNET);
|
||||
super("Litecoin", "LTC", new BitcoinAddressValidator(new LitecoinMainNetParams()), Network.MAINNET);
|
||||
}
|
||||
|
||||
public static class LitecoinMainNetParams extends NetworkParametersAdapter {
|
||||
public LitecoinMainNetParams() {
|
||||
this.addressHeader = 48;
|
||||
this.p2shHeader = 5;
|
||||
this.p2shHeader = 50;
|
||||
this.segwitAddressHrp = "ltc";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -31,6 +31,17 @@ public class LitecoinTest extends AbstractAssetTest {
|
||||
assertValidAddress("Lg3PX8wRWmApFCoCMAsPF5P9dPHYQHEWKW");
|
||||
assertValidAddress("LTuoeY6RBHV3n3cfhXVVTbJbxzxnXs9ofm");
|
||||
assertValidAddress("LgfapHEPhZbRF9pMd5WPT35hFXcZS1USrW");
|
||||
assertValidAddress("M8T1B2Z97gVdvmfkQcAtYbEepune1tzGua");
|
||||
assertValidAddress("ltc1qr07zu594qf63xm7l7x6pu3a2v39m2z6hh5pp4t");
|
||||
assertValidAddress("ltc1qzvcgmntglcuv4smv3lzj6k8szcvsrmvk0phrr9wfq8w493r096ssm2fgsw");
|
||||
assertValidAddress("MESruSiB2uC9i7tMU6VMUVom91ohM7Rnbd");
|
||||
assertValidAddress("ltc1q2a0laq2jg2gntzhfs43qptajd325kkx7hrq9cs");
|
||||
assertValidAddress("ltc1qd6d54mt8xxcg0xg3l0vh6fymdfvd2tv0vnwyrv");
|
||||
assertValidAddress("ltc1gmay6ht028aurcm680f8e8wxdup07y2tq46f6z2d4v8rutewqmmcqk29jtm");
|
||||
assertValidAddress("MTf4tP1TCNBn8dNkyxeBVoPrFCcVzxJvvh");
|
||||
assertValidAddress("LaRoRBC6utQtY3U2FbHwhmhhDPyxodDeKA");
|
||||
assertValidAddress("MDMFP9Dx84tyaxiYksjvkG1jymBdqCuHGA");
|
||||
//assertValidAddress("3MSvaVbVFFLML86rt5eqgA9SvW23upaXdY"); // deprecated
|
||||
}
|
||||
|
||||
@Test
|
||||
@ -38,5 +49,14 @@ public class LitecoinTest extends AbstractAssetTest {
|
||||
assertInvalidAddress("1LgfapHEPhZbRF9pMd5WPT35hFXcZS1USrW");
|
||||
assertInvalidAddress("LgfapHEPhZbdRF9pMd5WPT35hFXcZS1USrW");
|
||||
assertInvalidAddress("LgfapHEPhZbRF9pMd5WPT35hFXcZS1USrW#");
|
||||
assertInvalidAddress("3MSvaVbVFFLML86rt5eqgl9SvW23upaXdY"); // contains lowercase l
|
||||
assertInvalidAddress("LURw7hYhREXjWHyiXhQNsKInWtPezwNe98"); // contains uppercase I
|
||||
assertInvalidAddress("LM4ch8ZtAowdiGLSnf92MrMOC9dVmve2hr"); // contains uppercase O
|
||||
assertInvalidAddress("MArsfeyS7P0HzsqLpAFGC9pFdhuqHgdL2R"); // contains number 0
|
||||
assertInvalidAddress("ltc1qr6quwn3v2gxpadd0cu040r9385gayk5vdcyl5"); // too short
|
||||
assertInvalidAddress("ltc1q5det08ke2gpet06wczcdfs2v3hgfqllxw28uln8vxxx82qlue6uswceljma"); // too long
|
||||
assertInvalidAddress("MADpfTtabZ6pDjms4pMd3ZmnrgyhTCo4N8?time=1708476729&exp=86400"); // additional information
|
||||
assertInvalidAddress("ltc1q8tk47lvgqu55h4pfast39r3t9360gmll5z9m6z?time=1708476604&exp=600"); // additional information
|
||||
assertInvalidAddress("ltc1q026xyextkwhmveh7rpf6v6mp5p88vwc25aynxr?time=1708476626"); // additional information
|
||||
}
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ configure(subprojects) {
|
||||
gsonVersion = '2.8.5'
|
||||
guavaVersion = '32.1.1-jre'
|
||||
guiceVersion = '7.0.0'
|
||||
moneroJavaVersion = '0.8.10'
|
||||
moneroJavaVersion = '0.8.11'
|
||||
httpclient5Version = '5.0'
|
||||
hamcrestVersion = '2.2'
|
||||
httpclientVersion = '4.5.12'
|
||||
@ -71,7 +71,7 @@ configure(subprojects) {
|
||||
loggingVersion = '1.2'
|
||||
lombokVersion = '1.18.30'
|
||||
mockitoVersion = '5.10.0'
|
||||
netlayerVersion = '6797461310f077bbea4f43a3a509c077b0ed8c34' // Netlayer version 0.7.3 with Tor browser version 11.0.14 and tor binary version: 0.4.7.7
|
||||
netlayerVersion = '2b459dc' // Tor browser version 11.5.2 and tor binary version: 0.4.7.10
|
||||
protobufVersion = '3.19.1'
|
||||
protocVersion = protobufVersion
|
||||
pushyVersion = '0.13.2'
|
||||
@ -436,6 +436,11 @@ configure(project(':core')) {
|
||||
systemProperty 'jdk.attach.allowAttachSelf', true
|
||||
}
|
||||
|
||||
task generateKeypairs(type: JavaExec) {
|
||||
mainClass = 'haveno.core.util.GenerateKeyPairs'
|
||||
classpath = sourceSets.main.runtimeClasspath
|
||||
}
|
||||
|
||||
task havenoDeps {
|
||||
doLast {
|
||||
// get monero binaries download url
|
||||
|
@ -22,7 +22,6 @@ import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.CountDownLatch;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.Future;
|
||||
@ -41,10 +40,10 @@ public class ThreadUtils {
|
||||
* @param command the command to execute
|
||||
* @param threadId the thread id
|
||||
*/
|
||||
public static void execute(Runnable command, String threadId) {
|
||||
public static Future<?> execute(Runnable command, String threadId) {
|
||||
synchronized (EXECUTORS) {
|
||||
if (!EXECUTORS.containsKey(threadId)) EXECUTORS.put(threadId, Executors.newFixedThreadPool(1));
|
||||
EXECUTORS.get(threadId).execute(() -> {
|
||||
return EXECUTORS.get(threadId).submit(() -> {
|
||||
synchronized (THREADS) {
|
||||
THREADS.put(threadId, Thread.currentThread());
|
||||
}
|
||||
@ -60,24 +59,10 @@ public class ThreadUtils {
|
||||
* @param threadId the thread id
|
||||
*/
|
||||
public static void await(Runnable command, String threadId) {
|
||||
if (isCurrentThread(Thread.currentThread(), threadId)) {
|
||||
command.run();
|
||||
} else {
|
||||
CountDownLatch latch = new CountDownLatch(1);
|
||||
execute(() -> {
|
||||
try {
|
||||
command.run();
|
||||
} catch (Exception e) {
|
||||
throw e;
|
||||
} finally {
|
||||
latch.countDown();
|
||||
}
|
||||
}, threadId);
|
||||
try {
|
||||
latch.await();
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
try {
|
||||
execute(command, threadId).get();
|
||||
} catch (Exception e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -84,6 +84,7 @@ public class Config {
|
||||
public static final String USE_TOR_FOR_XMR = "useTorForXmr";
|
||||
public static final String TORRC_FILE = "torrcFile";
|
||||
public static final String TORRC_OPTIONS = "torrcOptions";
|
||||
public static final String TOR_CONTROL_HOST = "torControlHost";
|
||||
public static final String TOR_CONTROL_PORT = "torControlPort";
|
||||
public static final String TOR_CONTROL_PASSWORD = "torControlPassword";
|
||||
public static final String TOR_CONTROL_COOKIE_FILE = "torControlCookieFile";
|
||||
@ -173,6 +174,7 @@ public class Config {
|
||||
public final String socks5ProxyHttpAddress;
|
||||
public final File torrcFile;
|
||||
public final String torrcOptions;
|
||||
public final String torControlHost;
|
||||
public final int torControlPort;
|
||||
public final String torControlPassword;
|
||||
public final File torControlCookieFile;
|
||||
@ -446,6 +448,11 @@ public class Config {
|
||||
.withValuesConvertedBy(RegexMatcher.regex("^([^\\s,]+\\s[^,]+,?\\s*)+$"))
|
||||
.defaultsTo("");
|
||||
|
||||
ArgumentAcceptingOptionSpec<String> torControlHostOpt =
|
||||
parser.accepts(TOR_CONTROL_HOST, "The control hostname of an already running Tor service to be used by Haveno.")
|
||||
.withRequiredArg()
|
||||
.defaultsTo("127.0.0.1");
|
||||
|
||||
ArgumentAcceptingOptionSpec<Integer> torControlPortOpt =
|
||||
parser.accepts(TOR_CONTROL_PORT,
|
||||
"The control port of an already running Tor service to be used by Haveno.")
|
||||
@ -667,6 +674,7 @@ public class Config {
|
||||
this.bitcoinRegtestHost = options.valueOf(bitcoinRegtestHostOpt);
|
||||
this.torrcFile = options.has(torrcFileOpt) ? options.valueOf(torrcFileOpt).toFile() : null;
|
||||
this.torrcOptions = options.valueOf(torrcOptionsOpt);
|
||||
this.torControlHost = options.valueOf(torControlHostOpt);
|
||||
this.torControlPort = options.valueOf(torControlPortOpt);
|
||||
this.torControlPassword = options.valueOf(torControlPasswordOpt);
|
||||
this.torControlCookieFile = options.has(torControlCookieFileOpt) ?
|
||||
|
@ -19,16 +19,6 @@ package haveno.common.crypto;
|
||||
|
||||
import haveno.common.util.Hex;
|
||||
import haveno.common.util.Utilities;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.OAEPParameterSpec;
|
||||
import javax.crypto.spec.PSource;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.security.InvalidKeyException;
|
||||
@ -43,10 +33,17 @@ import java.security.spec.InvalidKeySpecException;
|
||||
import java.security.spec.MGF1ParameterSpec;
|
||||
import java.security.spec.X509EncodedKeySpec;
|
||||
import java.util.Arrays;
|
||||
import javax.crypto.Cipher;
|
||||
import javax.crypto.KeyGenerator;
|
||||
import javax.crypto.Mac;
|
||||
import javax.crypto.SecretKey;
|
||||
import javax.crypto.spec.OAEPParameterSpec;
|
||||
import javax.crypto.spec.PSource;
|
||||
import javax.crypto.spec.SecretKeySpec;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
@Slf4j
|
||||
public class Encryption {
|
||||
private static final Logger log = LoggerFactory.getLogger(Encryption.class);
|
||||
|
||||
public static final String ASYM_KEY_ALGO = "RSA";
|
||||
private static final String ASYM_CIPHER = "RSA/ECB/OAEPWithSHA-256AndMGF1PADDING";
|
||||
|
||||
|
@ -458,8 +458,8 @@ public class CoreApi {
|
||||
paymentAccount);
|
||||
}
|
||||
|
||||
public void cancelOffer(String id) {
|
||||
coreOffersService.cancelOffer(id);
|
||||
public void cancelOffer(String id, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
coreOffersService.cancelOffer(id, resultHandler, errorMessageHandler);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -38,6 +38,7 @@ import com.google.inject.Inject;
|
||||
import com.google.inject.Singleton;
|
||||
import haveno.common.crypto.KeyRing;
|
||||
import haveno.common.handlers.ErrorMessageHandler;
|
||||
import haveno.common.handlers.ResultHandler;
|
||||
import static haveno.common.util.MathUtils.exactMultiply;
|
||||
import static haveno.common.util.MathUtils.roundDoubleToLong;
|
||||
import static haveno.common.util.MathUtils.scaleUpByPowerOf10;
|
||||
@ -236,14 +237,9 @@ public class CoreOffersService {
|
||||
paymentAccount);
|
||||
}
|
||||
|
||||
void cancelOffer(String id) {
|
||||
void cancelOffer(String id, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||
Offer offer = getMyOffer(id).getOffer();
|
||||
openOfferManager.removeOffer(offer,
|
||||
() -> {
|
||||
},
|
||||
errorMessage -> {
|
||||
throw new IllegalStateException(errorMessage);
|
||||
});
|
||||
openOfferManager.removeOffer(offer, resultHandler, errorMessageHandler);
|
||||
}
|
||||
|
||||
// -------------------------- PRIVATE HELPERS -----------------------------
|
||||
|
@ -133,7 +133,6 @@ class CoreWalletsService {
|
||||
verifyWalletCurrencyCodeIsValid(currencyCode);
|
||||
verifyWalletsAreAvailable();
|
||||
verifyEncryptedWalletIsUnlocked();
|
||||
if (balances.getAvailableBalance().get() == null) throw new IllegalStateException("balance is not yet available");
|
||||
|
||||
switch (currencyCode.trim().toUpperCase()) {
|
||||
case "":
|
||||
@ -418,28 +417,8 @@ class CoreWalletsService {
|
||||
private XmrBalanceInfo getXmrBalances() {
|
||||
verifyWalletsAreAvailable();
|
||||
verifyEncryptedWalletIsUnlocked();
|
||||
|
||||
var availableBalance = balances.getAvailableBalance().get();
|
||||
if (availableBalance == null)
|
||||
throw new IllegalStateException("available balance is not yet available");
|
||||
|
||||
var pendingBalance = balances.getPendingBalance().get();
|
||||
if (pendingBalance == null)
|
||||
throw new IllegalStateException("locked balance is not yet available");
|
||||
|
||||
var reservedOfferBalance = balances.getReservedOfferBalance().get();
|
||||
if (reservedOfferBalance == null)
|
||||
throw new IllegalStateException("reserved offer balance is not yet available");
|
||||
|
||||
var reservedTradeBalance = balances.getReservedTradeBalance().get();
|
||||
if (reservedTradeBalance == null)
|
||||
throw new IllegalStateException("reserved trade balance is not yet available");
|
||||
|
||||
return new XmrBalanceInfo(availableBalance.longValue() + pendingBalance.longValue(),
|
||||
availableBalance.longValue(),
|
||||
pendingBalance.longValue(),
|
||||
reservedOfferBalance.longValue(),
|
||||
reservedTradeBalance.longValue());
|
||||
if (balances.getAvailableBalance() == null) throw new IllegalStateException("Balances are not yet available");
|
||||
return balances.getBalances();
|
||||
}
|
||||
|
||||
// Returns a Coin for the transfer amount string, or a RuntimeException if invalid.
|
||||
|
@ -1,10 +1,10 @@
|
||||
package haveno.core.api.model;
|
||||
|
||||
import java.math.BigInteger;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import haveno.common.Payload;
|
||||
import lombok.Getter;
|
||||
|
||||
@Getter
|
||||
public class XmrBalanceInfo implements Payload {
|
||||
|
||||
public static final XmrBalanceInfo EMPTY = new XmrBalanceInfo(-1,
|
||||
@ -19,17 +19,19 @@ public class XmrBalanceInfo implements Payload {
|
||||
private final long pendingBalance;
|
||||
private final long reservedOfferBalance;
|
||||
private final long reservedTradeBalance;
|
||||
private final long reservedBalance;
|
||||
|
||||
public XmrBalanceInfo(long balance,
|
||||
long unlockedBalance,
|
||||
long lockedBalance,
|
||||
long pendingBalance,
|
||||
long reservedOfferBalance,
|
||||
long reservedTradeBalance) {
|
||||
this.balance = balance;
|
||||
this.availableBalance = unlockedBalance;
|
||||
this.pendingBalance = lockedBalance;
|
||||
this.pendingBalance = pendingBalance;
|
||||
this.reservedOfferBalance = reservedOfferBalance;
|
||||
this.reservedTradeBalance = reservedTradeBalance;
|
||||
this.reservedBalance = reservedOfferBalance + reservedTradeBalance;
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@ -45,6 +47,30 @@ public class XmrBalanceInfo implements Payload {
|
||||
reservedTradeBalance);
|
||||
}
|
||||
|
||||
public BigInteger getBalance() {
|
||||
return BigInteger.valueOf(balance);
|
||||
}
|
||||
|
||||
public BigInteger getAvailableBalance() {
|
||||
return BigInteger.valueOf(availableBalance);
|
||||
}
|
||||
|
||||
public BigInteger getPendingBalance() {
|
||||
return BigInteger.valueOf(pendingBalance);
|
||||
}
|
||||
|
||||
public BigInteger getReservedOfferBalance() {
|
||||
return BigInteger.valueOf(reservedOfferBalance);
|
||||
}
|
||||
|
||||
public BigInteger getReservedTradeBalance() {
|
||||
return BigInteger.valueOf(reservedTradeBalance);
|
||||
}
|
||||
|
||||
public BigInteger getReservedBalance() {
|
||||
return BigInteger.valueOf(reservedBalance);
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
// PROTO BUFFER
|
||||
///////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -620,9 +620,13 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
||||
if (!offersToBeEdited.containsKey(openOffer.getId())) {
|
||||
if (openOffer.isDeactivated()) {
|
||||
onCancelled(openOffer);
|
||||
resultHandler.handleResult();
|
||||
} else {
|
||||
offerBookService.removeOffer(openOffer.getOffer().getOfferPayload(),
|
||||
() -> onCancelled(openOffer),
|
||||
() -> {
|
||||
onCancelled(openOffer);
|
||||
resultHandler.handleResult();
|
||||
},
|
||||
errorMessageHandler);
|
||||
}
|
||||
} else {
|
||||
|
@ -19,6 +19,7 @@ package haveno.core.presentation;
|
||||
|
||||
import com.google.inject.Inject;
|
||||
import haveno.common.UserThread;
|
||||
import haveno.core.api.model.XmrBalanceInfo;
|
||||
import haveno.core.trade.HavenoUtils;
|
||||
import haveno.core.xmr.Balances;
|
||||
import javafx.beans.property.SimpleStringProperty;
|
||||
@ -38,14 +39,13 @@ public class BalancePresentation {
|
||||
|
||||
@Inject
|
||||
public BalancePresentation(Balances balances) {
|
||||
balances.getAvailableBalance().addListener((observable, oldValue, newValue) -> {
|
||||
UserThread.execute(() -> availableBalance.set(HavenoUtils.formatXmr(newValue, true)));
|
||||
});
|
||||
balances.getPendingBalance().addListener((observable, oldValue, newValue) -> {
|
||||
UserThread.execute(() -> pendingBalance.set(HavenoUtils.formatXmr(newValue, true)));
|
||||
});
|
||||
balances.getReservedBalance().addListener((observable, oldValue, newValue) -> {
|
||||
UserThread.execute(() -> reservedBalance.set(HavenoUtils.formatXmr(newValue, true)));
|
||||
balances.getUpdateCounter().addListener((observable, oldValue, newValue) -> {
|
||||
XmrBalanceInfo info = balances.getBalances();
|
||||
UserThread.execute(() -> {
|
||||
availableBalance.set(HavenoUtils.formatXmr(info.getAvailableBalance(), true));
|
||||
pendingBalance.set(HavenoUtils.formatXmr(info.getPendingBalance(), true));
|
||||
reservedBalance.set(HavenoUtils.formatXmr(info.getReservedBalance(), true));
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -12,29 +12,29 @@ import org.bitcoinj.core.Utils;
|
||||
import haveno.common.crypto.Encryption;
|
||||
|
||||
/**
|
||||
* This utility generates and prints public/private keypairs
|
||||
* This utility generates and prints public/private key-pairs
|
||||
* which can be used to register arbitrators on the network.
|
||||
*/
|
||||
public class GenerateKeypairs {
|
||||
|
||||
public class GenerateKeyPairs {
|
||||
|
||||
public static void main(String[] args) {
|
||||
|
||||
// generate public/private keypairs
|
||||
List<SecretKey> secretKeys = new ArrayList<SecretKey>();
|
||||
|
||||
// generate public/private key-pairs
|
||||
List<SecretKey> secretKeys = new ArrayList<>();
|
||||
for (int i = 0; i < 20; i++) {
|
||||
secretKeys.add(Encryption.generateSecretKey(256));
|
||||
}
|
||||
|
||||
// print keypairs
|
||||
// print key-pairs
|
||||
System.out.println("Private keys:");
|
||||
for (SecretKey sk : secretKeys) {
|
||||
String privKey = Utils.HEX.encode(sk.getEncoded());
|
||||
System.out.println(privKey);
|
||||
String privateKey = Utils.HEX.encode(sk.getEncoded());
|
||||
System.out.println(privateKey);
|
||||
}
|
||||
System.out.println("Corresponding public keys:");
|
||||
for (SecretKey sk : secretKeys) {
|
||||
String privKey = Utils.HEX.encode(sk.getEncoded());
|
||||
ECKey ecKey = ECKey.fromPrivate(new BigInteger(1, Utils.HEX.decode(privKey)));
|
||||
String privateKey = Utils.HEX.encode(sk.getEncoded());
|
||||
ECKey ecKey = ECKey.fromPrivate(new BigInteger(1, Utils.HEX.decode(privateKey)));
|
||||
String pubKey = Utils.HEX.encode(ecKey.getPubKey());
|
||||
System.out.println(pubKey);
|
||||
}
|
@ -37,6 +37,7 @@ package haveno.core.xmr;
|
||||
import com.google.inject.Inject;
|
||||
import haveno.common.ThreadUtils;
|
||||
import haveno.common.UserThread;
|
||||
import haveno.core.api.model.XmrBalanceInfo;
|
||||
import haveno.core.offer.OpenOffer;
|
||||
import haveno.core.offer.OpenOfferManager;
|
||||
import haveno.core.support.dispute.Dispute;
|
||||
@ -51,8 +52,8 @@ import haveno.core.xmr.wallet.XmrWalletService;
|
||||
import java.math.BigInteger;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import javafx.beans.property.ObjectProperty;
|
||||
import javafx.beans.property.SimpleObjectProperty;
|
||||
import javafx.beans.property.IntegerProperty;
|
||||
import javafx.beans.property.SimpleIntegerProperty;
|
||||
import javafx.collections.ListChangeListener;
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
@ -67,15 +68,18 @@ public class Balances {
|
||||
private final RefundManager refundManager;
|
||||
|
||||
@Getter
|
||||
private final ObjectProperty<BigInteger> availableBalance = new SimpleObjectProperty<>();
|
||||
private BigInteger availableBalance;
|
||||
@Getter
|
||||
private final ObjectProperty<BigInteger> pendingBalance = new SimpleObjectProperty<>();
|
||||
private BigInteger pendingBalance;
|
||||
@Getter
|
||||
private final ObjectProperty<BigInteger> reservedOfferBalance = new SimpleObjectProperty<>();
|
||||
private BigInteger reservedOfferBalance;
|
||||
@Getter
|
||||
private final ObjectProperty<BigInteger> reservedTradeBalance = new SimpleObjectProperty<>();
|
||||
private BigInteger reservedTradeBalance;
|
||||
@Getter
|
||||
private final ObjectProperty<BigInteger> reservedBalance = new SimpleObjectProperty<>(); // TODO (woodser): this balance is sum of reserved funds for offers and trade multisigs; remove?
|
||||
private BigInteger reservedBalance; // TODO (woodser): this balance is sum of reserved funds for offers and trade multisigs; remove?
|
||||
|
||||
@Getter
|
||||
private final IntegerProperty updateCounter = new SimpleIntegerProperty(0);
|
||||
|
||||
@Inject
|
||||
public Balances(TradeManager tradeManager,
|
||||
@ -103,52 +107,57 @@ public class Balances {
|
||||
updateBalances();
|
||||
}
|
||||
|
||||
public XmrBalanceInfo getBalances() {
|
||||
synchronized (this) {
|
||||
return new XmrBalanceInfo(availableBalance.longValue() + pendingBalance.longValue(),
|
||||
availableBalance.longValue(),
|
||||
pendingBalance.longValue(),
|
||||
reservedOfferBalance.longValue(),
|
||||
reservedTradeBalance.longValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void updateBalances() {
|
||||
ThreadUtils.submitToPool(() -> doUpdateBalances());
|
||||
}
|
||||
|
||||
private void doUpdateBalances() {
|
||||
synchronized (this) {
|
||||
|
||||
// get wallet balances
|
||||
BigInteger balance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getBalance();
|
||||
availableBalance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getAvailableBalance();
|
||||
|
||||
// get wallet balances
|
||||
BigInteger balance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getWallet().getBalance(0);
|
||||
BigInteger unlockedBalance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getWallet().getUnlockedBalance(0);
|
||||
// calculate pending balance by adding frozen trade balances - reserved amounts
|
||||
pendingBalance = balance.subtract(availableBalance);
|
||||
List<Trade> trades = tradeManager.getTradesStreamWithFundsLockedIn().collect(Collectors.toList());
|
||||
for (Trade trade : trades) {
|
||||
if (trade.getFrozenAmount().equals(new BigInteger("0"))) continue;
|
||||
BigInteger tradeFee = trade instanceof MakerTrade ? trade.getMakerFee() : trade.getTakerFee();
|
||||
pendingBalance = pendingBalance.add(trade.getFrozenAmount()).subtract(trade.getReservedAmount()).subtract(tradeFee).subtract(trade.getSelf().getDepositTxFee());
|
||||
}
|
||||
|
||||
// calculate pending balance by adding frozen trade balances - reserved amounts
|
||||
BigInteger pendingBalance = balance.subtract(unlockedBalance);
|
||||
List<Trade> trades = tradeManager.getTradesStreamWithFundsLockedIn().collect(Collectors.toList());
|
||||
for (Trade trade : trades) {
|
||||
if (trade.getFrozenAmount().equals(new BigInteger("0"))) continue;
|
||||
BigInteger tradeFee = trade instanceof MakerTrade ? trade.getMakerFee() : trade.getTakerFee();
|
||||
pendingBalance = pendingBalance.add(trade.getFrozenAmount()).subtract(trade.getReservedAmount()).subtract(tradeFee).subtract(trade.getSelf().getDepositTxFee());
|
||||
// calculate reserved offer balance
|
||||
reservedOfferBalance = BigInteger.ZERO;
|
||||
if (xmrWalletService.getWallet() != null) {
|
||||
List<MoneroOutputWallet> frozenOutputs = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery().setIsFrozen(true).setIsSpent(false));
|
||||
for (MoneroOutputWallet frozenOutput : frozenOutputs) reservedOfferBalance = reservedOfferBalance.add(frozenOutput.getAmount());
|
||||
}
|
||||
for (Trade trade : trades) {
|
||||
reservedOfferBalance = reservedOfferBalance.subtract(trade.getFrozenAmount()); // subtract frozen trade balances
|
||||
}
|
||||
|
||||
// calculate reserved trade balance
|
||||
reservedTradeBalance = BigInteger.ZERO;
|
||||
for (Trade trade : trades) {
|
||||
reservedTradeBalance = reservedTradeBalance.add(trade.getReservedAmount());
|
||||
}
|
||||
|
||||
// calculate reserved balance
|
||||
reservedBalance = reservedOfferBalance.add(reservedTradeBalance);
|
||||
|
||||
// notify balance update
|
||||
UserThread.execute(() -> updateCounter.set(updateCounter.get() + 1));
|
||||
}
|
||||
|
||||
// calculate reserved offer balance
|
||||
BigInteger reservedOfferBalance = BigInteger.ZERO;
|
||||
if (xmrWalletService.getWallet() != null) {
|
||||
List<MoneroOutputWallet> frozenOutputs = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery().setIsFrozen(true).setIsSpent(false));
|
||||
for (MoneroOutputWallet frozenOutput : frozenOutputs) reservedOfferBalance = reservedOfferBalance.add(frozenOutput.getAmount());
|
||||
}
|
||||
for (Trade trade : trades) {
|
||||
reservedOfferBalance = reservedOfferBalance.subtract(trade.getFrozenAmount()); // subtract frozen trade balances
|
||||
}
|
||||
|
||||
// calculate reserved trade balance
|
||||
BigInteger reservedTradeBalance = BigInteger.ZERO;
|
||||
for (Trade trade : trades) {
|
||||
reservedTradeBalance = reservedTradeBalance.add(trade.getReservedAmount());
|
||||
}
|
||||
|
||||
// set balances
|
||||
setBalances(balance, unlockedBalance, pendingBalance, reservedOfferBalance, reservedTradeBalance);
|
||||
}
|
||||
|
||||
private void setBalances(BigInteger balance, BigInteger unlockedBalance, BigInteger pendingBalance, BigInteger reservedOfferBalance, BigInteger reservedTradeBalance) {
|
||||
UserThread.execute(() -> {
|
||||
this.availableBalance.set(unlockedBalance);
|
||||
this.pendingBalance.set(pendingBalance);
|
||||
this.reservedOfferBalance.set(reservedOfferBalance);
|
||||
this.reservedTradeBalance.set(reservedTradeBalance);
|
||||
this.reservedBalance.set(reservedOfferBalance.add(reservedTradeBalance));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
@ -333,7 +333,9 @@ public class XmrWalletService {
|
||||
Callable<MoneroSyncResult> task = () -> wallet.sync();
|
||||
Future<MoneroSyncResult> future = syncWalletThreadPool.submit(task);
|
||||
try {
|
||||
return future.get();
|
||||
MoneroSyncResult result = future.get();
|
||||
wallet.getTxs(); // TODO: this is necessary to sync from pool, otherwise balance can be incorrect
|
||||
return result;
|
||||
} catch (Exception e) {
|
||||
throw new MoneroError(e.getMessage());
|
||||
}
|
||||
@ -893,7 +895,7 @@ public class XmrWalletService {
|
||||
}
|
||||
|
||||
// register internal listener to notify external listeners
|
||||
wallet.addListener(new XmrWalletListener());
|
||||
wallet.addListener(new XmrWalletListener()); // TODO: initial snapshot calls getTxs() which updates balance after returning but will not announce change
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -140,11 +140,7 @@ class GrpcOffersService extends OffersImplBase {
|
||||
@Override
|
||||
public void postOffer(PostOfferRequest req,
|
||||
StreamObserver<PostOfferReply> responseObserver) {
|
||||
GrpcErrorMessageHandler errorMessageHandler =
|
||||
new GrpcErrorMessageHandler(getPostOfferMethod().getFullMethodName(),
|
||||
responseObserver,
|
||||
exceptionHandler,
|
||||
log);
|
||||
GrpcErrorMessageHandler errorMessageHandler = new GrpcErrorMessageHandler(getPostOfferMethod().getFullMethodName(), responseObserver, exceptionHandler, log);
|
||||
try {
|
||||
coreApi.postOffer(
|
||||
req.getCurrencyCode(),
|
||||
@ -170,8 +166,7 @@ class GrpcOffersService extends OffersImplBase {
|
||||
responseObserver.onCompleted();
|
||||
},
|
||||
errorMessage -> {
|
||||
if (!errorMessageHandler.isErrorHandled())
|
||||
errorMessageHandler.handleErrorMessage(errorMessage);
|
||||
if (!errorMessageHandler.isErrorHandled()) errorMessageHandler.handleErrorMessage(errorMessage);
|
||||
});
|
||||
} catch (Throwable cause) {
|
||||
exceptionHandler.handleException(log, cause, responseObserver);
|
||||
@ -181,11 +176,15 @@ class GrpcOffersService extends OffersImplBase {
|
||||
@Override
|
||||
public void cancelOffer(CancelOfferRequest req,
|
||||
StreamObserver<CancelOfferReply> responseObserver) {
|
||||
GrpcErrorMessageHandler errorMessageHandler = new GrpcErrorMessageHandler(getCancelOfferMethod().getFullMethodName(), responseObserver, exceptionHandler, log);
|
||||
try {
|
||||
coreApi.cancelOffer(req.getId());
|
||||
var reply = CancelOfferReply.newBuilder().build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
coreApi.cancelOffer(req.getId(), () -> {
|
||||
var reply = CancelOfferReply.newBuilder().build();
|
||||
responseObserver.onNext(reply);
|
||||
responseObserver.onCompleted();
|
||||
}, errorMessage -> {
|
||||
if (!errorMessageHandler.isErrorHandled()) errorMessageHandler.handleErrorMessage(errorMessage);
|
||||
});
|
||||
} catch (Throwable cause) {
|
||||
exceptionHandler.handleException(log, cause, responseObserver);
|
||||
}
|
||||
|
@ -236,203 +236,44 @@
|
||||
<sha256 value="6306d89cfdb12bd0b6436390de71cef31879985da10d071a3bdad56bf287bbbb" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.netlayer" name="tor" version="6797461310f077bbea4f43a3a509c077b0ed8c34">
|
||||
<artifact name="tor-6797461310f077bbea4f43a3a509c077b0ed8c34.jar">
|
||||
<sha256 value="1536211d3f204059e2ad49c136978b36ebaa19e62103fcd46dcb926842fa0718" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-6797461310f077bbea4f43a3a509c077b0ed8c34.pom">
|
||||
<sha256 value="7a0ccbecf1471f6be02fb034c006e36b7a6fd249544521c653fed09fbbcec0b1" origin="Generated by Gradle"/>
|
||||
<component group="com.github.bisq-network.netlayer" name="tor" version="2b459dc">
|
||||
<artifact name="tor-2b459dc.jar">
|
||||
<sha256 value="d8aba69568795826bd1139b6854b479d9af9fc945eccf2b15d7f9ecb304c5cc4" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.netlayer" name="tor" version="8db4a13">
|
||||
<artifact name="tor-8db4a13.jar">
|
||||
<sha256 value="37198bc56e8fe112f8c80441544a2b9731929dae586bda841a4a926fdc04f457" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-8db4a13.pom">
|
||||
<sha256 value="d1cb5d57710c43642771681d8b1c9039c722fb949bdc5a2022389f5a81501f42" origin="Generated by Gradle"/>
|
||||
<component group="com.github.bisq-network.netlayer" name="tor.external" version="2b459dc">
|
||||
<artifact name="tor.external-2b459dc.jar">
|
||||
<sha256 value="6646b6ce9312a16f6b4b61ee91512b8725b55a2f7204aec29f64974207fd5015" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.netlayer" name="tor.external" version="0.7.2">
|
||||
<artifact name="tor.external-0.7.2.jar">
|
||||
<sha256 value="45daf9b30f753c49b62cf56226539e824886ce1ff430e03dbef1bddff919cbfc" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor.external-0.7.2.pom">
|
||||
<sha256 value="605e15f473aa7163c4dfa75b0fa17a96466d24c6e3d7a66925b29aadde98dfb4" origin="Generated by Gradle"/>
|
||||
<component group="com.github.bisq-network.netlayer" name="tor.native" version="2b459dc">
|
||||
<artifact name="tor.native-2b459dc.jar">
|
||||
<sha256 value="dc5850e232f2c579d948213a3ea1ce536f56bcc49045a43d3bc63f1e065f1c94" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.netlayer" name="tor.external" version="6797461310f077bbea4f43a3a509c077b0ed8c34">
|
||||
<artifact name="tor.external-6797461310f077bbea4f43a3a509c077b0ed8c34.jar">
|
||||
<sha256 value="d79dee1380fcc912dd9f321e6689b99129a90c6b30085b3f86a0b81830ecee71" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor.external-6797461310f077bbea4f43a3a509c077b0ed8c34.pom">
|
||||
<sha256 value="949ab51a912ba5c126ffda083da2f0366bc9eda36afc5358183e040fee24d86f" origin="Generated by Gradle"/>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-geoip" version="580d31bdcf1fabccd38456aa084044064d89d5c1">
|
||||
<artifact name="tor-binary-geoip-580d31bdcf1fabccd38456aa084044064d89d5c1.jar">
|
||||
<sha256 value="5a1795e95128e8c6fb3381d1c31ac39f2ec4e4fc3a0262f3f9ac3c7987e0c87e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.netlayer" name="tor.external" version="8db4a13">
|
||||
<artifact name="tor.external-8db4a13.jar">
|
||||
<sha256 value="e1d6b8fe73891207701c6b14317be789fd4acd25f7b499425d2471598d9a22ac" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor.external-8db4a13.pom">
|
||||
<sha256 value="11918499210e0c12e9d517596eedb34b897021686cf8a1efd8ea87ae3b7e184d" origin="Generated by Gradle"/>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-linux32" version="580d31bdcf1fabccd38456aa084044064d89d5c1">
|
||||
<artifact name="tor-binary-linux32-580d31bdcf1fabccd38456aa084044064d89d5c1.jar">
|
||||
<sha256 value="2516ce5549ef5687ef7f855db5940574fc9232ff3ba531fbc216275b8d51ae85" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.netlayer" name="tor.native" version="0.7.2">
|
||||
<artifact name="tor.native-0.7.2.jar">
|
||||
<sha256 value="ebb37e76fa14461be1ab2750daa3f8e5b78c8ff0d2adb72832ca0d38a1fb8f0d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor.native-0.7.2.pom">
|
||||
<sha256 value="021ab6d438023653afee96c0fab1262eed6b7522fce76e114593d55e6d7d9928" origin="Generated by Gradle"/>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-linux64" version="580d31bdcf1fabccd38456aa084044064d89d5c1">
|
||||
<artifact name="tor-binary-linux64-580d31bdcf1fabccd38456aa084044064d89d5c1.jar">
|
||||
<sha256 value="afc7ad5e1bc57e73aae55d9b022ff63f41f7c73a9a7603d4c24975288432daa1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.netlayer" name="tor.native" version="6797461310f077bbea4f43a3a509c077b0ed8c34">
|
||||
<artifact name="tor.native-6797461310f077bbea4f43a3a509c077b0ed8c34.jar">
|
||||
<sha256 value="7ab70a9948fffea33da9fee161c5783a74aeb1531e3fda09995c47bb5e2de0f5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor.native-6797461310f077bbea4f43a3a509c077b0ed8c34.pom">
|
||||
<sha256 value="17ba4bb22d00441e286dde286045d68190003e849f49871bdac96a5b41478533" origin="Generated by Gradle"/>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-macos" version="580d31bdcf1fabccd38456aa084044064d89d5c1">
|
||||
<artifact name="tor-binary-macos-580d31bdcf1fabccd38456aa084044064d89d5c1.jar">
|
||||
<sha256 value="5bfb2eaf7efe5d280d6b68e222c910cc6ae2a925e3d06fa35c6b5295ebf94651" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.netlayer" name="tor.native" version="8db4a13">
|
||||
<artifact name="tor.native-8db4a13.jar">
|
||||
<sha256 value="aa3edf9c27071fdc2b7d55b00dbc7c6cd5dc9aa9f87aafa4be0805f818a466be" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor.native-8db4a13.pom">
|
||||
<sha256 value="13e497b9fa97fc994e907aaad69ed81c5433380887a8ac7237bc18e8da48683b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary" version="6d1fd95">
|
||||
<artifact name="tor-binary-6d1fd95.pom">
|
||||
<sha256 value="ac20fe51c6473ecaa440458c8255294ff2b30cfed45918527742315bb3d74a86" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary" version="787183b147286d783a6392bb9ffcd8ba920d6fff">
|
||||
<artifact name="tor-binary-787183b147286d783a6392bb9ffcd8ba920d6fff.pom">
|
||||
<sha256 value="4e127121fefb50fed62a83d5fbd31064b9f16f1a528571675e0ec3042376dab3" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary" version="b9c6227">
|
||||
<artifact name="tor-binary-b9c6227.pom">
|
||||
<sha256 value="f1ef0c2b2a1df585f057b96b62b05e2e7d7953353b64e29ac798810ff2919b42" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-geoip" version="6d1fd95">
|
||||
<artifact name="tor-binary-geoip-6d1fd95.jar">
|
||||
<sha256 value="5a55df3a5bed0aa57165e9bae9ecda8b14d5e85b97dd1a266fa77602fbdaec54" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-geoip-6d1fd95.pom">
|
||||
<sha256 value="14fbcfc4de8e07b8c5bf7c1e279704905cc98795e7460cf558288ce1eaaf1927" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-geoip" version="787183b147286d783a6392bb9ffcd8ba920d6fff">
|
||||
<artifact name="tor-binary-geoip-787183b147286d783a6392bb9ffcd8ba920d6fff.jar">
|
||||
<sha256 value="e1f0a9708ad5fc5373db84fb14570d36eff842eb71e99c0930db64617604a2bf" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-geoip-787183b147286d783a6392bb9ffcd8ba920d6fff.pom">
|
||||
<sha256 value="a6f45951fb73b57c9ac37d389f5adcfecde5f06c2e50d1a8381e640261e5a6b5" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-geoip" version="b9c6227">
|
||||
<artifact name="tor-binary-geoip-b9c6227.jar">
|
||||
<sha256 value="cfefbf2d8591b5dd321ec17a02a3682d21763cf50525fa5496c9ec8968413c4e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-geoip-b9c6227.pom">
|
||||
<sha256 value="197d034216b332fcfaa7111442ac4a23bddc60fb71fefba1c736fe9844c1001b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-linux32" version="6d1fd95">
|
||||
<artifact name="tor-binary-linux32-6d1fd95.jar">
|
||||
<sha256 value="fe8b0ddb1c109b453adf9b055e067be04b6ca4cda9d2b33c875b99d2092f0eae" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-linux32-6d1fd95.pom">
|
||||
<sha256 value="0ae70e17d9566c88204d02de32c1646d672e78711da97124d23fd397a1da9d13" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-linux32" version="787183b147286d783a6392bb9ffcd8ba920d6fff">
|
||||
<artifact name="tor-binary-linux32-787183b147286d783a6392bb9ffcd8ba920d6fff.jar">
|
||||
<sha256 value="b1e8b3f83b08c839a4282a32ef75be69db3ec3061b3472e367606782b861cb55" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-linux32-787183b147286d783a6392bb9ffcd8ba920d6fff.pom">
|
||||
<sha256 value="4166e686e18b875fe09e34e19ea294a5841b9d0354072e60fb7779b813c9ff45" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-linux32" version="b9c6227">
|
||||
<artifact name="tor-binary-linux32-b9c6227.jar">
|
||||
<sha256 value="b82b6595f78ef52a44e58000fe5d7f679681739451872f5bbd123e5dbd2af050" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-linux32-b9c6227.pom">
|
||||
<sha256 value="a01902c476556a0529413b0f3810e954a5eb8a7cdc1a9cc604ec2d24ceca91ce" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-linux64" version="6d1fd95">
|
||||
<artifact name="tor-binary-linux64-6d1fd95.jar">
|
||||
<sha256 value="7f58d31dd684b2e361e2980ba23922cadd5d9d8f8dbab9b3a2c6737741b21f7e" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-linux64-6d1fd95.pom">
|
||||
<sha256 value="48f0435519eae6ff6af88656a64502320befc392b2c5d59ac2fb47412c9ba52d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-linux64" version="787183b147286d783a6392bb9ffcd8ba920d6fff">
|
||||
<artifact name="tor-binary-linux64-787183b147286d783a6392bb9ffcd8ba920d6fff.jar">
|
||||
<sha256 value="4e956beca59ffce771d0fa40a0b20181c3531d278ff0f1d474a378c0fa9bc76b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-linux64-787183b147286d783a6392bb9ffcd8ba920d6fff.pom">
|
||||
<sha256 value="1f98896ea3822644bebd3c3278497684504e291df03531bf72f072ab2d6b44a1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-linux64" version="b9c6227">
|
||||
<artifact name="tor-binary-linux64-b9c6227.jar">
|
||||
<sha256 value="d5c1d54b2c2323ac1124435be633c7822a28e6fe9160486d03102cc2b444df24" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-linux64-b9c6227.pom">
|
||||
<sha256 value="ee305ee12585057bcce380710e4a5ae3a3ed43e1701f5e565f15b75854e3e715" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-macos" version="6d1fd95">
|
||||
<artifact name="tor-binary-macos-6d1fd95.jar">
|
||||
<sha256 value="a23802ff66d4ac01366ebe712879e2f51df960572dc34db269588da87453a70d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-macos-6d1fd95.pom">
|
||||
<sha256 value="0c1b6633882ca625f50c78b960714baa81ef286b5dfc26886145f7960feab738" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-macos" version="787183b147286d783a6392bb9ffcd8ba920d6fff">
|
||||
<artifact name="tor-binary-macos-787183b147286d783a6392bb9ffcd8ba920d6fff.jar">
|
||||
<sha256 value="9b4114bd7699951dc6b04a10398bd6acc17a966db48c7fa79e302cc0b6fe7ecf" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-macos-787183b147286d783a6392bb9ffcd8ba920d6fff.pom">
|
||||
<sha256 value="6b8f372ac6dc38c06575612cc00f5e6d804d80dfe761f8ca0d1aa4562da9d2dd" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-macos" version="b9c6227">
|
||||
<artifact name="tor-binary-macos-b9c6227.jar">
|
||||
<sha256 value="6216d66241e020fec1a55648d7176ef64959e094c493df8f49e7e8e8f62fe1e1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-macos-b9c6227.pom">
|
||||
<sha256 value="143a9bfc539101d8293b7d151d6a952135fa5ad76d752639d2ed72fb9c9c494d" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-windows" version="6d1fd95">
|
||||
<artifact name="tor-binary-windows-6d1fd95.jar">
|
||||
<sha256 value="8e0dee7429228aa0c9f7a36f40f303a016ed8dfb40fea77382f7076c13fc27f1" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-windows-6d1fd95.pom">
|
||||
<sha256 value="08dd80bd3c5e6c6b031ea3e28d8819adec875593a8f1fb9101c0f952f8307b80" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-windows" version="787183b147286d783a6392bb9ffcd8ba920d6fff">
|
||||
<artifact name="tor-binary-windows-787183b147286d783a6392bb9ffcd8ba920d6fff.jar">
|
||||
<sha256 value="eebd616315cb7263f07837d5a95c96fdcd627f7fcbfc69e9ca7b840495895197" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-windows-787183b147286d783a6392bb9ffcd8ba920d6fff.pom">
|
||||
<sha256 value="fa1cc1b84e4705b9102f269a3ec2602e00ed8dae035d99f60a70194551dc8e08" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-windows" version="b9c6227">
|
||||
<artifact name="tor-binary-windows-b9c6227.jar">
|
||||
<sha256 value="28a1031d7610863f774eedbd00b83b06b132781c31077b805033299de3e3a263" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
<artifact name="tor-binary-windows-b9c6227.pom">
|
||||
<sha256 value="e067cfa37ee54a2f31d05391319e46484366fda4ef0ee28c3483194b02025e8f" origin="Generated by Gradle"/>
|
||||
<component group="com.github.bisq-network.tor-binary" name="tor-binary-windows" version="580d31bdcf1fabccd38456aa084044064d89d5c1">
|
||||
<artifact name="tor-binary-windows-580d31bdcf1fabccd38456aa084044064d89d5c1.jar">
|
||||
<sha256 value="b5fbe9f9e2681b0cfdd0d8a26c7b216c38acfea74fe2103633fe7e81b6cc4bf7" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="com.github.johnrengelman" name="shadow" version="8.1.1">
|
||||
@ -1005,9 +846,9 @@
|
||||
<sha256 value="c92e2ca40a3f2474d61e56831aeb379cf8ae3dddeea61b4a828cee2d99f71f38" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.github.woodser" name="monero-java" version="0.8.10">
|
||||
<artifact name="monero-java-0.8.10.jar">
|
||||
<sha256 value="3ea921cb8122e9be4401479e7040055063b2132e8210f7129117b8b10472f773" origin="Generated by Gradle"/>
|
||||
<component group="io.github.woodser" name="monero-java" version="0.8.11">
|
||||
<artifact name="monero-java-0.8.11.jar">
|
||||
<sha256 value="37c125a31463c44e43452bc3e18e74a05b65d1fbebb11adc5131521b29b48a6b" origin="Generated by Gradle"/>
|
||||
</artifact>
|
||||
</component>
|
||||
<component group="io.grpc" name="grpc-api" version="1.42.1">
|
||||
|
@ -47,6 +47,7 @@ public class NetworkNodeProvider implements Provider<NetworkNode> {
|
||||
@Named(Config.TOR_DIR) File torDir,
|
||||
@Nullable @Named(Config.TORRC_FILE) File torrcFile,
|
||||
@Named(Config.TORRC_OPTIONS) String torrcOptions,
|
||||
@Named(Config.TOR_CONTROL_HOST) String controlHost,
|
||||
@Named(Config.TOR_CONTROL_PORT) int controlPort,
|
||||
@Named(Config.TOR_CONTROL_PASSWORD) String password,
|
||||
@Nullable @Named(Config.TOR_CONTROL_COOKIE_FILE) File cookieFile,
|
||||
@ -59,11 +60,12 @@ public class NetworkNodeProvider implements Provider<NetworkNode> {
|
||||
torDir,
|
||||
torrcFile,
|
||||
torrcOptions,
|
||||
controlHost,
|
||||
controlPort,
|
||||
password,
|
||||
cookieFile,
|
||||
useSafeCookieAuthentication);
|
||||
networkNode = new TorNetworkNode(port, networkProtoResolver, streamIsolation, torMode, banFilter, maxConnections);
|
||||
networkNode = new TorNetworkNode(port, networkProtoResolver, streamIsolation, torMode, banFilter, maxConnections, controlHost);
|
||||
}
|
||||
}
|
||||
|
||||
@ -71,12 +73,13 @@ public class NetworkNodeProvider implements Provider<NetworkNode> {
|
||||
File torDir,
|
||||
@Nullable File torrcFile,
|
||||
String torrcOptions,
|
||||
String controlHost,
|
||||
int controlPort,
|
||||
String password,
|
||||
@Nullable File cookieFile,
|
||||
boolean useSafeCookieAuthentication) {
|
||||
return controlPort != Config.UNSPECIFIED_PORT ?
|
||||
new RunningTor(torDir, controlPort, password, cookieFile, useSafeCookieAuthentication) :
|
||||
new RunningTor(torDir, controlHost, controlPort, password, cookieFile, useSafeCookieAuthentication) :
|
||||
new NewTor(torDir, torrcFile, torrcOptions, bridgeAddressProvider);
|
||||
}
|
||||
|
||||
|
@ -19,8 +19,26 @@ package haveno.network.p2p;
|
||||
|
||||
import com.google.inject.Singleton;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import static com.google.inject.name.Names.named;
|
||||
import static com.google.inject.util.Providers.of;
|
||||
import haveno.common.app.AppModule;
|
||||
import haveno.common.config.Config;
|
||||
import static haveno.common.config.Config.BAN_LIST;
|
||||
import static haveno.common.config.Config.MAX_CONNECTIONS;
|
||||
import static haveno.common.config.Config.NODE_PORT;
|
||||
import static haveno.common.config.Config.REPUBLISH_MAILBOX_ENTRIES;
|
||||
import static haveno.common.config.Config.SOCKS_5_PROXY_HTTP_ADDRESS;
|
||||
import static haveno.common.config.Config.SOCKS_5_PROXY_XMR_ADDRESS;
|
||||
import static haveno.common.config.Config.TORRC_FILE;
|
||||
import static haveno.common.config.Config.TORRC_OPTIONS;
|
||||
import static haveno.common.config.Config.TOR_CONTROL_COOKIE_FILE;
|
||||
import static haveno.common.config.Config.TOR_CONTROL_HOST;
|
||||
import static haveno.common.config.Config.TOR_CONTROL_PASSWORD;
|
||||
import static haveno.common.config.Config.TOR_CONTROL_PORT;
|
||||
import static haveno.common.config.Config.TOR_CONTROL_USE_SAFE_COOKIE_AUTH;
|
||||
import static haveno.common.config.Config.TOR_DIR;
|
||||
import static haveno.common.config.Config.TOR_STREAM_ISOLATION;
|
||||
import static haveno.common.config.Config.USE_LOCALHOST_FOR_P2P;
|
||||
import haveno.network.Socks5ProxyProvider;
|
||||
import haveno.network.http.HttpClient;
|
||||
import haveno.network.http.HttpClientImpl;
|
||||
@ -35,29 +53,10 @@ import haveno.network.p2p.storage.P2PDataStorage;
|
||||
import haveno.network.p2p.storage.persistence.AppendOnlyDataStoreService;
|
||||
import haveno.network.p2p.storage.persistence.ProtectedDataStoreService;
|
||||
import haveno.network.p2p.storage.persistence.ResourceDataStoreService;
|
||||
|
||||
import java.io.File;
|
||||
import java.time.Clock;
|
||||
import java.util.List;
|
||||
|
||||
import static com.google.inject.name.Names.named;
|
||||
import static com.google.inject.util.Providers.of;
|
||||
import static haveno.common.config.Config.BAN_LIST;
|
||||
import static haveno.common.config.Config.MAX_CONNECTIONS;
|
||||
import static haveno.common.config.Config.NODE_PORT;
|
||||
import static haveno.common.config.Config.REPUBLISH_MAILBOX_ENTRIES;
|
||||
import static haveno.common.config.Config.SOCKS_5_PROXY_XMR_ADDRESS;
|
||||
import static haveno.common.config.Config.SOCKS_5_PROXY_HTTP_ADDRESS;
|
||||
import static haveno.common.config.Config.TORRC_FILE;
|
||||
import static haveno.common.config.Config.TORRC_OPTIONS;
|
||||
import static haveno.common.config.Config.TOR_CONTROL_COOKIE_FILE;
|
||||
import static haveno.common.config.Config.TOR_CONTROL_PASSWORD;
|
||||
import static haveno.common.config.Config.TOR_CONTROL_PORT;
|
||||
import static haveno.common.config.Config.TOR_CONTROL_USE_SAFE_COOKIE_AUTH;
|
||||
import static haveno.common.config.Config.TOR_DIR;
|
||||
import static haveno.common.config.Config.TOR_STREAM_ISOLATION;
|
||||
import static haveno.common.config.Config.USE_LOCALHOST_FOR_P2P;
|
||||
|
||||
public class P2PModule extends AppModule {
|
||||
|
||||
public P2PModule(Config config) {
|
||||
@ -96,6 +95,7 @@ public class P2PModule extends AppModule {
|
||||
bindConstant().annotatedWith(named(SOCKS_5_PROXY_HTTP_ADDRESS)).to(config.socks5ProxyHttpAddress);
|
||||
bind(File.class).annotatedWith(named(TORRC_FILE)).toProvider(of(config.torrcFile)); // allow null value
|
||||
bindConstant().annotatedWith(named(TORRC_OPTIONS)).to(config.torrcOptions);
|
||||
bindConstant().annotatedWith(named(TOR_CONTROL_HOST)).to(config.torControlHost);
|
||||
bindConstant().annotatedWith(named(TOR_CONTROL_PORT)).to(config.torControlPort);
|
||||
bindConstant().annotatedWith(named(TOR_CONTROL_PASSWORD)).to(config.torControlPassword);
|
||||
bind(File.class).annotatedWith(named(TOR_CONTROL_COOKIE_FILE)).toProvider(of(config.torControlCookieFile));
|
||||
|
@ -17,15 +17,13 @@
|
||||
|
||||
package haveno.network.p2p.network;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Date;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.berndpruenster.netlayer.tor.ExternalTor;
|
||||
import org.berndpruenster.netlayer.tor.Tor;
|
||||
import org.berndpruenster.netlayer.tor.TorCtlException;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* This class creates a brand new instance of the Tor onion router.
|
||||
*
|
||||
@ -39,15 +37,21 @@ import java.util.Date;
|
||||
@Slf4j
|
||||
public class RunningTor extends TorMode {
|
||||
|
||||
private final String controlHost;
|
||||
private final int controlPort;
|
||||
private final String password;
|
||||
private final File cookieFile;
|
||||
private final boolean useSafeCookieAuthentication;
|
||||
|
||||
|
||||
public RunningTor(final File torDir, final int controlPort, final String password, final File cookieFile,
|
||||
final boolean useSafeCookieAuthentication) {
|
||||
public RunningTor(final File torDir,
|
||||
final String controlHost,
|
||||
final int controlPort,
|
||||
final String password,
|
||||
final File cookieFile,
|
||||
final boolean useSafeCookieAuthentication) {
|
||||
super(torDir);
|
||||
this.controlHost = controlHost;
|
||||
this.controlPort = controlPort;
|
||||
this.password = password;
|
||||
this.cookieFile = cookieFile;
|
||||
@ -55,18 +59,18 @@ public class RunningTor extends TorMode {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Tor getTor() throws IOException, TorCtlException {
|
||||
public Tor getTor() throws TorCtlException {
|
||||
long ts1 = new Date().getTime();
|
||||
|
||||
log.info("Connecting to running tor");
|
||||
|
||||
Tor result;
|
||||
if (!password.isEmpty())
|
||||
result = new ExternalTor(controlPort, password);
|
||||
result = new ExternalTor(controlHost, controlPort, password);
|
||||
else if (cookieFile != null && cookieFile.exists())
|
||||
result = new ExternalTor(controlPort, cookieFile, useSafeCookieAuthentication);
|
||||
result = new ExternalTor(controlHost, controlPort, cookieFile, useSafeCookieAuthentication);
|
||||
else
|
||||
result = new ExternalTor(controlPort);
|
||||
result = new ExternalTor(controlHost, controlPort);
|
||||
|
||||
log.info(
|
||||
"\n################################################################\n"
|
||||
|
@ -51,6 +51,8 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||
public class TorNetworkNode extends NetworkNode {
|
||||
private static final long SHUT_DOWN_TIMEOUT = 2;
|
||||
|
||||
private final String torControlHost;
|
||||
|
||||
private HiddenServiceSocket hiddenServiceSocket;
|
||||
private Timer shutDownTimeoutTimer;
|
||||
private Tor tor;
|
||||
@ -70,10 +72,11 @@ public class TorNetworkNode extends NetworkNode {
|
||||
boolean useStreamIsolation,
|
||||
TorMode torMode,
|
||||
@Nullable BanFilter banFilter,
|
||||
int maxConnections) {
|
||||
int maxConnections, String torControlHost) {
|
||||
super(servicePort, networkProtoResolver, banFilter, maxConnections);
|
||||
this.torMode = torMode;
|
||||
this.streamIsolation = useStreamIsolation;
|
||||
this.torControlHost = torControlHost;
|
||||
|
||||
executor = SingleThreadExecutorUtils.getSingleThreadExecutor("StartTor");
|
||||
}
|
||||
@ -97,7 +100,7 @@ public class TorNetworkNode extends NetworkNode {
|
||||
checkArgument(peerNodeAddress.getHostName().endsWith(".onion"), "PeerAddress is not an onion address");
|
||||
// If streamId is null stream isolation gets deactivated.
|
||||
// Hidden services use stream isolation by default, so we pass null.
|
||||
return new TorSocket(peerNodeAddress.getHostName(), peerNodeAddress.getPort(), null);
|
||||
return new TorSocket(peerNodeAddress.getHostName(), peerNodeAddress.getPort(), torControlHost, null);
|
||||
}
|
||||
|
||||
public Socks5Proxy getSocksProxy() {
|
||||
@ -111,7 +114,7 @@ public class TorNetworkNode extends NetworkNode {
|
||||
|
||||
if (socksProxy == null || streamIsolation) {
|
||||
tor = Tor.getDefault();
|
||||
socksProxy = tor != null ? tor.getProxy(stream) : null;
|
||||
socksProxy = tor != null ? tor.getProxy(torControlHost, stream) : null;
|
||||
}
|
||||
return socksProxy;
|
||||
} catch (Throwable t) {
|
||||
|
@ -51,7 +51,7 @@ public class TorNetworkNodeTest {
|
||||
latch = new CountDownLatch(1);
|
||||
int port = 9001;
|
||||
TorNetworkNode node1 = new TorNetworkNode(port, TestUtils.getNetworkProtoResolver(), false,
|
||||
new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null, 12);
|
||||
new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null, 12, "127.0.0.1");
|
||||
node1.start(new SetupListener() {
|
||||
@Override
|
||||
public void onTorNodeReady() {
|
||||
@ -78,7 +78,7 @@ public class TorNetworkNodeTest {
|
||||
latch = new CountDownLatch(1);
|
||||
int port2 = 9002;
|
||||
TorNetworkNode node2 = new TorNetworkNode(port2, TestUtils.getNetworkProtoResolver(), false,
|
||||
new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null, 12);
|
||||
new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null, 12, "127.0.0.1");
|
||||
node2.start(new SetupListener() {
|
||||
@Override
|
||||
public void onTorNodeReady() {
|
||||
@ -136,7 +136,7 @@ public class TorNetworkNodeTest {
|
||||
latch = new CountDownLatch(2);
|
||||
int port = 9001;
|
||||
TorNetworkNode node1 = new TorNetworkNode(port, TestUtils.getNetworkProtoResolver(), false,
|
||||
new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null, 12);
|
||||
new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null, 12, "127.0.0.1");
|
||||
node1.start(new SetupListener() {
|
||||
@Override
|
||||
public void onTorNodeReady() {
|
||||
@ -162,7 +162,7 @@ public class TorNetworkNodeTest {
|
||||
|
||||
int port2 = 9002;
|
||||
TorNetworkNode node2 = new TorNetworkNode(port2, TestUtils.getNetworkProtoResolver(), false,
|
||||
new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null, 12);
|
||||
new NewTor(new File("torNode_" + port), null, "", this::getBridgeAddresses), null, 12, "127.0.0.1");
|
||||
node2.start(new SetupListener() {
|
||||
@Override
|
||||
public void onTorNodeReady() {
|
||||
|
@ -1,7 +1,7 @@
|
||||
# docker run -it -p 9050 -p 2002 --restart-policy unless-stopped --name haveno-seednode haveno-seednode
|
||||
# TODO: image very heavy, but it's hard to significantly reduce the size without bins
|
||||
|
||||
FROM openjdk:11
|
||||
FROM openjdk:21-jdk-bullseye
|
||||
|
||||
RUN set -ex && \
|
||||
apt update && \
|
||||
|
@ -1,11 +1,11 @@
|
||||
# configuration for haveno service
|
||||
# install in /etc/default/haveno.env
|
||||
|
||||
# java home, set to openjdk 10
|
||||
JAVA_HOME=/usr/lib/jvm/openjdk-10.0.2
|
||||
# java home, set to latest openjdk 21 from os repository
|
||||
JAVA_HOME=/usr/lib/jvm/openjdk-21
|
||||
|
||||
# java memory and remote management options
|
||||
JAVA_OPTS="-Xms4096M -Xmx4096M"
|
||||
JAVA_OPTS="-Xms4096M -Xmx4096M" -XX:+ExitOnOutOfMemoryError"
|
||||
|
||||
# use external tor (change to -1 for internal tor binary)
|
||||
HAVENO_EXTERNAL_TOR_PORT=9051
|
||||
@ -28,7 +28,7 @@ BITCOIN_RPC_BLOCKNOTIFY_PORT=5120
|
||||
HAVENO_HOME=__HAVENO_HOME__
|
||||
HAVENO_APP_NAME=haveno-seednode
|
||||
HAVENO_ENTRYPOINT=haveno-seednode
|
||||
HAVENO_BASE_CURRENCY=btc_mainnet
|
||||
HAVENO_BASE_CURRENCY=xmr_mainnet
|
||||
|
||||
# haveno node settings
|
||||
HAVENO_NODE_PORT=8000
|
||||
|
@ -7,22 +7,21 @@ echo "[*] Haveno Seednode installation script"
|
||||
|
||||
ROOT_USER=root
|
||||
ROOT_GROUP=root
|
||||
ROOT_PKG="build-essential libtool autotools-dev automake pkg-config bsdmainutils python3 git vim screen ufw"
|
||||
ROOT_PKG="build-essential libtool autotools-dev automake pkg-config bsdmainutils python3 git vim screen ufw openjdk-21-jdk"
|
||||
ROOT_HOME=/root
|
||||
|
||||
SYSTEMD_SERVICE_HOME=/etc/systemd/system
|
||||
SYSTEMD_ENV_HOME=/etc/default
|
||||
|
||||
HAVENO_REPO_URL=https://github.com/bisq-network/bisq
|
||||
HAVENO_REPO_URL=https://github.com/haveno-dex/haveno
|
||||
HAVENO_REPO_NAME=haveno
|
||||
HAVENO_REPO_TAG=master
|
||||
HAVENO_LATEST_RELEASE=$(curl -s https://api.github.com/repos/bisq-network/bisq/releases/latest|grep tag_name|head -1|cut -d '"' -f4)
|
||||
HAVENO_LATEST_RELEASE=$(curl -s https://api.github.com/repos/haveno-dex/haveno/releases/latest|grep tag_name|head -1|cut -d '"' -f4)
|
||||
HAVENO_HOME=/haveno
|
||||
HAVENO_USER=haveno
|
||||
|
||||
# by default, this script will build and setup bitcoin fullnode
|
||||
# if you want to use an existing bitcoin fullnode, see next section
|
||||
BITCOIN_INSTALL=true
|
||||
# by default, this script will not build and setup bitcoin full-node
|
||||
BITCOIN_INSTALL=false
|
||||
BITCOIN_REPO_URL=https://github.com/bitcoin/bitcoin
|
||||
BITCOIN_REPO_NAME=bitcoin
|
||||
BITCOIN_REPO_TAG=$(curl -s https://api.github.com/repos/bitcoin/bitcoin/releases/latest|grep tag_name|head -1|cut -d '"' -f4)
|
||||
@ -60,19 +59,13 @@ sudo -H -i -u "${ROOT_USER}" DEBIAN_FRONTEND=noninteractive apt-get upgrade -qq
|
||||
echo "[*] Installing base packages"
|
||||
sudo -H -i -u "${ROOT_USER}" DEBIAN_FRONTEND=noninteractive apt-get install -qq -y ${ROOT_PKG}
|
||||
|
||||
echo "[*] Installing Git LFS"
|
||||
sudo -H -i -u "${ROOT_USER}" apt-get install git-lfs
|
||||
sudo -H -i -u "${ROOT_USER}" git lfs install
|
||||
|
||||
echo "[*] Cloning Haveno repo"
|
||||
sudo -H -i -u "${ROOT_USER}" git config --global advice.detachedHead false
|
||||
sudo -H -i -u "${ROOT_USER}" git clone --branch "${HAVENO_REPO_TAG}" "${HAVENO_REPO_URL}" "${ROOT_HOME}/${HAVENO_REPO_NAME}"
|
||||
|
||||
echo "[*] Installing Tor"
|
||||
sudo -H -i -u "${ROOT_USER}" wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gp
|
||||
g --dearmor | tee /usr/share/keyrings/tor-archive-keyring.gpg >/dev/null
|
||||
sudo -H -i -u "${ROOT_USER}" echo "deb [arch=amd64 signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.o
|
||||
rg/torproject.org focal main" > /etc/apt/sources.list.d/tor.list
|
||||
sudo -H -i -u "${ROOT_USER}" wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | sudo gpg --dearmor | sudo tee /usr/share/keyrings/tor-archive-keyring.gpg >/dev/null
|
||||
echo "deb [arch=amd64 signed-by=/usr/share/keyrings/tor-archive-keyring.gpg] https://deb.torproject.org/torproject.org focal main" | sudo -H -i -u "${ROOT_USER}" tee /etc/apt/sources.list.d/tor.list
|
||||
sudo -H -i -u "${ROOT_USER}" DEBIAN_FRONTEND=noninteractive apt-get update -q
|
||||
sudo -H -i -u "${ROOT_USER}" DEBIAN_FRONTEND=noninteractive apt-get install -qq -y ${TOR_PKG}
|
||||
|
||||
@ -128,17 +121,14 @@ echo "[*] Moving Haveno repo"
|
||||
sudo -H -i -u "${ROOT_USER}" mv "${ROOT_HOME}/${HAVENO_REPO_NAME}" "${HAVENO_HOME}/${HAVENO_REPO_NAME}"
|
||||
sudo -H -i -u "${ROOT_USER}" chown -R "${HAVENO_USER}:${HAVENO_GROUP}" "${HAVENO_HOME}/${HAVENO_REPO_NAME}"
|
||||
|
||||
echo "[*] Installing OpenJDK 10.0.2 from Haveno repo"
|
||||
sudo -H -i -u "${ROOT_USER}" "${HAVENO_HOME}/${HAVENO_REPO_NAME}/scripts/install_java.sh"
|
||||
|
||||
echo "[*] Installing Haveno init script"
|
||||
sudo -H -i -u "${ROOT_USER}" install -c -o "${ROOT_USER}" -g "${ROOT_GROUP}" -m 644 "${HAVENO_HOME}/${HAVENO_REPO_NAME}/seednode/haveno.service" "${SYSTEMD_SERVICE_HOME}/haveno.service"
|
||||
sudo -H -i -u "${ROOT_USER}" install -c -o "${ROOT_USER}" -g "${ROOT_GROUP}" -m 644 "${HAVENO_HOME}/${HAVENO_REPO_NAME}/seednode/haveno-seednode.service" "${SYSTEMD_SERVICE_HOME}/haveno-seednode.service"
|
||||
if [ "${BITCOIN_INSTALL}" = true ];then
|
||||
sudo sed -i -e "s/#Requires=bitcoin.service/Requires=bitcoin.service/" "${SYSTEMD_SERVICE_HOME}/haveno.service"
|
||||
sudo sed -i -e "s/#BindsTo=bitcoin.service/BindsTo=bitcoin.service/" "${SYSTEMD_SERVICE_HOME}/haveno.service"
|
||||
sudo sed -i -e "s/#Requires=bitcoin.service/Requires=bitcoin.service/" "${SYSTEMD_SERVICE_HOME}/haveno-seednode.service"
|
||||
sudo sed -i -e "s/#BindsTo=bitcoin.service/BindsTo=bitcoin.service/" "${SYSTEMD_SERVICE_HOME}/haveno-seednode.service"
|
||||
fi
|
||||
sudo sed -i -e "s/__HAVENO_REPO_NAME__/${HAVENO_REPO_NAME}/" "${SYSTEMD_SERVICE_HOME}/haveno.service"
|
||||
sudo sed -i -e "s!__HAVENO_HOME__!${HAVENO_HOME}!" "${SYSTEMD_SERVICE_HOME}/haveno.service"
|
||||
sudo sed -i -e "s/__HAVENO_REPO_NAME__/${HAVENO_REPO_NAME}/" "${SYSTEMD_SERVICE_HOME}/haveno-seednode.service"
|
||||
sudo sed -i -e "s!__HAVENO_HOME__!${HAVENO_HOME}!" "${SYSTEMD_SERVICE_HOME}/haveno-seednode.service"
|
||||
|
||||
echo "[*] Installing Haveno environment file with Bitcoin RPC credentials"
|
||||
sudo -H -i -u "${ROOT_USER}" install -c -o "${ROOT_USER}" -g "${ROOT_GROUP}" -m 644 "${HAVENO_HOME}/${HAVENO_REPO_NAME}/seednode/haveno.env" "${SYSTEMD_ENV_HOME}/haveno.env"
|
||||
@ -154,16 +144,13 @@ sudo sed -i -e "s!__HAVENO_HOME__!${HAVENO_HOME}!" "${SYSTEMD_ENV_HOME}/haveno.e
|
||||
echo "[*] Checking out Haveno ${HAVENO_LATEST_RELEASE}"
|
||||
sudo -H -i -u "${HAVENO_USER}" sh -c "cd ${HAVENO_HOME}/${HAVENO_REPO_NAME} && git checkout ${HAVENO_LATEST_RELEASE}"
|
||||
|
||||
echo "[*] Performing Git LFS pull"
|
||||
sudo -H -i -u "${HAVENO_USER}" sh -c "cd ${HAVENO_HOME}/${HAVENO_REPO_NAME} && git lfs pull"
|
||||
|
||||
echo "[*] Building Haveno from source"
|
||||
sudo -H -i -u "${HAVENO_USER}" sh -c "cd ${HAVENO_HOME}/${HAVENO_REPO_NAME} && ./gradlew build -x test < /dev/null" # redirect from /dev/null is necessary to workaround gradlew non-interactive shell hanging issue
|
||||
|
||||
echo "[*] Updating systemd daemon configuration"
|
||||
sudo -H -i -u "${ROOT_USER}" systemctl daemon-reload
|
||||
sudo -H -i -u "${ROOT_USER}" systemctl enable tor.service
|
||||
sudo -H -i -u "${ROOT_USER}" systemctl enable haveno.service
|
||||
sudo -H -i -u "${ROOT_USER}" systemctl enable haveno-seednode.service
|
||||
if [ "${BITCOIN_INSTALL}" = true ];then
|
||||
sudo -H -i -u "${ROOT_USER}" systemctl enable bitcoin.service
|
||||
fi
|
||||
@ -185,13 +172,13 @@ fi
|
||||
echo "[*] Adding notes to motd"
|
||||
sudo -H -i -u "${ROOT_USER}" sh -c 'echo " " >> /etc/motd'
|
||||
sudo -H -i -u "${ROOT_USER}" sh -c 'echo "Haveno Seednode instructions:" >> /etc/motd'
|
||||
sudo -H -i -u "${ROOT_USER}" sh -c 'echo "https://github.com/bisq-network/bisq/tree/master/seednode" >> /etc/motd'
|
||||
sudo -H -i -u "${ROOT_USER}" sh -c 'echo "https://github.com/haveno-dex/haveno/tree/master/seednode" >> /etc/motd'
|
||||
sudo -H -i -u "${ROOT_USER}" sh -c 'echo " " >> /etc/motd'
|
||||
sudo -H -i -u "${ROOT_USER}" sh -c 'echo "How to check logs for Haveno-Seednode service:" >> /etc/motd'
|
||||
sudo -H -i -u "${ROOT_USER}" sh -c 'echo "sudo journalctl --no-pager --unit haveno" >> /etc/motd'
|
||||
sudo -H -i -u "${ROOT_USER}" sh -c 'echo "sudo journalctl --no-pager --unit haveno-seednode" >> /etc/motd'
|
||||
sudo -H -i -u "${ROOT_USER}" sh -c 'echo " " >> /etc/motd'
|
||||
sudo -H -i -u "${ROOT_USER}" sh -c 'echo "How to restart Haveno-Seednode service:" >> /etc/motd'
|
||||
sudo -H -i -u "${ROOT_USER}" sh -c 'echo "sudo service haveno restart" >> /etc/motd'
|
||||
sudo -H -i -u "${ROOT_USER}" sh -c 'echo "sudo service haveno-seednode restart" >> /etc/motd'
|
||||
|
||||
echo '[*] Done!'
|
||||
|
||||
|
@ -3,9 +3,9 @@ echo "[*] Uninstalling Bitcoin and Haveno, will delete all data!!"
|
||||
sleep 10
|
||||
sudo rm -rf /root/haveno
|
||||
sudo systemctl stop bitcoin
|
||||
sudo systemctl stop haveno
|
||||
sudo systemctl stop haveno-seednode
|
||||
sudo systemctl disable bitcoin
|
||||
sudo systemctl disable haveno
|
||||
sudo systemctl disable haveno-seednode
|
||||
sudo userdel -f -r haveno
|
||||
sudo userdel -f -r bitcoin
|
||||
echo "[*] Done!"
|
||||
|
Loading…
Reference in New Issue
Block a user