Compare commits

...

17 Commits

Author SHA1 Message Date
Jabster28
b3ddde4c2e
Merge 5bc2816491 into 11c0f7613b 2024-09-30 10:43:38 +00:00
justynboyer@gmail.com
5bc2816491 move hash file to macos location 2024-09-30 11:43:32 +01:00
justynboyer@gmail.com
11c0f7613b fix(ci): pin ubuntu ci version 2024-09-26 10:19:00 -04:00
woodser
1329902a55 add transaction fee column to funds > transactions
Co-authored-by: niyid <neeyeed@gmail.com>
2024-09-26 10:10:31 -04:00
woodser
6c640ddbef resize donation qrs 2024-09-26 08:29:02 -04:00
woodser
50f3bd510a log stack traces at warn or error level 2024-09-25 09:40:50 -04:00
woodser
8d55abe3b9 add deprecated tails support as backup 2024-09-23 18:56:27 -04:00
woodser
c04fc7b2db save multisig wallet on same thread in trade wallet operations 2024-09-17 12:23:34 -04:00
woodser
0ed640be16 save multisig wallet on same thread when initialized 2024-09-17 12:23:34 -04:00
woodser
2a9bc87f65 check multisig state on initialization 2024-09-17 12:23:34 -04:00
woodser
2f310b420d
use error level for error log file 2024-09-17 12:00:35 -04:00
preland
d4f1dc5b8e
Create error log file 2024-09-17 11:44:20 -04:00
woodser
a4e43f1045 update to monero-java v0.8.33 2024-09-16 21:12:53 -04:00
woodser
7306972d19 fix reference to backup cache file 2024-09-15 09:41:10 -04:00
woodser
1ea9a6f750 add notes for tails installation 2024-09-12 12:11:11 -04:00
woodser
c08b4d0772
print stack trace on error closing dispute ticket 2024-09-12 11:41:26 -04:00
woodser
874075b371
add curl command for tails install script 2024-09-09 09:13:47 -04:00
52 changed files with 326 additions and 173 deletions

View File

@ -78,6 +78,7 @@ jobs:
else else
mv desktop/build/temp-*/binaries/Haveno-*.dmg ${{ github.workspace }}/release/Haveno-x86_64.dmg mv desktop/build/temp-*/binaries/Haveno-*.dmg ${{ github.workspace }}/release/Haveno-x86_64.dmg
fi fi
cp desktop/build/temp-*/binaries/desktop-*.jar.SHA-256 ${{ github.workspace }}/release
cp desktop/build/temp-*/binaries/desktop-*.jar.SHA-256 ${{ github.workspace }}/release-deb cp desktop/build/temp-*/binaries/desktop-*.jar.SHA-256 ${{ github.workspace }}/release-deb
cp desktop/build/temp-*/binaries/desktop-*.jar.SHA-256 ${{ github.workspace }}/release-rpm cp desktop/build/temp-*/binaries/desktop-*.jar.SHA-256 ${{ github.workspace }}/release-rpm
shell: bash shell: bash

View File

@ -72,7 +72,7 @@ To bring Haveno to life, we need resources. If you have the possibility, please
### Monero ### Monero
<p> <p>
<img src="https://raw.githubusercontent.com/haveno-dex/haveno/master/media/donate_monero.png" alt="Donate Monero" width="150" height="150"><br> <img src="https://raw.githubusercontent.com/haveno-dex/haveno/master/media/donate_monero.png" alt="Donate Monero" width="115" height="115"><br>
<code>42sjokkT9FmiWPqVzrWPFE5NCJXwt96bkBozHf4vgLR9hXyJDqKHEHKVscAARuD7in5wV1meEcSTJTanCTDzidTe2cFXS1F</code> <code>42sjokkT9FmiWPqVzrWPFE5NCJXwt96bkBozHf4vgLR9hXyJDqKHEHKVscAARuD7in5wV1meEcSTJTanCTDzidTe2cFXS1F</code>
</p> </p>
@ -81,6 +81,6 @@ If you are using a wallet that supports OpenAlias (like the 'official' CLI and G
### Bitcoin ### Bitcoin
<p> <p>
<img src="https://raw.githubusercontent.com/haveno-dex/haveno/master/media/donate_bitcoin.png" alt="Donate Bitcoin" width="150" height="150"><br> <img src="https://raw.githubusercontent.com/haveno-dex/haveno/master/media/donate_bitcoin.png" alt="Donate Bitcoin" width="115" height="115"><br>
<code>1AKq3CE1yBAnxGmHXbNFfNYStcByNDc5gQ</code> <code>1AKq3CE1yBAnxGmHXbNFfNYStcByNDc5gQ</code>
</p> </p>

View File

@ -78,7 +78,7 @@ public class ApiTestMain {
} catch (Throwable ex) { } catch (Throwable ex) {
err.println("Fault: An unexpected error occurred. " + err.println("Fault: An unexpected error occurred. " +
"Please file a report at https://haveno.exchange/issues"); "Please file a report at https://github.com/haveno-dex/haveno/issues");
ex.printStackTrace(err); ex.printStackTrace(err);
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }

View File

@ -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.31' moneroJavaVersion = '0.8.33'
httpclient5Version = '5.0' httpclient5Version = '5.0'
hamcrestVersion = '2.2' hamcrestVersion = '2.2'
httpclientVersion = '4.5.12' httpclientVersion = '4.5.12'
@ -334,6 +334,7 @@ configure(project(':p2p')) {
implementation "com.google.protobuf:protobuf-java:$protobufVersion" implementation "com.google.protobuf:protobuf-java:$protobufVersion"
implementation "org.fxmisc.easybind:easybind:$easybindVersion" implementation "org.fxmisc.easybind:easybind:$easybindVersion"
implementation "org.slf4j:slf4j-api:$slf4jVersion" implementation "org.slf4j:slf4j-api:$slf4jVersion"
implementation "org.apache.commons:commons-lang3:$langVersion"
implementation("com.github.haveno-dex.netlayer:tor.external:$netlayerVersion") { implementation("com.github.haveno-dex.netlayer:tor.external:$netlayerVersion") {
exclude(module: 'slf4j-api') exclude(module: 'slf4j-api')
} }

View File

@ -21,6 +21,7 @@ import ch.qos.logback.classic.Level;
import ch.qos.logback.classic.Logger; import ch.qos.logback.classic.Logger;
import ch.qos.logback.classic.LoggerContext; import ch.qos.logback.classic.LoggerContext;
import ch.qos.logback.classic.encoder.PatternLayoutEncoder; import ch.qos.logback.classic.encoder.PatternLayoutEncoder;
import ch.qos.logback.classic.filter.ThresholdFilter;
import ch.qos.logback.classic.spi.ILoggingEvent; import ch.qos.logback.classic.spi.ILoggingEvent;
import ch.qos.logback.core.rolling.FixedWindowRollingPolicy; import ch.qos.logback.core.rolling.FixedWindowRollingPolicy;
import ch.qos.logback.core.rolling.RollingFileAppender; import ch.qos.logback.core.rolling.RollingFileAppender;
@ -52,11 +53,12 @@ public class Log {
SizeBasedTriggeringPolicy<ILoggingEvent> triggeringPolicy = new SizeBasedTriggeringPolicy<>(); SizeBasedTriggeringPolicy<ILoggingEvent> triggeringPolicy = new SizeBasedTriggeringPolicy<>();
triggeringPolicy.setMaxFileSize(FileSize.valueOf("10MB")); triggeringPolicy.setMaxFileSize(FileSize.valueOf("10MB"));
triggeringPolicy.setContext(loggerContext);
triggeringPolicy.start(); triggeringPolicy.start();
PatternLayoutEncoder encoder = new PatternLayoutEncoder(); PatternLayoutEncoder encoder = new PatternLayoutEncoder();
encoder.setContext(loggerContext); encoder.setContext(loggerContext);
encoder.setPattern("%d{MMM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{15}: %msg %xEx%n"); encoder.setPattern("%d{MMM-dd HH:mm:ss.SSS} [%thread] %-5level %logger{15}: %msg%n");
encoder.start(); encoder.start();
appender.setEncoder(encoder); appender.setEncoder(encoder);
@ -64,25 +66,43 @@ public class Log {
appender.setTriggeringPolicy(triggeringPolicy); appender.setTriggeringPolicy(triggeringPolicy);
appender.start(); appender.start();
logbackLogger = loggerContext.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
logbackLogger.addAppender(appender);
logbackLogger.setLevel(Level.INFO);
// log errors in separate file // log errors in separate file
// not working as expected still.... damn logback... PatternLayoutEncoder errorEncoder = new PatternLayoutEncoder();
/* FileAppender errorAppender = new FileAppender(); errorEncoder.setContext(loggerContext);
errorAppender.setEncoder(encoder); errorEncoder.setPattern("%d{MMM-dd HH:mm:ss.SSS} [%thread] %-5level %logger: %msg%n%ex");
errorEncoder.start();
RollingFileAppender<ILoggingEvent> errorAppender = new RollingFileAppender<>();
errorAppender.setEncoder(errorEncoder);
errorAppender.setName("Error"); errorAppender.setName("Error");
errorAppender.setContext(loggerContext); errorAppender.setContext(loggerContext);
errorAppender.setFile(fileName + "_error.log"); errorAppender.setFile(fileName + "_error.log");
LevelFilter levelFilter = new LevelFilter();
levelFilter.setLevel(Level.ERROR); FixedWindowRollingPolicy errorRollingPolicy = new FixedWindowRollingPolicy();
levelFilter.setOnMatch(FilterReply.ACCEPT); errorRollingPolicy.setContext(loggerContext);
levelFilter.setOnMismatch(FilterReply.DENY); errorRollingPolicy.setParent(errorAppender);
levelFilter.start(); errorRollingPolicy.setFileNamePattern(fileName + "_error_%i.log");
errorAppender.addFilter(levelFilter); errorRollingPolicy.setMinIndex(1);
errorRollingPolicy.setMaxIndex(20);
errorRollingPolicy.start();
SizeBasedTriggeringPolicy<ILoggingEvent> errorTriggeringPolicy = new SizeBasedTriggeringPolicy<>();
errorTriggeringPolicy.setMaxFileSize(FileSize.valueOf("10MB"));
errorTriggeringPolicy.start();
ThresholdFilter thresholdFilter = new ThresholdFilter();
thresholdFilter.setLevel("WARN");
thresholdFilter.start();
errorAppender.setRollingPolicy(errorRollingPolicy);
errorAppender.setTriggeringPolicy(errorTriggeringPolicy);
errorAppender.addFilter(thresholdFilter);
errorAppender.start(); errorAppender.start();
logbackLogger.addAppender(errorAppender);*/
logbackLogger = loggerContext.getLogger(org.slf4j.Logger.ROOT_LOGGER_NAME);
logbackLogger.addAppender(errorAppender);
logbackLogger.addAppender(appender);
logbackLogger.setLevel(Level.INFO);
} }
public static void setCustomLogLevel(String pattern, Level logLevel) { public static void setCustomLogLevel(String pattern, Level logLevel) {

View File

@ -68,8 +68,7 @@ public class FileUtil {
pruneBackup(backupFileDir, numMaxBackupFiles); pruneBackup(backupFileDir, numMaxBackupFiles);
} catch (IOException e) { } catch (IOException e) {
log.error("Backup key failed: " + e.getMessage()); log.error("Backup key failed: {}\n", e.getMessage(), e);
e.printStackTrace();
} }
} }
} }
@ -97,7 +96,7 @@ public class FileUtil {
try { try {
FileUtils.deleteDirectory(backupFileDir); FileUtils.deleteDirectory(backupFileDir);
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); log.error("Delete backup key failed: {}\n", e.getMessage(), e);
} }
} }
@ -173,8 +172,7 @@ public class FileUtil {
} }
} }
} catch (Throwable t) { } catch (Throwable t) {
log.error(t.toString()); log.error("Could not delete file, error={}\n", t.getMessage(), t);
t.printStackTrace();
throw new IOException(t); throw new IOException(t);
} }
} }

