Compare commits
9 Commits
mainnet_pl
...
master
Author | SHA1 | Date | |
---|---|---|---|
|
5c36b00d07 | ||
|
9c0af85ed8 | ||
|
216260da85 | ||
|
4a57b26469 | ||
|
8d7bb250c5 | ||
|
82eb081089 | ||
|
697828d773 | ||
|
5ad099a33c | ||
|
77d3879013 |
@ -17,19 +17,20 @@
|
|||||||
|
|
||||||
package haveno.asset.coins;
|
package haveno.asset.coins;
|
||||||
|
|
||||||
import haveno.asset.Base58AddressValidator;
|
import haveno.asset.BitcoinAddressValidator;
|
||||||
import haveno.asset.Coin;
|
import haveno.asset.Coin;
|
||||||
import haveno.asset.NetworkParametersAdapter;
|
import haveno.asset.NetworkParametersAdapter;
|
||||||
|
|
||||||
public class Litecoin extends Coin {
|
public class Litecoin extends Coin {
|
||||||
public Litecoin() {
|
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 static class LitecoinMainNetParams extends NetworkParametersAdapter {
|
||||||
public LitecoinMainNetParams() {
|
public LitecoinMainNetParams() {
|
||||||
this.addressHeader = 48;
|
this.addressHeader = 48;
|
||||||
this.p2shHeader = 5;
|
this.p2shHeader = 50;
|
||||||
|
this.segwitAddressHrp = "ltc";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
@ -31,6 +31,17 @@ public class LitecoinTest extends AbstractAssetTest {
|
|||||||
assertValidAddress("Lg3PX8wRWmApFCoCMAsPF5P9dPHYQHEWKW");
|
assertValidAddress("Lg3PX8wRWmApFCoCMAsPF5P9dPHYQHEWKW");
|
||||||
assertValidAddress("LTuoeY6RBHV3n3cfhXVVTbJbxzxnXs9ofm");
|
assertValidAddress("LTuoeY6RBHV3n3cfhXVVTbJbxzxnXs9ofm");
|
||||||
assertValidAddress("LgfapHEPhZbRF9pMd5WPT35hFXcZS1USrW");
|
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
|
@Test
|
||||||
@ -38,5 +49,14 @@ public class LitecoinTest extends AbstractAssetTest {
|
|||||||
assertInvalidAddress("1LgfapHEPhZbRF9pMd5WPT35hFXcZS1USrW");
|
assertInvalidAddress("1LgfapHEPhZbRF9pMd5WPT35hFXcZS1USrW");
|
||||||
assertInvalidAddress("LgfapHEPhZbdRF9pMd5WPT35hFXcZS1USrW");
|
assertInvalidAddress("LgfapHEPhZbdRF9pMd5WPT35hFXcZS1USrW");
|
||||||
assertInvalidAddress("LgfapHEPhZbRF9pMd5WPT35hFXcZS1USrW#");
|
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
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
19
build.gradle
19
build.gradle
@ -49,7 +49,7 @@ configure(subprojects) {
|
|||||||
gsonVersion = '2.8.5'
|
gsonVersion = '2.8.5'
|
||||||
guavaVersion = '32.1.1-jre'
|
guavaVersion = '32.1.1-jre'
|
||||||
guiceVersion = '7.0.0'
|
guiceVersion = '7.0.0'
|
||||||
moneroJavaVersion = '0.8.10'
|
moneroJavaVersion = '0.8.11'
|
||||||
httpclient5Version = '5.0'
|
httpclient5Version = '5.0'
|
||||||
hamcrestVersion = '2.2'
|
hamcrestVersion = '2.2'
|
||||||
httpclientVersion = '4.5.12'
|
httpclientVersion = '4.5.12'
|
||||||
@ -436,16 +436,21 @@ configure(project(':core')) {
|
|||||||
systemProperty 'jdk.attach.allowAttachSelf', true
|
systemProperty 'jdk.attach.allowAttachSelf', true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
task generateKeypairs(type: JavaExec) {
|
||||||
|
mainClass = 'haveno.core.util.GenerateKeyPairs'
|
||||||
|
classpath = sourceSets.main.runtimeClasspath
|
||||||
|
}
|
||||||
|
|
||||||
task havenoDeps {
|
task havenoDeps {
|
||||||
doLast {
|
doLast {
|
||||||
// get monero binaries download url
|
// get monero binaries download url
|
||||||
Map moneroBinaries = [
|
Map moneroBinaries = [
|
||||||
'linux' : 'https://github.com/haveno-dex/monero/releases/download/release1/monero-bins-haveno-linux.tar.gz',
|
'linux' : 'https://github.com/haveno-dex/monero/releases/download/release2/monero-bins-haveno-linux.tar.gz',
|
||||||
'linux-sha256' : '4020274ef546410f218c3c3a3c2a8c2c2cda3f653f8cc6fe8e3cd74334500489',
|
'linux-sha256' : '3537fe2006997a1065748d27e9513ac3e0c942ab56a97a6e43065ddfd1820394',
|
||||||
'mac' : 'https://github.com/haveno-dex/monero/releases/download/release1/monero-bins-haveno-mac.tar.gz',
|
'mac' : 'https://github.com/haveno-dex/monero/releases/download/release2/monero-bins-haveno-mac.tar.gz',
|
||||||
'mac-sha256' : '72514caac499c4900c5cb6e957e5e3aaabba48968ae798c419f4559a51e5fc79',
|
'mac-sha256' : 'c7cafe1000a5839f02d02ed2edce5b1df3a06b5c77f4d91eaba106d948347730',
|
||||||
'windows' : 'https://github.com/haveno-dex/monero/releases/download/release1/monero-bins-haveno-windows.zip',
|
'windows' : 'https://github.com/haveno-dex/monero/releases/download/release2/monero-bins-haveno-windows.zip',
|
||||||
'windows-sha256': '27d8315d5da876e57fd12ed1c1d60a622763de99f0cc2521ce7f31c7fa4ab0ee'
|
'windows-sha256': '9b900faefa75f354870646989484978d1fb11add392ffd05eb5abe7e514e395a'
|
||||||
]
|
]
|
||||||
|
|
||||||
String osKey
|
String osKey
|
||||||
|
@ -22,7 +22,6 @@ import java.util.Collection;
|
|||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.CountDownLatch;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
@ -41,10 +40,10 @@ public class ThreadUtils {
|
|||||||
* @param command the command to execute
|
* @param command the command to execute
|
||||||
* @param threadId the thread id
|
* @param threadId the thread id
|
||||||
*/
|
*/
|
||||||
public static void execute(Runnable command, String threadId) {
|
public static Future<?> execute(Runnable command, String threadId) {
|
||||||
synchronized (EXECUTORS) {
|
synchronized (EXECUTORS) {
|
||||||
if (!EXECUTORS.containsKey(threadId)) EXECUTORS.put(threadId, Executors.newFixedThreadPool(1));
|
if (!EXECUTORS.containsKey(threadId)) EXECUTORS.put(threadId, Executors.newFixedThreadPool(1));
|
||||||
EXECUTORS.get(threadId).execute(() -> {
|
return EXECUTORS.get(threadId).submit(() -> {
|
||||||
synchronized (THREADS) {
|
synchronized (THREADS) {
|
||||||
THREADS.put(threadId, Thread.currentThread());
|
THREADS.put(threadId, Thread.currentThread());
|
||||||
}
|
}
|
||||||
@ -60,26 +59,12 @@ public class ThreadUtils {
|
|||||||
* @param threadId the thread id
|
* @param threadId the thread id
|
||||||
*/
|
*/
|
||||||
public static void await(Runnable command, String threadId) {
|
public static void await(Runnable command, String threadId) {
|
||||||
if (isCurrentThread(Thread.currentThread(), threadId)) {
|
|
||||||
command.run();
|
|
||||||
} else {
|
|
||||||
CountDownLatch latch = new CountDownLatch(1);
|
|
||||||
execute(() -> {
|
|
||||||
try {
|
try {
|
||||||
command.run();
|
execute(command, threadId).get();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
throw e;
|
|
||||||
} finally {
|
|
||||||
latch.countDown();
|
|
||||||
}
|
|
||||||
}, threadId);
|
|
||||||
try {
|
|
||||||
latch.await();
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
public static void shutDown(String threadId) {
|
public static void shutDown(String threadId) {
|
||||||
shutDown(threadId, null);
|
shutDown(threadId, null);
|
||||||
|
@ -19,16 +19,6 @@ package haveno.common.crypto;
|
|||||||
|
|
||||||
import haveno.common.util.Hex;
|
import haveno.common.util.Hex;
|
||||||
import haveno.common.util.Utilities;
|
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.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.security.InvalidKeyException;
|
import java.security.InvalidKeyException;
|
||||||
@ -43,10 +33,17 @@ import java.security.spec.InvalidKeySpecException;
|
|||||||
import java.security.spec.MGF1ParameterSpec;
|
import java.security.spec.MGF1ParameterSpec;
|
||||||
import java.security.spec.X509EncodedKeySpec;
|
import java.security.spec.X509EncodedKeySpec;
|
||||||
import java.util.Arrays;
|
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 {
|
public class Encryption {
|
||||||
private static final Logger log = LoggerFactory.getLogger(Encryption.class);
|
|
||||||
|
|
||||||
public static final String ASYM_KEY_ALGO = "RSA";
|
public static final String ASYM_KEY_ALGO = "RSA";
|
||||||
private static final String ASYM_CIPHER = "RSA/ECB/OAEPWithSHA-256AndMGF1PADDING";
|
private static final String ASYM_CIPHER = "RSA/ECB/OAEPWithSHA-256AndMGF1PADDING";
|
||||||
|
|
||||||
|
@ -458,8 +458,8 @@ public class CoreApi {
|
|||||||
paymentAccount);
|
paymentAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancelOffer(String id) {
|
public void cancelOffer(String id, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||||
coreOffersService.cancelOffer(id);
|
coreOffersService.cancelOffer(id, resultHandler, errorMessageHandler);
|
||||||
}
|
}
|
||||||
|
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -38,6 +38,7 @@ import com.google.inject.Inject;
|
|||||||
import com.google.inject.Singleton;
|
import com.google.inject.Singleton;
|
||||||
import haveno.common.crypto.KeyRing;
|
import haveno.common.crypto.KeyRing;
|
||||||
import haveno.common.handlers.ErrorMessageHandler;
|
import haveno.common.handlers.ErrorMessageHandler;
|
||||||
|
import haveno.common.handlers.ResultHandler;
|
||||||
import static haveno.common.util.MathUtils.exactMultiply;
|
import static haveno.common.util.MathUtils.exactMultiply;
|
||||||
import static haveno.common.util.MathUtils.roundDoubleToLong;
|
import static haveno.common.util.MathUtils.roundDoubleToLong;
|
||||||
import static haveno.common.util.MathUtils.scaleUpByPowerOf10;
|
import static haveno.common.util.MathUtils.scaleUpByPowerOf10;
|
||||||
@ -236,14 +237,9 @@ public class CoreOffersService {
|
|||||||
paymentAccount);
|
paymentAccount);
|
||||||
}
|
}
|
||||||
|
|
||||||
void cancelOffer(String id) {
|
void cancelOffer(String id, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
|
||||||
Offer offer = getMyOffer(id).getOffer();
|
Offer offer = getMyOffer(id).getOffer();
|
||||||
openOfferManager.removeOffer(offer,
|
openOfferManager.removeOffer(offer, resultHandler, errorMessageHandler);
|
||||||
() -> {
|
|
||||||
},
|
|
||||||
errorMessage -> {
|
|
||||||
throw new IllegalStateException(errorMessage);
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// -------------------------- PRIVATE HELPERS -----------------------------
|
// -------------------------- PRIVATE HELPERS -----------------------------
|
||||||
|
@ -133,7 +133,6 @@ class CoreWalletsService {
|
|||||||
verifyWalletCurrencyCodeIsValid(currencyCode);
|
verifyWalletCurrencyCodeIsValid(currencyCode);
|
||||||
verifyWalletsAreAvailable();
|
verifyWalletsAreAvailable();
|
||||||
verifyEncryptedWalletIsUnlocked();
|
verifyEncryptedWalletIsUnlocked();
|
||||||
if (balances.getAvailableBalance().get() == null) throw new IllegalStateException("balance is not yet available");
|
|
||||||
|
|
||||||
switch (currencyCode.trim().toUpperCase()) {
|
switch (currencyCode.trim().toUpperCase()) {
|
||||||
case "":
|
case "":
|
||||||
@ -418,28 +417,8 @@ class CoreWalletsService {
|
|||||||
private XmrBalanceInfo getXmrBalances() {
|
private XmrBalanceInfo getXmrBalances() {
|
||||||
verifyWalletsAreAvailable();
|
verifyWalletsAreAvailable();
|
||||||
verifyEncryptedWalletIsUnlocked();
|
verifyEncryptedWalletIsUnlocked();
|
||||||
|
if (balances.getAvailableBalance() == null) throw new IllegalStateException("Balances are not yet available");
|
||||||
var availableBalance = balances.getAvailableBalance().get();
|
return balances.getBalances();
|
||||||
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());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns a Coin for the transfer amount string, or a RuntimeException if invalid.
|
// Returns a Coin for the transfer amount string, or a RuntimeException if invalid.
|
||||||
|
@ -1,10 +1,10 @@
|
|||||||
package haveno.core.api.model;
|
package haveno.core.api.model;
|
||||||
|
|
||||||
|
import java.math.BigInteger;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import haveno.common.Payload;
|
import haveno.common.Payload;
|
||||||
import lombok.Getter;
|
|
||||||
|
|
||||||
@Getter
|
|
||||||
public class XmrBalanceInfo implements Payload {
|
public class XmrBalanceInfo implements Payload {
|
||||||
|
|
||||||
public static final XmrBalanceInfo EMPTY = new XmrBalanceInfo(-1,
|
public static final XmrBalanceInfo EMPTY = new XmrBalanceInfo(-1,
|
||||||
@ -19,17 +19,19 @@ public class XmrBalanceInfo implements Payload {
|
|||||||
private final long pendingBalance;
|
private final long pendingBalance;
|
||||||
private final long reservedOfferBalance;
|
private final long reservedOfferBalance;
|
||||||
private final long reservedTradeBalance;
|
private final long reservedTradeBalance;
|
||||||
|
private final long reservedBalance;
|
||||||
|
|
||||||
public XmrBalanceInfo(long balance,
|
public XmrBalanceInfo(long balance,
|
||||||
long unlockedBalance,
|
long unlockedBalance,
|
||||||
long lockedBalance,
|
long pendingBalance,
|
||||||
long reservedOfferBalance,
|
long reservedOfferBalance,
|
||||||
long reservedTradeBalance) {
|
long reservedTradeBalance) {
|
||||||
this.balance = balance;
|
this.balance = balance;
|
||||||
this.availableBalance = unlockedBalance;
|
this.availableBalance = unlockedBalance;
|
||||||
this.pendingBalance = lockedBalance;
|
this.pendingBalance = pendingBalance;
|
||||||
this.reservedOfferBalance = reservedOfferBalance;
|
this.reservedOfferBalance = reservedOfferBalance;
|
||||||
this.reservedTradeBalance = reservedTradeBalance;
|
this.reservedTradeBalance = reservedTradeBalance;
|
||||||
|
this.reservedBalance = reservedOfferBalance + reservedTradeBalance;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
@ -45,6 +47,30 @@ public class XmrBalanceInfo implements Payload {
|
|||||||
reservedTradeBalance);
|
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
|
// PROTO BUFFER
|
||||||
///////////////////////////////////////////////////////////////////////////////////////////
|
///////////////////////////////////////////////////////////////////////////////////////////
|
||||||
|
@ -620,9 +620,13 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
|
|||||||
if (!offersToBeEdited.containsKey(openOffer.getId())) {
|
if (!offersToBeEdited.containsKey(openOffer.getId())) {
|
||||||
if (openOffer.isDeactivated()) {
|
if (openOffer.isDeactivated()) {
|
||||||
onCancelled(openOffer);
|
onCancelled(openOffer);
|
||||||
|
resultHandler.handleResult();
|
||||||
} else {
|
} else {
|
||||||
offerBookService.removeOffer(openOffer.getOffer().getOfferPayload(),
|
offerBookService.removeOffer(openOffer.getOffer().getOfferPayload(),
|
||||||
() -> onCancelled(openOffer),
|
() -> {
|
||||||
|
onCancelled(openOffer);
|
||||||
|
resultHandler.handleResult();
|
||||||
|
},
|
||||||
errorMessageHandler);
|
errorMessageHandler);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -19,6 +19,7 @@ package haveno.core.presentation;
|
|||||||
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import haveno.common.UserThread;
|
import haveno.common.UserThread;
|
||||||
|
import haveno.core.api.model.XmrBalanceInfo;
|
||||||
import haveno.core.trade.HavenoUtils;
|
import haveno.core.trade.HavenoUtils;
|
||||||
import haveno.core.xmr.Balances;
|
import haveno.core.xmr.Balances;
|
||||||
import javafx.beans.property.SimpleStringProperty;
|
import javafx.beans.property.SimpleStringProperty;
|
||||||
@ -38,14 +39,13 @@ public class BalancePresentation {
|
|||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public BalancePresentation(Balances balances) {
|
public BalancePresentation(Balances balances) {
|
||||||
balances.getAvailableBalance().addListener((observable, oldValue, newValue) -> {
|
balances.getUpdateCounter().addListener((observable, oldValue, newValue) -> {
|
||||||
UserThread.execute(() -> availableBalance.set(HavenoUtils.formatXmr(newValue, true)));
|
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));
|
||||||
});
|
});
|
||||||
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)));
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -12,29 +12,29 @@ import org.bitcoinj.core.Utils;
|
|||||||
import haveno.common.crypto.Encryption;
|
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.
|
* which can be used to register arbitrators on the network.
|
||||||
*/
|
*/
|
||||||
public class GenerateKeypairs {
|
public class GenerateKeyPairs {
|
||||||
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
|
|
||||||
// generate public/private keypairs
|
// generate public/private key-pairs
|
||||||
List<SecretKey> secretKeys = new ArrayList<SecretKey>();
|
List<SecretKey> secretKeys = new ArrayList<>();
|
||||||
for (int i = 0; i < 20; i++) {
|
for (int i = 0; i < 20; i++) {
|
||||||
secretKeys.add(Encryption.generateSecretKey(256));
|
secretKeys.add(Encryption.generateSecretKey(256));
|
||||||
}
|
}
|
||||||
|
|
||||||
// print keypairs
|
// print key-pairs
|
||||||
System.out.println("Private keys:");
|
System.out.println("Private keys:");
|
||||||
for (SecretKey sk : secretKeys) {
|
for (SecretKey sk : secretKeys) {
|
||||||
String privKey = Utils.HEX.encode(sk.getEncoded());
|
String privateKey = Utils.HEX.encode(sk.getEncoded());
|
||||||
System.out.println(privKey);
|
System.out.println(privateKey);
|
||||||
}
|
}
|
||||||
System.out.println("Corresponding public keys:");
|
System.out.println("Corresponding public keys:");
|
||||||
for (SecretKey sk : secretKeys) {
|
for (SecretKey sk : secretKeys) {
|
||||||
String privKey = Utils.HEX.encode(sk.getEncoded());
|
String privateKey = Utils.HEX.encode(sk.getEncoded());
|
||||||
ECKey ecKey = ECKey.fromPrivate(new BigInteger(1, Utils.HEX.decode(privKey)));
|
ECKey ecKey = ECKey.fromPrivate(new BigInteger(1, Utils.HEX.decode(privateKey)));
|
||||||
String pubKey = Utils.HEX.encode(ecKey.getPubKey());
|
String pubKey = Utils.HEX.encode(ecKey.getPubKey());
|
||||||
System.out.println(pubKey);
|
System.out.println(pubKey);
|
||||||
}
|
}
|
@ -37,6 +37,7 @@ package haveno.core.xmr;
|
|||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import haveno.common.ThreadUtils;
|
import haveno.common.ThreadUtils;
|
||||||
import haveno.common.UserThread;
|
import haveno.common.UserThread;
|
||||||
|
import haveno.core.api.model.XmrBalanceInfo;
|
||||||
import haveno.core.offer.OpenOffer;
|
import haveno.core.offer.OpenOffer;
|
||||||
import haveno.core.offer.OpenOfferManager;
|
import haveno.core.offer.OpenOfferManager;
|
||||||
import haveno.core.support.dispute.Dispute;
|
import haveno.core.support.dispute.Dispute;
|
||||||
@ -51,8 +52,8 @@ import haveno.core.xmr.wallet.XmrWalletService;
|
|||||||
import java.math.BigInteger;
|
import java.math.BigInteger;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.stream.Collectors;
|
import java.util.stream.Collectors;
|
||||||
import javafx.beans.property.ObjectProperty;
|
import javafx.beans.property.IntegerProperty;
|
||||||
import javafx.beans.property.SimpleObjectProperty;
|
import javafx.beans.property.SimpleIntegerProperty;
|
||||||
import javafx.collections.ListChangeListener;
|
import javafx.collections.ListChangeListener;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.extern.slf4j.Slf4j;
|
import lombok.extern.slf4j.Slf4j;
|
||||||
@ -67,15 +68,18 @@ public class Balances {
|
|||||||
private final RefundManager refundManager;
|
private final RefundManager refundManager;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
private final ObjectProperty<BigInteger> availableBalance = new SimpleObjectProperty<>();
|
private BigInteger availableBalance;
|
||||||
@Getter
|
@Getter
|
||||||
private final ObjectProperty<BigInteger> pendingBalance = new SimpleObjectProperty<>();
|
private BigInteger pendingBalance;
|
||||||
@Getter
|
@Getter
|
||||||
private final ObjectProperty<BigInteger> reservedOfferBalance = new SimpleObjectProperty<>();
|
private BigInteger reservedOfferBalance;
|
||||||
@Getter
|
@Getter
|
||||||
private final ObjectProperty<BigInteger> reservedTradeBalance = new SimpleObjectProperty<>();
|
private BigInteger reservedTradeBalance;
|
||||||
@Getter
|
@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
|
@Inject
|
||||||
public Balances(TradeManager tradeManager,
|
public Balances(TradeManager tradeManager,
|
||||||
@ -103,18 +107,29 @@ public class Balances {
|
|||||||
updateBalances();
|
updateBalances();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public XmrBalanceInfo getBalances() {
|
||||||
|
synchronized (this) {
|
||||||
|
return new XmrBalanceInfo(availableBalance.longValue() + pendingBalance.longValue(),
|
||||||
|
availableBalance.longValue(),
|
||||||
|
pendingBalance.longValue(),
|
||||||
|
reservedOfferBalance.longValue(),
|
||||||
|
reservedTradeBalance.longValue());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private void updateBalances() {
|
private void updateBalances() {
|
||||||
ThreadUtils.submitToPool(() -> doUpdateBalances());
|
ThreadUtils.submitToPool(() -> doUpdateBalances());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doUpdateBalances() {
|
private void doUpdateBalances() {
|
||||||
|
synchronized (this) {
|
||||||
|
|
||||||
// get wallet balances
|
// get wallet balances
|
||||||
BigInteger balance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getWallet().getBalance(0);
|
BigInteger balance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getBalance();
|
||||||
BigInteger unlockedBalance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getWallet().getUnlockedBalance(0);
|
availableBalance = xmrWalletService.getWallet() == null ? BigInteger.ZERO : xmrWalletService.getAvailableBalance();
|
||||||
|
|
||||||
// calculate pending balance by adding frozen trade balances - reserved amounts
|
// calculate pending balance by adding frozen trade balances - reserved amounts
|
||||||
BigInteger pendingBalance = balance.subtract(unlockedBalance);
|
pendingBalance = balance.subtract(availableBalance);
|
||||||
List<Trade> trades = tradeManager.getTradesStreamWithFundsLockedIn().collect(Collectors.toList());
|
List<Trade> trades = tradeManager.getTradesStreamWithFundsLockedIn().collect(Collectors.toList());
|
||||||
for (Trade trade : trades) {
|
for (Trade trade : trades) {
|
||||||
if (trade.getFrozenAmount().equals(new BigInteger("0"))) continue;
|
if (trade.getFrozenAmount().equals(new BigInteger("0"))) continue;
|
||||||
@ -123,7 +138,7 @@ public class Balances {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// calculate reserved offer balance
|
// calculate reserved offer balance
|
||||||
BigInteger reservedOfferBalance = BigInteger.ZERO;
|
reservedOfferBalance = BigInteger.ZERO;
|
||||||
if (xmrWalletService.getWallet() != null) {
|
if (xmrWalletService.getWallet() != null) {
|
||||||
List<MoneroOutputWallet> frozenOutputs = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery().setIsFrozen(true).setIsSpent(false));
|
List<MoneroOutputWallet> frozenOutputs = xmrWalletService.getWallet().getOutputs(new MoneroOutputQuery().setIsFrozen(true).setIsSpent(false));
|
||||||
for (MoneroOutputWallet frozenOutput : frozenOutputs) reservedOfferBalance = reservedOfferBalance.add(frozenOutput.getAmount());
|
for (MoneroOutputWallet frozenOutput : frozenOutputs) reservedOfferBalance = reservedOfferBalance.add(frozenOutput.getAmount());
|
||||||
@ -133,22 +148,16 @@ public class Balances {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// calculate reserved trade balance
|
// calculate reserved trade balance
|
||||||
BigInteger reservedTradeBalance = BigInteger.ZERO;
|
reservedTradeBalance = BigInteger.ZERO;
|
||||||
for (Trade trade : trades) {
|
for (Trade trade : trades) {
|
||||||
reservedTradeBalance = reservedTradeBalance.add(trade.getReservedAmount());
|
reservedTradeBalance = reservedTradeBalance.add(trade.getReservedAmount());
|
||||||
}
|
}
|
||||||
|
|
||||||
// set balances
|
// calculate reserved balance
|
||||||
setBalances(balance, unlockedBalance, pendingBalance, reservedOfferBalance, reservedTradeBalance);
|
reservedBalance = reservedOfferBalance.add(reservedTradeBalance);
|
||||||
}
|
|
||||||
|
|
||||||
private void setBalances(BigInteger balance, BigInteger unlockedBalance, BigInteger pendingBalance, BigInteger reservedOfferBalance, BigInteger reservedTradeBalance) {
|
// notify balance update
|
||||||
UserThread.execute(() -> {
|
UserThread.execute(() -> updateCounter.set(updateCounter.get() + 1));
|
||||||
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();
|
Callable<MoneroSyncResult> task = () -> wallet.sync();
|
||||||
Future<MoneroSyncResult> future = syncWalletThreadPool.submit(task);
|
Future<MoneroSyncResult> future = syncWalletThreadPool.submit(task);
|
||||||
try {
|
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) {
|
} catch (Exception e) {
|
||||||
throw new MoneroError(e.getMessage());
|
throw new MoneroError(e.getMessage());
|
||||||
}
|
}
|
||||||
@ -893,7 +895,7 @@ public class XmrWalletService {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// register internal listener to notify external listeners
|
// 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
|
@Override
|
||||||
public void postOffer(PostOfferRequest req,
|
public void postOffer(PostOfferRequest req,
|
||||||
StreamObserver<PostOfferReply> responseObserver) {
|
StreamObserver<PostOfferReply> responseObserver) {
|
||||||
GrpcErrorMessageHandler errorMessageHandler =
|
GrpcErrorMessageHandler errorMessageHandler = new GrpcErrorMessageHandler(getPostOfferMethod().getFullMethodName(), responseObserver, exceptionHandler, log);
|
||||||
new GrpcErrorMessageHandler(getPostOfferMethod().getFullMethodName(),
|
|
||||||
responseObserver,
|
|
||||||
exceptionHandler,
|
|
||||||
log);
|
|
||||||
try {
|
try {
|
||||||
coreApi.postOffer(
|
coreApi.postOffer(
|
||||||
req.getCurrencyCode(),
|
req.getCurrencyCode(),
|
||||||
@ -170,8 +166,7 @@ class GrpcOffersService extends OffersImplBase {
|
|||||||
responseObserver.onCompleted();
|
responseObserver.onCompleted();
|
||||||
},
|
},
|
||||||
errorMessage -> {
|
errorMessage -> {
|
||||||
if (!errorMessageHandler.isErrorHandled())
|
if (!errorMessageHandler.isErrorHandled()) errorMessageHandler.handleErrorMessage(errorMessage);
|
||||||
errorMessageHandler.handleErrorMessage(errorMessage);
|
|
||||||
});
|
});
|
||||||
} catch (Throwable cause) {
|
} catch (Throwable cause) {
|
||||||
exceptionHandler.handleException(log, cause, responseObserver);
|
exceptionHandler.handleException(log, cause, responseObserver);
|
||||||
@ -181,11 +176,15 @@ class GrpcOffersService extends OffersImplBase {
|
|||||||
@Override
|
@Override
|
||||||
public void cancelOffer(CancelOfferRequest req,
|
public void cancelOffer(CancelOfferRequest req,
|
||||||
StreamObserver<CancelOfferReply> responseObserver) {
|
StreamObserver<CancelOfferReply> responseObserver) {
|
||||||
|
GrpcErrorMessageHandler errorMessageHandler = new GrpcErrorMessageHandler(getCancelOfferMethod().getFullMethodName(), responseObserver, exceptionHandler, log);
|
||||||
try {
|
try {
|
||||||
coreApi.cancelOffer(req.getId());
|
coreApi.cancelOffer(req.getId(), () -> {
|
||||||
var reply = CancelOfferReply.newBuilder().build();
|
var reply = CancelOfferReply.newBuilder().build();
|
||||||
responseObserver.onNext(reply);
|
responseObserver.onNext(reply);
|
||||||
responseObserver.onCompleted();
|
responseObserver.onCompleted();
|
||||||
|
}, errorMessage -> {
|
||||||
|
if (!errorMessageHandler.isErrorHandled()) errorMessageHandler.handleErrorMessage(errorMessage);
|
||||||
|
});
|
||||||
} catch (Throwable cause) {
|
} catch (Throwable cause) {
|
||||||
exceptionHandler.handleException(log, cause, responseObserver);
|
exceptionHandler.handleException(log, cause, responseObserver);
|
||||||
}
|
}
|
||||||
|
@ -48,7 +48,7 @@ Follow [instructions](https://github.com/haveno-dex/haveno-ts#run-tests) to run
|
|||||||
|
|
||||||
Based on these instructions: https://github.com/monero-project/monero#cross-compiling
|
Based on these instructions: https://github.com/monero-project/monero#cross-compiling
|
||||||
|
|
||||||
1. Install Ubuntu 20.04.
|
1. Install Ubuntu 20.04 on x86_64.
|
||||||
2. `sudo apt-get update && sudo apt-get upgrade`
|
2. `sudo apt-get update && sudo apt-get upgrade`
|
||||||
3. Install monero dependencies: `sudo apt update && sudo apt install build-essential cmake pkg-config libssl-dev libzmq3-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libpgm-dev qttools5-dev-tools libhidapi-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler libudev-dev libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-locale-dev libboost-program-options-dev libboost-regex-dev libboost-serialization-dev libboost-system-dev libboost-thread-dev python3 ccache`
|
3. Install monero dependencies: `sudo apt update && sudo apt install build-essential cmake pkg-config libssl-dev libzmq3-dev libsodium-dev libunwind8-dev liblzma-dev libreadline6-dev libpgm-dev qttools5-dev-tools libhidapi-dev libusb-1.0-0-dev libprotobuf-dev protobuf-compiler libudev-dev libboost-chrono-dev libboost-date-time-dev libboost-filesystem-dev libboost-locale-dev libboost-program-options-dev libboost-regex-dev libboost-serialization-dev libboost-system-dev libboost-thread-dev python3 ccache`
|
||||||
4. `sudo apt install cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev libtinfo5 autoconf libtool libtool-bin gperf git curl`
|
4. `sudo apt install cmake imagemagick libcap-dev librsvg2-bin libz-dev libbz2-dev libtiff-tools python-dev libtinfo5 autoconf libtool libtool-bin gperf git curl`
|
||||||
|
@ -31,7 +31,7 @@ If it's the first time you are building Haveno, run the following commands to do
|
|||||||
```
|
```
|
||||||
git clone https://github.com/haveno-dex/haveno.git
|
git clone https://github.com/haveno-dex/haveno.git
|
||||||
cd haveno
|
cd haveno
|
||||||
git checkout v0.0.18
|
git checkout v0.0.19
|
||||||
make
|
make
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -40,7 +40,7 @@ make
|
|||||||
If you are updating from a previous version, run from the root of the repository:
|
If you are updating from a previous version, run from the root of the repository:
|
||||||
|
|
||||||
```
|
```
|
||||||
git checkout v0.0.18
|
git checkout v0.0.19
|
||||||
git pull
|
git pull
|
||||||
make clean && make
|
make clean && make
|
||||||
```
|
```
|
||||||
|
@ -846,9 +846,9 @@
|
|||||||
<sha256 value="c92e2ca40a3f2474d61e56831aeb379cf8ae3dddeea61b4a828cee2d99f71f38" origin="Generated by Gradle"/>
|
<sha256 value="c92e2ca40a3f2474d61e56831aeb379cf8ae3dddeea61b4a828cee2d99f71f38" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="io.github.woodser" name="monero-java" version="0.8.10">
|
<component group="io.github.woodser" name="monero-java" version="0.8.11">
|
||||||
<artifact name="monero-java-0.8.10.jar">
|
<artifact name="monero-java-0.8.11.jar">
|
||||||
<sha256 value="3ea921cb8122e9be4401479e7040055063b2132e8210f7129117b8b10472f773" origin="Generated by Gradle"/>
|
<sha256 value="37c125a31463c44e43452bc3e18e74a05b65d1fbebb11adc5131521b29b48a6b" origin="Generated by Gradle"/>
|
||||||
</artifact>
|
</artifact>
|
||||||
</component>
|
</component>
|
||||||
<component group="io.grpc" name="grpc-api" version="1.42.1">
|
<component group="io.grpc" name="grpc-api" version="1.42.1">
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
# docker run -it -p 9050 -p 2002 --restart-policy unless-stopped --name haveno-seednode haveno-seednode
|
# 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
|
# 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 && \
|
RUN set -ex && \
|
||||||
apt update && \
|
apt update && \
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
# configuration for haveno service
|
# configuration for haveno service
|
||||||
# install in /etc/default/haveno.env
|
# install in /etc/default/haveno.env
|
||||||
|
|
||||||
# java home, set to openjdk 10
|
# java home, set to latest openjdk 21 from os repository
|
||||||
JAVA_HOME=/usr/lib/jvm/openjdk-10.0.2
|
JAVA_HOME=/usr/lib/jvm/openjdk-21
|
||||||
|
|
||||||
# java memory and remote management options
|
# 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)
|
# use external tor (change to -1 for internal tor binary)
|
||||||
HAVENO_EXTERNAL_TOR_PORT=9051
|
HAVENO_EXTERNAL_TOR_PORT=9051
|
||||||
@ -28,7 +28,7 @@ BITCOIN_RPC_BLOCKNOTIFY_PORT=5120
|
|||||||
HAVENO_HOME=__HAVENO_HOME__
|
HAVENO_HOME=__HAVENO_HOME__
|
||||||
HAVENO_APP_NAME=haveno-seednode
|
HAVENO_APP_NAME=haveno-seednode
|
||||||
HAVENO_ENTRYPOINT=haveno-seednode
|
HAVENO_ENTRYPOINT=haveno-seednode
|
||||||
HAVENO_BASE_CURRENCY=btc_mainnet
|
HAVENO_BASE_CURRENCY=xmr_mainnet
|
||||||
|
|
||||||
# haveno node settings
|
# haveno node settings
|
||||||
HAVENO_NODE_PORT=8000
|
HAVENO_NODE_PORT=8000
|
||||||
|
@ -7,22 +7,21 @@ echo "[*] Haveno Seednode installation script"
|
|||||||
|
|
||||||
ROOT_USER=root
|
ROOT_USER=root
|
||||||
ROOT_GROUP=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
|
ROOT_HOME=/root
|
||||||
|
|
||||||
SYSTEMD_SERVICE_HOME=/etc/systemd/system
|
SYSTEMD_SERVICE_HOME=/etc/systemd/system
|
||||||
SYSTEMD_ENV_HOME=/etc/default
|
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_NAME=haveno
|
||||||
HAVENO_REPO_TAG=master
|
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_HOME=/haveno
|
||||||
HAVENO_USER=haveno
|
HAVENO_USER=haveno
|
||||||
|
|
||||||
# by default, this script will build and setup bitcoin fullnode
|
# by default, this script will not build and setup bitcoin full-node
|
||||||
# if you want to use an existing bitcoin fullnode, see next section
|
BITCOIN_INSTALL=false
|
||||||
BITCOIN_INSTALL=true
|
|
||||||
BITCOIN_REPO_URL=https://github.com/bitcoin/bitcoin
|
BITCOIN_REPO_URL=https://github.com/bitcoin/bitcoin
|
||||||
BITCOIN_REPO_NAME=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)
|
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"
|
echo "[*] Installing base packages"
|
||||||
sudo -H -i -u "${ROOT_USER}" DEBIAN_FRONTEND=noninteractive apt-get install -qq -y ${ROOT_PKG}
|
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"
|
echo "[*] Cloning Haveno repo"
|
||||||
sudo -H -i -u "${ROOT_USER}" git config --global advice.detachedHead false
|
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}"
|
sudo -H -i -u "${ROOT_USER}" git clone --branch "${HAVENO_REPO_TAG}" "${HAVENO_REPO_URL}" "${ROOT_HOME}/${HAVENO_REPO_NAME}"
|
||||||
|
|
||||||
echo "[*] Installing Tor"
|
echo "[*] Installing Tor"
|
||||||
sudo -H -i -u "${ROOT_USER}" wget -qO- https://deb.torproject.org/torproject.org/A3C4F0F979CAA22CDBA8F512EE8CBC9E886DDD89.asc | gp
|
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
|
||||||
g --dearmor | 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}" 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}" DEBIAN_FRONTEND=noninteractive apt-get update -q
|
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}
|
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}" 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}"
|
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"
|
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
|
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/#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.service"
|
sudo sed -i -e "s/#BindsTo=bitcoin.service/BindsTo=bitcoin.service/" "${SYSTEMD_SERVICE_HOME}/haveno-seednode.service"
|
||||||
fi
|
fi
|
||||||
sudo sed -i -e "s/__HAVENO_REPO_NAME__/${HAVENO_REPO_NAME}/" "${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.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"
|
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"
|
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}"
|
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}"
|
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"
|
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
|
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"
|
echo "[*] Updating systemd daemon configuration"
|
||||||
sudo -H -i -u "${ROOT_USER}" systemctl daemon-reload
|
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 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
|
if [ "${BITCOIN_INSTALL}" = true ];then
|
||||||
sudo -H -i -u "${ROOT_USER}" systemctl enable bitcoin.service
|
sudo -H -i -u "${ROOT_USER}" systemctl enable bitcoin.service
|
||||||
fi
|
fi
|
||||||
@ -185,13 +172,13 @@ fi
|
|||||||
echo "[*] Adding notes to motd"
|
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 " " >> /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 "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 " " >> /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 "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 " " >> /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 "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!'
|
echo '[*] Done!'
|
||||||
|
|
||||||
|
@ -3,9 +3,9 @@ echo "[*] Uninstalling Bitcoin and Haveno, will delete all data!!"
|
|||||||
sleep 10
|
sleep 10
|
||||||
sudo rm -rf /root/haveno
|
sudo rm -rf /root/haveno
|
||||||
sudo systemctl stop bitcoin
|
sudo systemctl stop bitcoin
|
||||||
sudo systemctl stop haveno
|
sudo systemctl stop haveno-seednode
|
||||||
sudo systemctl disable bitcoin
|
sudo systemctl disable bitcoin
|
||||||
sudo systemctl disable haveno
|
sudo systemctl disable haveno-seednode
|
||||||
sudo userdel -f -r haveno
|
sudo userdel -f -r haveno
|
||||||
sudo userdel -f -r bitcoin
|
sudo userdel -f -r bitcoin
|
||||||
echo "[*] Done!"
|
echo "[*] Done!"
|
||||||
|
Loading…
Reference in New Issue
Block a user