general rebase in order to update payment methods and desktop app

Co-authored-by: Alva Swanson <alvasw@protonmail.com>
Co-authored-by: andyheko <haoen.ko@gmail.com>
Co-authored-by: Bisq GitHub Admin <51445974+bisq-github-admin-3@users.noreply.github.com>
Co-authored-by: BtcContributor <79100296+BtcContributor@users.noreply.github.com>
Co-authored-by: cd2357 <cd2357@users.noreply.github.com>
Co-authored-by: chimp1984 <chimp1984@gmx.com>
Co-authored-by: Chris Beams <chris@beams.io>
Co-authored-by: Christoph Atteneder <christoph.atteneder@gmail.com>
Co-authored-by: Devin Bileck <603793+devinbileck@users.noreply.github.com>
Co-authored-by: ghubstan <36207203+ghubstan@users.noreply.github.com>
Co-authored-by: Huey <hueydane@gmail.com>
Co-authored-by: Jakub Loucký <jakub.loucky@outlook.cz>
Co-authored-by: jmacxx <47253594+jmacxx@users.noreply.github.com>
Co-authored-by: KanoczTomas <tomas.kanocz@cnl.sk>
Co-authored-by: m52go <735155+m52go@users.noreply.github.com>
Co-authored-by: Marcus0x <marcus0x@xrhodium.org>
Co-authored-by: MarnixCroes <93143998+MarnixCroes@users.noreply.github.com>
Co-authored-by: Martin Harrigan <martinharrigan@gmail.com>
Co-authored-by: MwithM <50149324+MwithM@users.noreply.github.com>
Co-authored-by: sqrrm <sqrrm@users.noreply.github.com>
Co-authored-by: Stan <36207203+ghubstan@users.noreply.github.com>
Co-authored-by: Stephan Oeste <emzy@emzy.de>
Co-authored-by: Steven Barclay <stejbac@gmail.com>
Co-authored-by: WAT <shiido.it@gmail.com>
Co-authored-by: wiz <j@wiz.biz>
Co-authored-by: xyzmaker123 <84982606+xyzmaker123@users.noreply.github.com>
This commit is contained in:
woodser 2022-05-26 13:42:10 -04:00
parent 15a1fe8a36
commit 88578bed10
539 changed files with 27629 additions and 8178 deletions

View file