View File

@ -69,11 +69,7 @@ public class CommonSetup {
"The system tray is not supported on the current platform.".equals(throwable.getMessage())) { "The system tray is not supported on the current platform.".equals(throwable.getMessage())) {
log.warn(throwable.getMessage()); log.warn(throwable.getMessage());
} else { } else {
log.error("Uncaught Exception from thread " + Thread.currentThread().getName()); log.error("Uncaught Exception from thread {}, error={}\n", Thread.currentThread().getName(), throwable.getMessage(), throwable);
log.error("throwableMessage= " + throwable.getMessage());
log.error("throwableClass= " + throwable.getClass());
log.error("Stack trace:\n" + ExceptionUtils.getStackTrace(throwable));
throwable.printStackTrace();
UserThread.execute(() -> uncaughtExceptionHandler.handleUncaughtException(throwable, false)); UserThread.execute(() -> uncaughtExceptionHandler.handleUncaughtException(throwable, false));
} }
}; };
@ -113,8 +109,7 @@ public class CommonSetup {
if (!pathOfCodeSource.endsWith("classes")) if (!pathOfCodeSource.endsWith("classes"))
log.info("Path to Haveno jar file: " + pathOfCodeSource); log.info("Path to Haveno jar file: " + pathOfCodeSource);
} catch (URISyntaxException e) { } catch (URISyntaxException e) {
log.error(e.toString()); log.error(ExceptionUtils.getStackTrace(e));
e.printStackTrace();
} }
} }
} }

View File

@ -25,6 +25,8 @@ import java.util.Arrays;
import java.util.Queue; import java.util.Queue;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
import org.apache.commons.lang3.exception.ExceptionUtils;
@Slf4j @Slf4j
public class TaskRunner<T extends Model> { public class TaskRunner<T extends Model> {
private final Queue<Class<? extends Task<T>>> tasks = new LinkedBlockingQueue<>(); private final Queue<Class<? extends Task<T>>> tasks = new LinkedBlockingQueue<>();
@ -67,8 +69,8 @@ public class TaskRunner<T extends Model> {
log.info("Run task: " + currentTask.getSimpleName()); log.info("Run task: " + currentTask.getSimpleName());
currentTask.getDeclaredConstructor(TaskRunner.class, sharedModelClass).newInstance(this, sharedModel).run(); currentTask.getDeclaredConstructor(TaskRunner.class, sharedModelClass).newInstance(this, sharedModel).run();
} catch (Throwable throwable) { } catch (Throwable throwable) {
throwable.printStackTrace(); log.error(ExceptionUtils.getStackTrace(throwable));
handleErrorMessage("Error at taskRunner: " + throwable.getMessage()); handleErrorMessage("Error at taskRunner, error=" + throwable.getMessage());
} }
} else { } else {
resultHandler.handleResult(); resultHandler.handleResult();

View File

@ -331,8 +331,7 @@ public class Utilities {
clipboard.setContent(clipboardContent); clipboard.setContent(clipboardContent);
} }
} catch (Throwable e) { } catch (Throwable e) {
log.error("copyToClipboard failed " + e.getMessage()); log.error("copyToClipboard failed: {}\n", e.getMessage(), e);
e.printStackTrace();
} }
} }

View File

@ -52,6 +52,9 @@ import java.util.ArrayList;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
import java.util.Optional; import java.util.Optional;
import org.apache.commons.lang3.exception.ExceptionUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@ -204,7 +207,7 @@ public class CoreDisputesService {
throw new IllegalStateException(errMessage, err); throw new IllegalStateException(errMessage, err);
}); });
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.error(ExceptionUtils.getStackTrace(e));
throw new IllegalStateException(e.getMessage() == null ? ("Error resolving dispute for trade " + trade.getId()) : e.getMessage()); throw new IllegalStateException(e.getMessage() == null ? ("Error resolving dispute for trade " + trade.getId()) : e.getMessage());
} }
} }

View File

@ -66,6 +66,8 @@ import java.util.List;
import java.util.Optional; import java.util.Optional;
import java.util.function.Consumer; import java.util.function.Consumer;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.bitcoinj.core.Coin; import org.bitcoinj.core.Coin;
@Singleton @Singleton
@ -161,7 +163,7 @@ class CoreTradesService {
errorMessageHandler errorMessageHandler
); );
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.error(ExceptionUtils.getStackTrace(e));
errorMessageHandler.handleErrorMessage(e.getMessage()); errorMessageHandler.handleErrorMessage(e.getMessage());
} }
} }

View File

@ -41,6 +41,9 @@ import java.util.HashSet;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import org.apache.commons.lang3.exception.ExceptionUtils;
import javafx.beans.property.IntegerProperty; import javafx.beans.property.IntegerProperty;
import javafx.beans.property.LongProperty; import javafx.beans.property.LongProperty;
import javafx.beans.property.ObjectProperty; import javafx.beans.property.ObjectProperty;
@ -464,7 +467,7 @@ public final class XmrConnectionService {
log.info(getClass() + ".onAccountOpened() called"); log.info(getClass() + ".onAccountOpened() called");
initialize(); initialize();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.error("Error initializing connection service after account opened, error={}\n", e.getMessage(), e);
throw new RuntimeException(e); throw new RuntimeException(e);
} }
} }
@ -622,8 +625,7 @@ public final class XmrConnectionService {
log.info("Starting local node"); log.info("Starting local node");
xmrLocalNode.startMoneroNode(); xmrLocalNode.startMoneroNode();
} catch (Exception e) { } catch (Exception e) {
log.warn("Unable to start local monero node: " + e.getMessage()); log.error("Unable to start local monero node, error={}\n", e.getMessage(), e);
e.printStackTrace();
} }
} }
} }
@ -721,8 +723,8 @@ public final class XmrConnectionService {
// log error message periodically // log error message periodically
if (lastLogPollErrorTimestamp == null || System.currentTimeMillis() - lastLogPollErrorTimestamp > HavenoUtils.LOG_POLL_ERROR_PERIOD_MS) { if (lastLogPollErrorTimestamp == null || System.currentTimeMillis() - lastLogPollErrorTimestamp > HavenoUtils.LOG_POLL_ERROR_PERIOD_MS) {
log.warn("Failed to fetch daemon info, trying to switch to best connection: " + e.getMessage()); log.warn("Failed to fetch daemon info, trying to switch to best connection, error={}", e.getMessage());
if (DevEnv.isDevMode()) e.printStackTrace(); if (DevEnv.isDevMode()) log.error(ExceptionUtils.getStackTrace(e));
lastLogPollErrorTimestamp = System.currentTimeMillis(); lastLogPollErrorTimestamp = System.currentTimeMillis();
} }

View File

@ -124,7 +124,7 @@ public abstract class HavenoExecutable implements GracefulShutDownHandler, Haven
System.exit(EXIT_FAILURE); System.exit(EXIT_FAILURE);
} catch (Throwable ex) { } catch (Throwable ex) {
System.err.println("fault: An unexpected error occurred. " + System.err.println("fault: An unexpected error occurred. " +
"Please file a report at https://haveno.exchange/issues"); "Please file a report at https://github.com/haveno-dex/haveno/issues");
ex.printStackTrace(System.err); ex.printStackTrace(System.err);
System.exit(EXIT_FAILURE); System.exit(EXIT_FAILURE);
} }
@ -201,8 +201,7 @@ public abstract class HavenoExecutable implements GracefulShutDownHandler, Haven
startApplication(); startApplication();
} }
} catch (InterruptedException | ExecutionException e) { } catch (InterruptedException | ExecutionException e) {
log.error("An error occurred: {}", e.getMessage()); log.error("An error occurred: {}\n", e.getMessage(), e);
e.printStackTrace();
} }
}); });
} }
@ -362,7 +361,7 @@ public abstract class HavenoExecutable implements GracefulShutDownHandler, Haven
try { try {
ThreadUtils.awaitTasks(tasks, tasks.size(), 90000l); // run in parallel with timeout ThreadUtils.awaitTasks(tasks, tasks.size(), 90000l); // run in parallel with timeout
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.error("Failed to notify all services to prepare for shutdown: {}\n", e.getMessage(), e);
} }
injector.getInstance(TradeManager.class).shutDown(); injector.getInstance(TradeManager.class).shutDown();
@ -397,8 +396,7 @@ public abstract class HavenoExecutable implements GracefulShutDownHandler, Haven
}); });
}); });
} catch (Throwable t) { } catch (Throwable t) {
log.error("App shutdown failed with exception {}", t.toString()); log.error("App shutdown failed with exception: {}\n", t.getMessage(), t);
t.printStackTrace();
completeShutdown(resultHandler, EXIT_FAILURE, systemExit); completeShutdown(resultHandler, EXIT_FAILURE, systemExit);
} }
} }

