diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/Configuration.java b/apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/BucketConfig.java
similarity index 60%
rename from apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/Configuration.java
rename to apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/BucketConfig.java
index abac55e6fe..a63f008649 100644
--- a/apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/Configuration.java
+++ b/apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/BucketConfig.java
@@ -17,11 +17,12 @@
package bisq.desktop.components.cathash;
+import bisq.common.util.MathUtils;
import lombok.extern.slf4j.Slf4j;
@Slf4j
-public class Configuration {
- private static final String ROOT = "";
+public class BucketConfig {
+ static final String DIGIT = "#";
private static final int BG0_COUNT = 16;
private static final int BG1_COUNT = 16;
@@ -33,42 +34,42 @@ public class Configuration {
private static final int NOSE0_COUNT = 6;
private static final int WHISKERS0_COUNT = 7;
- private static final int BUCKET_COUNT = 9;
- private static final int FACET_COUNT = 9;
-
private static final int[] BUCKET_SIZES = new int[]{BG0_COUNT, BG1_COUNT, EARS0_COUNT, EARS1_COUNT, FACE0_COUNT,
FACE1_COUNT, EYES0_COUNT, NOSE0_COUNT, WHISKERS0_COUNT};
- private static final String[] FACET_PATH_TEMPLATES;
+ private static final String[] PATH_TEMPLATES;
static {
String postFix = ".png";
- FACET_PATH_TEMPLATES = new String[]{
- ROOT + "bg0/NUM" + postFix,
- ROOT + "bg1/NUM" + postFix,
- ROOT + "ears0/NUM" + postFix,
- ROOT + "ears1/NUM" + postFix,
- ROOT + "face0/NUM" + postFix,
- ROOT + "face1/NUM" + postFix,
- ROOT + "eyes0/NUM" + postFix,
- ROOT + "nose0/NUM" + postFix,
- ROOT + "whiskers0/NUM" + postFix,
+ PATH_TEMPLATES = new String[]{
+ "bg0/" + DIGIT + postFix,
+ "bg1/" + DIGIT + postFix,
+ "ears0/" + DIGIT + postFix,
+ "ears1/" + DIGIT + postFix,
+ "face0/" + DIGIT + postFix,
+ "face1/" + DIGIT + postFix,
+ "eyes0/" + DIGIT + postFix,
+ "nose0/" + DIGIT + postFix,
+ "whiskers0/" + DIGIT + postFix
};
- }
-
- static int getBucketCount() {
- return BUCKET_COUNT;
- }
- static int getFacetCount() {
- return FACET_COUNT;
+ long numCombinations = getNumCombinations();
+ log.info("Number of combinations: 2^{} = {}", MathUtils.getLog2(numCombinations), numCombinations);
}
static int[] getBucketSizes() {
return BUCKET_SIZES;
}
- static String[] getFacetPathTemplates() {
- return FACET_PATH_TEMPLATES;
+ static String[] getPathTemplates() {
+ return PATH_TEMPLATES;
+ }
+
+ static long getNumCombinations() {
+ long result = 1;
+ for (int bucketSize : BUCKET_SIZES) {
+ result *= bucketSize;
+ }
+ return result;
}
}
diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/BucketEncoder.java b/apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/BucketEncoder.java
new file mode 100644
index 0000000000..d6288e546e
--- /dev/null
+++ b/apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/BucketEncoder.java
@@ -0,0 +1,53 @@
+/*
+ * This file is part of Bisq.
+ *
+ * Bisq 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.
+ *
+ * Bisq 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 Bisq. If not, see
- * Assumption: the value of hash is (much) larger than `16^bucketSizes.length` and uniformly distributed (random) - * - * @param input Any BigInteger that is to be split up in buckets according to the bucket configuration #bucketSizes. - * @return buckets The distributed hash - */ - static int[] createBuckets(BigInteger input, int[] bucketSizes) { - int currentBucket = 0; - int[] result = new int[bucketSizes.length]; - while (currentBucket < bucketSizes.length) { - BigInteger[] divisorReminder = input.divideAndRemainder(BigInteger.valueOf(bucketSizes[currentBucket])); - input = divisorReminder[0]; - long reminder = divisorReminder[1].longValue(); - result[currentBucket] = (int) Math.abs(reminder % bucketSizes[currentBucket]); - currentBucket++; - } - return result; - } - - private static String generatePath(String facetPathTemplate, int bucketValue) { - return facetPathTemplate.replaceAll("NUM", String.format("%02d", bucketValue)); - } -} \ No newline at end of file diff --git a/apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/CatHash.java b/apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/CatHash.java index 5b2be5a5c4..ceb0849b1a 100644 --- a/apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/CatHash.java +++ b/apps/desktop/desktop/src/main/java/bisq/desktop/components/cathash/CatHash.java @@ -26,7 +26,6 @@ import java.util.concurrent.ConcurrentHashMap; // Derived from https://github.com/neuhalje/android-robohash -// Number of combinations: 3 * 15 * 15 * 15 * 15 * 15 * 15 = 34171875 (2 ^ 25) @Slf4j public class CatHash { private static final int SIZE = 300; @@ -45,21 +44,13 @@ private static Image getImage(ByteArray pubKeyHash, boolean useCache) { if (useCache && CACHE.containsKey(pubKeyHash)) { return CACHE.get(pubKeyHash); } - BigInteger bigInteger = new BigInteger(pubKeyHash.getBytes()); - int[] buckets = BucketGenerator.createBuckets(bigInteger, Configuration.getBucketSizes()); - Image image = imageFromBuckets(buckets); + BigInteger input = new BigInteger(pubKeyHash.getBytes()); + int[] buckets = BucketEncoder.encode(input, BucketConfig.getBucketSizes()); + String[] paths = BucketEncoder.toPaths(buckets, BucketConfig.getPathTemplates()); + Image image = ImageUtil.composeImage(paths, SIZE, SIZE); if (useCache && CACHE.size() < MAX_CACHE_SIZE) { CACHE.put(pubKeyHash, image); } return image; } - - - private static Image imageFromBuckets(int[] integerBuckets) { - String[] paths = BucketGenerator.integerBucketsToPaths(integerBuckets, - Configuration.getBucketCount(), - Configuration.getFacetCount(), - Configuration.getFacetPathTemplates()); - return ImageUtil.composeImage(paths, SIZE, SIZE); - } } diff --git a/common/src/main/java/bisq/common/util/MathUtils.java b/common/src/main/java/bisq/common/util/MathUtils.java index da046d4177..16428cf4ec 100644 --- a/common/src/main/java/bisq/common/util/MathUtils.java +++ b/common/src/main/java/bisq/common/util/MathUtils.java @@ -108,4 +108,8 @@ public static long bounded(long lowerBound, long upperBound, long value) { "lowerBound must not be larger than upperBound"); return Math.min(Math.max(value, lowerBound), upperBound); } + + public static double getLog2(long value) { + return Math.log(value) / Math.log(2); + } }