@ -122,7 +122,7 @@ public class Config {
public static final int UNSPECIFIED_PORT = -1;
public static final String DEFAULT_REGTEST_HOST = "none";
public static final int DEFAULT_NUM_CONNECTIONS_FOR_BTC = 9; // down from BitcoinJ default of 12
static final String DEFAULT_CONFIG_FILE_NAME = "bisq.properties";
static final String DEFAULT_CONFIG_FILE_NAME = "haveno.properties";
// Static fields that provide access to Config properties in locations where injecting
// a Config instance is not feasible. See Javadoc for corresponding static accessors.
@ -599,7 +599,7 @@ public class Config {
// Option parsing is strict at the command line, but we relax it now for any
// subsequent config file processing. This is for compatibility with pre-1.2.6
// versions that allowed unrecognized options in the bisq.properties config
// versions that allowed unrecognized options in the haveno.properties config
// file and because it follows suit with Bitcoin Core's config file behavior.
parser.allowsUnrecognizedOptions();

View file

@ -29,6 +29,7 @@ import bisq.common.file.FileUtil;
import bisq.common.handlers.ResultHandler;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistenceProtoResolver;
import bisq.common.util.GcUtil;
import bisq.common.util.Utilities;
import com.google.inject.Inject;
@ -325,7 +326,11 @@ public class PersistenceManager<T extends PersistableEnvelope> {
new Thread(() -> {
T persisted = getPersisted(fileName);
if (persisted != null) {
UserThread.execute(() -> resultHandler.accept(persisted));
UserThread.execute(() -> {
resultHandler.accept(persisted);
GcUtil.maybeReleaseMemory();
});
} else {
UserThread.execute(orElse);
}
@ -434,7 +439,16 @@ public class PersistenceManager<T extends PersistableEnvelope> {
}
}
public void forcePersistNow() {
// Tor Bridges settings are edited before app init completes, require persistNow to be forced, see writeToDisk()
persistNow(null, true);
}
public void persistNow(@Nullable Runnable completeHandler) {
persistNow(completeHandler, false);
}
private void persistNow(@Nullable Runnable completeHandler, boolean force) {
long ts = System.currentTimeMillis();
try {
// The serialisation is done on the user thread to avoid threading issue with potential mutations of the
@ -444,7 +458,7 @@ public class PersistenceManager<T extends PersistableEnvelope> {
// For the write to disk task we use a thread. We do not have any issues anymore if the persistable objects
// gets mutated while the thread is running as we have serialized it already and do not operate on the
// reference to the persistable object.
getWriteToDiskExecutor().execute(() -> writeToDisk(serialized, completeHandler));
getWriteToDiskExecutor().execute(() -> writeToDisk(serialized, completeHandler, force));
long duration = System.currentTimeMillis() - ts;
if (duration > 100) {
@ -457,8 +471,8 @@ public class PersistenceManager<T extends PersistableEnvelope> {
}
}
public void writeToDisk(protobuf.PersistableEnvelope serialized, @Nullable Runnable completeHandler) {
if (!allServicesInitialized.get()) {
private void writeToDisk(protobuf.PersistableEnvelope serialized, @Nullable Runnable completeHandler, boolean force) {
if (!allServicesInitialized.get() && !force) {
log.warn("Application has not completed start up yet so we do not permit writing data to disk.");
if (completeHandler != null) {
UserThread.execute(completeHandler);

View file

@ -0,0 +1,39 @@
/*
* This file is part of Haveno.
*
* Haveno is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Haveno is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.common.util;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.stream.Collectors;
public class CompletableFutureUtils {
/**
* @param list List of futures
* @param <T> The generic type of the future
* @return Returns a CompletableFuture with a list of the futures we got as parameter once all futures
* are completed (incl. exceptionally completed).
*/
public static <T> CompletableFuture<List<T>> allOf(List<CompletableFuture<T>> list) {
CompletableFuture<Void> allFuturesResult = CompletableFuture.allOf(list.toArray(new CompletableFuture[list.size()]));
return allFuturesResult.thenApply(v ->
list.stream().
map(CompletableFuture::join).
collect(Collectors.<T>toList())
);
}
}

View file

@ -0,0 +1,85 @@
/*
* This file is part of Haveno.
*
* Haveno is free software: you can redistribute it and/or modify it
* under the terms of the GNU Affero General Public License as published by
* the Free Software Foundation, either version 3 of the License, or (at
* your option) any later version.
*
* Haveno is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public
* License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with Haveno. If not, see <http://www.gnu.org/licenses/>.
*/
package bisq.common.util;
import bisq.common.UserThread;
import lombok.Setter;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class GcUtil {
@Setter
private static boolean DISABLE_GC_CALLS = false;
private static final int TRIGGER_MEM = 1000;
private static final int TRIGGER_MAX_MEM = 3000;
private static int totalInvocations;
private static long totalGCTime;
public static void autoReleaseMemory() {
if (DISABLE_GC_CALLS)
return;
autoReleaseMemory(TRIGGER_MEM);
}
public static void maybeReleaseMemory() {
if (DISABLE_GC_CALLS)
return;
maybeReleaseMemory(TRIGGER_MAX_MEM);
}
/**
* @param trigger Threshold for free memory in MB when we invoke the garbage collector
*/
private static void autoReleaseMemory(long trigger) {
UserThread.runPeriodically(() -> maybeReleaseMemory(trigger), 120);
}
/**
* @param trigger Threshold for free memory in MB when we invoke the garbage collector
*/
private static void maybeReleaseMemory(long trigger) {
long ts = System.currentTimeMillis();
long preGcMemory = Runtime.getRuntime().totalMemory();
if (preGcMemory > trigger * 1024 * 1024) {
System.gc();
totalInvocations++;
long postGcMemory = Runtime.getRuntime().totalMemory();
long duration = System.currentTimeMillis() - ts;
totalGCTime += duration;
log.info("GC reduced memory by {}. Total memory before/after: {}/{}. Free memory: {}. Took {} ms. Total GC invocations: {} / Total GC time {} sec",
Utilities.readableFileSize(preGcMemory - postGcMemory),
Utilities.readableFileSize(preGcMemory),
Utilities.readableFileSize(postGcMemory),
Utilities.readableFileSize(Runtime.getRuntime().freeMemory()),
duration,
totalInvocations,
totalGCTime / 1000d);
/* if (DevEnv.isDevMode()) {
try {
// To see from where we got called
throw new RuntimeException("Dummy Exception for print stacktrace at maybeReleaseMemory");
} catch (Throwable t) {
t.printStackTrace();
}
}*/
}
}
}

View file

@ -22,7 +22,7 @@ import java.util.Collections;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BiFunction;
import java.util.function.BiPredicate;
import lombok.NonNull;
import lombok.extern.slf4j.Slf4j;
@ -58,9 +58,9 @@ public class PermutationUtil {
public static <T, R> List<T> findMatchingPermutation(R targetValue,
List<T> list,
BiFunction<R, List<T>, Boolean> predicate,
BiPredicate<R, List<T>> predicate,
int maxIterations) {
if (predicate.apply(targetValue, list)) {
if (predicate.test(targetValue, list)) {
return list;
} else {
return findMatchingPermutation(targetValue,
@ -74,7 +74,7 @@ public class PermutationUtil {
private static <T, R> List<T> findMatchingPermutation(R targetValue,
List<T> list,
List<List<T>> lists,
BiFunction<R, List<T>, Boolean> predicate,
BiPredicate<R, List<T>> predicate,
AtomicInteger maxIterations) {
for (int level = 0; level < list.size(); level++) {
// Test one level at a time
@ -90,7 +90,7 @@ public class PermutationUtil {
@NonNull
private static <T, R> List<T> checkLevel(R targetValue,
List<T> previousLevel,
BiFunction<R, List<T>, Boolean> predicate,
BiPredicate<R, List<T>> predicate,
int level,
int permutationIndex,
AtomicInteger maxIterations) {
@ -106,7 +106,7 @@ public class PermutationUtil {
if (level == 0) {
maxIterations.decrementAndGet();
// Check all permutations on this level
if (predicate.apply(targetValue, newList)) {
if (predicate.test(targetValue, newList)) {
return newList;
}
} else {

View file

@ -17,18 +17,30 @@
package bisq.common.util;
import bisq.common.UserThread;
import java.util.concurrent.TimeUnit;
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class Profiler {
public static void printSystemLoadPeriodically(long delay, TimeUnit timeUnit) {
UserThread.runPeriodically(Profiler::printSystemLoad, delay, timeUnit);
}
public static void printSystemLoad() {
Runtime runtime = Runtime.getRuntime();
long free = runtime.freeMemory() / 1024 / 1024;
long total = runtime.totalMemory() / 1024 / 1024;
long free = runtime.freeMemory();
long total = runtime.totalMemory();
long used = total - free;
log.info("System report: Used memory: {} MB; Free memory: {} MB; Total memory: {} MB; No. of threads: {}",
used, free, total, Thread.activeCount());
log.info("Total memory: {}; Used memory: {}; Free memory: {}; Max memory: {}; No. of threads: {}",
Utilities.readableFileSize(total),
Utilities.readableFileSize(used),
Utilities.readableFileSize(free),
Utilities.readableFileSize(runtime.maxMemory()),
Thread.activeCount());
}
public static long getUsedMemoryInMB() {

View file

@ -19,12 +19,8 @@ package bisq.common.util;
import org.bitcoinj.core.Utils;
import com.google.gson.ExclusionStrategy;
import com.google.gson.FieldAttributes;
import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.google.common.base.Splitter;
import com.google.common.primitives.Ints;
import com.google.common.util.concurrent.FutureCallback;
import com.google.common.util.concurrent.ListeningExecutorService;
import com.google.common.util.concurrent.MoreExecutors;
@ -52,9 +48,11 @@ import java.nio.file.Paths;
import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Random;
@ -85,15 +83,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class Utilities {
public static String objectToJson(Object object) {
Gson gson = new GsonBuilder()
.setExclusionStrategies(new AnnotationExclusionStrategy())
/*.excludeFieldsWithModifiers(Modifier.TRANSIENT)*/
/* .setFieldNamingPolicy(FieldNamingPolicy.UPPER_CAMEL_CASE)*/
.setPrettyPrinting()
.create();
return gson.toJson(object);
}
public static ExecutorService getSingleThreadExecutor(String name) {
final ThreadFactory threadFactory = new ThreadFactoryBuilder()
@ -337,12 +326,12 @@ public class Utilities {
public static void openURI(URI uri) throws IOException {
if (!DesktopUtil.browse(uri))
throw new IOException("Failed to open URI: " + uri.toString());
throw new IOException("Failed to open URI: " + uri);
}
public static void openFile(File file) throws IOException {
if (!DesktopUtil.open(file))
throw new IOException("Failed to open file: " + file.toString());
throw new IOException("Failed to open file: " + file);
}
public static String getDownloadOfHomeDir() {
@ -447,18 +436,6 @@ public class Utilities {
return new File(Utilities.class.getProtectionDomain().getCodeSource().getLocation().toURI()).getPath();
}
private static class AnnotationExclusionStrategy implements ExclusionStrategy {
@Override
public boolean shouldSkipField(FieldAttributes f) {
return f.getAnnotation(JsonExclude.class) != null;
}
@Override
public boolean shouldSkipClass(Class<?> clazz) {
return false;
}
}
public static String toTruncatedString(Object message) {
return toTruncatedString(message, 200, true);
}
@ -480,6 +457,16 @@ public class Utilities {
}
public static List<String> toListOfWrappedStrings(String s, int wrapLength) {
StringBuilder sb = new StringBuilder(s);
int i = 0;
while (i + wrapLength < sb.length() && (i = sb.lastIndexOf(" ", i + wrapLength)) != -1) {
sb.replace(i, i + 1, "\n");
}
String[] splitLine = sb.toString().split("\n");
return Arrays.asList(splitLine);
}
public static String getRandomPrefix(int minLength, int maxLength) {
int length = minLength + new Random().nextInt(maxLength - minLength + 1);
String result;
@ -539,6 +526,34 @@ public class Utilities {
return result;
}
public static byte[] copyRightAligned(byte[] src, int newLength) {
byte[] dest = new byte[newLength];
int srcPos = Math.max(src.length - newLength, 0);
int destPos = Math.max(newLength - src.length, 0);
System.arraycopy(src, srcPos, dest, destPos, newLength - destPos);
return dest;
}
public static byte[] intsToBytesBE(int[] ints) {
byte[] bytes = new byte[ints.length * 4];
int i = 0;
for (int v : ints) {
bytes[i++] = (byte) (v >> 24);
bytes[i++] = (byte) (v >> 16);
bytes[i++] = (byte) (v >> 8);
bytes[i++] = (byte) v;
}
return bytes;
}
public static int[] bytesToIntsBE(byte[] bytes) {
int[] ints = new int[bytes.length / 4];
for (int i = 0, j = 0; i < bytes.length / 4; i++) {
ints[i] = Ints.fromBytes(bytes[j++], bytes[j++], bytes[j++], bytes[j++]);
}
return ints;
}
// Helper to filter unique elements by key
public static <T> Predicate<T> distinctByKey(Function<? super T, Object> keyExtractor) {
Map<Object, Boolean> map = new ConcurrentHashMap<>();
@ -591,4 +606,8 @@ public class Utilities {
}
return result;
}
public static String cleanString(String string) {
return string.replaceAll("[\\t\\n\\r]+", " ");
}
}