View File

@ -376,8 +376,7 @@ public class HavenoSetup {
moneroWalletRpcFile.setExecutable(true); moneroWalletRpcFile.setExecutable(true);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.warn("Failed to install Monero binaries: {}\n", e.getMessage(), e);
log.warn("Failed to install Monero binaries: " + e.toString());
} }
} }

View File

@ -28,6 +28,9 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Paths; import java.nio.file.Paths;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.apache.commons.lang3.exception.ExceptionUtils;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
@Slf4j @Slf4j
@ -48,8 +51,7 @@ public class TorSetup {
if (resultHandler != null) if (resultHandler != null)
resultHandler.run(); resultHandler.run();
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); log.error(ExceptionUtils.getStackTrace(e));
log.error(e.toString());
if (errorMessageHandler != null) if (errorMessageHandler != null)
errorMessageHandler.handleErrorMessage(e.toString()); errorMessageHandler.handleErrorMessage(e.toString());
} }

View File

@ -123,7 +123,7 @@ public abstract class ExecutableForAppWithP2p extends HavenoExecutable {
try { try {
ThreadUtils.awaitTasks(tasks, tasks.size(), 120000l); // run in parallel with timeout ThreadUtils.awaitTasks(tasks, tasks.size(), 120000l); // run in parallel with timeout
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.error("Error awaiting tasks to complete: {}\n", e.getMessage(), e);
} }
JsonFileManager.shutDownAllInstances(); JsonFileManager.shutDownAllInstances();
@ -177,8 +177,7 @@ public abstract class ExecutableForAppWithP2p extends HavenoExecutable {
}, 1); }, 1);
} }
} catch (Throwable t) { } catch (Throwable t) {
log.debug("App shutdown failed with exception"); log.info("App shutdown failed with exception: {}\n", t.getMessage(), t);
t.printStackTrace();
PersistenceManager.flushAllDataToDiskAtShutdown(() -> { PersistenceManager.flushAllDataToDiskAtShutdown(() -> {
resultHandler.handleResult(); resultHandler.handleResult();
log.info("Graceful shutdown resulted in an error. Exiting now."); log.info("Graceful shutdown resulted in an error. Exiting now.");

View File

@ -977,7 +977,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
// handle result // handle result
resultHandler.handleResult(null); resultHandler.handleResult(null);
} catch (Exception e) { } catch (Exception e) {
if (!openOffer.isCanceled()) e.printStackTrace(); if (!openOffer.isCanceled()) log.error("Error processing pending offer: {}\n", e.getMessage(), e);
errorMessageHandler.handleErrorMessage(e.getMessage()); errorMessageHandler.handleErrorMessage(e.getMessage());
} }
}).start(); }).start();
@ -1365,9 +1365,8 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
}); });
result = true; result = true;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace();
errorMessage = "Exception at handleSignOfferRequest " + e.getMessage(); errorMessage = "Exception at handleSignOfferRequest " + e.getMessage();
log.error(errorMessage); log.error(errorMessage + "\n", e);
} finally { } finally {
sendAckMessage(request.getClass(), peer, request.getPubKeyRing(), request.getOfferId(), request.getUid(), result, errorMessage); sendAckMessage(request.getClass(), peer, request.getPubKeyRing(), request.getOfferId(), request.getUid(), result, errorMessage);
} }
@ -1519,8 +1518,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
result = true; result = true;
} catch (Throwable t) { } catch (Throwable t) {
errorMessage = "Exception at handleRequestIsOfferAvailableMessage " + t.getMessage(); errorMessage = "Exception at handleRequestIsOfferAvailableMessage " + t.getMessage();
log.error(errorMessage); log.error(errorMessage + "\n", t);
t.printStackTrace();
} finally { } finally {
sendAckMessage(request.getClass(), peer, request.getPubKeyRing(), request.getOfferId(), request.getUid(), result, errorMessage); sendAckMessage(request.getClass(), peer, request.getPubKeyRing(), request.getOfferId(), request.getUid(), result, errorMessage);
} }

View File

@ -59,8 +59,7 @@ public class FeeProvider extends HttpClientProvider {
map.put(Config.BTC_TX_FEE, btcTxFee); map.put(Config.BTC_TX_FEE, btcTxFee);
map.put(Config.BTC_MIN_TX_FEE, btcMinTxFee); map.put(Config.BTC_MIN_TX_FEE, btcMinTxFee);
} catch (Throwable t) { } catch (Throwable t) {
log.error(t.toString()); log.error("Error getting fees: {}\n", t.getMessage(), t);
t.printStackTrace();
} }
return new Tuple2<>(tsMap, map); return new Tuple2<>(tsMap, map);
} }

View File

@ -68,8 +68,7 @@ public class PriceProvider extends HttpClientProvider {
long timestampSec = MathUtils.doubleToLong((Double) treeMap.get("timestampSec")); long timestampSec = MathUtils.doubleToLong((Double) treeMap.get("timestampSec"));
marketPriceMap.put(currencyCode, new MarketPrice(currencyCode, price, timestampSec, true)); marketPriceMap.put(currencyCode, new MarketPrice(currencyCode, price, timestampSec, true));
} catch (Throwable t) { } catch (Throwable t) {
log.error(t.toString()); log.error("Error getting all prices: {}\n", t.getMessage(), t);
t.printStackTrace();
} }
}); });

View File

@ -83,6 +83,9 @@ import monero.wallet.model.MoneroTxConfig;
import monero.wallet.model.MoneroTxWallet; import monero.wallet.model.MoneroTxWallet;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.apache.commons.lang3.exception.ExceptionUtils;
import java.math.BigInteger; import java.math.BigInteger;
import java.security.KeyPair; import java.security.KeyPair;
import java.time.Instant; import java.time.Instant;
@ -523,7 +526,7 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
DisputeValidation.validateSenderNodeAddress(dispute, message.getSenderNodeAddress(), config); DisputeValidation.validateSenderNodeAddress(dispute, message.getSenderNodeAddress(), config);
//DisputeValidation.testIfDisputeTriesReplay(dispute, disputeList.getList()); //DisputeValidation.testIfDisputeTriesReplay(dispute, disputeList.getList());
} catch (DisputeValidation.ValidationException e) { } catch (DisputeValidation.ValidationException e) {
e.printStackTrace(); log.error(ExceptionUtils.getStackTrace(e));
validationExceptions.add(e); validationExceptions.add(e);
throw e; throw e;
} }
@ -532,9 +535,9 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
try { try {
DisputeValidation.validatePaymentAccountPayload(dispute); // TODO: add field to dispute details: valid, invalid, missing DisputeValidation.validatePaymentAccountPayload(dispute); // TODO: add field to dispute details: valid, invalid, missing
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.error(ExceptionUtils.getStackTrace(e));
log.warn(e.getMessage());
trade.prependErrorMessage(e.getMessage()); trade.prependErrorMessage(e.getMessage());
throw e;
} }
// get sender // get sender
@ -606,9 +609,8 @@ public abstract class DisputeManager<T extends DisputeList<Dispute>> extends Sup
} }
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.error(ExceptionUtils.getStackTrace(e));
errorMessage = e.getMessage(); errorMessage = e.getMessage();
log.warn(errorMessage);
if (trade != null) trade.setErrorMessage(errorMessage); if (trade != null) trade.setErrorMessage(errorMessage);
} }

View File

@ -71,7 +71,7 @@ public class DisputeSummaryVerification {
disputeAgent = arbitratorManager.getDisputeAgentByNodeAddress(nodeAddress).orElse(null); disputeAgent = arbitratorManager.getDisputeAgentByNodeAddress(nodeAddress).orElse(null);
checkNotNull(disputeAgent, "Dispute agent is null"); checkNotNull(disputeAgent, "Dispute agent is null");
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); log.error("Error verifying signature: {}\n", e.getMessage(), e);
throw new IllegalArgumentException(Res.get("support.sigCheck.popup.invalidFormat")); throw new IllegalArgumentException(Res.get("support.sigCheck.popup.invalidFormat"));
} }
@ -93,7 +93,7 @@ public class DisputeSummaryVerification {
throw new IllegalArgumentException(Res.get("support.sigCheck.popup.failed")); throw new IllegalArgumentException(Res.get("support.sigCheck.popup.failed"));
} }
} catch (Throwable e) { } catch (Throwable e) {
e.printStackTrace(); log.error("Error verifying signature with agent pub key ring: {}\n", e.getMessage(), e);
throw new IllegalArgumentException(Res.get("support.sigCheck.popup.invalidFormat")); throw new IllegalArgumentException(Res.get("support.sigCheck.popup.invalidFormat"));
} }
} }

View File

@ -94,6 +94,8 @@ import java.util.Map;
import java.util.Optional; import java.util.Optional;
import java.util.Set; import java.util.Set;
import org.apache.commons.lang3.exception.ExceptionUtils;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j @Slf4j
@ -355,7 +357,7 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
requestPersistence(trade); requestPersistence(trade);
} catch (Exception e) { } catch (Exception e) {
log.warn("Error processing dispute closed message: {}", e.getMessage()); log.warn("Error processing dispute closed message: {}", e.getMessage());
e.printStackTrace(); log.warn(ExceptionUtils.getStackTrace(e));
requestPersistence(trade); requestPersistence(trade);
// nack bad message and do not reprocess // nack bad message and do not reprocess
@ -489,8 +491,7 @@ public final class ArbitrationManager extends DisputeManager<ArbitrationDisputeL
try { try {
feeEstimateTx = createDisputePayoutTx(trade, dispute.getContract(), disputeResult, false); feeEstimateTx = createDisputePayoutTx(trade, dispute.getContract(), disputeResult, false);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.warn("Could not recreate dispute payout tx to verify fee: {}\n", e.getMessage(), e);
log.warn("Could not recreate dispute payout tx to verify fee: " + e.getMessage());
} }
if (feeEstimateTx != null) { if (feeEstimateTx != null) {
BigInteger feeEstimate = feeEstimateTx.getFee(); BigInteger feeEstimate = feeEstimateTx.getFee();

View File

@ -999,8 +999,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
xmrWalletService.deleteWallet(getWalletName()); xmrWalletService.deleteWallet(getWalletName());
xmrWalletService.deleteWalletBackups(getWalletName()); xmrWalletService.deleteWalletBackups(getWalletName());
} catch (Exception e) { } catch (Exception e) {
log.warn(e.getMessage()); log.warn("Error deleting wallet for {} {}: {}\n", getClass().getSimpleName(), getId(), e.getMessage(), e);
e.printStackTrace();
setErrorMessage(e.getMessage()); setErrorMessage(e.getMessage());
processModel.getTradeManager().getNotificationService().sendErrorNotification("Error", e.getMessage()); processModel.getTradeManager().getNotificationService().sendErrorNotification("Error", e.getMessage());
} }
@ -1051,7 +1050,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
synchronized (HavenoUtils.getWalletFunctionLock()) { synchronized (HavenoUtils.getWalletFunctionLock()) {
MoneroTxWallet tx = wallet.createTx(txConfig); MoneroTxWallet tx = wallet.createTx(txConfig);
exportMultisigHex(); exportMultisigHex();
requestSaveWallet(); saveWallet();
return tx; return tx;
} }
} }
@ -1152,7 +1151,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
throw e; throw e;
} }
} }
requestSaveWallet(); saveWallet();
} }
log.info("Done importing multisig hexes for {} {} in {} ms, count={}", getClass().getSimpleName(), getShortId(), System.currentTimeMillis() - startTime, multisigHexes.size()); log.info("Done importing multisig hexes for {} {} in {} ms, count={}", getClass().getSimpleName(), getShortId(), System.currentTimeMillis() - startTime, multisigHexes.size());
} }
@ -1365,6 +1364,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
// verify fee is within tolerance by recreating payout tx // verify fee is within tolerance by recreating payout tx
// TODO (monero-project): creating tx will require exchanging updated multisig hex if message needs reprocessed. provide weight with describe_transfer so fee can be estimated? // TODO (monero-project): creating tx will require exchanging updated multisig hex if message needs reprocessed. provide weight with describe_transfer so fee can be estimated?
log.info("Creating fee estimate tx for {} {}", getClass().getSimpleName(), getId()); log.info("Creating fee estimate tx for {} {}", getClass().getSimpleName(), getId());
saveWallet(); // save wallet before creating fee estimate tx
MoneroTxWallet feeEstimateTx = createPayoutTx(); MoneroTxWallet feeEstimateTx = createPayoutTx();
BigInteger feeEstimate = feeEstimateTx.getFee(); BigInteger feeEstimate = feeEstimateTx.getFee();
double feeDiff = payoutTx.getFee().subtract(feeEstimate).abs().doubleValue() / feeEstimate.doubleValue(); // TODO: use BigDecimal? double feeDiff = payoutTx.getFee().subtract(feeEstimate).abs().doubleValue() / feeEstimate.doubleValue(); // TODO: use BigDecimal?
@ -1373,6 +1373,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
} }
// save trade state // save trade state
saveWallet();
requestPersistence(); requestPersistence();
// submit payout tx // submit payout tx
@ -1536,8 +1537,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
try { try {
ThreadUtils.awaitTask(shutDownTask, SHUTDOWN_TIMEOUT_MS); ThreadUtils.awaitTask(shutDownTask, SHUTDOWN_TIMEOUT_MS);
} catch (Exception e) { } catch (Exception e) {
log.warn("Error shutting down {} {}: {}", getClass().getSimpleName(), getId(), e.getMessage()); log.warn("Error shutting down {} {}: {}\n", getClass().getSimpleName(), getId(), e.getMessage(), e);
e.printStackTrace();
// force close wallet // force close wallet
forceCloseWallet(); forceCloseWallet();
@ -2817,8 +2817,7 @@ public abstract class Trade extends XmrWalletBase implements Tradable, Model {
processing = false; processing = false;
if (!isInitialized || isShutDownStarted) return; if (!isInitialized || isShutDownStarted) return;
if (isWalletConnectedToDaemon()) { if (isWalletConnectedToDaemon()) {
e.printStackTrace(); log.warn("Error polling idle trade for {} {}: {}. Monerod={}\n", getClass().getSimpleName(), getId(), e.getMessage(), getXmrWalletService().getXmrConnectionService().getConnection(), e);
log.warn("Error polling idle trade for {} {}: {}. Monerod={}", getClass().getSimpleName(), getId(), e.getMessage(), getXmrWalletService().getXmrConnectionService().getConnection());
}; };
} }
}, getId()); }, getId());

View File

@ -366,8 +366,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
trade.onShutDownStarted(); trade.onShutDownStarted();
} catch (Exception e) { } catch (Exception e) {
if (e.getMessage() != null && e.getMessage().contains("Connection reset")) return; // expected if shut down with ctrl+c if (e.getMessage() != null && e.getMessage().contains("Connection reset")) return; // expected if shut down with ctrl+c
log.warn("Error notifying {} {} that shut down started {}", trade.getClass().getSimpleName(), trade.getId()); log.warn("Error notifying {} {} that shut down started: {}\n", trade.getClass().getSimpleName(), trade.getId(), e.getMessage(), e);
e.printStackTrace();
} }
}); });
try { try {
@ -396,15 +395,13 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
trade.shutDown(); trade.shutDown();
} catch (Exception e) { } catch (Exception e) {
if (e.getMessage() != null && (e.getMessage().contains("Connection reset") || e.getMessage().contains("Connection refused"))) return; // expected if shut down with ctrl+c if (e.getMessage() != null && (e.getMessage().contains("Connection reset") || e.getMessage().contains("Connection refused"))) return; // expected if shut down with ctrl+c
log.warn("Error closing {} {}", trade.getClass().getSimpleName(), trade.getId()); log.warn("Error closing {} {}: {}", trade.getClass().getSimpleName(), trade.getId(), e.getMessage(), e);
e.printStackTrace();
} }
}); });
try { try {
ThreadUtils.awaitTasks(tasks); ThreadUtils.awaitTasks(tasks);
} catch (Exception e) { } catch (Exception e) {
log.warn("Error shutting down trades: {}", e.getMessage()); log.warn("Error shutting down trades: {}\n", e.getMessage(), e);
e.printStackTrace();
} }
} }
@ -462,8 +459,7 @@ public class TradeManager implements PersistedDataHost, DecryptedDirectMessageLi
} }
} catch (Exception e) { } catch (Exception e) {
if (!isShutDownStarted) { if (!isShutDownStarted) {
e.printStackTrace(); log.warn("Error initializing {} {}: {}\n", trade.getClass().getSimpleName(), trade.getId(), e.getMessage(), e);
log.warn("Error initializing {} {}: {}", trade.getClass().getSimpleName(), trade.getId(), e.getMessage());
trade.setInitError(e); trade.setInitError(e);
} }
} }

View File

@ -68,7 +68,7 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
complete(); complete();
} catch (Throwable t) { } catch (Throwable t) {
this.error = t; this.error = t;
t.printStackTrace(); log.error("Error processing deposit request for trade {}: {}\n", trade.getId(), t.getMessage(), t);
trade.setStateIfValidTransitionTo(Trade.State.PUBLISH_DEPOSIT_TX_REQUEST_FAILED); trade.setStateIfValidTransitionTo(Trade.State.PUBLISH_DEPOSIT_TX_REQUEST_FAILED);
failed(t); failed(t);
} }
@ -155,15 +155,14 @@ public class ArbitratorProcessDepositRequest extends TradeTask {
log.info("Arbitrator published deposit txs for trade " + trade.getId()); log.info("Arbitrator published deposit txs for trade " + trade.getId());
trade.setStateIfValidTransitionTo(Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS); trade.setStateIfValidTransitionTo(Trade.State.ARBITRATOR_PUBLISHED_DEPOSIT_TXS);
} catch (Exception e) { } catch (Exception e) {
log.warn("Arbitrator error publishing deposit txs for trade {} {}: {}", trade.getClass().getSimpleName(), trade.getShortId(), e.getMessage()); log.warn("Arbitrator error publishing deposit txs for trade {} {}: {}\n", trade.getClass().getSimpleName(), trade.getShortId(), e.getMessage(), e);
e.printStackTrace();
if (!depositTxsRelayed) { if (!depositTxsRelayed) {
// flush txs from pool // flush txs from pool
try { try {
daemon.flushTxPool(processModel.getMaker().getDepositTxHash(), processModel.getTaker().getDepositTxHash()); daemon.flushTxPool(processModel.getMaker().getDepositTxHash(), processModel.getTaker().getDepositTxHash());
} catch (Exception e2) { } catch (Exception e2) {
e2.printStackTrace(); log.warn("Error flushing deposit txs from pool for trade {}: {}\n", trade.getId(), e2.getMessage(), e2);
} }
} }
throw e; throw e;

View File

@ -29,6 +29,8 @@ import monero.daemon.model.MoneroTx;
import java.math.BigInteger; import java.math.BigInteger;
import org.apache.commons.lang3.exception.ExceptionUtils;
/** /**
* Arbitrator verifies reserve tx from maker or taker. * Arbitrator verifies reserve tx from maker or taker.
* *
@ -73,7 +75,7 @@ public class ArbitratorProcessReserveTx extends TradeTask {
request.getReserveTxKey(), request.getReserveTxKey(),
null); null);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.error(ExceptionUtils.getStackTrace(e));
throw new RuntimeException("Error processing reserve tx from " + (isFromMaker ? "maker " : "taker ") + processModel.getTempTradePeerNodeAddress() + ", offerId=" + offer.getId() + ": " + e.getMessage()); throw new RuntimeException("Error processing reserve tx from " + (isFromMaker ? "maker " : "taker ") + processModel.getTempTradePeerNodeAddress() + ", offerId=" + offer.getId() + ": " + e.getMessage());
} }

View File

@ -62,7 +62,7 @@ public class MaybeResendDisputeClosedMessageWithPayout extends TradeTask {
HavenoUtils.arbitrationManager.closeDisputeTicket(dispute.getDisputeResultProperty().get(), dispute, dispute.getDisputeResultProperty().get().summaryNotesProperty().get(), () -> { HavenoUtils.arbitrationManager.closeDisputeTicket(dispute.getDisputeResultProperty().get(), dispute, dispute.getDisputeResultProperty().get().summaryNotesProperty().get(), () -> {
completeAux(); completeAux();
}, (errMessage, err) -> { }, (errMessage, err) -> {
err.printStackTrace(); log.error("Failed to close dispute ticket for trade {}: {}\n", trade.getId(), errMessage, err);
failed(err); failed(err);
}); });
ticketClosed = true; ticketClosed = true;

View File

@ -70,7 +70,7 @@ public class ProcessDepositsConfirmedMessage extends TradeTask {
try { try {
trade.importMultisigHex(); trade.importMultisigHex();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.warn("Error importing multisig hex on deposits confirmed for trade " + trade.getId() + ": " + e.getMessage() + "\n", e);
} }
}); });
} }

View File

@ -32,6 +32,7 @@ import haveno.network.p2p.NodeAddress;
import haveno.network.p2p.SendDirectMessageListener; import haveno.network.p2p.SendDirectMessageListener;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import monero.wallet.MoneroWallet; import monero.wallet.MoneroWallet;
import monero.wallet.model.MoneroMultisigInfo;
import monero.wallet.model.MoneroMultisigInitResult; import monero.wallet.model.MoneroMultisigInitResult;
import java.util.Arrays; import java.util.Arrays;
@ -118,8 +119,17 @@ public class ProcessInitMultisigRequest extends TradeTask {
if (processModel.getMultisigAddress() == null && peers[0].getExchangedMultisigHex() != null && peers[1].getExchangedMultisigHex() != null) { if (processModel.getMultisigAddress() == null && peers[0].getExchangedMultisigHex() != null && peers[1].getExchangedMultisigHex() != null) {
log.info("Importing exchanged multisig hex for trade {}", trade.getId()); log.info("Importing exchanged multisig hex for trade {}", trade.getId());
MoneroMultisigInitResult result = multisigWallet.exchangeMultisigKeys(Arrays.asList(peers[0].getExchangedMultisigHex(), peers[1].getExchangedMultisigHex()), xmrWalletService.getWalletPassword()); MoneroMultisigInitResult result = multisigWallet.exchangeMultisigKeys(Arrays.asList(peers[0].getExchangedMultisigHex(), peers[1].getExchangedMultisigHex()), xmrWalletService.getWalletPassword());
// check multisig state
MoneroMultisigInfo multisigInfo = multisigWallet.getMultisigInfo();
if (!multisigInfo.isMultisig()) throw new RuntimeException("Multisig wallet is not multisig on completion");
if (!multisigInfo.isReady()) throw new RuntimeException("Multisig wallet is not ready on completion");
if (multisigInfo.getThreshold() != 2) throw new RuntimeException("Multisig wallet has unexpected threshold: " + multisigInfo.getThreshold());
if (multisigInfo.getNumParticipants() != 3) throw new RuntimeException("Multisig wallet has unexpected number of participants: " + multisigInfo.getNumParticipants());
// set final address and save
processModel.setMultisigAddress(result.getAddress()); processModel.setMultisigAddress(result.getAddress());
new Thread(() -> trade.saveWallet()).start(); // save multisig wallet off thread on completion trade.saveWallet();
trade.setStateIfValidTransitionTo(Trade.State.MULTISIG_COMPLETED); trade.setStateIfValidTransitionTo(Trade.State.MULTISIG_COMPLETED);
} }

View File

@ -61,7 +61,7 @@ public abstract class TradeTask extends Task<Trade> {
@Override @Override
protected void failed(Throwable t) { protected void failed(Throwable t) {
t.printStackTrace(); log.error("Trade task failed, error={}\n", t.getMessage(), t);
appendExceptionToErrorMessage(t); appendExceptionToErrorMessage(t);
trade.setErrorMessage(errorMessage); trade.setErrorMessage(errorMessage);
processModel.getTradeManager().requestPersistence(); processModel.getTradeManager().requestPersistence();

View File

@ -6,6 +6,8 @@ import java.util.Optional;
import java.util.concurrent.CountDownLatch; import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeUnit;
import org.apache.commons.lang3.exception.ExceptionUtils;
import haveno.common.Timer; import haveno.common.Timer;
import haveno.common.UserThread; import haveno.common.UserThread;
import haveno.core.api.XmrConnectionService; import haveno.core.api.XmrConnectionService;
@ -106,7 +108,7 @@ public class XmrWalletBase {
height = wallet.getHeight(); // can get read timeout while syncing height = wallet.getHeight(); // can get read timeout while syncing
} catch (Exception e) { } catch (Exception e) {
log.warn("Error getting wallet height while syncing with progress: " + e.getMessage()); log.warn("Error getting wallet height while syncing with progress: " + e.getMessage());
if (wallet != null && !isShutDownStarted) e.printStackTrace(); if (wallet != null && !isShutDownStarted) log.warn(ExceptionUtils.getStackTrace(e));
// stop polling and release latch // stop polling and release latch
syncProgressError = e; syncProgressError = e;

View File

@ -818,7 +818,7 @@ public class XmrWalletService extends XmrWalletBase {
MoneroFeeEstimate feeEstimates = getDaemon().getFeeEstimate(); MoneroFeeEstimate feeEstimates = getDaemon().getFeeEstimate();
BigInteger baseFeeEstimate = feeEstimates.getFees().get(2); // get elevated fee per kB BigInteger baseFeeEstimate = feeEstimates.getFees().get(2); // get elevated fee per kB
BigInteger qmask = feeEstimates.getQuantizationMask(); BigInteger qmask = feeEstimates.getQuantizationMask();
log.info("Monero base fee estimate={}, qmask={}: " + baseFeeEstimate, qmask); log.info("Monero base fee estimate={}, qmask={}", baseFeeEstimate, qmask);
// get tx base fee // get tx base fee
BigInteger baseFee = baseFeeEstimate.multiply(BigInteger.valueOf(txWeight)); BigInteger baseFee = baseFeeEstimate.multiply(BigInteger.valueOf(txWeight));
@ -922,8 +922,7 @@ public class XmrWalletService extends XmrWalletBase {
try { try {
ThreadUtils.awaitTask(shutDownTask, SHUTDOWN_TIMEOUT_MS); ThreadUtils.awaitTask(shutDownTask, SHUTDOWN_TIMEOUT_MS);
} catch (Exception e) { } catch (Exception e) {
log.warn("Error shutting down {}: {}", getClass().getSimpleName(), e.getMessage()); log.warn("Error shutting down {}: {}\n", getClass().getSimpleName(), e.getMessage(), e);
e.printStackTrace();
// force close wallet // force close wallet
forceCloseMainWallet(); forceCloseMainWallet();
@ -945,8 +944,7 @@ public class XmrWalletService extends XmrWalletBase {
List<XmrAddressEntry> unusedAddressEntries = getUnusedAddressEntries(); List<XmrAddressEntry> unusedAddressEntries = getUnusedAddressEntries();
if (!unusedAddressEntries.isEmpty()) return xmrAddressEntryList.swapAvailableToAddressEntryWithOfferId(unusedAddressEntries.get(0), context, offerId); if (!unusedAddressEntries.isEmpty()) return xmrAddressEntryList.swapAvailableToAddressEntryWithOfferId(unusedAddressEntries.get(0), context, offerId);
} catch (Exception e) { } catch (Exception e) {
log.warn("Error getting new address entry based on incoming transactions"); log.warn("Error getting new address entry based on incoming transactions: {}\n", e.getMessage(), e);
e.printStackTrace();
} }
// create new entry // create new entry
@ -1172,8 +1170,7 @@ public class XmrWalletService extends XmrWalletBase {
try { try {
balanceListener.onBalanceChanged(balance); balanceListener.onBalanceChanged(balance);
} catch (Exception e) { } catch (Exception e) {
log.warn("Failed to notify balance listener of change"); log.warn("Failed to notify balance listener of change: {}\n", e.getMessage(), e);
e.printStackTrace();
} }
}); });
} }
@ -1309,8 +1306,7 @@ public class XmrWalletService extends XmrWalletBase {
try { try {
doMaybeInitMainWallet(sync, MAX_SYNC_ATTEMPTS); doMaybeInitMainWallet(sync, MAX_SYNC_ATTEMPTS);
} catch (Exception e) { } catch (Exception e) {
log.warn("Error initializing main wallet: " + e.getMessage()); log.warn("Error initializing main wallet: {}\n", e.getMessage(), e);
e.printStackTrace();
HavenoUtils.setTopError(e.getMessage()); HavenoUtils.setTopError(e.getMessage());
throw e; throw e;
} }
@ -1459,9 +1455,10 @@ public class XmrWalletService extends XmrWalletBase {
log.info("Done creating full wallet " + config.getPath() + " in " + (System.currentTimeMillis() - time) + " ms"); log.info("Done creating full wallet " + config.getPath() + " in " + (System.currentTimeMillis() - time) + " ms");
return walletFull; return walletFull;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); String errorMsg = "Could not create wallet '" + config.getPath() + "': " + e.getMessage();
log.warn(errorMsg + "\n", e);
if (walletFull != null) forceCloseWallet(walletFull, config.getPath()); if (walletFull != null) forceCloseWallet(walletFull, config.getPath());
throw new IllegalStateException("Could not create wallet '" + config.getPath() + "'"); throw new IllegalStateException(errorMsg);
} }
} }
@ -1503,15 +1500,15 @@ public class XmrWalletService extends XmrWalletBase {
} }
// handle success or failure // handle success or failure
File originalCacheBackup = new File(cachePath + ".backup");
if (retrySuccessful) { if (retrySuccessful) {
originalCacheFile.delete(); // delete original wallet cache backup if (originalCacheBackup.exists()) originalCacheBackup.delete(); // delete original wallet cache backup
} else { } else {
// restore original wallet cache // restore original wallet cache
log.warn("Failed to open full wallet using backup cache, restoring original cache"); log.warn("Failed to open full wallet using backup cache, restoring original cache");
File cacheFile = new File(cachePath); File cacheFile = new File(cachePath);
if (cacheFile.exists()) cacheFile.delete(); if (cacheFile.exists()) cacheFile.delete();
File originalCacheBackup = new File(cachePath + ".backup");
if (originalCacheBackup.exists()) originalCacheBackup.renameTo(new File(cachePath)); if (originalCacheBackup.exists()) originalCacheBackup.renameTo(new File(cachePath));
// throw exception // throw exception
@ -1525,9 +1522,10 @@ public class XmrWalletService extends XmrWalletBase {
log.info("Done opening full wallet " + config.getPath()); log.info("Done opening full wallet " + config.getPath());
return walletFull; return walletFull;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); String errorMsg = "Could not open full wallet '" + config.getPath() + "': " + e.getMessage();
log.warn(errorMsg + "\n", e);
if (walletFull != null) forceCloseWallet(walletFull, config.getPath()); if (walletFull != null) forceCloseWallet(walletFull, config.getPath());
throw new IllegalStateException("Could not open full wallet '" + config.getPath() + "'"); throw new IllegalStateException(errorMsg);
} }
} }
@ -1557,7 +1555,7 @@ public class XmrWalletService extends XmrWalletBase {
log.info("Done creating RPC wallet " + config.getPath() + " in " + (System.currentTimeMillis() - time) + " ms"); log.info("Done creating RPC wallet " + config.getPath() + " in " + (System.currentTimeMillis() - time) + " ms");
return walletRpc; return walletRpc;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.warn("Could not create wallet '" + config.getPath() + "': " + e.getMessage() + "\n", e);
if (walletRpc != null) forceCloseWallet(walletRpc, config.getPath()); if (walletRpc != null) forceCloseWallet(walletRpc, config.getPath());
throw new IllegalStateException("Could not create wallet '" + config.getPath() + "'. Please close Haveno, stop all monero-wallet-rpc processes in your task manager, and restart Haveno."); throw new IllegalStateException("Could not create wallet '" + config.getPath() + "'. Please close Haveno, stop all monero-wallet-rpc processes in your task manager, and restart Haveno.");
} }
@ -1607,15 +1605,15 @@ public class XmrWalletService extends XmrWalletBase {
} }
// handle success or failure // handle success or failure
File originalCacheBackup = new File(cachePath + ".backup");
if (retrySuccessful) { if (retrySuccessful) {
originalCacheFile.delete(); // delete original wallet cache backup if (originalCacheBackup.exists()) originalCacheBackup.delete(); // delete original wallet cache backup
} else { } else {
// restore original wallet cache // restore original wallet cache
log.warn("Failed to open RPC wallet using backup cache, restoring original cache"); log.warn("Failed to open RPC wallet using backup cache, restoring original cache");
File cacheFile = new File(cachePath); File cacheFile = new File(cachePath);
if (cacheFile.exists()) cacheFile.delete(); if (cacheFile.exists()) cacheFile.delete();
File originalCacheBackup = new File(cachePath + ".backup");
if (originalCacheBackup.exists()) originalCacheBackup.renameTo(new File(cachePath)); if (originalCacheBackup.exists()) originalCacheBackup.renameTo(new File(cachePath));
// throw exception // throw exception
@ -1629,7 +1627,7 @@ public class XmrWalletService extends XmrWalletBase {
log.info("Done opening RPC wallet " + config.getPath()); log.info("Done opening RPC wallet " + config.getPath());
return walletRpc; return walletRpc;
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.warn("Could not open wallet '" + config.getPath() + "': " + e.getMessage() + "\n", e);
if (walletRpc != null) forceCloseWallet(walletRpc, config.getPath()); if (walletRpc != null) forceCloseWallet(walletRpc, config.getPath());
throw new IllegalStateException("Could not open wallet '" + config.getPath() + "'. Please close Haveno, stop all monero-wallet-rpc processes in your task manager, and restart Haveno.\n\nError message: " + e.getMessage()); throw new IllegalStateException("Could not open wallet '" + config.getPath() + "'. Please close Haveno, stop all monero-wallet-rpc processes in your task manager, and restart Haveno.\n\nError message: " + e.getMessage());
} }
@ -1733,7 +1731,7 @@ public class XmrWalletService extends XmrWalletBase {
wallet.changePassword(oldPassword, newPassword); wallet.changePassword(oldPassword, newPassword);
saveMainWallet(); saveMainWallet();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.warn("Error changing main wallet password: " + e.getMessage() + "\n", e);
throw e; throw e;
} }
}); });
@ -1916,7 +1914,7 @@ public class XmrWalletService extends XmrWalletBase {
cacheWalletInfo(); cacheWalletInfo();
requestSaveMainWallet(); requestSaveMainWallet();
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.warn("Error caching wallet info: " + e.getMessage() + "\n", e);
} }
} }
} }

View File

@ -54,6 +54,7 @@ class TransactionsListItem {
private boolean received; private boolean received;
private boolean detailsAvailable; private boolean detailsAvailable;
private BigInteger amount = BigInteger.ZERO; private BigInteger amount = BigInteger.ZERO;
private BigInteger txFee = BigInteger.ZERO;
private String memo = ""; private String memo = "";
private long confirmations = 0; private long confirmations = 0;
@Getter @Getter
@ -107,6 +108,7 @@ class TransactionsListItem {
amount = valueSentFromMe.multiply(BigInteger.valueOf(-1)); amount = valueSentFromMe.multiply(BigInteger.valueOf(-1));
received = false; received = false;
direction = Res.get("funds.tx.direction.sentTo"); direction = Res.get("funds.tx.direction.sentTo");
txFee = tx.getFee().multiply(BigInteger.valueOf(-1));
} }
if (optionalTradable.isPresent()) { if (optionalTradable.isPresent()) {
@ -201,6 +203,14 @@ class TransactionsListItem {
return amount; return amount;
} }
public BigInteger getTxFee() {
return txFee;
}
public String getTxFeeStr() {
return txFee.equals(BigInteger.ZERO) ? "" : HavenoUtils.formatXmr(txFee);
}
public String getAddressString() { public String getAddressString() {
return addressString; return addressString;
} }

View File

@ -36,7 +36,8 @@
<TableColumn fx:id="detailsColumn" minWidth="220" maxWidth="220"/> <TableColumn fx:id="detailsColumn" minWidth="220" maxWidth="220"/>
<TableColumn fx:id="addressColumn" minWidth="260"/> <TableColumn fx:id="addressColumn" minWidth="260"/>
<TableColumn fx:id="transactionColumn" minWidth="180"/> <TableColumn fx:id="transactionColumn" minWidth="180"/>
<TableColumn fx:id="amountColumn" minWidth="130" maxWidth="130"/> <TableColumn fx:id="amountColumn" minWidth="110" maxWidth="110"/>
<TableColumn fx:id="txFeeColumn" minWidth="110" maxWidth="110"/>
<TableColumn fx:id="memoColumn" minWidth="40"/> <TableColumn fx:id="memoColumn" minWidth="40"/>
<TableColumn fx:id="confidenceColumn" minWidth="120" maxWidth="130"/> <TableColumn fx:id="confidenceColumn" minWidth="120" maxWidth="130"/>
<TableColumn fx:id="revertTxColumn" sortable="false" minWidth="110" maxWidth="110" visible="false"/> <TableColumn fx:id="revertTxColumn" sortable="false" minWidth="110" maxWidth="110" visible="false"/>

View File

@ -70,7 +70,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
@FXML @FXML
TableView<TransactionsListItem> tableView; TableView<TransactionsListItem> tableView;
@FXML @FXML
TableColumn<TransactionsListItem, TransactionsListItem> dateColumn, detailsColumn, addressColumn, transactionColumn, amountColumn, memoColumn, confidenceColumn, revertTxColumn; TableColumn<TransactionsListItem, TransactionsListItem> dateColumn, detailsColumn, addressColumn, transactionColumn, amountColumn, txFeeColumn, memoColumn, confidenceColumn, revertTxColumn;
@FXML @FXML
Label numItems; Label numItems;
@FXML @FXML
@ -89,7 +89,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
private EventHandler<KeyEvent> keyEventEventHandler; private EventHandler<KeyEvent> keyEventEventHandler;
private Scene scene; private Scene scene;
private TransactionsUpdater transactionsUpdater = new TransactionsUpdater(); private final TransactionsUpdater transactionsUpdater = new TransactionsUpdater();
private class TransactionsUpdater extends MoneroWalletListener { private class TransactionsUpdater extends MoneroWalletListener {
@Override @Override
@ -129,11 +129,12 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
addressColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.address"))); addressColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.address")));
transactionColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.txId", Res.getBaseCurrencyCode()))); transactionColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.txId", Res.getBaseCurrencyCode())));
amountColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amountWithCur", Res.getBaseCurrencyCode()))); amountColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.amountWithCur", Res.getBaseCurrencyCode())));
txFeeColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.txFee", Res.getBaseCurrencyCode())));
memoColumn.setGraphic(new AutoTooltipLabel(Res.get("funds.tx.memo"))); memoColumn.setGraphic(new AutoTooltipLabel(Res.get("funds.tx.memo")));
confidenceColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.confirmations", Res.getBaseCurrencyCode()))); confidenceColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.confirmations", Res.getBaseCurrencyCode())));
revertTxColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.revert", Res.getBaseCurrencyCode()))); revertTxColumn.setGraphic(new AutoTooltipLabel(Res.get("shared.revert", Res.getBaseCurrencyCode())));
tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY); tableView.setColumnResizePolicy(TableView.CONSTRAINED_RESIZE_POLICY_FLEX_LAST_COLUMN);
tableView.setPlaceholder(new AutoTooltipLabel(Res.get("funds.tx.noTxAvailable"))); tableView.setPlaceholder(new AutoTooltipLabel(Res.get("funds.tx.noTxAvailable")));
setDateColumnCellFactory(); setDateColumnCellFactory();
@ -141,6 +142,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
setAddressColumnCellFactory(); setAddressColumnCellFactory();
setTransactionColumnCellFactory(); setTransactionColumnCellFactory();
setAmountColumnCellFactory(); setAmountColumnCellFactory();
setTxFeeColumnCellFactory();
setMemoColumnCellFactory(); setMemoColumnCellFactory();
setConfidenceColumnCellFactory(); setConfidenceColumnCellFactory();
setRevertTxColumnCellFactory(); setRevertTxColumnCellFactory();
@ -156,7 +158,7 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
addressColumn.setComparator(Comparator.comparing(item -> item.getDirection() + item.getAddressString())); addressColumn.setComparator(Comparator.comparing(item -> item.getDirection() + item.getAddressString()));
transactionColumn.setComparator(Comparator.comparing(TransactionsListItem::getTxId)); transactionColumn.setComparator(Comparator.comparing(TransactionsListItem::getTxId));
amountColumn.setComparator(Comparator.comparing(TransactionsListItem::getAmount)); amountColumn.setComparator(Comparator.comparing(TransactionsListItem::getAmount));
confidenceColumn.setComparator(Comparator.comparingLong(item -> item.getNumConfirmations())); confidenceColumn.setComparator(Comparator.comparingLong(TransactionsListItem::getNumConfirmations));
memoColumn.setComparator(Comparator.comparing(TransactionsListItem::getMemo)); memoColumn.setComparator(Comparator.comparing(TransactionsListItem::getMemo));
dateColumn.setSortType(TableColumn.SortType.DESCENDING); dateColumn.setSortType(TableColumn.SortType.DESCENDING);
@ -216,8 +218,9 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
columns[2] = item.getDirection() + " " + item.getAddressString(); columns[2] = item.getDirection() + " " + item.getAddressString();
columns[3] = item.getTxId(); columns[3] = item.getTxId();
columns[4] = item.getAmountStr(); columns[4] = item.getAmountStr();
columns[5] = item.getMemo() == null ? "" : item.getMemo(); columns[5] = item.getTxFeeStr();
columns[6] = String.valueOf(item.getNumConfirmations()); columns[6] = item.getMemo() == null ? "" : item.getMemo();
columns[7] = String.valueOf(item.getNumConfirmations());
return columns; return columns;
}; };
@ -414,6 +417,33 @@ public class TransactionsView extends ActivatableView<VBox, Void> {
}); });
} }
private void setTxFeeColumnCellFactory() {
txFeeColumn.setCellValueFactory((addressListItem) ->
new ReadOnlyObjectWrapper<>(addressListItem.getValue()));
txFeeColumn.setCellFactory(
new Callback<>() {
@Override
public TableCell<TransactionsListItem, TransactionsListItem> call(TableColumn<TransactionsListItem,
TransactionsListItem> column) {
return new TableCell<>() {
@Override
public void updateItem(final TransactionsListItem item, boolean empty) {
super.updateItem(item, empty);
if (item != null && !empty) {
setGraphic(new AutoTooltipLabel(item.getTxFeeStr()));
} else {
setGraphic(null);
}
}
};
}
});
}
private void setMemoColumnCellFactory() { private void setMemoColumnCellFactory() {
memoColumn.setCellValueFactory((addressListItem) -> memoColumn.setCellValueFactory((addressListItem) ->
new ReadOnlyObjectWrapper<>(addressListItem.getValue())); new ReadOnlyObjectWrapper<>(addressListItem.getValue()));

View File

@ -678,7 +678,7 @@ public class DisputeSummaryWindow extends Overlay<DisputeSummaryWindow> {
closeTicketButton.disableProperty().unbind(); closeTicketButton.disableProperty().unbind();
hide(); hide();
}, (errMessage, err) -> { }, (errMessage, err) -> {
log.error(errMessage); log.error("Error closing dispute ticket: " + errMessage + "\n", err);
new Popup().error(err.toString()).show(); new Popup().error(err.toString()).show();
}); });
} }

View File

@ -153,8 +153,7 @@ public abstract class TradeSubView extends HBox {
tradeStepView.setChatCallback(chatCallback); tradeStepView.setChatCallback(chatCallback);
tradeStepView.activate(); tradeStepView.activate();
} catch (Exception e) { } catch (Exception e) {
log.error("Creating viewClass {} caused an error {}", viewClass, e.getMessage()); log.error("Creating viewClass {} caused an error {}\n", viewClass, e.getMessage(), e);
e.printStackTrace();
} }
} }

View File

@ -65,6 +65,7 @@ import javafx.scene.text.TextAlignment;
import javafx.geometry.Insets; import javafx.geometry.Insets;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.Subscription; import org.fxmisc.easybind.Subscription;
@ -565,12 +566,10 @@ public class ChatView extends AnchorPane {
inputTextArea.setText(inputTextArea.getText() + "\n[" + Res.get("support.attachment") + " " + result.getName() + "]"); inputTextArea.setText(inputTextArea.getText() + "\n[" + Res.get("support.attachment") + " " + result.getName() + "]");
} }
} catch (java.io.IOException e) { } catch (java.io.IOException e) {
e.printStackTrace(); log.error(ExceptionUtils.getStackTrace(e));
log.error(e.getMessage());
} }
} catch (MalformedURLException e2) { } catch (MalformedURLException e2) {
e2.printStackTrace(); log.error(ExceptionUtils.getStackTrace(e2));
log.error(e2.getMessage());
} }
} }
} else { } else {
@ -593,8 +592,7 @@ public class ChatView extends AnchorPane {
inputTextArea.setText(inputTextArea.getText() + "\n[" + Res.get("support.attachment") + " " + name + "]"); inputTextArea.setText(inputTextArea.getText() + "\n[" + Res.get("support.attachment") + " " + name + "]");
} }
} catch (Exception e) { } catch (Exception e) {
log.error(e.toString()); log.error(ExceptionUtils.getStackTrace(e));
e.printStackTrace();
} }
} }
@ -629,8 +627,7 @@ public class ChatView extends AnchorPane {
try (FileOutputStream fileOutputStream = new FileOutputStream(file.getAbsolutePath())) { try (FileOutputStream fileOutputStream = new FileOutputStream(file.getAbsolutePath())) {
fileOutputStream.write(attachment.getBytes()); fileOutputStream.write(attachment.getBytes());
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); log.error("Error opening attachment: {}\n", e.getMessage(), e);
System.out.println(e.getMessage());
} }
} }
} }

View File

@ -878,9 +878,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.31"> <component group="io.github.woodser" name="monero-java" version="0.8.33">
<artifact name="monero-java-0.8.31.jar"> <artifact name="monero-java-0.8.33.jar">
<sha256 value="46b81b98bc76f60a965bc7de429ff72cf6c443858987cbd51b9cacd2f8a8d28b" origin="Generated by Gradle"/> <sha256 value="f9a02386ec0870b13a512bf5f72da464c9507e1a1ed6982716bff87641f94e81" 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">

View File

@ -24,6 +24,7 @@ import haveno.common.config.Config;
import haveno.network.p2p.network.NetworkNode; import haveno.network.p2p.network.NetworkNode;
import java.net.UnknownHostException; import java.net.UnknownHostException;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -96,8 +97,7 @@ public class Socks5ProxyProvider {
try { try {
return new Socks5Proxy(tokens[0], Integer.valueOf(tokens[1])); return new Socks5Proxy(tokens[0], Integer.valueOf(tokens[1]));
} catch (UnknownHostException e) { } catch (UnknownHostException e) {
log.error(e.getMessage()); log.error(ExceptionUtils.getStackTrace(e));
e.printStackTrace();
} }
} else { } else {
log.error("Incorrect format for socks5ProxyAddress. Should be: host:port.\n" + log.error("Incorrect format for socks5ProxyAddress. Should be: host:port.\n" +

View File

@ -57,6 +57,8 @@ import javafx.beans.property.ReadOnlyIntegerProperty;
import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleBooleanProperty;
import javafx.beans.property.SimpleIntegerProperty; import javafx.beans.property.SimpleIntegerProperty;
import lombok.Getter; import lombok.Getter;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.Subscription; import org.fxmisc.easybind.Subscription;
import org.fxmisc.easybind.monadic.MonadicBinding; import org.fxmisc.easybind.monadic.MonadicBinding;
@ -433,15 +435,12 @@ public class P2PService implements SetupListener, MessageListener, ConnectionLis
@Override @Override
public void onFailure(@NotNull Throwable throwable) { public void onFailure(@NotNull Throwable throwable) {
log.error(throwable.toString()); log.error(ExceptionUtils.getStackTrace(throwable));
throwable.printStackTrace();
sendDirectMessageListener.onFault(throwable.toString()); sendDirectMessageListener.onFault(throwable.toString());
} }
}, MoreExecutors.directExecutor()); }, MoreExecutors.directExecutor());
} catch (CryptoException e) { } catch (CryptoException e) {
e.printStackTrace(); log.error("Error sending encrypted direct message, message={}, error={}\n", message.toString(), e.getMessage(), e);
log.error(message.toString());
log.error(e.toString());
sendDirectMessageListener.onFault(e.toString()); sendDirectMessageListener.onFault(e.toString());
} }
} }

View File

@ -63,8 +63,7 @@ public class MailboxMessageList extends PersistableList<MailboxItem> {
try { try {
return MailboxItem.fromProto(e, networkProtoResolver); return MailboxItem.fromProto(e, networkProtoResolver);
} catch (ProtobufferException protobufferException) { } catch (ProtobufferException protobufferException) {
protobufferException.printStackTrace(); log.error("Error at MailboxItem.fromProto: {}", protobufferException.toString(), protobufferException);
log.error("Error at MailboxItem.fromProto: {}", protobufferException.toString());
return null; return null;
} }
}) })

View File

@ -335,8 +335,7 @@ public class MailboxMessageService implements HashMapChangedListener, PersistedD
} }
}, MoreExecutors.directExecutor()); }, MoreExecutors.directExecutor());
} catch (CryptoException e) { } catch (CryptoException e) {
log.error("sendEncryptedMessage failed"); log.error("sendEncryptedMessage failed: {}\n", e.getMessage(), e);
e.printStackTrace();
sendMailboxMessageListener.onFault("sendEncryptedMailboxMessage failed " + e); sendMailboxMessageListener.onFault("sendEncryptedMailboxMessage failed " + e);
} }
} }
@ -644,8 +643,7 @@ public class MailboxMessageService implements HashMapChangedListener, PersistedD
log.info("The mailboxEntry was already removed earlier."); log.info("The mailboxEntry was already removed earlier.");
} }
} catch (CryptoException e) { } catch (CryptoException e) {
e.printStackTrace(); log.error("Could not remove ProtectedMailboxStorageEntry from network. Error: {}\n", e.toString(), e);
log.error("Could not remove ProtectedMailboxStorageEntry from network. Error: {}", e.toString());
} }
} }

View File

@ -91,6 +91,8 @@ import javafx.beans.property.ObjectProperty;
import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleObjectProperty;
import lombok.Getter; import lombok.Getter;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.jetbrains.annotations.Nullable; import org.jetbrains.annotations.Nullable;
/** /**
@ -511,8 +513,7 @@ public class Connection implements HasCapabilities, Runnable, MessageListener {
Uninterruptibles.sleepUninterruptibly(200, TimeUnit.MILLISECONDS); Uninterruptibles.sleepUninterruptibly(200, TimeUnit.MILLISECONDS);
} catch (Throwable t) { } catch (Throwable t) {
log.error(t.getMessage()); log.error(ExceptionUtils.getStackTrace(t));
t.printStackTrace();
} finally { } finally {
stopped = true; stopped = true;
ThreadUtils.execute(() -> doShutDown(closeConnectionReason, shutDownCompleteHandler), THREAD_ID); ThreadUtils.execute(() -> doShutDown(closeConnectionReason, shutDownCompleteHandler), THREAD_ID);
@ -537,16 +538,14 @@ public class Connection implements HasCapabilities, Runnable, MessageListener {
} catch (SocketException e) { } catch (SocketException e) {
log.trace("SocketException at shutdown might be expected {}", e.getMessage()); log.trace("SocketException at shutdown might be expected {}", e.getMessage());
} catch (IOException e) { } catch (IOException e) {
log.error("Exception at shutdown. " + e.getMessage()); log.error("Exception at shutdown. {}\n", e.getMessage(), e);
e.printStackTrace();
} finally { } finally {
capabilitiesListeners.clear(); capabilitiesListeners.clear();
try { try {
protoInputStream.close(); protoInputStream.close();
} catch (IOException e) { } catch (IOException e) {
log.error(e.getMessage()); log.error(ExceptionUtils.getStackTrace(e));
e.printStackTrace();
} }
Utilities.shutdownAndAwaitTermination(executorService, SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS); Utilities.shutdownAndAwaitTermination(executorService, SHUTDOWN_TIMEOUT, TimeUnit.MILLISECONDS);

View File

@ -76,8 +76,7 @@ public class LocalhostNetworkNode extends NetworkNode {
try { try {
startServer(new ServerSocket(servicePort)); startServer(new ServerSocket(servicePort));
} catch (IOException e) { } catch (IOException e) {
e.printStackTrace(); log.error("Exception at startServer: {}\n", e.getMessage(), e);
log.error("Exception at startServer: " + e.getMessage());
} }
setupListeners.stream().forEach(SetupListener::onHiddenServicePublished); setupListeners.stream().forEach(SetupListener::onHiddenServicePublished);
}, simulateTorDelayTorNode, TimeUnit.MILLISECONDS); }, simulateTorDelayTorNode, TimeUnit.MILLISECONDS);

View File

@ -97,11 +97,10 @@ class Server implements Runnable {
} }
} catch (IOException e) { } catch (IOException e) {
if (isServerActive()) if (isServerActive())
e.printStackTrace(); log.error("Error executing server loop: {}\n", e.getMessage(), e);
} }
} catch (Throwable t) { } catch (Throwable t) {
log.error("Executing task failed. " + t.getMessage()); log.error("Executing task failed: {}\n", t.getMessage(), t);
t.printStackTrace();
} }
} }

View File

@ -974,8 +974,7 @@ public class P2PDataStorage implements MessageListener, ConnectionListener, Pers
broadcaster.broadcast(refreshTTLMessage, sender); broadcaster.broadcast(refreshTTLMessage, sender);
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
log.error("refreshTTL failed, missing data: {}", e.toString()); log.error("refreshTTL failed, missing data: {}\n", e.toString(), e);
e.printStackTrace();
return false; return false;
} }
return true; return true;

View File

@ -116,8 +116,7 @@ public abstract class StoreService<T extends PersistableEnvelope> {
log.debug("Could not find resourceFile " + resourceFileName + ". That is expected if none is provided yet."); log.debug("Could not find resourceFile " + resourceFileName + ". That is expected if none is provided yet.");
} catch (Throwable e) { } catch (Throwable e) {
log.error("Could not copy resourceFile " + resourceFileName + " to " + log.error("Could not copy resourceFile " + resourceFileName + " to " +
destinationFile.getAbsolutePath() + ".\n" + e.getMessage()); destinationFile.getAbsolutePath() + ".\n", e);
e.printStackTrace();
} }
} else { } else {
log.debug("No resource file was copied. {} exists already.", fileName); log.debug("No resource file was copied. {} exists already.", fileName);

View File

@ -2,8 +2,13 @@
Install Haveno on Tails by following these steps: Install Haveno on Tails by following these steps:
1. Enable persistent storage dotfiles and admin password before starting tails. 1. Enable persistent storage dotfiles and admin password before starting Tails.
2. Download [haveno-install.sh](haveno-install.sh). 2. Download [haveno-install.sh](haveno-install.sh):
```
curl -fsSLO https://github.com/haveno-dex/haveno/raw/master/scripts/install_tails/haveno-install.sh
```
3. Execute installation script: 3. Execute installation script:
``` ```
@ -17,3 +22,9 @@ Install Haveno on Tails by following these steps:
``` ```
4. Upon successful execution of the script (no errors), the Haveno release will be installed to persistent storage and can be launched via the desktop shortcut in the 'Other' section of the start menu. 4. Upon successful execution of the script (no errors), the Haveno release will be installed to persistent storage and can be launched via the desktop shortcut in the 'Other' section of the start menu.
> [!note]
> If you have already installed Haveno on Tails, we recommend moving your data directory (/home/amnesia/Persistent/Haveno-example) to the new default location (/home/amnesia/Persistent/haveno/Data/Haveno-example), to retain your history and for future support.
> [!note]
> Modern versions of Tails will invoke `curl` over Tor, but if your installation does not, then you can add `--socks5-hostname 127.0.0.1:9050` when invoking the install script.

View File

@ -0,0 +1,11 @@
# Steps to use (This has serious security concerns to tails threat model only run when you need to access haveno)
## 1. Enable persistent storage and admin password before starting tails
## 2. Get your haveno deb file in persistent storage (amd64 version for tails)
## 3. Edit the path to the haveno deb file if necessary then run ```sudo ./haveno-install.sh```
## 4. As amnesia run ```source ~/.bashrc```
## 5. Start haveno using ```haveno-tails```
## You will need to run this script after each reset, but your data will be saved persistently in /home/amnesia/Persistence/Haveno

View File

@ -0,0 +1,77 @@
#!/bin/bash
#############################################################################
# Written by BrandyJson, with heavy inspiration from bisq.wiki tails script #
#############################################################################
echo "Installing dpkg from persistent, (1.07-1, if this is out of date change the deb path in the script or manually install after running"
dpkg -i "/home/amnesia/Persistent/haveno_1.0.7-1_amd64.deb"
echo -e "Allowing amnesia to read tor control port cookie, only run this script when you actually want to use haveno\n\n!!! not secure !!!\n"
chmod o+r /var/run/tor/control.authcookie
echo "Updating apparmor-profile"
echo "---
- apparmor-profiles:
- '/opt/haveno/bin/Haveno'
users:
- 'amnesia'
commands:
AUTHCHALLENGE:
- 'SAFECOOKIE .*'
SETEVENTS:
- 'CIRC ORCONN INFO NOTICE WARN ERR HS_DESC HS_DESC_CONTENT'
GETINFO:
- pattern: 'status/bootstrap-phase'
response:
- pattern: '250-status/bootstrap-phase=*'
replacement: '250-status/bootstrap-phase=NOTICE BOOTSTRAP PROGRESS=100 TAG=done SUMMARY="Done"'
- 'net/listeners/socks'
ADD_ONION:
- pattern: 'NEW:(\S+) Port=9999,(\S+)'
replacement: 'NEW:{} Port=9999,{client-address}:{}'
- pattern: '(\S+):(\S+) Port=9999,(\S+)'
replacement: '{}:{} Port=9999,{client-address}:{}'
DEL_ONION:
- '.+'
HSFETCH:
- '.+'
events:
CIRC:
suppress: true
ORCONN:
suppress: true
INFO:
suppress: true
NOTICE:
suppress: true
WARN:
suppress: true
ERR:
suppress: true
HS_DESC:
response:
- pattern: '650 HS_DESC CREATED (\S+) (\S+) (\S+) \S+ (.+)'
replacement: '650 HS_DESC CREATED {} {} {} redacted {}'
- pattern: '650 HS_DESC UPLOAD (\S+) (\S+) .*'
replacement: '650 HS_DESC UPLOAD {} {} redacted redacted'
- pattern: '650 HS_DESC UPLOADED (\S+) (\S+) .+'
replacement: '650 HS_DESC UPLOADED {} {} redacted'
- pattern: '650 HS_DESC REQUESTED (\S+) NO_AUTH'
replacement: '650 HS_DESC REQUESTED {} NO_AUTH'
- pattern: '650 HS_DESC REQUESTED (\S+) NO_AUTH \S+ \S+'
replacement: '650 HS_DESC REQUESTED {} NO_AUTH redacted redacted'
- pattern: '650 HS_DESC RECEIVED (\S+) NO_AUTH \S+ \S+'
replacement: '650 HS_DESC RECEIVED {} NO_AUTH redacted redacted'
- pattern: '.*'
replacement: ''
HS_DESC_CONTENT:
suppress: true" > /etc/onion-grater.d/haveno.yml
echo "Adding rule to iptables to allow for monero-wallet-rpc to work"
iptables -I OUTPUT 2 -p tcp -d 127.0.0.1 -m tcp --dport 18081 -m owner --uid-owner 1855 -j ACCEPT
echo "Updating torsocks to allow for inbound connection"
sed -i 's/#AllowInbound/AllowInbound/g' /etc/tor/torsocks.conf
echo "Restarting onion-grater service"
systemctl restart onion-grater.service
echo "alias haveno-tails='torsocks /opt/haveno/bin/Haveno --torControlPort 951 --torControlCookieFile=/var/run/tor/control.authcookie --torControlUseSafeCookieAuth --useTorForXmr=ON --userDataDir=/home/amnesia/Persistent/'" >> /home/amnesia/.bashrc
echo -e "Everything is set up just run\n\nsource ~/.bashrc\n\nThen you can start haveno using haveno-tails"

View File

@ -75,7 +75,7 @@ public class SeedNodeMain extends ExecutableForAppWithP2p {
seedNode = new SeedNode(); seedNode = new SeedNode();
UserThread.execute(this::onApplicationLaunched); UserThread.execute(this::onApplicationLaunched);
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); log.error("Error launching seed node: {}\n", e.toString(), e);
} }
}); });
} }