diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
index 59b70d9459c..d52f38b3e8f 100644
--- a/.idea/codeStyles/Project.xml
+++ b/.idea/codeStyles/Project.xml
@@ -180,6 +180,7 @@
+
diff --git a/.travis.yml b/.travis.yml
index 9a389a5e411..f5c829c3ec0 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -1,10 +1,13 @@
language: java
-jdk: openjdk10
+jdk:
+ - openjdk10
+ - openjdk12
+
before_install:
- grep -v '^#' assets/src/main/resources/META-INF/services/bisq.asset.Asset | sort --check --dictionary-order --ignore-case
+ grep -v '^#' assets/src/main/resources/META-INF/services/bisq.asset.Asset | sort --check --dictionary-order --ignore-case
notifications:
- slack:
- on_success: change
- on_failure: always
- rooms:
- - secure: EzlqWTBuhb3FCfApjUXaShWgsWOVDwMXI7ISMiVBkcl2VFISYs/lc/7Qjr7rdy4iqQOQXMcUPHdwMUp0diX+GxiSjLARjUpKIvNOPswZWBL+3Z1h28jyOwtHRviZbM1EU0BZROrr+ODyTNz2lf+L1iXTkpSvk50o5JAnAkumsPw=
+ slack:
+ on_success: change
+ on_failure: always
+ rooms:
+ - secure: EzlqWTBuhb3FCfApjUXaShWgsWOVDwMXI7ISMiVBkcl2VFISYs/lc/7Qjr7rdy4iqQOQXMcUPHdwMUp0diX+GxiSjLARjUpKIvNOPswZWBL+3Z1h28jyOwtHRviZbM1EU0BZROrr+ODyTNz2lf+L1iXTkpSvk50o5JAnAkumsPw=
diff --git a/README.md b/README.md
index 14238b9b83f..b76c4d0ef98 100644
--- a/README.md
+++ b/README.md
@@ -17,4 +17,4 @@ Follow the step-by-step instructions at https://bisq.network/get-started.
## Contribute to Bisq
-See [CONTRIBUTING.md](CONTRIBUTING.md) and the [developer docs](docs#readme).
+See [CONTRIBUTING.md](CONTRIBUTING.md) and the [developer docs](docs/README.md).
diff --git a/assets/src/main/java/bisq/asset/EtherAddressValidator.java b/assets/src/main/java/bisq/asset/EtherAddressValidator.java
index f646ed57ef7..4ed2cee4923 100644
--- a/assets/src/main/java/bisq/asset/EtherAddressValidator.java
+++ b/assets/src/main/java/bisq/asset/EtherAddressValidator.java
@@ -33,4 +33,8 @@ public class EtherAddressValidator extends RegexAddressValidator {
public EtherAddressValidator() {
super("^(0x)?[0-9a-fA-F]{40}$");
}
+
+ public EtherAddressValidator(String errorMessageI18nKey) {
+ super("^(0x)?[0-9a-fA-F]{40}$", errorMessageI18nKey);
+ }
}
diff --git a/assets/src/main/java/bisq/asset/I18n.java b/assets/src/main/java/bisq/asset/I18n.java
new file mode 100644
index 00000000000..86bcdecc448
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/I18n.java
@@ -0,0 +1,8 @@
+package bisq.asset;
+
+import java.util.ResourceBundle;
+
+public class I18n {
+
+ public static ResourceBundle DISPLAY_STRINGS = ResourceBundle.getBundle("i18n.displayStrings-assets");
+}
diff --git a/assets/src/main/java/bisq/asset/coins/Byteball.java b/assets/src/main/java/bisq/asset/coins/Byteball.java
deleted file mode 100644
index d4baec091ce..00000000000
--- a/assets/src/main/java/bisq/asset/coins/Byteball.java
+++ /dev/null
@@ -1,198 +0,0 @@
-/*
- * 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 .
- */
-
-package bisq.asset.coins;
-
-import bisq.asset.AddressValidationResult;
-import bisq.asset.AddressValidator;
-import bisq.asset.Coin;
-
-import org.apache.commons.codec.binary.Base32;
-import org.apache.commons.codec.binary.Base64;
-
-import java.security.MessageDigest;
-import java.security.NoSuchAlgorithmException;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.List;
-
-public class Byteball extends Coin {
-
- public Byteball() {
- super("Byte", "GBYTE", new ByteballAddressValidator());
- }
-
-
- public static class ByteballAddressValidator implements AddressValidator {
- private static final Base32 base32 = new Base32();
- private static final Base64 base64 = new Base64();
- private static final String PI = "14159265358979323846264338327950288419716939937510";
- private static final String[] arrRelativeOffsets = PI.split("");
- @SuppressWarnings("CanBeFinal")
- private static Integer[] arrOffsets160;
- @SuppressWarnings("CanBeFinal")
- private static Integer[] arrOffsets288;
-
- static {
- try {
- arrOffsets160 = calcOffsets(160);
- } catch (Exception e) {
- e.printStackTrace();
- }
- try {
- arrOffsets288 = calcOffsets(288);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
-
- public AddressValidationResult validate(String input) {
- if (!isValidAddress(input)) {
- return AddressValidationResult.invalidStructure();
- }
- return AddressValidationResult.validAddress();
- }
-
- private static boolean isValidAddress(String address) {
- return isValidChash(address, 32);
- }
-
- private static boolean isValidChash(String str, int len) {
- return (isStringOfLength(str, len) && isChashValid(str));
- }
-
- private static boolean isStringOfLength(String str, int len) {
- return str.length() == len;
- }
-
- private static void checkLength(int chash_length) throws Exception {
- if (chash_length != 160 && chash_length != 288)
- throw new Exception("unsupported c-hash length: " + chash_length);
- }
-
- private static Integer[] calcOffsets(int chash_length) throws Exception {
- checkLength(chash_length);
- List arrOffsets = new ArrayList<>(chash_length);
- int offset = 0;
- int index = 0;
-
- for (int i = 0; offset < chash_length; i++) {
- int relative_offset = Integer.parseInt(arrRelativeOffsets[i]);
- if (relative_offset == 0)
- continue;
- offset += relative_offset;
- if (chash_length == 288)
- offset += 4;
- if (offset >= chash_length)
- break;
- arrOffsets.add(offset);
- //console.log("index="+index+", offset="+offset);
- index++;
- }
-
- if (index != 32)
- throw new Exception("wrong number of checksum bits");
-
- //noinspection ToArrayCallWithZeroLengthArrayArgument
- return arrOffsets.toArray(new Integer[0]);
- }
-
- private static ByteballAddressValidator.SeparatedData separateIntoCleanDataAndChecksum(String bin)
- throws Exception {
-
- int len = bin.length();
- Integer[] arrOffsets;
- if (len == 160)
- arrOffsets = arrOffsets160;
- else if (len == 288)
- arrOffsets = arrOffsets288;
- else
- throw new Exception("bad length");
- StringBuilder arrFrags = new StringBuilder();
- StringBuilder arrChecksumBits = new StringBuilder();
- int start = 0;
- //noinspection ForLoopReplaceableByForEach
- for (int i = 0; i < arrOffsets.length; i++) {
- arrFrags.append(bin.substring(start, arrOffsets[i]));
- arrChecksumBits.append(bin.substring(arrOffsets[i], arrOffsets[i] + 1));
- start = arrOffsets[i] + 1;
- }
- // add last frag
- if (start < bin.length())
- arrFrags.append(bin.substring(start));
- String binCleanData = arrFrags.toString();
- String binChecksum = arrChecksumBits.toString();
- return new ByteballAddressValidator.SeparatedData(binCleanData, binChecksum);
- }
-
- private static String buffer2bin(byte[] buf) {
- StringBuilder bytes = new StringBuilder();
- //noinspection ForLoopReplaceableByForEach
- for (int i = 0; i < buf.length; i++) {
- String bin = String.format("%8s", Integer.toBinaryString(buf[i] & 0xFF)).replace(' ', '0');
- bytes.append(bin);
- }
- return bytes.toString();
- }
-
- private static byte[] bin2buffer(String bin) {
- int len = bin.length() / 8;
- byte[] buf = new byte[len];
- for (int i = 0; i < len; i++)
- buf[i] = (byte) Integer.parseInt(bin.substring(i * 8, (i + 1) * 8), 2);
- return buf;
- }
-
- private static boolean isChashValid(String encoded) {
- int encoded_len = encoded.length();
- if (encoded_len != 32 && encoded_len != 48) // 160/5 = 32, 288/6 = 48
- return false;
- byte[] chash = (encoded_len == 32) ? base32.decode(encoded) : base64.decode(encoded);
- String binChash = buffer2bin(chash);
- ByteballAddressValidator.SeparatedData separated;
- try {
- separated = separateIntoCleanDataAndChecksum(binChash);
- } catch (Exception e) {
- return false;
- }
- byte[] clean_data = bin2buffer(separated.clean_data);
- byte[] checksum = bin2buffer(separated.checksum);
- return Arrays.equals(getChecksum(clean_data), checksum);
- }
-
- private static byte[] getChecksum(byte[] clean_data) {
-
- try {
- byte[] full_checksum = MessageDigest.getInstance("SHA-256").digest(clean_data);
- return new byte[]{full_checksum[5], full_checksum[13], full_checksum[21], full_checksum[29]};
- } catch (NoSuchAlgorithmException e) {
- return null;
- }
- }
-
- private static class SeparatedData {
- final String clean_data;
- final String checksum;
-
- public SeparatedData(String clean_data, String checksum) {
- this.clean_data = clean_data;
- this.checksum = checksum;
- }
- }
- }
-}
diff --git a/assets/src/main/java/bisq/asset/coins/Counterparty.java b/assets/src/main/java/bisq/asset/coins/Counterparty.java
index d08542fc692..daea00e87c3 100644
--- a/assets/src/main/java/bisq/asset/coins/Counterparty.java
+++ b/assets/src/main/java/bisq/asset/coins/Counterparty.java
@@ -18,11 +18,19 @@
package bisq.asset.coins;
import bisq.asset.Coin;
-import bisq.asset.DefaultAddressValidator;
+import bisq.asset.I18n;
+import bisq.asset.RegexAddressValidator;
public class Counterparty extends Coin {
-
+
public Counterparty() {
- super("Counterparty", "XCP", new DefaultAddressValidator());
+ super("Counterparty", "XCP", new XcpAddressValidator());
+ }
+
+ public static class XcpAddressValidator extends RegexAddressValidator {
+
+ public XcpAddressValidator() {
+ super("^[1][a-zA-Z0-9]{33}", I18n.DISPLAY_STRINGS.getString("account.altcoin.popup.validation.XCP"));
+ }
}
}
diff --git a/assets/src/main/java/bisq/asset/coins/DarkPay.java b/assets/src/main/java/bisq/asset/coins/DarkPay.java
new file mode 100644
index 00000000000..ac10111f944
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/coins/DarkPay.java
@@ -0,0 +1,36 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.Base58BitcoinAddressValidator;
+import bisq.asset.Coin;
+import bisq.asset.NetworkParametersAdapter;
+
+public class DarkPay extends Coin {
+ public DarkPay() {
+ super("DarkPay", "D4RK", new Base58BitcoinAddressValidator(new DarkPayMainNetParams()));
+ }
+
+ public static class DarkPayMainNetParams extends NetworkParametersAdapter {
+ public DarkPayMainNetParams() {
+ this.addressHeader = 31;
+ this.p2shHeader = 60;
+ this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
+ }
+ }
+}
diff --git a/assets/src/main/java/bisq/asset/coins/Decred.java b/assets/src/main/java/bisq/asset/coins/Decred.java
index c3a8bc937a4..551937f2983 100644
--- a/assets/src/main/java/bisq/asset/coins/Decred.java
+++ b/assets/src/main/java/bisq/asset/coins/Decred.java
@@ -18,11 +18,19 @@
package bisq.asset.coins;
import bisq.asset.Coin;
-import bisq.asset.DefaultAddressValidator;
+import bisq.asset.I18n;
+import bisq.asset.RegexAddressValidator;
public class Decred extends Coin {
- public Decred() {
- super("Decred", "DCR", new DefaultAddressValidator());
+ public Decred() {
+ super("Decred", "DCR", new DcrAddressValidator());
+ }
+
+ public static class DcrAddressValidator extends RegexAddressValidator {
+
+ public DcrAddressValidator() {
+ super("^[Dk|Ds|De|DS|Dc|Pm][a-zA-Z0-9]{24,34}", I18n.DISPLAY_STRINGS.getString("account.altcoin.popup.validation.DCR"));
+ }
}
}
diff --git a/assets/src/main/java/bisq/asset/coins/Neos.java b/assets/src/main/java/bisq/asset/coins/Donu.java
similarity index 79%
rename from assets/src/main/java/bisq/asset/coins/Neos.java
rename to assets/src/main/java/bisq/asset/coins/Donu.java
index 86f9b6ea6d8..67c87b41edd 100644
--- a/assets/src/main/java/bisq/asset/coins/Neos.java
+++ b/assets/src/main/java/bisq/asset/coins/Donu.java
@@ -22,17 +22,17 @@
import bisq.asset.Coin;
import bisq.asset.NetworkParametersAdapter;
-public class Neos extends Coin {
+public class Donu extends Coin {
- public Neos() {
- super("Neos", "NEOS", new NeosAddressValidator());
+ public Donu() {
+ super("Donu", "DONU", new DonuAddressValidator());
}
- public static class NeosAddressValidator extends Base58BitcoinAddressValidator {
+ public static class DonuAddressValidator extends Base58BitcoinAddressValidator {
- public NeosAddressValidator() {
- super(new NeosParams());
+ public DonuAddressValidator() {
+ super(new DonuParams());
}
@Override
@@ -45,9 +45,9 @@ public AddressValidationResult validate(String address) {
}
- public static class NeosParams extends NetworkParametersAdapter {
+ public static class DonuParams extends NetworkParametersAdapter {
- public NeosParams() {
+ public DonuParams() {
addressHeader = 53;
p2shHeader = 5;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
diff --git a/assets/src/main/java/bisq/asset/coins/Emercoin.java b/assets/src/main/java/bisq/asset/coins/Emercoin.java
new file mode 100644
index 00000000000..071eb05d003
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/coins/Emercoin.java
@@ -0,0 +1,37 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.Base58BitcoinAddressValidator;
+import bisq.asset.Coin;
+import bisq.asset.NetworkParametersAdapter;
+
+public class Emercoin extends Coin {
+
+ public Emercoin() {
+ super("Emercoin", "EMC", new Base58BitcoinAddressValidator(new EmercoinMainNetParams()), Network.MAINNET);
+ }
+
+ public static class EmercoinMainNetParams extends NetworkParametersAdapter {
+ public EmercoinMainNetParams() {
+ this.addressHeader = 33;
+ this.p2shHeader = 92;
+ this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
+ }
+ }
+}
diff --git a/assets/src/main/java/bisq/asset/coins/Ergo.java b/assets/src/main/java/bisq/asset/coins/Ergo.java
new file mode 100644
index 00000000000..5cca197f340
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/coins/Ergo.java
@@ -0,0 +1,66 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.AddressValidationResult;
+import bisq.asset.AddressValidator;
+import bisq.asset.Coin;
+
+import java.util.Arrays;
+
+import org.bitcoinj.core.Base58;
+import org.bitcoinj.core.AddressFormatException;
+import org.bouncycastle.crypto.digests.Blake2bDigest;
+
+public class Ergo extends Coin {
+
+ public Ergo() {
+ super("Ergo", "ERG", new ErgoAddressValidator());
+ }
+
+ public static class ErgoAddressValidator implements AddressValidator {
+
+ @Override
+ public AddressValidationResult validate(String address) {
+ try {
+ byte[] decoded = Base58.decode(address);
+ if (decoded.length < 4) {
+ return AddressValidationResult.invalidAddress("Input too short: " + decoded.length);
+ }
+ if (decoded[0] != 1 && decoded[0] != 2 && decoded[0] != 3) {
+ return AddressValidationResult.invalidAddress("Invalid prefix");
+ }
+ byte[] data = Arrays.copyOfRange(decoded, 0, decoded.length - 4);
+ byte[] checksum = Arrays.copyOfRange(decoded, decoded.length - 4, decoded.length);
+ byte[] hashed = new byte[32];
+ {
+ Blake2bDigest digest = new Blake2bDigest(256);
+ digest.update(data, 0, data.length);
+ digest.doFinal(hashed, 0);
+ }
+ byte[] actualChecksum = Arrays.copyOfRange(hashed, 0, 4);
+ if (!Arrays.equals(checksum, actualChecksum)) {
+ return AddressValidationResult.invalidAddress("Invalid checksum");
+ }
+ } catch (AddressFormatException e) {
+ return AddressValidationResult.invalidAddress(e);
+ }
+ return AddressValidationResult.validAddress();
+ }
+ }
+}
diff --git a/assets/src/main/java/bisq/asset/coins/EtherClassic.java b/assets/src/main/java/bisq/asset/coins/EtherClassic.java
index 14bcadc6b13..7b13a915593 100644
--- a/assets/src/main/java/bisq/asset/coins/EtherClassic.java
+++ b/assets/src/main/java/bisq/asset/coins/EtherClassic.java
@@ -18,11 +18,12 @@
package bisq.asset.coins;
import bisq.asset.Coin;
-import bisq.asset.DefaultAddressValidator;
+import bisq.asset.EtherAddressValidator;
+import bisq.asset.I18n;
public class EtherClassic extends Coin {
public EtherClassic() {
- super("Ether Classic", "ETC", new DefaultAddressValidator());
+ super("Ether Classic", "ETC", new EtherAddressValidator(I18n.DISPLAY_STRINGS.getString("account.altcoin.popup.validation.ETC")));
}
}
diff --git a/assets/src/main/java/bisq/asset/coins/KnowYourDeveloper.java b/assets/src/main/java/bisq/asset/coins/KnowYourDeveloper.java
index 65b4cd8d7c2..b0f93f3d776 100644
--- a/assets/src/main/java/bisq/asset/coins/KnowYourDeveloper.java
+++ b/assets/src/main/java/bisq/asset/coins/KnowYourDeveloper.java
@@ -23,7 +23,7 @@
public class KnowYourDeveloper extends Coin {
public KnowYourDeveloper() {
- super("Know Your Developer", "KYD", new Base58BitcoinAddressValidator(new KydMainNetParams()));
+ super("Know Your Developer", "KYDC", new Base58BitcoinAddressValidator(new KydMainNetParams()));
}
public static class KydMainNetParams extends NetworkParametersAdapter {
diff --git a/assets/src/main/java/bisq/asset/coins/Kore.java b/assets/src/main/java/bisq/asset/coins/Kore.java
new file mode 100644
index 00000000000..98f635719ad
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/coins/Kore.java
@@ -0,0 +1,36 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.Base58BitcoinAddressValidator;
+import bisq.asset.Coin;
+import bisq.asset.NetworkParametersAdapter;
+
+public class Kore extends Coin {
+ public Kore() {
+ super("Kore", "KORE", new Base58BitcoinAddressValidator(new KoreMainNetParams()));
+ }
+
+ public static class KoreMainNetParams extends NetworkParametersAdapter {
+ public KoreMainNetParams() {
+ this.addressHeader = 45;
+ this.p2shHeader = 85;
+ this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
+ }
+ }
+}
diff --git a/assets/src/main/java/bisq/asset/coins/Masari.java b/assets/src/main/java/bisq/asset/coins/Masari.java
new file mode 100644
index 00000000000..0d057610275
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/coins/Masari.java
@@ -0,0 +1,30 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.AltCoinAccountDisclaimer;
+import bisq.asset.Coin;
+import bisq.asset.CryptoNoteAddressValidator;
+
+@AltCoinAccountDisclaimer("account.altcoin.popup.msr.msg")
+public class Masari extends Coin {
+
+ public Masari() {
+ super("Masari", "MSR", new CryptoNoteAddressValidator(28, 52));
+ }
+}
diff --git a/assets/src/main/java/bisq/asset/coins/Monero.java b/assets/src/main/java/bisq/asset/coins/Monero.java
index 68c2c774f68..91f22d4cb6c 100644
--- a/assets/src/main/java/bisq/asset/coins/Monero.java
+++ b/assets/src/main/java/bisq/asset/coins/Monero.java
@@ -25,6 +25,6 @@
public class Monero extends Coin {
public Monero() {
- super("Monero", "XMR", new CryptoNoteAddressValidator(18, 42));
+ super("Monero", "XMR", new CryptoNoteAddressValidator(18, 19, 42));
}
}
diff --git a/assets/src/main/java/bisq/asset/coins/Namecoin.java b/assets/src/main/java/bisq/asset/coins/Namecoin.java
index 3789ff04c1b..02bec802ba2 100644
--- a/assets/src/main/java/bisq/asset/coins/Namecoin.java
+++ b/assets/src/main/java/bisq/asset/coins/Namecoin.java
@@ -18,11 +18,19 @@
package bisq.asset.coins;
import bisq.asset.Coin;
-import bisq.asset.DefaultAddressValidator;
+import bisq.asset.I18n;
+import bisq.asset.RegexAddressValidator;
public class Namecoin extends Coin {
- public Namecoin() {
- super("Namecoin", "NMC", new DefaultAddressValidator());
+ public Namecoin() {
+ super("Namecoin", "NMC", new NmcAddressValidator());
+ }
+
+ public static class NmcAddressValidator extends RegexAddressValidator {
+
+ public NmcAddressValidator() {
+ super("^[NM][a-zA-Z0-9]{33}$", I18n.DISPLAY_STRINGS.getString("account.altcoin.popup.validation.NMC"));
+ }
}
}
diff --git a/assets/src/main/java/bisq/asset/coins/PENG.java b/assets/src/main/java/bisq/asset/coins/PENG.java
new file mode 100644
index 00000000000..2445038a10c
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/coins/PENG.java
@@ -0,0 +1,28 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.Coin;
+import bisq.asset.RegexAddressValidator;
+
+public class PENG extends Coin {
+
+ public PENG() {
+ super("PENG Coin", "PENG", new RegexAddressValidator("^[P][a-km-zA-HJ-NP-Z1-9]{33}$"));
+ }
+}
\ No newline at end of file
diff --git a/assets/src/main/java/bisq/asset/coins/Particl.java b/assets/src/main/java/bisq/asset/coins/Particl.java
new file mode 100644
index 00000000000..8f14c47dd3d
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/coins/Particl.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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.Base58BitcoinAddressValidator;
+import bisq.asset.Coin;
+import bisq.asset.NetworkParametersAdapter;
+import bisq.asset.AddressValidationResult;
+
+
+public class Particl extends Coin {
+ public Particl() {
+ super("Particl", "PART", new ParticlMainNetAddressValidator());
+ }
+
+ public static class ParticlMainNetParams extends NetworkParametersAdapter {
+ public ParticlMainNetParams() {
+ this.addressHeader = 56;
+ this.p2shHeader = 60;
+ this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
+ }
+ }
+ public static class ParticlMainNetAddressValidator extends Base58BitcoinAddressValidator {
+
+ public ParticlMainNetAddressValidator() {
+ super(new ParticlMainNetParams());
+ }
+
+ @Override
+ public AddressValidationResult validate(String address) {
+ if (!address.matches("^[RP][a-km-zA-HJ-NP-Z1-9]{25,34}$"))
+ return AddressValidationResult.invalidStructure();
+
+ return super.validate(address);
+ }
+ }
+
+}
diff --git a/assets/src/main/java/bisq/asset/coins/Siafund.java b/assets/src/main/java/bisq/asset/coins/Siafund.java
index f31ade51ec1..12b9008dcfc 100644
--- a/assets/src/main/java/bisq/asset/coins/Siafund.java
+++ b/assets/src/main/java/bisq/asset/coins/Siafund.java
@@ -18,11 +18,20 @@
package bisq.asset.coins;
import bisq.asset.Coin;
-import bisq.asset.DefaultAddressValidator;
+import bisq.asset.I18n;
+import bisq.asset.RegexAddressValidator;
public class Siafund extends Coin {
public Siafund() {
- super("Siafund", "SF", new DefaultAddressValidator());
+ super("Siafund", "SF", new SfAddressValidator());
}
+
+ public static class SfAddressValidator extends RegexAddressValidator {
+
+ public SfAddressValidator() {
+ super("^[0-9a-fA-F]{76}$", I18n.DISPLAY_STRINGS.getString("account.altcoin.popup.validation.XCP"));
+ }
+ }
+
}
diff --git a/assets/src/main/java/bisq/asset/coins/SixEleven.java b/assets/src/main/java/bisq/asset/coins/SixEleven.java
new file mode 100644
index 00000000000..ded86da4ef2
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/coins/SixEleven.java
@@ -0,0 +1,36 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.Base58BitcoinAddressValidator;
+import bisq.asset.Coin;
+import bisq.asset.NetworkParametersAdapter;
+
+public class SixEleven extends Coin {
+
+ public SixEleven() {
+ super("SixEleven", "SIL", new Base58BitcoinAddressValidator(new SixElevenChainParams()));
+ }
+
+ public static class SixElevenChainParams extends NetworkParametersAdapter {
+ public SixElevenChainParams() {
+ addressHeader = 52;
+ acceptableAddressCodes = new int[]{addressHeader};
+ }
+ }
+}
diff --git a/assets/src/main/java/bisq/asset/coins/Solo.java b/assets/src/main/java/bisq/asset/coins/Solo.java
new file mode 100644
index 00000000000..02d2beb948f
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/coins/Solo.java
@@ -0,0 +1,30 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.AltCoinAccountDisclaimer;
+import bisq.asset.Coin;
+import bisq.asset.CryptoNoteAddressValidator;
+
+@AltCoinAccountDisclaimer("account.altcoin.popup.solo.msg")
+public class Solo extends Coin {
+
+ public Solo() {
+ super("Solo", "XSL", new CryptoNoteAddressValidator(13975, 23578));
+ }
+}
diff --git a/assets/src/main/java/bisq/asset/coins/Unobtanium.java b/assets/src/main/java/bisq/asset/coins/Unobtanium.java
index 079131cb6c6..dd9b16055bb 100644
--- a/assets/src/main/java/bisq/asset/coins/Unobtanium.java
+++ b/assets/src/main/java/bisq/asset/coins/Unobtanium.java
@@ -18,11 +18,19 @@
package bisq.asset.coins;
import bisq.asset.Coin;
-import bisq.asset.DefaultAddressValidator;
+import bisq.asset.I18n;
+import bisq.asset.RegexAddressValidator;
public class Unobtanium extends Coin {
- public Unobtanium() {
- super("Unobtanium", "UNO", new DefaultAddressValidator());
+ public Unobtanium() {
+ super("Unobtanium", "UNO", new UnoAddressValidator());
+ }
+
+ public static class UnoAddressValidator extends RegexAddressValidator {
+
+ public UnoAddressValidator() {
+ super("^[u]?[a-zA-Z0-9]{33}", I18n.DISPLAY_STRINGS.getString("account.altcoin.popup.validation.UNO"));
+ }
}
}
diff --git a/assets/src/main/java/bisq/asset/coins/VARIUS.java b/assets/src/main/java/bisq/asset/coins/VARIUS.java
new file mode 100644
index 00000000000..abb3e00ce1b
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/coins/VARIUS.java
@@ -0,0 +1,28 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.Coin;
+import bisq.asset.RegexAddressValidator;
+
+public class VARIUS extends Coin {
+
+ public VARIUS() {
+ super("VARIUS Coin", "VARIUS", new RegexAddressValidator("^[V][a-km-zA-HJ-NP-Z1-9]{33}$"));
+ }
+}
\ No newline at end of file
diff --git a/assets/src/main/java/bisq/asset/coins/Vertcoin.java b/assets/src/main/java/bisq/asset/coins/Vertcoin.java
new file mode 100644
index 00000000000..1f8dae6471b
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/coins/Vertcoin.java
@@ -0,0 +1,36 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.Base58BitcoinAddressValidator;
+import bisq.asset.Coin;
+import bisq.asset.NetworkParametersAdapter;
+
+public class Vertcoin extends Coin {
+ public Vertcoin() {
+ super("Vertcoin", "VTC", new Base58BitcoinAddressValidator(new VertcoinMainNetParams()));
+ }
+
+ public static class VertcoinMainNetParams extends NetworkParametersAdapter {
+ public VertcoinMainNetParams() {
+ this.addressHeader = 71;
+ this.p2shHeader = 5;
+ this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader};
+ }
+ }
+}
diff --git a/assets/src/main/java/bisq/asset/coins/WORX.java b/assets/src/main/java/bisq/asset/coins/WORX.java
new file mode 100644
index 00000000000..837b3fe544e
--- /dev/null
+++ b/assets/src/main/java/bisq/asset/coins/WORX.java
@@ -0,0 +1,28 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.Coin;
+import bisq.asset.RegexAddressValidator;
+
+public class WORX extends Coin {
+
+ public WORX() {
+ super("WORX Coin", "WORX", new RegexAddressValidator("^[W][a-km-zA-HJ-NP-Z1-9]{33}$"));
+ }
+}
\ No newline at end of file
diff --git a/assets/src/main/java/bisq/asset/coins/Zcoin.java b/assets/src/main/java/bisq/asset/coins/Zcoin.java
index ee8fd01b252..5981ad50619 100644
--- a/assets/src/main/java/bisq/asset/coins/Zcoin.java
+++ b/assets/src/main/java/bisq/asset/coins/Zcoin.java
@@ -19,12 +19,20 @@
import bisq.asset.AltCoinAccountDisclaimer;
import bisq.asset.Coin;
-import bisq.asset.DefaultAddressValidator;
+import bisq.asset.I18n;
+import bisq.asset.RegexAddressValidator;
@AltCoinAccountDisclaimer("account.altcoin.popup.XZC.msg")
public class Zcoin extends Coin {
- public Zcoin() {
- super("Zcoin", "XZC", new DefaultAddressValidator());
+ public Zcoin() {
+ super("Zcoin", "XZC", new XzcAddressValidator());
+ }
+
+ public static class XzcAddressValidator extends RegexAddressValidator {
+
+ public XzcAddressValidator() {
+ super("^a?[a-zA-Z0-9]{33}", I18n.DISPLAY_STRINGS.getString("account.altcoin.popup.validation.XZC"));
+ }
}
}
diff --git a/assets/src/main/resources/META-INF/services/bisq.asset.Asset b/assets/src/main/resources/META-INF/services/bisq.asset.Asset
index 8aa8a736e89..69e7b11d763 100644
--- a/assets/src/main/resources/META-INF/services/bisq.asset.Asset
+++ b/assets/src/main/resources/META-INF/services/bisq.asset.Asset
@@ -22,7 +22,6 @@ bisq.asset.coins.BSQ$Mainnet
bisq.asset.coins.BSQ$Regtest
bisq.asset.coins.BSQ$Testnet
bisq.asset.coins.BurntBlackCoin
-bisq.asset.coins.Byteball
bisq.asset.coins.Cash2
bisq.asset.coins.Chaucha
bisq.asset.coins.CloakCoin
@@ -30,14 +29,18 @@ bisq.asset.coins.Counterparty
bisq.asset.coins.Credits
bisq.asset.coins.Croat
bisq.asset.coins.CRowdCLassic
+bisq.asset.coins.DarkPay
bisq.asset.coins.Dash
bisq.asset.coins.Decred
bisq.asset.coins.DeepOnion
bisq.asset.coins.Dextro
bisq.asset.coins.Dogecoin
bisq.asset.coins.Doichain
+bisq.asset.coins.Donu
bisq.asset.coins.Dragonglass
bisq.asset.coins.DSTRA
+bisq.asset.coins.Emercoin
+bisq.asset.coins.Ergo
bisq.asset.coins.Ether
bisq.asset.coins.EtherClassic
bisq.asset.coins.FourtyTwo
@@ -53,10 +56,12 @@ bisq.asset.coins.IdaPay
bisq.asset.coins.Iridium
bisq.asset.coins.Kekcoin
bisq.asset.coins.KnowYourDeveloper
+bisq.asset.coins.Kore
bisq.asset.coins.Litecoin
bisq.asset.coins.LitecoinPlus
bisq.asset.coins.LitecoinZ
bisq.asset.coins.Lytix
+bisq.asset.coins.Masari
bisq.asset.coins.Mask
bisq.asset.coins.Mile
bisq.asset.coins.MirQuiX
@@ -67,9 +72,10 @@ bisq.asset.coins.MoX
bisq.asset.coins.Myce
bisq.asset.coins.Namecoin
bisq.asset.coins.Navcoin
-bisq.asset.coins.Neos
bisq.asset.coins.Noir
bisq.asset.coins.ParsiCoin
+bisq.asset.coins.Particl
+bisq.asset.coins.PENG
bisq.asset.coins.Persona
bisq.asset.coins.Pinkcoin
bisq.asset.coins.PIVX
@@ -83,6 +89,8 @@ bisq.asset.coins.Remix
bisq.asset.coins.Ryo
bisq.asset.coins.Siafund
bisq.asset.coins.SiaPrimeCoin
+bisq.asset.coins.SixEleven
+bisq.asset.coins.Solo
bisq.asset.coins.SpaceCash
bisq.asset.coins.Spectrecoin
bisq.asset.coins.Starwels
@@ -91,8 +99,11 @@ bisq.asset.coins.TEO
bisq.asset.coins.TurtleCoin
bisq.asset.coins.UnitedCommunityCoin
bisq.asset.coins.Unobtanium
+bisq.asset.coins.VARIUS
bisq.asset.coins.Veil
+bisq.asset.coins.Vertcoin
bisq.asset.coins.Webchain
+bisq.asset.coins.WORX
bisq.asset.coins.WrkzCoin
bisq.asset.coins.XDR
bisq.asset.coins.Zcash
diff --git a/assets/src/main/resources/i18n/displayStrings-assets.properties b/assets/src/main/resources/i18n/displayStrings-assets.properties
new file mode 100644
index 00000000000..beabf782fbf
--- /dev/null
+++ b/assets/src/main/resources/i18n/displayStrings-assets.properties
@@ -0,0 +1,28 @@
+# Keep display strings organized by domain
+# Naming convention: We use camelCase and dot separated name spaces.
+# Use as many sub spaces as required to make the structure clear, but as little as possible.
+# E.g.: [main-view].[component].[description]
+# In some cases we use enum values or constants to map to display strings
+
+# A annoying issue with property files is that we need to use 2 single quotes in display string
+# containing variables (e.g. {0}), otherwise the variable will not be resolved.
+# In display string which do not use a variable a single quote is ok.
+# E.g. Don''t .... {1}
+
+# We use sometimes dynamic parts which are put together in the code and therefore sometimes use line breaks or spaces
+# at the end of the string. Please never remove any line breaks or spaces. They are there with a purpose!
+# To make longer strings with better readable you can make a line break with \ which does not result in a line break
+# in the display but only in the editor.
+
+# Please use in all language files the exact same order of the entries, that way a comparison is easier.
+
+# Please try to keep the length of the translated string similar to English. If it is longer it might break layout or
+# get truncated. We will need some adjustments in the UI code to support that but we want to keep effort at the minimum.
+
+account.altcoin.popup.validation.XCP=XCP address must start with '1' and must have 34 characters.
+account.altcoin.popup.validation.DCR=DCR address must start with 'Dk' or 'Ds' or 'De' or 'DS' or 'Dc' or 'Pm' and must have 34 characters.
+account.altcoin.popup.validation.ETC=ETC address must start with '0x' and made up of letters A to F and numbers which are 40 characters long.
+account.altcoin.popup.validation.NMC=NMC address must start with 'N' or 'M' and must be 34 characters long.
+account.altcoin.popup.validation.SF= Siafund address must be made up of letters A to F and numbers which are 76 characters long.
+account.altcoin.popup.validation.UNO=UNO address must start with 'u' and must have 34 characters.
+account.altcoin.popup.validation.XZC=XZC address must start with 'a' and must have 34 characters.
\ No newline at end of file
diff --git a/assets/src/test/java/bisq/asset/coins/CounterpartyTest.java b/assets/src/test/java/bisq/asset/coins/CounterpartyTest.java
index 0f3fc7d4d80..c56f08090d5 100644
--- a/assets/src/test/java/bisq/asset/coins/CounterpartyTest.java
+++ b/assets/src/test/java/bisq/asset/coins/CounterpartyTest.java
@@ -17,11 +17,25 @@
package bisq.asset.coins;
-import bisq.asset.AbstractAssetWithDefaultValidatorTest;
+import bisq.asset.AbstractAssetTest;
-public class CounterpartyTest extends AbstractAssetWithDefaultValidatorTest {
+public class CounterpartyTest extends AbstractAssetTest {
public CounterpartyTest() {
super(new Counterparty());
}
+
+ @Override
+ public void testValidAddresses() {
+ assertValidAddress("1A1zP1eP5QGefi2DMPTfTL5SLmv7DivfNa");
+ assertValidAddress("1KBbojKRf1YnJKp1YK5eEz9TWlS4pFEbwS");
+ assertValidAddress("1AtLN6BMlW0Rwj800LNcBBR2o0k0sYVuIN");
+ }
+
+ @Override
+ public void testInvalidAddresses() {
+ assertInvalidAddress("MxmFPEPzF19JFPU3VPrRXvUbPjMQXnQerY");
+ assertInvalidAddress("122FRU9f3fx7Hty641DRK6S3sbf3");
+ assertInvalidAddress("MxmFPEPzF19JFPU3VPrRXvUbPjMQXnQerY");
+ }
}
diff --git a/assets/src/test/java/bisq/asset/coins/DarkPayTest.java b/assets/src/test/java/bisq/asset/coins/DarkPayTest.java
new file mode 100644
index 00000000000..caa947b23c9
--- /dev/null
+++ b/assets/src/test/java/bisq/asset/coins/DarkPayTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.AbstractAssetTest;
+
+import org.junit.Test;
+
+public class DarkPayTest extends AbstractAssetTest {
+
+ public DarkPayTest() {
+ super(new DarkPay());
+ }
+
+ @Test
+ public void testValidAddresses() {
+ assertValidAddress("DXSi43hpVRjy1yGF3Vh3nnCK6ydwyWxVAD");
+ assertValidAddress("DmHHAyocykozeW8fwJxPbn1o83dT4fDtoR");
+ assertValidAddress("RSBxWDDMNxCKtnHvqf8Dsif5sm52ik36rW");
+ }
+
+ @Test
+ public void testInvalidAddresses() {
+ assertInvalidAddress("DXSi43hpVRjy1yGF3Vh3nnCK6ydwyWxVAd");
+ assertInvalidAddress("DmHHAyocykozeW888888fwJxPbn1o83dT4fDtoR");
+ assertInvalidAddress("RSBxWDDMNxCKtnHvqf8Dsif5sm52ik35rW#");
+ assertInvalidAddress("3GyEtTwXhxbjBtmAR3CtzeayAyshtvd44P");
+ assertInvalidAddress("1CnXYrivw7pJy3asKftp41wRPgBggF9fBw");
+ }
+}
diff --git a/assets/src/test/java/bisq/asset/coins/DecredTest.java b/assets/src/test/java/bisq/asset/coins/DecredTest.java
index 20190981270..2f5a476a8fa 100644
--- a/assets/src/test/java/bisq/asset/coins/DecredTest.java
+++ b/assets/src/test/java/bisq/asset/coins/DecredTest.java
@@ -17,11 +17,27 @@
package bisq.asset.coins;
-import bisq.asset.AbstractAssetWithDefaultValidatorTest;
+import bisq.asset.AbstractAssetTest;
-public class DecredTest extends AbstractAssetWithDefaultValidatorTest {
+public class DecredTest extends AbstractAssetTest {
public DecredTest() {
super(new Decred());
}
+
+ @Override
+ public void testValidAddresses() {
+ // TODO Auto-generated method stub
+ assertValidAddress("Dcur2mcGjmENx4DhNqDctW5wJCVyT3Qeqkx");
+ assertValidAddress("Dsur2mcGjmENx4DhNqDctW5wJCVyT3Qeqkx");
+ assertValidAddress("Deur2mcGjmENx4DhNqDctW5wJCVyT3Qeqkx");
+ }
+
+ @Override
+ public void testInvalidAddresses() {
+ // TODO Auto-generated method stub
+ assertInvalidAddress("aHu897ivzmeFuLNB6956X6gyGeVNHUBRgD");
+ assertInvalidAddress("a1HwTdCmQV3NspP2QqCGpehoFpi8NY4Zg3");
+ assertInvalidAddress("aHu897ivzmeFuLNB6956X6gyGeVNHUBRgD");
+ }
}
diff --git a/assets/src/test/java/bisq/asset/coins/NeosTest.java b/assets/src/test/java/bisq/asset/coins/DonuTest.java
similarity index 93%
rename from assets/src/test/java/bisq/asset/coins/NeosTest.java
rename to assets/src/test/java/bisq/asset/coins/DonuTest.java
index 67c2e9521fc..04aba7be7d4 100644
--- a/assets/src/test/java/bisq/asset/coins/NeosTest.java
+++ b/assets/src/test/java/bisq/asset/coins/DonuTest.java
@@ -21,10 +21,10 @@
import org.junit.Test;
-public class NeosTest extends AbstractAssetTest {
+public class DonuTest extends AbstractAssetTest {
- public NeosTest() {
- super(new Neos());
+ public DonuTest() {
+ super(new Donu());
}
@Test
diff --git a/assets/src/test/java/bisq/asset/coins/EmercoinTest.java b/assets/src/test/java/bisq/asset/coins/EmercoinTest.java
new file mode 100644
index 00000000000..45aef5c76d1
--- /dev/null
+++ b/assets/src/test/java/bisq/asset/coins/EmercoinTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.AbstractAssetTest;
+
+import org.junit.Test;
+
+public class EmercoinTest extends AbstractAssetTest {
+
+ public EmercoinTest() {
+ super(new Emercoin());
+ }
+
+ @Test
+ public void testValidAddresses() {
+ assertValidAddress("EedXjU95QcVHLEFAs5EKNT9UWqAWXTyuhD"); // Regular p2pkh address
+ assertValidAddress("EHNiED27Un5yKHHsGFDsQipCH4TdsTo5xb"); // Regular p2pkh address
+ assertValidAddress("eMERCoinFunera1AddressXXXXXXYDAYke"); // Dummy p2sh address
+ }
+
+ @Test
+ public void testInvalidAddresses() {
+ assertInvalidAddress("19rem1SSWTphjsFLmcNEAvnfHaBFuDMMae"); // Valid BTC
+ assertInvalidAddress("EedXjU95QcVHLEFAs5EKNT9UWqAWXTyuhE"); // Invalid EMC address
+ assertInvalidAddress("DDWUYQ3GfMDj8hkx8cbnAMYkTzzAunAQxg"); // Valid DOGE
+
+ }
+}
diff --git a/assets/src/test/java/bisq/asset/coins/ErgoTest.java b/assets/src/test/java/bisq/asset/coins/ErgoTest.java
new file mode 100644
index 00000000000..4a4f6b65b27
--- /dev/null
+++ b/assets/src/test/java/bisq/asset/coins/ErgoTest.java
@@ -0,0 +1,48 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.AbstractAssetTest;
+
+import org.junit.Test;
+
+public class ErgoTest extends AbstractAssetTest {
+
+ public ErgoTest() {
+ super(new Ergo());
+ }
+
+ @Test
+ public void testValidAddresses() {
+ assertValidAddress("9fRAWhdxEsTcdb8PhGNrZfwqa65zfkuYHAMmkQLcic1gdLSV5vA");
+ assertValidAddress("25qGdVWg2yyYho8uC1pLtc7KxFn4nEEAwD");
+ assertValidAddress("23NL9a8ngN28ovtLiKLgHexcdTKBbUMLhH");
+ assertValidAddress("7bwdkU5V8");
+ assertValidAddress("BxKBaHkvrTvLZrDcZjcsxsF7aSsrN73ijeFZXtbj4CXZHHcvBtqSxQ");
+ }
+
+ @Test
+ public void testInvalidAddresses() {
+ assertInvalidAddress("9fRAWhdxEsTcdb8PhGNrZfwqa65zfkuYHAMmkQLcic1gdLSV5vAaa");
+ assertInvalidAddress("afRAWhdxEsTcdb8PhGNrZfwqa65zfkuYHAMmkQLcic1gdLSV5vA");
+ assertInvalidAddress("25qGdVWg2yyYho8uC1pLtc7KxFn4nEEAwDaa");
+ assertInvalidAddress("23NL9a8ngN28ovtLiKLgHexcdTKBbUMLhHaa");
+ assertInvalidAddress("7bwdkU5V8aa");
+ assertInvalidAddress("BxKBaHkvrTvLZrDcZjcsxsF7aSsrN73ijeFZXtbj4CXZHHcvBtqSxQ#");
+ }
+}
diff --git a/assets/src/test/java/bisq/asset/coins/EtherClassicTest.java b/assets/src/test/java/bisq/asset/coins/EtherClassicTest.java
index f8f09cad346..0aadbd78002 100644
--- a/assets/src/test/java/bisq/asset/coins/EtherClassicTest.java
+++ b/assets/src/test/java/bisq/asset/coins/EtherClassicTest.java
@@ -17,11 +17,26 @@
package bisq.asset.coins;
-import bisq.asset.AbstractAssetWithDefaultValidatorTest;
+import bisq.asset.AbstractAssetTest;
-public class EtherClassicTest extends AbstractAssetWithDefaultValidatorTest {
+public class EtherClassicTest extends AbstractAssetTest {
public EtherClassicTest() {
super(new EtherClassic());
}
+
+ @Override
+ public void testValidAddresses() {
+ assertValidAddress("0x353c13b940aa5eed75aa97d477954289e7880bb8");
+ assertValidAddress("0x9f5304DA62A5408416Ea58A17a92611019bD5ce3");
+ assertValidAddress("0x180826b05452ce96E157F0708c43381Fee64a6B8");
+
+ }
+
+ @Override
+ public void testInvalidAddresses() {
+ assertInvalidAddress("MxmFPEPzF19JFPU3VPrRXvUbPjMQXnQerY");
+ assertInvalidAddress("N22FRU9f3fx7Hty641D5cg95kRK6S3sbf3");
+ assertInvalidAddress("MxmFPEPzF19JFPU3VPrRXvUbPjMQXnQerY");
+ }
}
diff --git a/assets/src/test/java/bisq/asset/coins/KoreTest.java b/assets/src/test/java/bisq/asset/coins/KoreTest.java
new file mode 100644
index 00000000000..699d80a5992
--- /dev/null
+++ b/assets/src/test/java/bisq/asset/coins/KoreTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.AbstractAssetTest;
+
+import org.junit.Test;
+
+public class KoreTest extends AbstractAssetTest {
+
+ public KoreTest() {
+ super(new Kore());
+ }
+
+ @Test
+ public void testValidAddresses() {
+ assertValidAddress("KViqqCDcdZn3DKJWGvmdUtmoDsxuGswzwU");
+ assertValidAddress("KNnThWKeyJ5ibYL3JhuBacyjJxKXs2cXgv");
+ assertValidAddress("bGcebbVyKD4PEBHeKRGX7cTydu1xRm63r4");
+ }
+
+ @Test
+ public void testInvalidAddresses() {
+ assertInvalidAddress("KmVwB5dxph84tb15XqRUtfX1MfmP8WpWWW");
+ assertInvalidAddress("Kt85555555555555c1QcQYE318zXqZUnjUB6fwjTrf1Xkb");
+ assertInvalidAddress("33ny4vAPJHFu5Nic7uMHQrvCACYTKPFJ6r#");
+ }
+}
diff --git a/assets/src/test/java/bisq/asset/coins/MasariTest.java b/assets/src/test/java/bisq/asset/coins/MasariTest.java
new file mode 100644
index 00000000000..0552df6285c
--- /dev/null
+++ b/assets/src/test/java/bisq/asset/coins/MasariTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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 .
+ */
+
+ package bisq.asset.coins;
+
+ import bisq.asset.AbstractAssetTest;
+ import org.junit.Test;
+
+ public class MasariTest extends AbstractAssetTest {
+
+ public MasariTest() {
+ super(new Masari());
+ }
+
+ @Test
+ public void testValidAddresses() {
+ assertValidAddress("5n9Y2vwnf8oKBhHxRAyjS9aS9j5hTPjtS8RKzMbD3tP95yxkQWbUHkFhLs2UsjgNxj28W6YzNL9WFeY91xPGFXAaUwyVm1h");
+ assertValidAddress("9n1AVze3gmj3ZpEz5Xju92FRiqtmcnQhhXJK7yx9D9qrHRvjZftndVci8HCYFttFeD7ftAMUqUGxG8iA4Sn2eVz45R2NUJj");
+ assertValidAddress("5iB4LfuyvA5HSJP5A1xUKGb8pw5NkywxSeRZPxzy1U7kT3wBmypemQUUzTiCwjy6PTSrJpAvxiNDSUEjNryt17C8RvPdEg3");
+ }
+
+ @Test
+ public void testInvalidAddresses() {
+ assertInvalidAddress("");
+ assertInvalidAddress("5hJpeWa9aogfpY5Su8YmeYaeuD7pyQvSZURcNx26QskbSk9UdZ6cR4HR4YsdWRiBJfCZKLHRTfj7ojGUJ7N5j5hg4pGGCE");
+ assertInvalidAddress("5kYyn6K8hRWg16nztTuvaZ6Jg3ytH84gjbUoEKjbMU4u659PKLpKuLWVSujFwJ1Qp3ZUxhcFHBXMQDmeAz46By3FRRkdaug2");
+ assertInvalidAddress("4okMfbVrFXE4nF9dRKnVLiJi2xiMDDuSk6MJexpBaNgsLutSaBN7euR8TCf4Z1dqmG85GdQHrzSpYgX8Lf2VJnkaAk9MtQV");
+ assertInvalidAddress("5jrE2mwcHkvZq9rQcvX1GCELnwAF6wwmJ4rhVdDP6y#326Gp6KSNbeWWb1sD2dmDZvczHFs8LGM1UjTQfQjjAu6S4eXGC5h");
+ }
+}
diff --git a/assets/src/test/java/bisq/asset/coins/MoneroTest.java b/assets/src/test/java/bisq/asset/coins/MoneroTest.java
index 0b28aa5ef77..48841ee5aa3 100644
--- a/assets/src/test/java/bisq/asset/coins/MoneroTest.java
+++ b/assets/src/test/java/bisq/asset/coins/MoneroTest.java
@@ -31,6 +31,11 @@ public void testValidAddresses() {
assertValidAddress("4BJHitCigGy6giuYsJFP26KGkTKiQDJ6HJP1pan2ir2CCV8Twc2WWmo4fu1NVXt8XLGYAkjo5cJ3yH68Lfz9ZXEUJ9MeqPW");
assertValidAddress("46tM15KsogEW5MiVmBn7waPF8u8ZsB6aHjJk7BAv1wvMKfWhQ2h2so5BCJ9cRakfPt5BFo452oy3K8UK6L2u2v7aJ3Nf7P2");
assertValidAddress("86iQTnEqQ9mXJFvBvbY3KU5do5Jh2NCkpTcZsw3TMZ6oKNJhELvAreZFQ1p8EknRRTKPp2vg9fJvy47Q4ARVChjLMuUAFQJ");
+
+ // integrated addresses
+ assertValidAddress("4LL9oSLmtpccfufTMvppY6JwXNouMBzSkbLYfpAV5Usx3skxNgYeYTRj5UzqtReoS44qo9mtmXCqY45DJ852K5Jv2bYXZKKQePHES9khPK");
+ assertValidAddress("4GdoN7NCTi8a5gZug7PrwZNKjvHFmKeV11L6pNJPgj5QNEHsN6eeX3DaAQFwZ1ufD4LYCZKArktt113W7QjWvQ7CWD1FFMXoYHeE6M55P9");
+ assertValidAddress("4GdoN7NCTi8a5gZug7PrwZNKjvHFmKeV11L6pNJPgj5QNEHsN6eeX3DaAQFwZ1ufD4LYCZKArktt113W7QjWvQ7CW82yHFEGvSG3NJRNtH");
}
@Test
diff --git a/assets/src/test/java/bisq/asset/coins/NamecoinTest.java b/assets/src/test/java/bisq/asset/coins/NamecoinTest.java
index 8c513ff7010..4f025fab26f 100644
--- a/assets/src/test/java/bisq/asset/coins/NamecoinTest.java
+++ b/assets/src/test/java/bisq/asset/coins/NamecoinTest.java
@@ -17,11 +17,29 @@
package bisq.asset.coins;
-import bisq.asset.AbstractAssetWithDefaultValidatorTest;
+import org.junit.Test;
+import bisq.asset.AbstractAssetTest;
-public class NamecoinTest extends AbstractAssetWithDefaultValidatorTest {
+public class NamecoinTest extends AbstractAssetTest {
public NamecoinTest() {
super(new Namecoin());
}
+
+ @Test
+ public void testValidAddresses() {
+ assertValidAddress("N7yhcPhzFduWXPc11AUK9zvtnsL6sgxmRs");
+ assertValidAddress("N22FRU9f3fx7Hty641D5cg95kRK6S3sbf3");
+ assertValidAddress("MxmFPEPzF19JFPU3VPrRXvUbPjMQXnQerY");
+ }
+
+ @Test
+ public void testInvalidAddresses() {
+ assertInvalidAddress("N7yhcPhzFduWXPc11AUK9zvtnsL6sgxmRsx");
+ assertInvalidAddress("MxmFPEPzF19JFPU3VPrRXvUbPjMQXnQer");
+ assertInvalidAddress("bc1qus65zpte6qa2408qu3540lfcyj9cx7dphfcspn");
+ assertInvalidAddress("3GyEtTwXhxbjBtmAR3CtzeayAyshtvd44P");
+ assertInvalidAddress("1CnXYrivw7pJy3asKftp41wRPgBggF9fBw");
+ }
}
+
diff --git a/assets/src/test/java/bisq/asset/coins/NoirTest.java b/assets/src/test/java/bisq/asset/coins/NoirTest.java
index 41ac9a081db..78bc7e3c67d 100644
--- a/assets/src/test/java/bisq/asset/coins/NoirTest.java
+++ b/assets/src/test/java/bisq/asset/coins/NoirTest.java
@@ -17,11 +17,11 @@
package bisq.asset.coins;
-import bisq.asset.AbstractAssetWithDefaultValidatorTest;
+import bisq.asset.AbstractAssetTest;
import org.junit.Test;
-public class NoirTest extends AbstractAssetWithDefaultValidatorTest {
+public class NoirTest extends AbstractAssetTest {
public NoirTest() {
super(new Noir());
diff --git a/assets/src/test/java/bisq/asset/coins/PENGTest.java b/assets/src/test/java/bisq/asset/coins/PENGTest.java
new file mode 100644
index 00000000000..56af71f0521
--- /dev/null
+++ b/assets/src/test/java/bisq/asset/coins/PENGTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.AbstractAssetTest;
+
+import org.junit.Test;
+
+public class PENGTest extends AbstractAssetTest {
+
+ public PENGTest() {
+ super(new PENG());
+ }
+
+ @Test
+ public void testValidAddresses() {
+ assertValidAddress("P9KqnVS9UpcJmLtCF1j4SV3fcccMuGEbhs");
+ assertValidAddress("PUTXyY73s3HDvEzNJQekXMnjNjTrzFBzE2");
+ assertValidAddress("PEfabj5DzRj6WBpc3jtVDorsVM5nddDxie");
+ assertValidAddress("PAvXbSUAdCyd9MEtDPYYSmezmeLGL1HcjG");
+ }
+
+ @Test
+ public void testInvalidAddresses() {
+ assertInvalidAddress("Pp9KqnVS9UpcJmLtCF1j4SV3fcccMuGEbhs");
+ assertInvalidAddress("PqUTXyY73s3HDvEzNJQekXMnjNjTrzFBzE2");
+ assertInvalidAddress("P8Efabj5DzRj6WBpc3jtVDorsVM5nddDxie");
+ assertInvalidAddress("P9AvXbSUAdCyd9MEtDPYYSmezmeLGL1HcjG");
+ }
+}
\ No newline at end of file
diff --git a/assets/src/test/java/bisq/asset/AbstractAssetWithDefaultValidatorTest.java b/assets/src/test/java/bisq/asset/coins/ParticlTest.java
similarity index 52%
rename from assets/src/test/java/bisq/asset/AbstractAssetWithDefaultValidatorTest.java
rename to assets/src/test/java/bisq/asset/coins/ParticlTest.java
index 9522298d1b1..9e7a398553e 100644
--- a/assets/src/test/java/bisq/asset/AbstractAssetWithDefaultValidatorTest.java
+++ b/assets/src/test/java/bisq/asset/coins/ParticlTest.java
@@ -15,37 +15,30 @@
* along with Bisq. If not, see .
*/
-package bisq.asset;
+package bisq.asset.coins;
+
+import bisq.asset.AbstractAssetTest;
import org.junit.Test;
-/**
- * Convenient abstract base class for {@link Asset} implementations still using the
- * deprecated {@link DefaultAddressValidator}.
- *
- * @author Bernard Labno
- * @since 0.7.0
- * @see DefaultAddressValidator
- */
-@Deprecated
-public abstract class AbstractAssetWithDefaultValidatorTest extends AbstractAssetTest {
+public class ParticlTest extends AbstractAssetTest {
- public AbstractAssetWithDefaultValidatorTest(Asset asset) {
- super(asset);
+ public ParticlTest() {
+ super(new Particl());
}
@Test
public void testValidAddresses() {
- assertValidAddress(" ");
- assertValidAddress("1");
- assertValidAddress("AQJTNtWcP7opxuR52Lf5vmoQTC8EHQ6GxV");
- assertValidAddress("ALEK7jttmqtx2ZhXHg69Zr426qKBnzYA9E");
- assertValidAddress("AP1egWUthPoYvZL57aBk4RPqUgjG1fJGn6");
- assertValidAddress("AST3zfvPdZ35npxAVC8ABgVCxxDLwTmAHU");
+ assertValidAddress("PZdYWHgyhuG7NHVCzEkkx3dcLKurTpvmo6");
+ assertValidAddress("RJAPhgckEgRGVPZa9WoGSWW24spskSfLTQ");
+ assertValidAddress("PaqMewoBY4vufTkKeSy91su3CNwviGg4EK");
+ assertValidAddress("PpWHwrkUKRYvbZbTic57YZ1zjmsV9X9Wu7");
}
@Test
public void testInvalidAddresses() {
- testBlank();
+ assertInvalidAddress("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhemqq");
+ assertInvalidAddress("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYheO");
+ assertInvalidAddress("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhek");
}
}
diff --git a/assets/src/test/java/bisq/asset/coins/SiafundTest.java b/assets/src/test/java/bisq/asset/coins/SiafundTest.java
index c1ea0f235f6..864a05ac125 100644
--- a/assets/src/test/java/bisq/asset/coins/SiafundTest.java
+++ b/assets/src/test/java/bisq/asset/coins/SiafundTest.java
@@ -17,11 +17,26 @@
package bisq.asset.coins;
-import bisq.asset.AbstractAssetWithDefaultValidatorTest;
+import bisq.asset.AbstractAssetTest;
-public class SiafundTest extends AbstractAssetWithDefaultValidatorTest {
+public class SiafundTest extends AbstractAssetTest {
public SiafundTest() {
super(new Siafund());
}
+
+ @Override
+ public void testValidAddresses() {
+ assertValidAddress("949f35966a9b5f329f7419f91a02301b71b9f776568b2c767842af22b408eb8662203a02ec53");
+ assertValidAddress("4daae3005456559972f4902217ee8394a890e2afede6f0b49015e5cfaecdcb13f466f5543346");
+ assertValidAddress("da4f7fdc0fa047851a9860b09bc9b1e7424333c977e53a5d8aad74f5843a20b7cfa77a7794ae");
+
+ }
+
+ @Override
+ public void testInvalidAddresses() {
+ assertInvalidAddress("MxmFPEPzF19JFPU3VPrRXvUbPjMQXnQerY");
+ assertInvalidAddress("N22FRU9f3fx7Hty641D5cg95kRK6S3sbf3");
+ assertInvalidAddress("MxmFPEPzF19JFPU3VPrRXvUbPjMQXnQerY");
+ }
}
diff --git a/assets/src/test/java/bisq/asset/coins/SixElevenTest.java b/assets/src/test/java/bisq/asset/coins/SixElevenTest.java
new file mode 100644
index 00000000000..a7de8d34e4c
--- /dev/null
+++ b/assets/src/test/java/bisq/asset/coins/SixElevenTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import org.junit.Test;
+import bisq.asset.AbstractAssetTest;
+
+public class SixElevenTest extends AbstractAssetTest {
+
+ public SixElevenTest() {
+ super(new SixEleven());
+ }
+
+ @Test
+ public void testValidAddresses() {
+ assertValidAddress("N7yhcPhzFduWXPc11AUK9zvtnsL6sgxmRs");
+ assertValidAddress("N22FRU9f3fx7Hty641D5cg95kRK6S3sbf3");
+ assertValidAddress("MxmFPEPzF19JFPU3VPrRXvUbPjMQXnQerY");
+ }
+
+ @Test
+ public void testInvalidAddresses() {
+ assertInvalidAddress("N7yhcPhzFduWXPc11AUK9zvtnsL6sgxmRsx");
+ assertInvalidAddress("MxmFPEPzF19JFPU3VPrRXvUbPjMQXnQer");
+ assertInvalidAddress("bc1qus65zpte6qa2408qu3540lfcyj9cx7dphfcspn");
+ assertInvalidAddress("3GyEtTwXhxbjBtmAR3CtzeayAyshtvd44P");
+ assertInvalidAddress("1CnXYrivw7pJy3asKftp41wRPgBggF9fBw");
+ }
+}
diff --git a/assets/src/test/java/bisq/asset/coins/SoloTest.java b/assets/src/test/java/bisq/asset/coins/SoloTest.java
new file mode 100644
index 00000000000..e95bbcafcaa
--- /dev/null
+++ b/assets/src/test/java/bisq/asset/coins/SoloTest.java
@@ -0,0 +1,44 @@
+/*
+ * 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 .
+ */
+
+ package bisq.asset.coins;
+
+ import bisq.asset.AbstractAssetTest;
+ import org.junit.Test;
+
+ public class SoloTest extends AbstractAssetTest {
+
+ public SoloTest() {
+ super(new Solo());
+ }
+
+ @Test
+ public void testValidAddresses() {
+ assertValidAddress("SL3UVNhEHuaWK9PwhVgMZWD5yaL6VBC4xRuXLnLFWizxavKvSqbcSpH2fG3dT36uMJEQ6XoKBqvFLUnzWG4Rb5e11yqsioFy8");
+ assertValidAddress("Ssy27ePzscCj4spPjgtc8NKGSud9eLFLHGEWNAo8PuC53NnWhDDTX17Cfo3BzFKdYZfU9ovtEYNtQ4ezTtPhAHEuAR5mF8dTqB");
+ assertValidAddress("Ssy2WFFnmi3XYJz8UsXPKzHtUxFdVhdSuU3sBGmpTbTLQqpZEMPS8GB486Q8UCaskdbGzxJxwdJYobtJmEPwDawa5mXD5spNbs");
+ }
+
+ @Test
+ public void testInvalidAddresses() {
+ assertInvalidAddress("");
+ assertInvalidAddress("SL3dqGkkFszKzjzyXSLkYB6X9uqad7ih3DJtTeB8hrzD9iaRjWAUHZ8FA3NErphWM00NzURSTL7FEZ9un9fgLYjK2f7mHRFBn");
+ assertInvalidAddress("Ssy2WLjegYxS5P1djMSRmVG8EzXDfHyde6BiZRd3aDyVh1vjwUB2GJHfWhVsvg1i4TjWyGRC9rD4n3kCE2gPA9yx6K34AyzcMZ");
+ assertInvalidAddress("Sl3UVNhEHuaWK9PwhVgMZWD5yaL6VBC4xRuXLnLFWizxavKvSXxXSpam8d3dMaDuMJEQ6XoKBqvFLUnzWG4Rb5e11yqsioFy8");
+ assertInvalidAddress("Ssy2WFFnmi3XYJz8UsXPKzHtUxFdVhdSuU3sBGmpTbTLQLoLIghGooDdf6QTryaskdbGzxJxwdJYobtJmEPwDawa5mXD5spNbs");
+ }
+}
diff --git a/assets/src/test/java/bisq/asset/coins/UnobtaniumTest.java b/assets/src/test/java/bisq/asset/coins/UnobtaniumTest.java
index ed90c1e63db..7a3ec5afe31 100644
--- a/assets/src/test/java/bisq/asset/coins/UnobtaniumTest.java
+++ b/assets/src/test/java/bisq/asset/coins/UnobtaniumTest.java
@@ -17,11 +17,25 @@
package bisq.asset.coins;
-import bisq.asset.AbstractAssetWithDefaultValidatorTest;
+import bisq.asset.AbstractAssetTest;
-public class UnobtaniumTest extends AbstractAssetWithDefaultValidatorTest {
+public class UnobtaniumTest extends AbstractAssetTest {
public UnobtaniumTest() {
super(new Unobtanium());
}
+
+ @Override
+ public void testValidAddresses() {
+ assertValidAddress("uXN2S9Soj4dSL7fPAuQi9twdaFmtwYndVP");
+ assertValidAddress("uZymbhuxhfvxzc5EDdqRWrrZKvabZibBu1");
+ assertValidAddress("uKdudT6DwojHYsBE9JWM43hRV28Rmp1Zm1");
+ }
+
+ @Override
+ public void testInvalidAddresses() {
+ assertInvalidAddress("aHu897ivzmeFuLNB6956X6gyGeVNHUBRgD");
+ assertInvalidAddress("a1HwTdCmQV3NspP2QqCGpehoFpi8NY4Zg3");
+ assertInvalidAddress("aHu897ivzmeFuLNB6956X6gyGeVNHUBRgD");
+ }
}
diff --git a/assets/src/test/java/bisq/asset/coins/ByteballTest.java b/assets/src/test/java/bisq/asset/coins/VARIUSTest.java
similarity index 64%
rename from assets/src/test/java/bisq/asset/coins/ByteballTest.java
rename to assets/src/test/java/bisq/asset/coins/VARIUSTest.java
index 81d290c8a78..a8b27d14063 100644
--- a/assets/src/test/java/bisq/asset/coins/ByteballTest.java
+++ b/assets/src/test/java/bisq/asset/coins/VARIUSTest.java
@@ -17,26 +17,27 @@
package bisq.asset.coins;
-import bisq.asset.AbstractAssetTest;
-
import org.junit.Test;
-public class ByteballTest extends AbstractAssetTest {
+import bisq.asset.AbstractAssetTest;
+
+public class VARIUSTest extends AbstractAssetTest {
- public ByteballTest() {
- super(new Byteball());
+ public VARIUSTest() {
+ super(new VARIUS());
}
@Test
public void testValidAddresses() {
- assertValidAddress("BN7JXKXWEG4BVJ7NW6Q3Z7SMJNZJYM3G");
- assertValidAddress("XGKZODTTTRXIUA75TKONWHFDCU6634DE");
+ assertValidAddress("VL85MGBCSfnSeiLxuQwXuvxHArzfr1574H");
+ assertValidAddress("VBKxFQULC6bjzWdb2PhZyoRdePq8fs55fi");
+ assertValidAddress("VXwmVvzX6KMqfkBJXRXu4VUbgzPhLKdBSq");
}
@Test
public void testInvalidAddresses() {
- assertInvalidAddress("XGKZODTGTRXIUA75TKONWHFDCU6634DE");
- assertInvalidAddress("XGKZODTTTRXIUA75TKONWHFDCU6634D");
- assertInvalidAddress("XGKZODTTTRXIUA75TKONWHFDCU6634DZ");
+ assertInvalidAddress("xLfnSeiLxuQwXuvxHArzfr1574H");
+ assertInvalidAddress("BBKzWdb2PhZyoRdePq8fs55fi");
+ assertInvalidAddress("vXwmVvzX6KMqfkBJXRXu4VUbgzPhLKdBSq");
}
-}
+}
\ No newline at end of file
diff --git a/assets/src/test/java/bisq/asset/coins/VertcoinTest.java b/assets/src/test/java/bisq/asset/coins/VertcoinTest.java
new file mode 100644
index 00000000000..a938eafac38
--- /dev/null
+++ b/assets/src/test/java/bisq/asset/coins/VertcoinTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.AbstractAssetTest;
+
+import org.junit.Test;
+
+public class VertcoinTest extends AbstractAssetTest {
+
+ public VertcoinTest() {
+ super(new Vertcoin());
+ }
+
+ @Test
+ public void testValidAddresses() {
+ assertValidAddress("VmVwB5dxph84tbi5XqRUtfX1MfmP8WpWWL");
+ assertValidAddress("Vt85c1QcQYE318zXqZUnjUB6fwjTrf1Xkb");
+ assertValidAddress("33ny4vAPJHFu5Nic7uMHQrvCACYTKPFJ5p");
+ }
+
+ @Test
+ public void testInvalidAddresses() {
+ assertInvalidAddress("VmVwB5dxph84tb15XqRUtfX1MfmP8WpWWW");
+ assertInvalidAddress("Vt85555555555555c1QcQYE318zXqZUnjUB6fwjTrf1Xkb");
+ assertInvalidAddress("33ny4vAPJHFu5Nic7uMHQrvCACYTKPFJ6r#");
+ }
+}
diff --git a/assets/src/test/java/bisq/asset/coins/WORXTest.java b/assets/src/test/java/bisq/asset/coins/WORXTest.java
new file mode 100644
index 00000000000..a9816333321
--- /dev/null
+++ b/assets/src/test/java/bisq/asset/coins/WORXTest.java
@@ -0,0 +1,45 @@
+/*
+ * 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 .
+ */
+
+package bisq.asset.coins;
+
+import bisq.asset.AbstractAssetTest;
+
+import org.junit.Test;
+
+public class WORXTest extends AbstractAssetTest {
+
+ public WORXTest() {
+ super(new WORX());
+ }
+
+ @Test
+ public void testValidAddresses() {
+ assertValidAddress("WgeBjv4PkmNnsUZ6QqhhT3ynEaqr3xDWuS");
+ assertValidAddress("WQDes3h9GBa72R9govQCic3f38m566Jydo");
+ assertValidAddress("WeNnnz8KFgmipcLhpbXSM9HT37pSqqeVbk");
+ assertValidAddress("WNzf7fZgc2frhBGqVvhVhYpSBMWd2WE6x5");
+ }
+
+ @Test
+ public void testInvalidAddresses() {
+ assertInvalidAddress("WgeBjv4PksmNnsUZ6QqhhT3ynEaqr3xDWuS");
+ assertInvalidAddress("W2QDes3h9GBa72R9govQCic3f38m566Jydo");
+ assertInvalidAddress("WeNnnz8KFgmipcLhpbXSM9HT37pSqqeVbk3");
+ assertInvalidAddress("WNzf7fZgc2frhBGqVvhVhYpSBMWd2WE6x54");
+ }
+}
\ No newline at end of file
diff --git a/assets/src/test/java/bisq/asset/coins/ZcoinTest.java b/assets/src/test/java/bisq/asset/coins/ZcoinTest.java
index eab34a266ba..5178a3f6722 100644
--- a/assets/src/test/java/bisq/asset/coins/ZcoinTest.java
+++ b/assets/src/test/java/bisq/asset/coins/ZcoinTest.java
@@ -17,11 +17,25 @@
package bisq.asset.coins;
-import bisq.asset.AbstractAssetWithDefaultValidatorTest;
+import bisq.asset.AbstractAssetTest;
-public class ZcoinTest extends AbstractAssetWithDefaultValidatorTest {
+public class ZcoinTest extends AbstractAssetTest {
public ZcoinTest() {
super(new Zcoin());
}
+
+ @Override
+ public void testValidAddresses() {
+ assertValidAddress("aHu897ivzmeFuLNB6956X6gyGeVNHUBRgD");
+ assertValidAddress("a1HwTdCmQV3NspP2QqCGpehoFpi8NY4Zg3");
+ assertValidAddress("aHu897ivzmeFuLNB6956X6gyGeVNHUBRgD");
+ }
+
+ @Override
+ public void testInvalidAddresses() {
+ assertInvalidAddress("MxmFPEPzF19JFPU3VPrRXvUbPjMQXnQerY");
+ assertInvalidAddress("N22FRU9f3fx7Hty641D5cg95kRK6S3sbf3");
+ assertInvalidAddress("MxmFPEPzF19JFPU3VPrRXvUbPjMQXnQerY");
+ }
}
diff --git a/build.gradle b/build.gradle
index 9bc56f88e4d..71f8134c890 100644
--- a/build.gradle
+++ b/build.gradle
@@ -3,11 +3,12 @@ buildscript {
jcenter()
}
dependencies {
- classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.5'
+ classpath 'com.google.protobuf:protobuf-gradle-plugin:0.8.10'
classpath 'com.google.gradle:osdetector-gradle-plugin:1.6.0'
classpath 'com.github.jengelman.gradle.plugins:shadow:4.0.2'
classpath files('gradle/witness/gradle-witness.jar')
classpath 'org.springframework.boot:spring-boot-gradle-plugin:1.5.10.RELEASE'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.3.41"
}
}
@@ -21,26 +22,53 @@ configure(rootProject) {
}
configure(subprojects) {
+ apply plugin: 'kotlin'
apply plugin: 'java'
apply plugin: 'com.google.osdetector'
sourceCompatibility = 1.10
- ext {
+ ext { // in alphabetical order
bcVersion = '1.56'
+ bitcoinjVersion = 'a88d36d'
+ btcdCli4jVersion = '975ff5d4'
codecVersion = '1.9'
+ controlsfxVersion = '8.0.6_20'
+ easybindVersion = '1.0.3'
easyVersion = '4.0.1'
- jmockitVersion = '1.42'
+ findbugsVersion = '3.0.2'
+ firebaseVersion = '6.2.0'
+ fontawesomefxVersion = '8.0.0'
+ fontawesomefxCommonsVersion = '9.1.2'
+ fontawesomefxMaterialdesignfontVersion = '2.0.26-9.1.2'
+ guavaVersion = '20.0'
+ guiceVersion = '4.2.2'
+ hamcrestVersion = '1.3'
+ httpclientVersion = '4.5.3'
+ ioVersion = '2.4'
+ jacksonVersion = '2.8.10'
+ jcsvVersion = '1.4.0'
+ jetbrainsAnnotationsVersion = '13.0'
+ jfoenixVersion = '9.0.6'
joptVersion = '5.0.3'
+ jsonsimpleVersion = '1.1.1'
+ junitVersion = '4.12'
+ jupiterVersion = '5.3.2'
+ kotlinVersion = '1.3.41'
+ knowmXchangeVersion = '4.3.3'
langVersion = '3.4'
- bitcoinjVersion = 'a88d36d'
logbackVersion = '1.1.10'
lombokVersion = '1.18.2'
- mockitoVersion = '2.21.0'
- powermockVersion = '2.0.0-beta.5'
- protobufVersion = '3.5.1'
+ mockitoVersion = '3.0.0'
+ netlayerVersion = '0.6.5.1'
+ protobufVersion = '3.9.1'
+ pushyVersion = '0.13.2'
+ qrgenVersion = '1.3'
+ reactfxVersion = '2.0-M3'
+ sarxosVersion = '0.3.12'
slf4jVersion = '1.7.22'
sparkVersion = '2.5.2'
+ springBootVersion = '1.5.10.RELEASE'
springVersion = '4.3.6.RELEASE'
os = osdetector.os == 'osx' ? 'mac' : osdetector.os == 'windows' ? 'win' : osdetector.os
@@ -52,7 +80,7 @@ configure(subprojects) {
}
dependencies {
- testCompile 'junit:junit:4.12'
+ testCompile "junit:junit:$junitVersion"
}
tasks.withType(JavaCompile) {
@@ -84,17 +112,6 @@ configure([project(':desktop'),
// copy generated shell scripts, e.g. `bisq-desktop` directly to the project
// root directory for discoverability and ease of use
- // TODO @cbeams The copy task below fails because the copied files are conflicting with the project
- // folder name. I temporarily delete those files as I think they are duplicated anyway (bisq-* are probably
- // the one to use). Would be good if those files don't get created in the first place.
- // The .bat files are also deleted.
- delete fileTree(dir: "$destinationDir/bin", include: 'desktop*')
- delete fileTree(dir: "$destinationDir/bin", include: 'monitor*')
- delete fileTree(dir: "$destinationDir/bin", include: 'seednode*')
- delete fileTree(dir: "$destinationDir/bin", include: 'pricenode*')
- delete fileTree(dir: "$destinationDir/bin", include: 'statsnode*')
- delete fileTree(dir: "$destinationDir/bin", include: 'relay*')
-
copy {
from "$destinationDir/bin"
into rootProject.projectDir
@@ -138,9 +155,8 @@ configure(project(':assets')) {
exclude(module: 'guava')
exclude(module: 'protobuf-java')
}
- compile 'com.google.guava:guava:20.0'
+ compile "com.google.guava:guava:$guavaVersion"
compile "org.slf4j:slf4j-api:$slf4jVersion"
- compile "commons-codec:commons-codec:$codecVersion"
compile "org.apache.commons:commons-lang3:$langVersion"
compile "org.bouncycastle:bcpg-jdk15on:$bcVersion"
}
@@ -159,20 +175,21 @@ configure(project(':common')) {
}
dependencies {
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk8:$kotlinVersion"
compile "org.openjfx:javafx-base:11:$os"
compile "org.openjfx:javafx-graphics:11:$os"
compile "com.google.protobuf:protobuf-java:$protobufVersion"
compile 'com.google.code.gson:gson:2.7'
- compile('com.googlecode.json-simple:json-simple:1.1.1') {
+ compile("com.googlecode.json-simple:json-simple:$jsonsimpleVersion") {
exclude(module: 'junit')
}
compile "org.springframework:spring-core:$springVersion"
compile "org.slf4j:slf4j-api:$slf4jVersion"
compile "ch.qos.logback:logback-core:$logbackVersion"
compile "ch.qos.logback:logback-classic:$logbackVersion"
- compile 'com.google.code.findbugs:jsr305:3.0.2'
- compile 'com.google.guava:guava:20.0'
- compile('com.google.inject:guice:4.1.0') {
+ compile "com.google.code.findbugs:jsr305:$findbugsVersion"
+ compile "com.google.guava:guava:$guavaVersion"
+ compile("com.google.inject:guice:$guiceVersion") {
exclude(module: 'guava')
}
compile("com.github.bisq-network.bitcoinj:bitcoinj-core:$bitcoinjVersion") {
@@ -181,10 +198,10 @@ configure(project(':common')) {
exclude(module: 'guava')
exclude(module: 'protobuf-java')
}
- compile 'org.jetbrains:annotations:13.0'
+ compile "org.jetbrains:annotations:$jetbrainsAnnotationsVersion"
runtime "org.bouncycastle:bcprov-jdk15on:$bcVersion"
compile "org.bouncycastle:bcpg-jdk15on:$bcVersion"
- compile 'commons-io:commons-io:2.4'
+ compile "commons-io:commons-io:$ioVersion"
compile "org.apache.commons:commons-lang3:$langVersion"
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
@@ -195,22 +212,22 @@ configure(project(':common')) {
configure(project(':p2p')) {
dependencies {
compile project(':common')
- compile('com.github.JesusMcCloud.netlayer:tor.native:0.6.5') {
+ compile("com.github.JesusMcCloud.netlayer:tor.native:$netlayerVersion") {
exclude(module: 'slf4j-api')
}
- compile('com.github.JesusMcCloud.netlayer:tor.external:0.6.5') {
+ compile("com.github.JesusMcCloud.netlayer:tor.external:$netlayerVersion") {
exclude(module: 'slf4j-api')
}
- compile('org.apache.httpcomponents:httpclient:4.5.3') {
+ compile("org.apache.httpcomponents:httpclient:$httpclientVersion") {
exclude(module: 'commons-logging')
}
compile "net.sf.jopt-simple:jopt-simple:$joptVersion"
- compile 'org.fxmisc.easybind:easybind:1.0.3'
+ compile "org.fxmisc.easybind:easybind:$easybindVersion"
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
- testCompile 'org.jmockit:jmockit:1.30' // must not use current $jmockitVersion
testCompileOnly "org.projectlombok:lombok:$lombokVersion"
testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
+ testCompile("org.mockito:mockito-core:$mockitoVersion")
}
}
@@ -220,7 +237,7 @@ configure(project(':core')) {
compile project(':assets')
compile project(':p2p')
compile "net.sf.jopt-simple:jopt-simple:$joptVersion"
- compile('network.bisq.btcd-cli4j:btcd-cli4j-core:065d3786') {
+ compile("network.bisq.btcd-cli4j:btcd-cli4j-core:$btcdCli4jVersion") {
exclude(module: 'slf4j-api')
exclude(module: 'httpclient')
exclude(module: 'commons-lang3')
@@ -228,7 +245,7 @@ configure(project(':core')) {
exclude(module: 'jackson-annotations')
exclude(module: 'jackson-databind')
}
- compile('network.bisq.btcd-cli4j:btcd-cli4j-daemon:065d3786') {
+ compile("network.bisq.btcd-cli4j:btcd-cli4j-daemon:$btcdCli4jVersion") {
exclude(module: 'slf4j-api')
exclude(module: 'httpclient')
exclude(module: 'commons-lang3')
@@ -236,33 +253,25 @@ configure(project(':core')) {
exclude(module: 'jackson-annotations')
exclude(module: 'jackson-databind')
}
- compile 'com.fasterxml.jackson.core:jackson-core:2.8.10'
- compile 'com.fasterxml.jackson.core:jackson-annotations:2.8.10'
- compile('com.fasterxml.jackson.core:jackson-databind:2.8.10') {
+ compile "com.fasterxml.jackson.core:jackson-core:$jacksonVersion"
+ compile "com.fasterxml.jackson.core:jackson-annotations:$jacksonVersion"
+ compile("com.fasterxml.jackson.core:jackson-databind:$jacksonVersion") {
exclude(module: 'jackson-annotations')
}
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
- testCompile "org.jmockit:jmockit:$jmockitVersion"
- testCompile("org.mockito:mockito-core:$mockitoVersion") {
- exclude(module: 'objenesis')
- }
- testCompile "org.powermock:powermock-module-junit4:$powermockVersion"
- testCompile "org.powermock:powermock-api-mockito2:$powermockVersion"
+ testCompile "org.mockito:mockito-core:$mockitoVersion"
testCompile "org.springframework:spring-test:$springVersion"
testCompile "com.natpryce:make-it-easy:$easyVersion"
- testCompile group: 'org.hamcrest', name: 'hamcrest-all', version: '1.3'
+ testCompile group: 'org.hamcrest', name: 'hamcrest-all', version: "$hamcrestVersion"
testCompileOnly "org.projectlombok:lombok:$lombokVersion"
testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
}
test {
systemProperty 'jdk.attach.allowAttachSelf', true
-
- def jmockit = configurations.testCompile.files.find { it.name.contains("jmockit") }.absolutePath
- jvmArgs "-javaagent:$jmockit"
}
}
@@ -272,7 +281,7 @@ configure(project(':desktop')) {
apply plugin: 'witness'
apply from: '../gradle/witness/gradle-witness.gradle'
- version = '1.1.5'
+ version = '1.1.6'
mainClassName = 'bisq.desktop.app.BisqAppMain'
@@ -284,31 +293,24 @@ configure(project(':desktop')) {
sourceSets.main.resources.srcDirs += ['src/main/java'] // to copy fxml and css files
dependencies {
- compile project(':p2p')
compile project(':core')
- compile project(':common')
- compile 'org.controlsfx:controlsfx:8.0.6_20'
- compile 'org.reactfx:reactfx:2.0-M3'
- compile 'net.glxn:qrgen:1.3'
- compile 'de.jensd:fontawesomefx:8.0.0'
- compile 'de.jensd:fontawesomefx-commons:9.1.2'
- compile 'de.jensd:fontawesomefx-materialdesignfont:2.0.26-9.1.2'
- compile 'com.googlecode.jcsv:jcsv:1.4.0'
- compile 'com.github.sarxos:webcam-capture:0.3.12'
+ compile "org.controlsfx:controlsfx:$controlsfxVersion"
+ compile "org.reactfx:reactfx:$reactfxVersion"
+ compile "net.glxn:qrgen:$qrgenVersion"
+ compile "de.jensd:fontawesomefx:$fontawesomefxVersion"
+ compile "de.jensd:fontawesomefx-commons:$fontawesomefxCommonsVersion"
+ compile "de.jensd:fontawesomefx-materialdesignfont:$fontawesomefxMaterialdesignfontVersion"
+ compile "com.googlecode.jcsv:jcsv:$jcsvVersion"
+ compile "com.github.sarxos:webcam-capture:$sarxosVersion"
compile "org.openjfx:javafx-controls:11:$os"
compile "org.openjfx:javafx-fxml:11:$os"
compile "org.openjfx:javafx-swing:11:$os"
- compile 'com.jfoenix:jfoenix:9.0.6'
+ compile "com.jfoenix:jfoenix:$jfoenixVersion"
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
- testCompile "org.jmockit:jmockit:$jmockitVersion"
- testCompile("org.mockito:mockito-core:$mockitoVersion") {
- exclude(module: 'objenesis')
- }
- testCompile "org.powermock:powermock-module-junit4:$powermockVersion"
- testCompile "org.powermock:powermock-api-mockito2:$powermockVersion"
+ testCompile "org.mockito:mockito-core:$mockitoVersion"
testCompile "org.springframework:spring-test:$springVersion"
testCompile "com.natpryce:make-it-easy:$easyVersion"
testCompileOnly "org.projectlombok:lombok:$lombokVersion"
@@ -317,9 +319,6 @@ configure(project(':desktop')) {
test {
systemProperty 'jdk.attach.allowAttachSelf', true
-
- def jmockit = configurations.testCompile.files.find { it.name.contains("jmockit") }.absolutePath
- jvmArgs "-javaagent:$jmockit"
}
}
@@ -339,16 +338,16 @@ configure(project(':monitor')) {
compile "org.slf4j:slf4j-api:$slf4jVersion"
compile "ch.qos.logback:logback-core:$logbackVersion"
compile "ch.qos.logback:logback-classic:$logbackVersion"
- compile 'com.google.guava:guava:20.0'
+ compile "com.google.guava:guava:$guavaVersion"
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
- testCompile 'org.junit.jupiter:junit-jupiter-api:5.3.2'
- testCompile 'org.junit.jupiter:junit-jupiter-params:5.3.2'
+ testCompile "org.junit.jupiter:junit-jupiter-api:$jupiterVersion"
+ testCompile "org.junit.jupiter:junit-jupiter-params:$jupiterVersion"
testCompileOnly "org.projectlombok:lombok:$lombokVersion"
testAnnotationProcessor "org.projectlombok:lombok:$lombokVersion"
- testRuntime('org.junit.jupiter:junit-jupiter-engine:5.3.2')
+ testRuntime("org.junit.jupiter:junit-jupiter-engine:$jupiterVersion")
}
}
@@ -364,10 +363,10 @@ configure(project(':pricenode')) {
dependencies {
compile project(":core")
- compile("org.knowm.xchange:xchange-bitcoinaverage:4.3.3")
- compile("org.knowm.xchange:xchange-coinmarketcap:4.3.3")
- compile("org.knowm.xchange:xchange-poloniex:4.3.3")
- compile("org.springframework.boot:spring-boot-starter-web:1.5.10.RELEASE")
+ compile("org.knowm.xchange:xchange-bitcoinaverage:$knowmXchangeVersion")
+ compile("org.knowm.xchange:xchange-coinmarketcap:$knowmXchangeVersion")
+ compile("org.knowm.xchange:xchange-poloniex:$knowmXchangeVersion")
+ compile("org.springframework.boot:spring-boot-starter-web:$springBootVersion")
compile("org.springframework.boot:spring-boot-starter-actuator")
}
@@ -383,8 +382,8 @@ configure(project(':relay')) {
dependencies {
compile project(':common')
compile "com.sparkjava:spark-core:$sparkVersion"
- compile 'com.turo:pushy:0.13.2'
- compile 'com.google.firebase:firebase-admin:6.2.0'
+ compile "com.turo:pushy:$pushyVersion"
+ compile "com.google.firebase:firebase-admin:$firebaseVersion"
compile "commons-codec:commons-codec:$codecVersion"
}
}
@@ -400,6 +399,7 @@ configure(project(':seednode')) {
runtime "org.bouncycastle:bcprov-jdk15on:$bcVersion"
compileOnly "org.projectlombok:lombok:$lombokVersion"
annotationProcessor "org.projectlombok:lombok:$lombokVersion"
+ testCompile "org.springframework:spring-test:$springVersion"
}
}
diff --git a/common/src/main/java/bisq/common/Clock.java b/common/src/main/java/bisq/common/ClockWatcher.java
similarity index 92%
rename from common/src/main/java/bisq/common/Clock.java
rename to common/src/main/java/bisq/common/ClockWatcher.java
index 3383b8eba51..1b673535fad 100644
--- a/common/src/main/java/bisq/common/Clock.java
+++ b/common/src/main/java/bisq/common/ClockWatcher.java
@@ -17,6 +17,8 @@
package bisq.common;
+import javax.inject.Singleton;
+
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.TimeUnit;
@@ -24,9 +26,10 @@
import lombok.extern.slf4j.Slf4j;
// Helps configure listener objects that are run by the `UserThread` each second
-// and can do per second, per minute and delayed second actions.
+// and can do per second, per minute and delayed second actions. Also detects when we were in standby, and logs it.
@Slf4j
-public class Clock {
+@Singleton
+public class ClockWatcher {
public static final int IDLE_TOLERANCE_MS = 20000;
public interface Listener {
@@ -46,7 +49,7 @@ default void onAwakeFromStandby(long missedMs) {
private long counter = 0;
private long lastSecondTick;
- public Clock() {
+ public ClockWatcher() {
}
public void start() {
@@ -66,7 +69,7 @@ public void start() {
long missedMs = diff - 1000;
listeners.forEach(listener -> listener.onMissedSecondTick(missedMs));
- if (missedMs > Clock.IDLE_TOLERANCE_MS) {
+ if (missedMs > ClockWatcher.IDLE_TOLERANCE_MS) {
log.info("We have been in standby mode for {} sec", missedMs / 1000);
listeners.forEach(listener -> listener.onAwakeFromStandby(missedMs));
}
diff --git a/common/src/main/java/bisq/common/app/Capabilities.java b/common/src/main/java/bisq/common/app/Capabilities.java
index 841b9d1c494..7af63477c0a 100644
--- a/common/src/main/java/bisq/common/app/Capabilities.java
+++ b/common/src/main/java/bisq/common/app/Capabilities.java
@@ -17,14 +17,19 @@
package bisq.common.app;
+import com.google.common.base.Joiner;
+
import java.util.Arrays;
import java.util.Collection;
+import java.util.Comparator;
import java.util.HashSet;
import java.util.List;
+import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;
import lombok.EqualsAndHashCode;
+import lombok.extern.slf4j.Slf4j;
/**
* hold a set of capabilities and offers appropriate comparison methods.
@@ -32,6 +37,7 @@
* @author Florian Reimair
*/
@EqualsAndHashCode
+@Slf4j
public class Capabilities {
/**
@@ -39,6 +45,10 @@ public class Capabilities {
*/
public static final Capabilities app = new Capabilities();
+ // Defines which most recent capability any node need to support.
+ // This helps to clean network from very old inactive but still running nodes.
+ private static final Capability MANDATORY_CAPABILITY = Capability.DAO_STATE;
+
protected final Set capabilities = new HashSet<>();
public Capabilities(Capability... capabilities) {
@@ -71,7 +81,7 @@ public void addAll(Capability... capabilities) {
}
public void addAll(Capabilities capabilities) {
- if(capabilities != null)
+ if (capabilities != null)
this.capabilities.addAll(capabilities.capabilities);
}
@@ -95,7 +105,7 @@ public boolean isEmpty() {
* @return int list of Capability ordinals
*/
public static List toIntList(Capabilities capabilities) {
- return capabilities.capabilities.stream().map(capability -> capability.ordinal()).sorted().collect(Collectors.toList());
+ return capabilities.capabilities.stream().map(Enum::ordinal).sorted().collect(Collectors.toList());
}
/**
@@ -107,15 +117,61 @@ public static List toIntList(Capabilities capabilities) {
public static Capabilities fromIntList(List capabilities) {
return new Capabilities(capabilities.stream()
.filter(integer -> integer < Capability.values().length)
+ .filter(integer -> integer >= 0)
.map(integer -> Capability.values()[integer])
.collect(Collectors.toSet()));
}
+ /**
+ *
+ * @param list Comma separated list of Capability ordinals.
+ * @return Capabilities
+ */
+ public static Capabilities fromStringList(String list) {
+ if (list == null || list.isEmpty())
+ return new Capabilities();
+
+ List entries = List.of(list.replace(" ", "").split(","));
+ List capabilitiesList = entries.stream()
+ .map(c -> {
+ try {
+ return Integer.parseInt(c);
+ } catch (Throwable e) {
+ return null;
+ }
+ })
+ .filter(Objects::nonNull)
+ .collect(Collectors.toList());
+ return Capabilities.fromIntList(capabilitiesList);
+ }
+
+ /**
+ * @return Converts capabilities to list of ordinals as comma separated strings
+ */
+ public String toStringList() {
+ return Joiner.on(", ").join(Capabilities.toIntList(this));
+ }
+
+ public static boolean hasMandatoryCapability(Capabilities capabilities) {
+ return hasMandatoryCapability(capabilities, MANDATORY_CAPABILITY);
+ }
+
+ public static boolean hasMandatoryCapability(Capabilities capabilities, Capability mandatoryCapability) {
+ return capabilities.capabilities.stream().anyMatch(c -> c == mandatoryCapability);
+ }
+
@Override
public String toString() {
return Arrays.toString(Capabilities.toIntList(this).toArray());
}
+ public String prettyPrint() {
+ return capabilities.stream()
+ .sorted(Comparator.comparingInt(Enum::ordinal))
+ .map(e -> e.name() + " [" + e.ordinal() + "]")
+ .collect(Collectors.joining(", "));
+ }
+
public int size() {
return capabilities.size();
}
diff --git a/common/src/main/java/bisq/common/app/Capability.java b/common/src/main/java/bisq/common/app/Capability.java
index 7bf426ba7c5..8d18736f7b9 100644
--- a/common/src/main/java/bisq/common/app/Capability.java
+++ b/common/src/main/java/bisq/common/app/Capability.java
@@ -20,18 +20,24 @@
// We can define here special features the client is supporting.
// Useful for updates to new versions where a new data type would break backwards compatibility or to
// limit a node to certain behaviour and roles like the seed nodes.
-// We don't use the Enum in any serialized data, as changes in the enum would break backwards compatibility. We use the ordinal integer instead.
+// We don't use the Enum in any serialized data, as changes in the enum would break backwards compatibility.
+// We use the ordinal integer instead.
// Sequence in the enum must not be changed (append only).
public enum Capability {
- TRADE_STATISTICS,
- TRADE_STATISTICS_2,
- ACCOUNT_AGE_WITNESS,
- SEED_NODE,
- DAO_FULL_NODE,
- PROPOSAL,
- BLIND_VOTE,
- ACK_MSG,
- RECEIVE_BSQ_BLOCK,
- DAO_STATE,
- BUNDLE_OF_ENVELOPES
+ @Deprecated TRADE_STATISTICS, // Not required anymore as no old clients out there not having that support
+ @Deprecated TRADE_STATISTICS_2, // Not required anymore as no old clients out there not having that support
+ @Deprecated ACCOUNT_AGE_WITNESS, // Not required anymore as no old clients out there not having that support
+ SEED_NODE, // Node is a seed node
+ DAO_FULL_NODE, // DAO full node can deliver BSQ blocks
+ @Deprecated PROPOSAL, // Not required anymore as no old clients out there not having that support
+ @Deprecated BLIND_VOTE, // Not required anymore as no old clients out there not having that support
+ @Deprecated ACK_MSG, // Not required anymore as no old clients out there not having that support
+ RECEIVE_BSQ_BLOCK, // Signaling that node which wants to receive BSQ blocks (DAO lite node)
+ @Deprecated DAO_STATE, // Not required anymore as no old clients out there not having that support
+
+ //TODO can be set deprecated after v1.1.6 as we enforce update there
+ BUNDLE_OF_ENVELOPES, // Supports bundling of messages if many messages are sent in short interval
+
+ SIGNED_ACCOUNT_AGE_WITNESS, // Supports the signed account age witness feature
+ MEDIATION // Supports mediation feature
}
diff --git a/common/src/main/java/bisq/common/app/DevEnv.java b/common/src/main/java/bisq/common/app/DevEnv.java
index 14429b7a3bb..5cf6132cf9f 100644
--- a/common/src/main/java/bisq/common/app/DevEnv.java
+++ b/common/src/main/java/bisq/common/app/DevEnv.java
@@ -41,7 +41,6 @@ public static void setup(Injector injector) {
// If set to true we ignore several UI behavior like confirmation popups as well dummy accounts are created and
// offers are filled with default values. Intended to make dev testing faster.
- @SuppressWarnings("PointlessBooleanExpression")
private static boolean devMode = false;
public static boolean isDevMode() {
diff --git a/common/src/main/java/bisq/common/app/Version.java b/common/src/main/java/bisq/common/app/Version.java
index 23d77913930..fdd518b4eea 100644
--- a/common/src/main/java/bisq/common/app/Version.java
+++ b/common/src/main/java/bisq/common/app/Version.java
@@ -27,7 +27,7 @@ public class Version {
// VERSION = 0.5.0 introduces proto buffer for the P2P network and local DB and is a not backward compatible update
// Therefore all sub versions start again with 1
// We use semantic versioning with major, minor and patch
- public static final String VERSION = "1.1.5";
+ public static final String VERSION = "1.1.6";
public static int getMajorVersion(String version) {
return getSubVersion(version, 0);
diff --git a/common/src/main/java/bisq/common/crypto/KeyRing.java b/common/src/main/java/bisq/common/crypto/KeyRing.java
index 4dab6ad3ac6..df457dcb8d5 100644
--- a/common/src/main/java/bisq/common/crypto/KeyRing.java
+++ b/common/src/main/java/bisq/common/crypto/KeyRing.java
@@ -18,6 +18,7 @@
package bisq.common.crypto;
import javax.inject.Inject;
+import javax.inject.Singleton;
import org.bouncycastle.openpgp.PGPKeyPair;
import org.bouncycastle.openpgp.PGPPublicKey;
@@ -34,7 +35,8 @@
@Getter
@EqualsAndHashCode
@Slf4j
-public class KeyRing {
+@Singleton
+public final class KeyRing {
private final KeyPair signatureKeyPair;
private final KeyPair encryptionKeyPair;
private final PubKeyRing pubKeyRing;
diff --git a/common/src/main/java/bisq/common/crypto/KeyStorage.java b/common/src/main/java/bisq/common/crypto/KeyStorage.java
index 1b1f00525da..82274c34d20 100644
--- a/common/src/main/java/bisq/common/crypto/KeyStorage.java
+++ b/common/src/main/java/bisq/common/crypto/KeyStorage.java
@@ -22,6 +22,7 @@
import com.google.inject.Inject;
import javax.inject.Named;
+import javax.inject.Singleton;
import org.bouncycastle.openpgp.PGPKeyPair;
@@ -56,6 +57,7 @@
import javax.annotation.Nullable;
// TODO: use a password protection for key storage
+@Singleton
public class KeyStorage {
private static final Logger log = LoggerFactory.getLogger(KeyStorage.class);
@@ -97,6 +99,7 @@ public String toString() {
@Inject
public KeyStorage(@Named(KEY_STORAGE_DIR) File storageDir) {
+ storageDir.mkdirs();
this.storageDir = storageDir;
}
diff --git a/common/src/main/java/bisq/common/crypto/PubKeyRing.java b/common/src/main/java/bisq/common/crypto/PubKeyRing.java
index b2eb108ded6..526d9f10971 100644
--- a/common/src/main/java/bisq/common/crypto/PubKeyRing.java
+++ b/common/src/main/java/bisq/common/crypto/PubKeyRing.java
@@ -21,8 +21,6 @@
import bisq.common.proto.network.NetworkPayload;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import com.google.common.annotations.VisibleForTesting;
@@ -83,15 +81,15 @@ public PubKeyRing(byte[] signaturePubKeyBytes, byte[] encryptionPubKeyBytes, @Nu
}
@Override
- public PB.PubKeyRing toProtoMessage() {
- return PB.PubKeyRing.newBuilder()
+ public protobuf.PubKeyRing toProtoMessage() {
+ return protobuf.PubKeyRing.newBuilder()
.setSignaturePubKeyBytes(ByteString.copyFrom(signaturePubKeyBytes))
.setEncryptionPubKeyBytes(ByteString.copyFrom(encryptionPubKeyBytes))
.setPgpPubKeyAsPem(pgpPubKeyAsPem)
.build();
}
- public static PubKeyRing fromProto(PB.PubKeyRing proto) {
+ public static PubKeyRing fromProto(protobuf.PubKeyRing proto) {
return new PubKeyRing(proto.getSignaturePubKeyBytes().toByteArray(),
proto.getEncryptionPubKeyBytes().toByteArray(),
proto.getPgpPubKeyAsPem());
diff --git a/common/src/main/java/bisq/common/crypto/PubKeyRingProvider.java b/common/src/main/java/bisq/common/crypto/PubKeyRingProvider.java
new file mode 100644
index 00000000000..2432005d7ed
--- /dev/null
+++ b/common/src/main/java/bisq/common/crypto/PubKeyRingProvider.java
@@ -0,0 +1,19 @@
+package bisq.common.crypto;
+
+import com.google.inject.Inject;
+import com.google.inject.Provider;
+
+public class PubKeyRingProvider implements Provider {
+
+ private PubKeyRing pubKeyRing;
+
+ @Inject
+ public PubKeyRingProvider(KeyRing keyRing) {
+ pubKeyRing = keyRing.getPubKeyRing();
+ }
+
+ @Override
+ public PubKeyRing get() {
+ return pubKeyRing;
+ }
+}
diff --git a/common/src/main/java/bisq/common/crypto/SealedAndSigned.java b/common/src/main/java/bisq/common/crypto/SealedAndSigned.java
index 68bc93781cc..c248064f4a3 100644
--- a/common/src/main/java/bisq/common/crypto/SealedAndSigned.java
+++ b/common/src/main/java/bisq/common/crypto/SealedAndSigned.java
@@ -19,8 +19,6 @@
import bisq.common.proto.network.NetworkPayload;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import java.security.PublicKey;
@@ -64,8 +62,8 @@ private SealedAndSigned(byte[] encryptedSecretKey,
sigPublicKey = Sig.getPublicKeyFromBytes(sigPublicKeyBytes);
}
- public PB.SealedAndSigned toProtoMessage() {
- return PB.SealedAndSigned.newBuilder()
+ public protobuf.SealedAndSigned toProtoMessage() {
+ return protobuf.SealedAndSigned.newBuilder()
.setEncryptedSecretKey(ByteString.copyFrom(encryptedSecretKey))
.setEncryptedPayloadWithHmac(ByteString.copyFrom(encryptedPayloadWithHmac))
.setSignature(ByteString.copyFrom(signature))
@@ -73,7 +71,7 @@ public PB.SealedAndSigned toProtoMessage() {
.build();
}
- public static SealedAndSigned fromProto(PB.SealedAndSigned proto) {
+ public static SealedAndSigned fromProto(protobuf.SealedAndSigned proto) {
return new SealedAndSigned(proto.getEncryptedSecretKey().toByteArray(),
proto.getEncryptedPayloadWithHmac().toByteArray(),
proto.getSignature().toByteArray(),
diff --git a/common/src/main/java/bisq/common/crypto/Sig.java b/common/src/main/java/bisq/common/crypto/Sig.java
index 85e14838967..659ed3d6b86 100644
--- a/common/src/main/java/bisq/common/crypto/Sig.java
+++ b/common/src/main/java/bisq/common/crypto/Sig.java
@@ -111,7 +111,7 @@ public static boolean verify(PublicKey publicKey, byte[] data, byte[] signature)
sig.update(data);
return sig.verify(signature);
} catch (SignatureException | InvalidKeyException | NoSuchAlgorithmException e) {
- throw new CryptoException("Signature verification failed. " + e.getMessage());
+ throw new CryptoException("Signature verification failed", e);
}
}
diff --git a/common/src/main/java/bisq/common/proto/ProtoResolver.java b/common/src/main/java/bisq/common/proto/ProtoResolver.java
index 34f7b1faaf0..61244239a11 100644
--- a/common/src/main/java/bisq/common/proto/ProtoResolver.java
+++ b/common/src/main/java/bisq/common/proto/ProtoResolver.java
@@ -20,10 +20,9 @@
import bisq.common.Payload;
import bisq.common.proto.persistable.PersistableEnvelope;
-import io.bisq.generated.protobuffer.PB;
public interface ProtoResolver {
- Payload fromProto(PB.PaymentAccountPayload proto);
+ Payload fromProto(protobuf.PaymentAccountPayload proto);
- PersistableEnvelope fromProto(PB.PersistableNetworkPayload proto);
+ PersistableEnvelope fromProto(protobuf.PersistableNetworkPayload proto);
}
diff --git a/common/src/main/java/bisq/common/proto/network/NetworkEnvelope.java b/common/src/main/java/bisq/common/proto/network/NetworkEnvelope.java
index b09996f1a8d..535d65d0486 100644
--- a/common/src/main/java/bisq/common/proto/network/NetworkEnvelope.java
+++ b/common/src/main/java/bisq/common/proto/network/NetworkEnvelope.java
@@ -19,8 +19,6 @@
import bisq.common.Envelope;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import lombok.EqualsAndHashCode;
@@ -41,8 +39,8 @@ protected NetworkEnvelope(int messageVersion) {
this.messageVersion = messageVersion;
}
- public PB.NetworkEnvelope.Builder getNetworkEnvelopeBuilder() {
- return PB.NetworkEnvelope.newBuilder().setMessageVersion(messageVersion);
+ public protobuf.NetworkEnvelope.Builder getNetworkEnvelopeBuilder() {
+ return protobuf.NetworkEnvelope.newBuilder().setMessageVersion(messageVersion);
}
@Override
@@ -51,7 +49,7 @@ public Message toProtoMessage() {
}
// todo remove
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder().build();
}
diff --git a/common/src/main/java/bisq/common/proto/network/NetworkProtoResolver.java b/common/src/main/java/bisq/common/proto/network/NetworkProtoResolver.java
index 74836c380be..fcbe82760a2 100644
--- a/common/src/main/java/bisq/common/proto/network/NetworkProtoResolver.java
+++ b/common/src/main/java/bisq/common/proto/network/NetworkProtoResolver.java
@@ -20,12 +20,11 @@
import bisq.common.proto.ProtoResolver;
import bisq.common.proto.ProtobufferException;
-import io.bisq.generated.protobuffer.PB;
public interface NetworkProtoResolver extends ProtoResolver {
- NetworkEnvelope fromProto(PB.NetworkEnvelope proto) throws ProtobufferException;
+ NetworkEnvelope fromProto(protobuf.NetworkEnvelope proto) throws ProtobufferException;
- NetworkPayload fromProto(PB.StoragePayload proto);
+ NetworkPayload fromProto(protobuf.StoragePayload proto);
- NetworkPayload fromProto(PB.StorageEntryWrapper proto);
+ NetworkPayload fromProto(protobuf.StorageEntryWrapper proto);
}
diff --git a/common/src/main/java/bisq/common/proto/persistable/NavigationPath.java b/common/src/main/java/bisq/common/proto/persistable/NavigationPath.java
index d7a1552fdb1..4be75cdcee4 100644
--- a/common/src/main/java/bisq/common/proto/persistable/NavigationPath.java
+++ b/common/src/main/java/bisq/common/proto/persistable/NavigationPath.java
@@ -17,7 +17,6 @@
package bisq.common.proto.persistable;
-import io.bisq.generated.protobuffer.PB;
import com.google.protobuf.Message;
@@ -42,12 +41,12 @@ public class NavigationPath implements PersistableEnvelope {
@Override
public Message toProtoMessage() {
- final PB.NavigationPath.Builder builder = PB.NavigationPath.newBuilder();
+ final protobuf.NavigationPath.Builder builder = protobuf.NavigationPath.newBuilder();
if (!CollectionUtils.isEmpty(path)) builder.addAllPath(path);
- return PB.PersistableEnvelope.newBuilder().setNavigationPath(builder).build();
+ return protobuf.PersistableEnvelope.newBuilder().setNavigationPath(builder).build();
}
- public static PersistableEnvelope fromProto(PB.NavigationPath proto) {
+ public static PersistableEnvelope fromProto(protobuf.NavigationPath proto) {
return new NavigationPath(new ArrayList<>(proto.getPathList()));
}
}
diff --git a/common/src/main/java/bisq/common/proto/persistable/PersistenceProtoResolver.java b/common/src/main/java/bisq/common/proto/persistable/PersistenceProtoResolver.java
index 218a17e34cb..1a7e8a0e9e7 100644
--- a/common/src/main/java/bisq/common/proto/persistable/PersistenceProtoResolver.java
+++ b/common/src/main/java/bisq/common/proto/persistable/PersistenceProtoResolver.java
@@ -19,8 +19,7 @@
import bisq.common.proto.ProtoResolver;
-import io.bisq.generated.protobuffer.PB;
public interface PersistenceProtoResolver extends ProtoResolver {
- PersistableEnvelope fromProto(PB.PersistableEnvelope persistable);
+ PersistableEnvelope fromProto(protobuf.PersistableEnvelope persistable);
}
diff --git a/common/src/main/java/bisq/common/storage/CorruptedDatabaseFilesHandler.java b/common/src/main/java/bisq/common/storage/CorruptedDatabaseFilesHandler.java
index f33d8ac4bca..ac967604519 100644
--- a/common/src/main/java/bisq/common/storage/CorruptedDatabaseFilesHandler.java
+++ b/common/src/main/java/bisq/common/storage/CorruptedDatabaseFilesHandler.java
@@ -18,6 +18,7 @@
package bisq.common.storage;
import javax.inject.Inject;
+import javax.inject.Singleton;
import java.util.ArrayList;
import java.util.List;
@@ -26,6 +27,7 @@
import lombok.extern.slf4j.Slf4j;
@Slf4j
+@Singleton
public class CorruptedDatabaseFilesHandler {
private List corruptedDatabaseFiles = new ArrayList<>();
diff --git a/common/src/main/java/bisq/common/storage/FileManager.java b/common/src/main/java/bisq/common/storage/FileManager.java
index a0f907cc9cf..c66d08803d7 100644
--- a/common/src/main/java/bisq/common/storage/FileManager.java
+++ b/common/src/main/java/bisq/common/storage/FileManager.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistenceProtoResolver;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.common.util.concurrent.CycleDetectingLockFactory;
import java.nio.file.Paths;
@@ -74,6 +72,10 @@ public FileManager(File dir, File storageFile, long delay, PersistenceProtoResol
try {
Thread.currentThread().setName("Save-file-task-" + new Random().nextInt(10000));
// Runs in an auto save thread.
+ // TODO: this looks like it could cause corrupt data as the savePending is unset before the actual
+ // save. By moving to after the save there might be some persist operations that are not performed
+ // and data would be lost. Probably all persist operations should happen sequencially rather than
+ // skip one when there is already one scheduled
if (!savePending.getAndSet(false)) {
// Some other scheduled request already beat us to it.
return null;
@@ -122,7 +124,7 @@ public synchronized T read(File file) {
log.debug("Read from disc: {}", file.getName());
try (final FileInputStream fileInputStream = new FileInputStream(file)) {
- PB.PersistableEnvelope persistable = PB.PersistableEnvelope.parseDelimitedFrom(fileInputStream);
+ protobuf.PersistableEnvelope persistable = protobuf.PersistableEnvelope.parseDelimitedFrom(fileInputStream);
return (T) persistenceProtoResolver.fromProto(persistable);
} catch (Throwable t) {
String errorMsg = "Exception at proto read: " + t.getMessage() + " file:" + file.getAbsolutePath();
@@ -188,7 +190,7 @@ public synchronized void backupFile(String fileName, int numMaxBackupFiles) {
private void saveNowInternal(T persistable) {
long now = System.currentTimeMillis();
saveToFile(persistable, dir, storageFile);
- log.trace("Save {} completed in {} msec", storageFile, System.currentTimeMillis() - now);
+ log.debug("Save {} completed in {} msec", storageFile, System.currentTimeMillis() - now);
}
private synchronized void saveToFile(T persistable, File dir, File storageFile) {
@@ -198,9 +200,9 @@ private synchronized void saveToFile(T persistable, File dir, File storageFile)
try {
log.debug("Write to disc: {}", storageFile.getName());
- PB.PersistableEnvelope protoPersistable;
+ protobuf.PersistableEnvelope protoPersistable;
try {
- protoPersistable = (PB.PersistableEnvelope) persistable.toProtoMessage();
+ protoPersistable = (protobuf.PersistableEnvelope) persistable.toProtoMessage();
if (protoPersistable.toByteArray().length == 0)
log.error("protoPersistable is empty. persistable=" + persistable.getClass().getSimpleName());
} catch (Throwable e) {
diff --git a/common/src/main/java/bisq/common/storage/Storage.java b/common/src/main/java/bisq/common/storage/Storage.java
index 21e5a89fb76..4d0de66e91f 100644
--- a/common/src/main/java/bisq/common/storage/Storage.java
+++ b/common/src/main/java/bisq/common/storage/Storage.java
@@ -52,11 +52,7 @@ public class Storage {
private static final Logger log = LoggerFactory.getLogger(Storage.class);
public static final String STORAGE_DIR = "storageDir";
- private static CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler;
-
- public static void setCorruptedDatabaseFilesHandler(CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) {
- Storage.corruptedDatabaseFilesHandler = corruptedDatabaseFilesHandler;
- }
+ private final CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler;
private final File dir;
private FileManager fileManager;
@@ -72,9 +68,12 @@ public static void setCorruptedDatabaseFilesHandler(CorruptedDatabaseFilesHandle
///////////////////////////////////////////////////////////////////////////////////////////
@Inject
- public Storage(@Named(STORAGE_DIR) File dir, PersistenceProtoResolver persistenceProtoResolver) {
+ public Storage(@Named(STORAGE_DIR) File dir,
+ PersistenceProtoResolver persistenceProtoResolver,
+ CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) {
this.dir = dir;
this.persistenceProtoResolver = persistenceProtoResolver;
+ this.corruptedDatabaseFilesHandler = corruptedDatabaseFilesHandler;
}
@Nullable
diff --git a/common/src/main/java/bisq/common/taskrunner/Task.java b/common/src/main/java/bisq/common/taskrunner/Task.java
index f21e7e58e2b..e6fce415507 100644
--- a/common/src/main/java/bisq/common/taskrunner/Task.java
+++ b/common/src/main/java/bisq/common/taskrunner/Task.java
@@ -35,7 +35,7 @@ public Task(TaskRunner taskHandler, T model) {
this.model = model;
}
- abstract protected void run();
+ protected abstract void run();
protected void runInterceptHook() {
if (getClass() == taskToIntercept)
@@ -64,9 +64,8 @@ protected void failed(String message) {
}
protected void failed(Throwable t) {
- t.printStackTrace();
- appendExceptionToErrorMessage(t);
- failed();
+ log.error(errorMessage, t);
+ taskHandler.handleErrorMessage(errorMessage);
}
protected void failed() {
diff --git a/common/src/main/java/bisq/common/util/MathUtils.java b/common/src/main/java/bisq/common/util/MathUtils.java
index 56685137629..cb3a32a9c71 100644
--- a/common/src/main/java/bisq/common/util/MathUtils.java
+++ b/common/src/main/java/bisq/common/util/MathUtils.java
@@ -92,4 +92,19 @@ public static double scaleDownByPowerOf10(long value, int exponent) {
public static double exactMultiply(double value1, double value2) {
return BigDecimal.valueOf(value1).multiply(BigDecimal.valueOf(value2)).doubleValue();
}
+
+ public static long getMedian(Long[] list) {
+ if (list.length == 0) {
+ return 0L;
+ }
+
+ int middle = list.length / 2;
+ long median;
+ if (list.length % 2 == 1) {
+ median = list[middle];
+ } else {
+ median = MathUtils.roundDoubleToLong((list[middle - 1] + list[middle]) / 2.0);
+ }
+ return median;
+ }
}
diff --git a/common/src/main/proto/pb.proto b/common/src/main/proto/pb.proto
index b1e3d291d68..e287f18040d 100644
--- a/common/src/main/proto/pb.proto
+++ b/common/src/main/proto/pb.proto
@@ -5,9 +5,9 @@ package io.bisq.protobuffer;
// Protobuffer v3 definitions of network messages and persisted objects.
//
-option java_package = "io.bisq.generated.protobuffer";
-option java_outer_classname = "PB";
+option java_package = "protobuf";
+option java_multiple_files = true;
///////////////////////////////////////////////////////////////////////////////////////////
// Network messages
///////////////////////////////////////////////////////////////////////////////////////////
@@ -44,7 +44,7 @@ message NetworkEnvelope {
OpenNewDisputeMessage open_new_dispute_message = 22;
PeerOpenedDisputeMessage peer_opened_dispute_message = 23;
- DisputeCommunicationMessage dispute_communication_message = 24;
+ ChatMessage chat_message = 24;
DisputeResultMessage dispute_result_message = 25;
PeerPublishedDisputePayoutTxMessage peer_published_dispute_payout_tx_message = 26;
@@ -68,6 +68,8 @@ message NetworkEnvelope {
GetBlindVoteStateHashesResponse get_blind_vote_state_hashes_response = 42;
BundleOfEnvelopes bundle_of_envelopes = 43;
+ MediatedPayoutTxSignatureMessage mediated_payout_tx_signature_message = 44;
+ MediatedPayoutTxPublishedMessage mediated_payout_tx_published_message = 45;
}
}
@@ -141,6 +143,7 @@ message OfferAvailabilityResponse {
repeated int32 supported_capabilities = 3;
string uid = 4;
NodeAddress arbitrator = 5;
+ NodeAddress mediator = 6;
}
message RefreshOfferMessage {
@@ -267,21 +270,43 @@ message PayoutTxPublishedMessage {
string uid = 4;
}
+message MediatedPayoutTxPublishedMessage {
+ string trade_id = 1;
+ bytes payout_tx = 2;
+ NodeAddress sender_node_address = 3;
+ string uid = 4;
+}
+
+message MediatedPayoutTxSignatureMessage {
+ string uid = 1;
+ bytes tx_signature = 2;
+ string trade_id = 3;
+ NodeAddress sender_node_address = 4;
+}
+
// dispute
+enum SupportType {
+ ARBITRATION = 0;
+ MEDIATION = 1;
+ TRADE = 2;
+}
+
message OpenNewDisputeMessage {
Dispute dispute = 1;
NodeAddress sender_node_address = 2;
string uid = 3;
+ SupportType type = 4;
}
message PeerOpenedDisputeMessage {
Dispute dispute = 1;
NodeAddress sender_node_address = 2;
string uid = 3;
+ SupportType type = 4;
}
-message DisputeCommunicationMessage {
+message ChatMessage {
int64 date = 1;
string trade_id = 2;
int32 trader_id = 3;
@@ -296,12 +321,15 @@ message DisputeCommunicationMessage {
string send_message_error = 12;
bool acknowledged = 13;
string ack_error = 14;
+ SupportType type = 15;
+ bool was_displayed = 16;
}
message DisputeResultMessage {
string uid = 1;
DisputeResult dispute_result = 2;
NodeAddress sender_node_address = 3;
+ SupportType type = 4;
}
message PeerPublishedDisputePayoutTxMessage {
@@ -309,9 +337,9 @@ message PeerPublishedDisputePayoutTxMessage {
bytes transaction = 2;
string trade_id = 3;
NodeAddress sender_node_address = 4;
+ SupportType type = 5;
}
-
message PrivateNotificationMessage {
string uid = 1;
NodeAddress sender_node_address = 2;
@@ -424,7 +452,7 @@ message StoragePayload {
// not used anymore from v0.6 on. But leave it for receiving TradeStatistics objects from older
// versions and convert it to TradeStatistics2 objects.
- TradeStatistics trade_statistics = 5;
+ TradeStatistics trade_statistics = 5 [deprecated = true];
MailboxStoragePayload mailbox_storage_payload = 6;
OfferPayload offer_payload = 7;
@@ -438,6 +466,7 @@ message PersistableNetworkPayload {
TradeStatistics2 trade_statistics2 = 2;
ProposalPayload proposal_payload = 3;
BlindVotePayload blind_vote_payload = 4;
+ SignedWitness signed_witness = 5;
}
}
@@ -538,6 +567,7 @@ message Filter {
bool disable_dao = 14;
string disable_dao_below_version = 15;
string disable_trade_below_version = 16;
+ repeated string mediators = 17;
}
// not used anymore from v0.6 on. But leave it for receiving TradeStatistics objects from older
@@ -606,8 +636,8 @@ message OfferPayload {
int64 min_amount = 10;
string base_currency_code = 11;
string counter_currency_code = 12;
- repeated NodeAddress arbitrator_node_addresses = 13;
- repeated NodeAddress mediator_node_addresses = 14;
+ repeated NodeAddress arbitrator_node_addresses = 13 [deprecated = true]; // not used anymore but still required as old clients check for nonNull
+ repeated NodeAddress mediator_node_addresses = 14 [deprecated = true]; // not used anymore but still required as old clients check for nonNull
string payment_method_id = 15;
string maker_payment_account_id = 16;
string offer_fee_payment_tx_id = 17;
@@ -639,6 +669,16 @@ message AccountAgeWitness {
int64 date = 2;
}
+message SignedWitness {
+ bool signed_by_arbitrator = 1;
+ bytes witness_hash = 2;
+ bytes signature = 3;
+ bytes signer_pub_key = 4;
+ bytes witness_owner_pub_key = 5;
+ int64 date = 6;
+ int64 trade_amount = 7;
+}
+
///////////////////////////////////////////////////////////////////////////////////////////
// Dispute payload
///////////////////////////////////////////////////////////////////////////////////////////
@@ -662,9 +702,9 @@ message Dispute {
string contract_as_json = 15;
string maker_contract_signature = 16;
string taker_contract_signature = 17;
- PubKeyRing arbitrator_pub_key_ring = 18;
+ PubKeyRing agent_pub_key_ring = 18;
bool is_support_ticket = 19;
- repeated DisputeCommunicationMessage dispute_communication_messages = 20;
+ repeated ChatMessage chat_message = 20;
bool is_closed = 21;
DisputeResult dispute_result = 22;
string dispute_payout_tx_id = 23;
@@ -701,7 +741,7 @@ message DisputeResult {
bool id_verification = 6;
bool screen_cast = 7;
string summary_notes = 8;
- DisputeCommunicationMessage dispute_communication_message = 9;
+ ChatMessage chat_message = 9;
bytes arbitrator_signature = 10;
int64 buyer_payout_amount = 11;
int64 seller_payout_amount = 12;
@@ -752,6 +792,7 @@ enum AvailabilityResult {
NO_ARBITRATORS = 6;
NO_MEDIATORS = 7;
USER_IGNORED = 8;
+ MISSING_MANDATORY_CAPABILITY = 9;
}
///////////////////////////////////////////////////////////////////////////////////////////
@@ -762,7 +803,7 @@ enum AvailabilityResult {
message PaymentAccountPayload {
string id = 1;
string payment_method_id = 2;
- int64 max_trade_period = 3; // not used anymore but we need to keep it in PB for backward compatibility
+ int64 max_trade_period = 3 [deprecated = true]; // not used anymore but we need to keep it in PB for backward compatibility
oneof message {
AliPayAccountPayload ali_pay_account_payload = 4;
ChaseQuickPayAccountPayload chase_quick_pay_account_payload = 5;
@@ -771,14 +812,14 @@ message PaymentAccountPayload {
CryptoCurrencyAccountPayload crypto_currency_account_payload = 8;
FasterPaymentsAccountPayload faster_payments_account_payload = 9;
InteracETransferAccountPayload interac_e_transfer_account_payload = 10;
- OKPayAccountPayload o_k_pay_account_payload = 11; // Deprecated, not used anymore
+ OKPayAccountPayload o_k_pay_account_payload = 11 [deprecated = true];
PerfectMoneyAccountPayload perfect_money_account_payload = 12;
SwishAccountPayload swish_account_payload = 13;
USPostalMoneyOrderAccountPayload u_s_postal_money_order_account_payload = 14;
UpholdAccountPayload uphold_account_payload = 16;
- CashAppAccountPayload cash_app_account_payload = 17; // Deprecated, not used anymore
+ CashAppAccountPayload cash_app_account_payload = 17 [deprecated = true];
MoneyBeamAccountPayload money_beam_account_payload = 18;
- VenmoAccountPayload venmo_account_payload = 19; // Deprecated, not used anymore
+ VenmoAccountPayload venmo_account_payload = 19 [deprecated = true];
PopmoneyAccountPayload popmoney_account_payload = 20;
RevolutAccountPayload revolut_account_payload = 21;
WeChatPayAccountPayload we_chat_pay_account_payload = 22;
@@ -787,6 +828,7 @@ message PaymentAccountPayload {
PromptPayAccountPayload prompt_pay_account_payload = 25;
AdvancedCashAccountPayload advanced_cash_account_payload = 26;
InstantCryptoCurrencyAccountPayload instant_crypto_currency_account_payload = 27;
+ JapanBankAccountPayload japan_bank_account_payload = 28;
}
map exclude_from_json_data = 15;
}
@@ -829,7 +871,7 @@ message BankAccountPayload {
string account_nr = 5;
string account_type = 6;
string holder_tax_id = 7;
- string email = 8; // not used anymore but keep for backward compatibility
+ string email = 8 [deprecated = true];
oneof message {
NationalBankAccountPayload national_bank_account_payload = 9;
SameBankAccountPayload same_bank_accont_payload = 10;
@@ -844,6 +886,16 @@ message NationalBankAccountPayload {
message SameBankAccountPayload {
}
+message JapanBankAccountPayload {
+ string bank_name = 1;
+ string bank_code = 2;
+ string bank_branch_name = 3;
+ string bank_branch_code = 4;
+ string bank_account_type = 5;
+ string bank_account_name = 6;
+ string bank_account_number = 7;
+}
+
message SpecificBanksAccountPayload {
repeated string accepted_banks = 1;
}
@@ -883,7 +935,7 @@ message SepaAccountPayload {
string holder_name = 1;
string iban = 2;
string bic = 3;
- string email = 4; // not used anymore but keep for backward compatibility
+ string email = 4 [deprecated = true];
repeated string accepted_country_codes = 5;
}
@@ -905,7 +957,7 @@ message InstantCryptoCurrencyAccountPayload {
message FasterPaymentsAccountPayload {
string sort_code = 1;
string account_nr = 2;
- string email = 3; // not used anymore but keep for backward compatibility
+ string email = 3 [deprecated = true];
}
message InteracETransferAccountPayload {
@@ -984,14 +1036,14 @@ message AdvancedCashAccountPayload {
message PersistableEnvelope {
oneof message {
SequenceNumberMap sequence_number_map = 1;
- PersistedEntryMap persisted_entry_map = 2; // deprecated. Not used anymore.
+ PersistedEntryMap persisted_entry_map = 2 [deprecated = true];
PeerList peer_list = 3;
AddressEntryList address_entry_list = 4;
NavigationPath navigation_path = 5;
TradableList tradable_list = 6;
- TradeStatisticsList trade_statistics_list = 7; // deprecated Was used in pre v0.6.0 version. Not used anymore.
- DisputeList dispute_list = 8;
+ TradeStatisticsList trade_statistics_list = 7 [deprecated = true]; // Was used in pre v0.6.0 version. Not used anymore.
+ ArbitrationDisputeList arbitration_dispute_list = 8;
PreferencesPayload preferences_payload = 9;
UserPayload user_payload = 10;
@@ -1006,7 +1058,7 @@ message PersistableEnvelope {
// we need to keep id 15 here otherwise the reading of the old data structure would not work anymore.
// can be removed after most people have updated as the reading of the PersistableNetworkPayloadList
// is not mandatory.
- PersistableNetworkPayloadList persistable_network_payload_list = 15; // deprecated. Not used anymore.
+ PersistableNetworkPayloadList persistable_network_payload_list = 15 [deprecated = true];
ProposalStore proposal_store = 16;
TempProposalStore temp_proposal_store = 17;
@@ -1020,6 +1072,8 @@ message PersistableEnvelope {
MyReputationList my_reputation_list = 25;
MyProofOfBurnList my_proof_of_burn_list = 26;
UnconfirmedBsqChangeOutputList unconfirmed_bsq_change_output_list = 27;
+ SignedWitnessStore signed_witness_store = 28;
+ MediationDisputeList mediation_dispute_list = 29;
}
}
@@ -1060,6 +1114,10 @@ message AccountAgeWitnessStore {
repeated AccountAgeWitness items = 1;
}
+message SignedWitnessStore {
+ repeated SignedWitness items = 1;
+}
+
// We use a list not a hash map to save disc space. The hash can be calculated from the payload anyway
message TradeStatistics2Store {
repeated TradeStatistics2 items = 1;
@@ -1139,6 +1197,7 @@ message OpenOffer {
Offer offer = 1;
State state = 2;
NodeAddress arbitrator_node_address = 3;
+ NodeAddress mediator_node_address = 4;
}
message Tradable {
@@ -1201,9 +1260,12 @@ message Trade {
enum DisputeState {
PB_ERROR_DISPUTE_STATE = 0;
NO_DISPUTE = 1;
- DISPUTE_REQUESTED = 2;
- DISPUTE_STARTED_BY_PEER = 3;
- DISPUTE_CLOSED = 4;
+ DISPUTE_REQUESTED = 2; // arbitration We use the enum name for resolving enums so it cannot be renamed
+ DISPUTE_STARTED_BY_PEER = 3; // arbitration We use the enum name for resolving enums so it cannot be renamed
+ DISPUTE_CLOSED = 4; // arbitration We use the enum name for resolving enums so it cannot be renamed
+ MEDIATION_REQUESTED = 5;
+ MEDIATION_STARTED_BY_PEER = 6;
+ MEDIATION_CLOSED = 7;
}
enum TradePeriodState {
@@ -1241,6 +1303,8 @@ message Trade {
PubKeyRing arbitrator_pub_key_ring = 26;
PubKeyRing mediator_pub_key_ring = 27;
string counter_currency_tx_id = 28;
+ repeated ChatMessage chat_message = 29;
+ MediationResultState mediation_result_state = 30;
}
message BuyerAsMakerTrade {
@@ -1277,6 +1341,9 @@ message ProcessModel {
bytes my_multi_sig_pub_key = 15;
NodeAddress temp_trading_peer_node_address = 16;
string payment_started_message_state = 17;
+ bytes mediated_payout_tx_signature = 18;
+ int64 buyer_payout_amount_from_mediation = 19;
+ int64 seller_payout_amount_from_mediation = 20;
}
message TradingPeer {
@@ -1294,16 +1361,40 @@ message TradingPeer {
bytes account_age_witness_nonce = 12;
bytes account_age_witness_signature = 13;
int64 current_date = 14;
+ bytes mediated_payout_tx_signature = 15;
}
///////////////////////////////////////////////////////////////////////////////////////////
// Dispute
///////////////////////////////////////////////////////////////////////////////////////////
-message DisputeList {
+message ArbitrationDisputeList {
+ repeated Dispute dispute = 1;
+}
+
+message MediationDisputeList {
repeated Dispute dispute = 1;
}
+enum MediationResultState {
+ PB_ERROR_MEDIATION_RESULT = 0;
+ UNDEFINED_MEDIATION_RESULT = 1;
+ MEDIATION_RESULT_ACCEPTED = 2;
+ MEDIATION_RESULT_REJECTED = 3;
+ SIG_MSG_SENT = 4;
+ SIG_MSG_ARRIVED = 5;
+ SIG_MSG_IN_MAILBOX = 6;
+ SIG_MSG_SEND_FAILED = 7;
+ RECEIVED_SIG_MSG = 8;
+ PAYOUT_TX_PUBLISHED = 9;
+ PAYOUT_TX_PUBLISHED_MSG_SENT = 10;
+ PAYOUT_TX_PUBLISHED_MSG_ARRIVED = 11;
+ PAYOUT_TX_PUBLISHED_MSG_IN_MAILBOX = 12;
+ PAYOUT_TX_PUBLISHED_MSG_SEND_FAILED = 13;
+ RECEIVED_PAYOUT_TX_PUBLISHED_MSG = 14;
+ PAYOUT_TX_SEEN_IN_NETWORK = 15;
+}
+
///////////////////////////////////////////////////////////////////////////////////////////
// Preferences
///////////////////////////////////////////////////////////////////////////////////////////
@@ -1338,7 +1429,7 @@ message PreferencesPayload {
string bitcoin_nodes = 27;
repeated string ignore_traders_list = 28;
string directory_chooser_path = 29;
- int64 buyer_security_deposit_as_long = 30; // Deprectated: Superseded by buyerSecurityDepositAsPercent
+ int64 buyer_security_deposit_as_long = 30 [deprecated = true]; // Superseded by buyerSecurityDepositAsPercent
bool use_animations = 31;
PaymentAccount selectedPayment_account_for_createOffer = 32;
bool pay_fee_in_Btc = 33;
@@ -1362,6 +1453,7 @@ message PreferencesPayload {
int32 ignore_dust_threshold = 51;
double buyer_security_deposit_as_percent_for_crypto = 52;
int32 block_notify_port = 53;
+ int32 css_theme = 54;
}
///////////////////////////////////////////////////////////////////////////////////////////
diff --git a/common/src/test/java/bisq/common/app/CapabilitiesTest.java b/common/src/test/java/bisq/common/app/CapabilitiesTest.java
index d0166e130c6..735fc899eaf 100644
--- a/common/src/test/java/bisq/common/app/CapabilitiesTest.java
+++ b/common/src/test/java/bisq/common/app/CapabilitiesTest.java
@@ -17,11 +17,16 @@
package bisq.common.app;
+import java.util.Arrays;
+import java.util.Collections;
import java.util.HashSet;
import org.junit.Test;
-import static bisq.common.app.Capability.*;
+import static bisq.common.app.Capability.SEED_NODE;
+import static bisq.common.app.Capability.TRADE_STATISTICS;
+import static bisq.common.app.Capability.TRADE_STATISTICS_2;
+import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
@@ -60,4 +65,47 @@ public void testMultiMatch() {
assertTrue(DUT.containsAll(new Capabilities(TRADE_STATISTICS, TRADE_STATISTICS_2)));
assertFalse(DUT.containsAll(new Capabilities(SEED_NODE, TRADE_STATISTICS_2)));
}
+
+ @Test
+ public void testToIntList() {
+ assertEquals(Collections.emptyList(), Capabilities.toIntList(new Capabilities()));
+ assertEquals(Collections.singletonList(12), Capabilities.toIntList(new Capabilities(Capability.MEDIATION)));
+ assertEquals(Arrays.asList(6, 12), Capabilities.toIntList(new Capabilities(Capability.MEDIATION, Capability.BLIND_VOTE)));
+ }
+
+ @Test
+ public void testFromIntList() {
+ assertEquals(new Capabilities(), Capabilities.fromIntList(Collections.emptyList()));
+ assertEquals(new Capabilities(Capability.MEDIATION), Capabilities.fromIntList(Collections.singletonList(12)));
+ assertEquals(new Capabilities(Capability.BLIND_VOTE, Capability.MEDIATION), Capabilities.fromIntList(Arrays.asList(6, 12)));
+
+ assertEquals(new Capabilities(), Capabilities.fromIntList(Collections.singletonList(-1)));
+ assertEquals(new Capabilities(), Capabilities.fromIntList(Collections.singletonList(99)));
+ assertEquals(new Capabilities(Capability.MEDIATION), Capabilities.fromIntList(Arrays.asList(-6, 12)));
+ assertEquals(new Capabilities(Capability.MEDIATION), Capabilities.fromIntList(Arrays.asList(12, 99)));
+ }
+
+ @Test
+ public void testToStringList() {
+ assertEquals("", new Capabilities().toStringList());
+ assertEquals("12", new Capabilities(Capability.MEDIATION).toStringList());
+ assertEquals("6, 12", new Capabilities(Capability.BLIND_VOTE, Capability.MEDIATION).toStringList());
+ // capabilities gets sorted, independent of our order
+ assertEquals("6, 12", new Capabilities(Capability.MEDIATION, Capability.BLIND_VOTE).toStringList());
+ }
+
+ @Test
+ public void testFromStringList() {
+ assertEquals(new Capabilities(), Capabilities.fromStringList(null));
+ assertEquals(new Capabilities(), Capabilities.fromStringList(""));
+ assertEquals(new Capabilities(Capability.MEDIATION), Capabilities.fromStringList("12"));
+ assertEquals(new Capabilities(Capability.BLIND_VOTE, Capability.MEDIATION), Capabilities.fromStringList("6,12"));
+ assertEquals(new Capabilities(Capability.BLIND_VOTE, Capability.MEDIATION), Capabilities.fromStringList("12, 6"));
+ assertEquals(new Capabilities(), Capabilities.fromStringList("a"));
+ assertEquals(new Capabilities(), Capabilities.fromStringList("99"));
+ assertEquals(new Capabilities(), Capabilities.fromStringList("-1"));
+ assertEquals(new Capabilities(Capability.MEDIATION), Capabilities.fromStringList("12, a"));
+ assertEquals(new Capabilities(Capability.MEDIATION), Capabilities.fromStringList("12, 99"));
+ assertEquals(new Capabilities(Capability.MEDIATION), Capabilities.fromStringList("a,12, 99"));
+ }
}
diff --git a/core/src/main/java/bisq/core/CoreModule.java b/core/src/main/java/bisq/core/CoreModule.java
index e22d44406ab..3e5812bbe3f 100644
--- a/core/src/main/java/bisq/core/CoreModule.java
+++ b/core/src/main/java/bisq/core/CoreModule.java
@@ -19,53 +19,34 @@
import bisq.core.alert.AlertModule;
import bisq.core.app.AppOptionKeys;
-import bisq.core.app.AvoidStandbyModeService;
import bisq.core.app.BisqEnvironment;
-import bisq.core.app.BisqSetup;
-import bisq.core.app.P2PNetworkSetup;
-import bisq.core.app.TorSetup;
-import bisq.core.app.WalletAppSetup;
-import bisq.core.arbitration.ArbitratorModule;
import bisq.core.btc.BitcoinModule;
import bisq.core.dao.DaoModule;
import bisq.core.filter.FilterModule;
import bisq.core.network.p2p.seed.DefaultSeedNodeRepository;
-import bisq.core.notifications.MobileMessageEncryption;
-import bisq.core.notifications.MobileModel;
-import bisq.core.notifications.MobileNotificationService;
-import bisq.core.notifications.MobileNotificationValidator;
-import bisq.core.notifications.alerts.DisputeMsgEvents;
-import bisq.core.notifications.alerts.MyOfferTakenEvents;
-import bisq.core.notifications.alerts.TradeEvents;
-import bisq.core.notifications.alerts.market.MarketAlerts;
-import bisq.core.notifications.alerts.price.PriceAlert;
import bisq.core.offer.OfferModule;
-import bisq.core.payment.TradeLimits;
import bisq.core.presentation.CorePresentationModule;
import bisq.core.proto.network.CoreNetworkProtoResolver;
import bisq.core.proto.persistable.CorePersistenceProtoResolver;
import bisq.core.trade.TradeModule;
import bisq.core.user.Preferences;
-import bisq.core.user.User;
import bisq.network.crypto.EncryptionServiceModule;
import bisq.network.p2p.P2PModule;
import bisq.network.p2p.network.BridgeAddressProvider;
import bisq.network.p2p.seed.SeedNodeRepository;
-import bisq.common.Clock;
import bisq.common.CommonOptionKeys;
import bisq.common.app.AppModule;
-import bisq.common.crypto.KeyRing;
import bisq.common.crypto.KeyStorage;
+import bisq.common.crypto.PubKeyRing;
+import bisq.common.crypto.PubKeyRingProvider;
import bisq.common.proto.network.NetworkProtoResolver;
import bisq.common.proto.persistable.PersistenceProtoResolver;
-import bisq.common.storage.CorruptedDatabaseFilesHandler;
import bisq.common.storage.Storage;
import org.springframework.core.env.Environment;
-import com.google.inject.Singleton;
import com.google.inject.name.Names;
import java.io.File;
@@ -80,25 +61,11 @@ public CoreModule(Environment environment) {
@Override
protected void configure() {
- bind(BisqSetup.class).in(Singleton.class);
- bind(TorSetup.class).in(Singleton.class);
- bind(P2PNetworkSetup.class).in(Singleton.class);
- bind(WalletAppSetup.class).in(Singleton.class);
-
bind(BisqEnvironment.class).toInstance((BisqEnvironment) environment);
- bind(TradeLimits.class).in(Singleton.class);
-
- bind(KeyStorage.class).in(Singleton.class);
- bind(KeyRing.class).in(Singleton.class);
- bind(User.class).in(Singleton.class);
- bind(Clock.class).in(Singleton.class);
- bind(Preferences.class).in(Singleton.class);
- bind(BridgeAddressProvider.class).to(Preferences.class).in(Singleton.class);
- bind(CorruptedDatabaseFilesHandler.class).in(Singleton.class);
- bind(AvoidStandbyModeService.class).in(Singleton.class);
+ bind(BridgeAddressProvider.class).to(Preferences.class);
- bind(SeedNodeRepository.class).to(DefaultSeedNodeRepository.class).in(Singleton.class);
+ bind(SeedNodeRepository.class).to(DefaultSeedNodeRepository.class);
File storageDir = new File(environment.getRequiredProperty(Storage.STORAGE_DIR));
bind(File.class).annotatedWith(named(Storage.STORAGE_DIR)).toInstance(storageDir);
@@ -106,8 +73,8 @@ protected void configure() {
File keyStorageDir = new File(environment.getRequiredProperty(KeyStorage.KEY_STORAGE_DIR));
bind(File.class).annotatedWith(named(KeyStorage.KEY_STORAGE_DIR)).toInstance(keyStorageDir);
- bind(NetworkProtoResolver.class).to(CoreNetworkProtoResolver.class).in(Singleton.class);
- bind(PersistenceProtoResolver.class).to(CorePersistenceProtoResolver.class).in(Singleton.class);
+ bind(NetworkProtoResolver.class).to(CoreNetworkProtoResolver.class);
+ bind(PersistenceProtoResolver.class).to(CorePersistenceProtoResolver.class);
Boolean useDevPrivilegeKeys = environment.getProperty(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS, Boolean.class, false);
bind(boolean.class).annotatedWith(Names.named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS)).toInstance(useDevPrivilegeKeys);
@@ -118,20 +85,10 @@ protected void configure() {
String referralId = environment.getProperty(AppOptionKeys.REFERRAL_ID, String.class, "");
bind(String.class).annotatedWith(Names.named(AppOptionKeys.REFERRAL_ID)).toInstance(referralId);
- bind(MobileNotificationService.class).in(Singleton.class);
- bind(MobileMessageEncryption.class).in(Singleton.class);
- bind(MobileNotificationValidator.class).in(Singleton.class);
- bind(MobileModel.class).in(Singleton.class);
- bind(MyOfferTakenEvents.class).in(Singleton.class);
- bind(TradeEvents.class).in(Singleton.class);
- bind(DisputeMsgEvents.class).in(Singleton.class);
- bind(PriceAlert.class).in(Singleton.class);
- bind(MarketAlerts.class).in(Singleton.class);
// ordering is used for shut down sequence
install(tradeModule());
install(encryptionServiceModule());
- install(arbitratorModule());
install(offerModule());
install(p2pModule());
install(bitcoinModule());
@@ -139,6 +96,7 @@ protected void configure() {
install(alertModule());
install(filterModule());
install(corePresentationModule());
+ bind(PubKeyRing.class).toProvider(PubKeyRingProvider.class);
}
private TradeModule tradeModule() {
@@ -149,10 +107,6 @@ private EncryptionServiceModule encryptionServiceModule() {
return new EncryptionServiceModule(environment);
}
- private ArbitratorModule arbitratorModule() {
- return new ArbitratorModule(environment);
- }
-
private AlertModule alertModule() {
return new AlertModule(environment);
}
diff --git a/core/src/main/java/bisq/core/account/sign/SignedWitness.java b/core/src/main/java/bisq/core/account/sign/SignedWitness.java
new file mode 100644
index 00000000000..111bb195cbd
--- /dev/null
+++ b/core/src/main/java/bisq/core/account/sign/SignedWitness.java
@@ -0,0 +1,170 @@
+/*
+ * 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 .
+ */
+
+package bisq.core.account.sign;
+
+import bisq.network.p2p.storage.P2PDataStorage;
+import bisq.network.p2p.storage.payload.CapabilityRequiringPayload;
+import bisq.network.p2p.storage.payload.DateTolerantPayload;
+import bisq.network.p2p.storage.payload.LazyProcessedPayload;
+import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
+
+import bisq.common.app.Capabilities;
+import bisq.common.app.Capability;
+import bisq.common.crypto.Hash;
+import bisq.common.proto.persistable.PersistableEnvelope;
+import bisq.common.util.Utilities;
+
+import com.google.protobuf.ByteString;
+
+import org.bitcoinj.core.Coin;
+
+import java.time.Clock;
+
+import java.util.Date;
+import java.util.concurrent.TimeUnit;
+
+import lombok.Value;
+import lombok.extern.slf4j.Slf4j;
+
+// Supports signatures made from EC key (arbitrators) and signature created with DSA key.
+@Slf4j
+@Value
+public class SignedWitness implements LazyProcessedPayload, PersistableNetworkPayload, PersistableEnvelope,
+ DateTolerantPayload, CapabilityRequiringPayload {
+ private static final long TOLERANCE = TimeUnit.DAYS.toMillis(1);
+
+ private final boolean signedByArbitrator;
+ private final byte[] witnessHash;
+ private final byte[] signature;
+ private final byte[] signerPubKey;
+ private final byte[] witnessOwnerPubKey;
+ private final long date;
+ private final long tradeAmount;
+
+ transient private final byte[] hash;
+
+ public SignedWitness(boolean signedByArbitrator,
+ byte[] witnessHash,
+ byte[] signature,
+ byte[] signerPubKey,
+ byte[] witnessOwnerPubKey,
+ long date,
+ long tradeAmount) {
+ this.signedByArbitrator = signedByArbitrator;
+ this.witnessHash = witnessHash.clone();
+ this.signature = signature.clone();
+ this.signerPubKey = signerPubKey.clone();
+ this.witnessOwnerPubKey = witnessOwnerPubKey.clone();
+ this.date = date;
+ this.tradeAmount = tradeAmount;
+
+ // The hash is only using the data which does not change in repeated trades between identical users (no date or amount).
+ // We only want to store the first and oldest one and will ignore others. That will also help to protect privacy
+ // so that the total number of trades is not revealed. We use putIfAbsent when we store the data so first
+ // object will win. We consider one signed trade with one peer enough and do not consider repeated trades with
+ // same peer to add more security as if that one would be colluding it would be not detected anyway. The total
+ // number of signed trades with different peers is still available and can be considered more valuable data for
+ // security.
+ byte[] data = Utilities.concatenateByteArrays(witnessHash, signature);
+ data = Utilities.concatenateByteArrays(data, signerPubKey);
+ hash = Hash.getSha256Ripemd160hash(data);
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // PROTOBUF
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ @Override
+ public protobuf.PersistableNetworkPayload toProtoMessage() {
+ final protobuf.SignedWitness.Builder builder = protobuf.SignedWitness.newBuilder()
+ .setSignedByArbitrator(signedByArbitrator)
+ .setWitnessHash(ByteString.copyFrom(witnessHash))
+ .setSignature(ByteString.copyFrom(signature))
+ .setSignerPubKey(ByteString.copyFrom(signerPubKey))
+ .setWitnessOwnerPubKey(ByteString.copyFrom(witnessOwnerPubKey))
+ .setDate(date)
+ .setTradeAmount(tradeAmount);
+ return protobuf.PersistableNetworkPayload.newBuilder().setSignedWitness(builder).build();
+ }
+
+ protobuf.SignedWitness toProtoSignedWitness() {
+ return toProtoMessage().getSignedWitness();
+ }
+
+ public static SignedWitness fromProto(protobuf.SignedWitness proto) {
+ return new SignedWitness(proto.getSignedByArbitrator(),
+ proto.getWitnessHash().toByteArray(),
+ proto.getSignature().toByteArray(),
+ proto.getSignerPubKey().toByteArray(),
+ proto.getWitnessOwnerPubKey().toByteArray(),
+ proto.getDate(),
+ proto.getTradeAmount());
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // API
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ @Override
+ public boolean isDateInTolerance(Clock clock) {
+ // We don't allow older or newer then 1 day.
+ // Preventing forward dating is also important to protect against a sophisticated attack
+ return Math.abs(new Date().getTime() - date) <= TOLERANCE;
+ }
+
+ @Override
+ public boolean verifyHashSize() {
+ return hash.length == 20;
+ }
+
+ // Pre 1.0.1 version don't know the new message type and throw an error which leads to disconnecting the peer.
+ @Override
+ public Capabilities getRequiredCapabilities() {
+ return new Capabilities(Capability.SIGNED_ACCOUNT_AGE_WITNESS);
+ }
+
+ @Override
+ public byte[] getHash() {
+ return hash;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Getters
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ P2PDataStorage.ByteArray getHashAsByteArray() {
+ return new P2PDataStorage.ByteArray(hash);
+ }
+
+ @Override
+ public String toString() {
+ return "SignedWitness{" +
+ ",\n signedByArbitrator=" + signedByArbitrator +
+ ",\n witnessHash=" + Utilities.bytesAsHexString(witnessHash) +
+ ",\n signature=" + Utilities.bytesAsHexString(signature) +
+ ",\n signerPubKey=" + Utilities.bytesAsHexString(signerPubKey) +
+ ",\n witnessOwnerPubKey=" + Utilities.bytesAsHexString(witnessOwnerPubKey) +
+ ",\n date=" + date +
+ ",\n tradeAmount=" + Coin.valueOf(tradeAmount).toFriendlyString() +
+ ",\n hash=" + Utilities.bytesAsHexString(hash) +
+ "\n}";
+ }
+}
diff --git a/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java b/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java
new file mode 100644
index 00000000000..ef87a6e35f1
--- /dev/null
+++ b/core/src/main/java/bisq/core/account/sign/SignedWitnessService.java
@@ -0,0 +1,370 @@
+/*
+ * 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 .
+ */
+
+package bisq.core.account.sign;
+
+import bisq.core.account.witness.AccountAgeWitness;
+import bisq.core.account.witness.AccountAgeWitnessService;
+import bisq.core.payment.ChargeBackRisk;
+import bisq.core.payment.payload.PaymentAccountPayload;
+import bisq.core.payment.payload.PaymentMethod;
+import bisq.core.support.dispute.Dispute;
+import bisq.core.support.dispute.DisputeResult;
+import bisq.core.support.dispute.arbitration.ArbitrationManager;
+import bisq.core.support.dispute.arbitration.BuyerDataItem;
+import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
+
+import bisq.network.p2p.P2PService;
+import bisq.network.p2p.storage.P2PDataStorage;
+import bisq.network.p2p.storage.persistence.AppendOnlyDataStoreService;
+
+import bisq.common.crypto.CryptoException;
+import bisq.common.crypto.KeyRing;
+import bisq.common.crypto.PubKeyRing;
+import bisq.common.crypto.Sig;
+import bisq.common.util.Utilities;
+
+import org.bitcoinj.core.Coin;
+import org.bitcoinj.core.ECKey;
+
+import javax.inject.Inject;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Charsets;
+
+import java.security.PublicKey;
+import java.security.SignatureException;
+
+import java.time.Instant;
+import java.time.temporal.ChronoUnit;
+
+import java.util.Arrays;
+import java.util.Date;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.Stack;
+import java.util.stream.Collectors;
+
+import lombok.extern.slf4j.Slf4j;
+
+import org.jetbrains.annotations.Nullable;
+
+@Slf4j
+public class SignedWitnessService {
+ public static final long CHARGEBACK_SAFETY_DAYS = 30;
+
+ private final KeyRing keyRing;
+ private final P2PService p2PService;
+ private final AccountAgeWitnessService accountAgeWitnessService;
+ private final ArbitratorManager arbitratorManager;
+ private final ArbitrationManager arbitrationManager;
+ private final ChargeBackRisk chargeBackRisk;
+
+ private final Map signedWitnessMap = new HashMap<>();
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Constructor
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ @Inject
+ public SignedWitnessService(KeyRing keyRing,
+ P2PService p2PService,
+ AccountAgeWitnessService accountAgeWitnessService,
+ ArbitratorManager arbitratorManager,
+ SignedWitnessStorageService signedWitnessStorageService,
+ AppendOnlyDataStoreService appendOnlyDataStoreService,
+ ArbitrationManager arbitrationManager,
+ ChargeBackRisk chargeBackRisk) {
+ this.keyRing = keyRing;
+ this.p2PService = p2PService;
+ this.accountAgeWitnessService = accountAgeWitnessService;
+ this.arbitratorManager = arbitratorManager;
+ this.arbitrationManager = arbitrationManager;
+ this.chargeBackRisk = chargeBackRisk;
+
+ // We need to add that early (before onAllServicesInitialized) as it will be used at startup.
+ appendOnlyDataStoreService.addService(signedWitnessStorageService);
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Lifecycle
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ public void onAllServicesInitialized() {
+ p2PService.getP2PDataStorage().addAppendOnlyDataStoreListener(payload -> {
+ if (payload instanceof SignedWitness)
+ addToMap((SignedWitness) payload);
+ });
+
+ // At startup the P2PDataStorage initializes earlier, otherwise we ge the listener called.
+ p2PService.getP2PDataStorage().getAppendOnlyDataStoreMap().values().forEach(e -> {
+ if (e instanceof SignedWitness)
+ addToMap((SignedWitness) e);
+ });
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // API
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ public List getMyWitnessAgeList(PaymentAccountPayload myPaymentAccountPayload) {
+ AccountAgeWitness accountAgeWitness = accountAgeWitnessService.getMyWitness(myPaymentAccountPayload);
+ // We do not validate as it would not make sense to cheat one self...
+ return getSignedWitnessSet(accountAgeWitness).stream()
+ .map(SignedWitness::getDate)
+ .sorted()
+ .collect(Collectors.toList());
+ }
+
+
+ public List getVerifiedWitnessAgeList(AccountAgeWitness accountAgeWitness) {
+ return signedWitnessMap.values().stream()
+ .filter(e -> Arrays.equals(e.getWitnessHash(), accountAgeWitness.getHash()))
+ .filter(this::verifySignature)
+ .map(SignedWitness::getDate)
+ .sorted()
+ .collect(Collectors.toList());
+ }
+
+ // Arbitrators sign with EC key
+ public SignedWitness signAccountAgeWitness(Coin tradeAmount,
+ AccountAgeWitness accountAgeWitness,
+ ECKey key,
+ PublicKey peersPubKey) {
+ String accountAgeWitnessHashAsHex = Utilities.encodeToHex(accountAgeWitness.getHash());
+ String signatureBase64 = key.signMessage(accountAgeWitnessHashAsHex);
+ SignedWitness signedWitness = new SignedWitness(true,
+ accountAgeWitness.getHash(),
+ signatureBase64.getBytes(Charsets.UTF_8),
+ key.getPubKey(),
+ peersPubKey.getEncoded(),
+ new Date().getTime(),
+ tradeAmount.value);
+ publishSignedWitness(signedWitness);
+ return signedWitness;
+ }
+
+ // Any peer can sign with DSA key
+ public SignedWitness signAccountAgeWitness(Coin tradeAmount,
+ AccountAgeWitness accountAgeWitness,
+ PublicKey peersPubKey) throws CryptoException {
+ byte[] signature = Sig.sign(keyRing.getSignatureKeyPair().getPrivate(), accountAgeWitness.getHash());
+ SignedWitness signedWitness = new SignedWitness(false,
+ accountAgeWitness.getHash(),
+ signature,
+ keyRing.getSignatureKeyPair().getPublic().getEncoded(),
+ peersPubKey.getEncoded(),
+ new Date().getTime(),
+ tradeAmount.value);
+ publishSignedWitness(signedWitness);
+ return signedWitness;
+ }
+
+ public boolean verifySignature(SignedWitness signedWitness) {
+ if (signedWitness.isSignedByArbitrator()) {
+ return verifySignatureWithECKey(signedWitness);
+ } else {
+ return verifySignatureWithDSAKey(signedWitness);
+ }
+ }
+
+ private boolean verifySignatureWithECKey(SignedWitness signedWitness) {
+ try {
+ String message = Utilities.encodeToHex(signedWitness.getWitnessHash());
+ String signatureBase64 = new String(signedWitness.getSignature(), Charsets.UTF_8);
+ ECKey key = ECKey.fromPublicOnly(signedWitness.getSignerPubKey());
+ if (arbitratorManager.isPublicKeyInList(Utilities.encodeToHex(key.getPubKey()))) {
+ key.verifyMessage(message, signatureBase64);
+ return true;
+ } else {
+ log.warn("Provided EC key is not in list of valid arbitrators.");
+ return false;
+ }
+ } catch (SignatureException e) {
+ log.warn("verifySignature signedWitness failed. signedWitness={}", signedWitness);
+ log.warn("Caused by ", e);
+ return false;
+ }
+ }
+
+ private boolean verifySignatureWithDSAKey(SignedWitness signedWitness) {
+ try {
+ PublicKey signaturePubKey = Sig.getPublicKeyFromBytes(signedWitness.getSignerPubKey());
+ Sig.verify(signaturePubKey, signedWitness.getWitnessHash(), signedWitness.getSignature());
+ return true;
+ } catch (CryptoException e) {
+ log.warn("verifySignature signedWitness failed. signedWitness={}", signedWitness);
+ log.warn("Caused by ", e);
+ return false;
+ }
+ }
+
+ public Set getSignedWitnessSet(AccountAgeWitness accountAgeWitness) {
+ return signedWitnessMap.values().stream()
+ .filter(e -> Arrays.equals(e.getWitnessHash(), accountAgeWitness.getHash()))
+ .collect(Collectors.toSet());
+ }
+
+ // SignedWitness objects signed by arbitrators
+ public Set getArbitratorsSignedWitnessSet(AccountAgeWitness accountAgeWitness) {
+ return signedWitnessMap.values().stream()
+ .filter(SignedWitness::isSignedByArbitrator)
+ .filter(e -> Arrays.equals(e.getWitnessHash(), accountAgeWitness.getHash()))
+ .collect(Collectors.toSet());
+ }
+
+ // SignedWitness objects signed by any other peer
+ public Set getTrustedPeerSignedWitnessSet(AccountAgeWitness accountAgeWitness) {
+ return signedWitnessMap.values().stream()
+ .filter(e -> !e.isSignedByArbitrator())
+ .filter(e -> Arrays.equals(e.getWitnessHash(), accountAgeWitness.getHash()))
+ .collect(Collectors.toSet());
+ }
+
+ // We go one level up by using the signer Key to lookup for SignedWitness objects which contain the signerKey as
+ // witnessOwnerPubKey
+ public Set getSignedWitnessSetByOwnerPubKey(byte[] ownerPubKey,
+ Stack excluded) {
+ return signedWitnessMap.values().stream()
+ .filter(e -> Arrays.equals(e.getWitnessOwnerPubKey(), ownerPubKey))
+ .filter(e -> !excluded.contains(new P2PDataStorage.ByteArray(e.getSignerPubKey())))
+ .collect(Collectors.toSet());
+ }
+
+ /**
+ * Checks whether the accountAgeWitness has a valid signature from a peer/arbitrator.
+ * @param accountAgeWitness
+ * @return true if accountAgeWitness is valid, false otherwise.
+ */
+ public boolean isValidAccountAgeWitness(AccountAgeWitness accountAgeWitness) {
+ Stack excludedPubKeys = new Stack<>();
+ long now = new Date().getTime();
+ Set signedWitnessSet = getSignedWitnessSet(accountAgeWitness);
+ for (SignedWitness signedWitness : signedWitnessSet) {
+ if (isValidSignedWitnessInternal(signedWitness, now, excludedPubKeys)) {
+ return true;
+ }
+ }
+ // If we have not returned in the loops or they have been empty we have not found a valid signer.
+ return false;
+ }
+
+ /**
+ * Helper to isValidAccountAgeWitness(accountAgeWitness)
+ * @param signedWitness the signedWitness to validate
+ * @param childSignedWitnessDateMillis the date the child SignedWitness was signed or current time if it is a leave.
+ * @param excludedPubKeys stack to prevent recursive loops
+ * @return true if signedWitness is valid, false otherwise.
+ */
+ private boolean isValidSignedWitnessInternal(SignedWitness signedWitness,
+ long childSignedWitnessDateMillis,
+ Stack excludedPubKeys) {
+ if (!verifySignature(signedWitness)) {
+ return false;
+ }
+ if (signedWitness.isSignedByArbitrator()) {
+ // If signed by an arbitrator we don't have to check anything else.
+ return true;
+ } else {
+ if (!verifyDate(signedWitness, childSignedWitnessDateMillis)) {
+ return false;
+ }
+ if (excludedPubKeys.size() >= 2000) {
+ // Prevent DoS attack: an attacker floods the SignedWitness db with a long chain that takes lots of time to verify.
+ return false;
+ }
+ excludedPubKeys.push(new P2PDataStorage.ByteArray(signedWitness.getSignerPubKey()));
+ excludedPubKeys.push(new P2PDataStorage.ByteArray(signedWitness.getWitnessOwnerPubKey()));
+ // Iterate over signedWitness signers
+ Set signerSignedWitnessSet = getSignedWitnessSetByOwnerPubKey(signedWitness.getSignerPubKey(), excludedPubKeys);
+ for (SignedWitness signerSignedWitness : signerSignedWitnessSet) {
+ if (isValidSignedWitnessInternal(signerSignedWitness, signedWitness.getDate(), excludedPubKeys)) {
+ return true;
+ }
+ }
+ excludedPubKeys.pop();
+ excludedPubKeys.pop();
+ }
+ // If we have not returned in the loops or they have been empty we have not found a valid signer.
+ return false;
+ }
+
+ private boolean verifyDate(SignedWitness signedWitness, long childSignedWitnessDateMillis) {
+ long childSignedWitnessDateMinusChargebackPeriodMillis = Instant.ofEpochMilli(childSignedWitnessDateMillis).minus(CHARGEBACK_SAFETY_DAYS, ChronoUnit.DAYS).toEpochMilli();
+ long signedWitnessDateMillis = signedWitness.getDate();
+ return signedWitnessDateMillis <= childSignedWitnessDateMinusChargebackPeriodMillis;
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Private
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ @VisibleForTesting
+ void addToMap(SignedWitness signedWitness) {
+ signedWitnessMap.putIfAbsent(signedWitness.getHashAsByteArray(), signedWitness);
+ }
+
+ private void publishSignedWitness(SignedWitness signedWitness) {
+ if (!signedWitnessMap.containsKey(signedWitness.getHashAsByteArray())) {
+ p2PService.addPersistableNetworkPayload(signedWitness, false);
+ }
+ }
+
+ // Arbitrator signing
+ public List getBuyerPaymentAccounts(long safeDate, PaymentMethod paymentMethod) {
+ return arbitrationManager.getDisputesAsObservableList().stream()
+ .filter(dispute -> dispute.getContract().getPaymentMethodId().equals(paymentMethod.getId()))
+ .filter(this::hasChargebackRisk)
+ .filter(this::isBuyerWinner)
+ .map(this::getBuyerData)
+ .filter(Objects::nonNull)
+ .filter(buyerDataItem -> buyerDataItem.getAccountAgeWitness().getDate() < safeDate)
+ .distinct()
+ .collect(Collectors.toList());
+ }
+
+ private boolean hasChargebackRisk(Dispute dispute) {
+ return chargeBackRisk.hasChargebackRisk(dispute.getContract().getPaymentMethodId(),
+ dispute.getContract().getOfferPayload().getCurrencyCode());
+ }
+
+ private boolean isBuyerWinner(Dispute dispute) {
+ return dispute.getDisputeResultProperty().get().getWinner() == DisputeResult.Winner.BUYER;
+ }
+
+ @Nullable
+ private BuyerDataItem getBuyerData(Dispute dispute) {
+ PubKeyRing buyerPubKeyRing = dispute.getContract().getBuyerPubKeyRing();
+ PaymentAccountPayload buyerPaymentAccountPaload = dispute.getContract().getBuyerPaymentAccountPayload();
+ Optional optionalWitness = accountAgeWitnessService
+ .findWitness(buyerPaymentAccountPaload, buyerPubKeyRing);
+ return optionalWitness.map(witness -> new BuyerDataItem(
+ buyerPaymentAccountPaload,
+ witness,
+ dispute.getContract().getTradeAmount(),
+ dispute.getContract().getSellerPubKeyRing().getSignaturePubKey()))
+ .orElse(null);
+ }
+
+}
diff --git a/core/src/main/java/bisq/core/account/sign/SignedWitnessStorageService.java b/core/src/main/java/bisq/core/account/sign/SignedWitnessStorageService.java
new file mode 100644
index 00000000000..ad461c27b60
--- /dev/null
+++ b/core/src/main/java/bisq/core/account/sign/SignedWitnessStorageService.java
@@ -0,0 +1,89 @@
+/*
+ * 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 .
+ */
+
+package bisq.core.account.sign;
+
+import bisq.network.p2p.storage.P2PDataStorage;
+import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
+import bisq.network.p2p.storage.persistence.MapStoreService;
+
+import bisq.common.storage.Storage;
+
+import com.google.inject.name.Named;
+
+import javax.inject.Inject;
+
+import java.io.File;
+
+import java.util.Map;
+
+import lombok.extern.slf4j.Slf4j;
+
+import static com.google.common.base.Preconditions.checkArgument;
+
+@Slf4j
+public class SignedWitnessStorageService extends MapStoreService {
+ private static final String FILE_NAME = "SignedWitnessStore";
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Constructor
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ @Inject
+ public SignedWitnessStorageService(@Named(Storage.STORAGE_DIR) File storageDir,
+ Storage persistableNetworkPayloadMapStorage) {
+ super(storageDir, persistableNetworkPayloadMapStorage);
+ }
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // API
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ @Override
+ public String getFileName() {
+ return FILE_NAME;
+ }
+
+ @Override
+ public Map getMap() {
+ return store.getMap();
+ }
+
+ @Override
+ public boolean canHandle(PersistableNetworkPayload payload) {
+ return payload instanceof SignedWitness;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Protected
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ @Override
+ protected SignedWitnessStore createStore() {
+ return new SignedWitnessStore();
+ }
+
+ @Override
+ protected void readStore() {
+ super.readStore();
+ checkArgument(store instanceof SignedWitnessStore,
+ "Store is not instance of SignedWitnessStore. That can happen if the ProtoBuffer " +
+ "file got changed. We cleared the data store and recreated it again.");
+ }
+}
diff --git a/core/src/main/java/bisq/core/account/sign/SignedWitnessStore.java b/core/src/main/java/bisq/core/account/sign/SignedWitnessStore.java
new file mode 100644
index 00000000000..1f05e66ff59
--- /dev/null
+++ b/core/src/main/java/bisq/core/account/sign/SignedWitnessStore.java
@@ -0,0 +1,82 @@
+/*
+ * 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 .
+ */
+
+package bisq.core.account.sign;
+
+
+import bisq.network.p2p.storage.P2PDataStorage;
+import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
+
+import bisq.common.proto.persistable.PersistableEnvelope;
+
+import com.google.protobuf.Message;
+
+import java.util.List;
+import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.stream.Collectors;
+
+import lombok.Getter;
+import lombok.extern.slf4j.Slf4j;
+
+
+/**
+ * We store only the payload in the PB file to save disc space. The hash of the payload can be created anyway and
+ * is only used as key in the map. So we have a hybrid data structure which is represented as list in the protobuf
+ * definition and provide a hashMap for the domain access.
+ */
+@Slf4j
+public class SignedWitnessStore implements PersistableEnvelope {
+ @Getter
+ private Map map = new ConcurrentHashMap<>();
+
+ SignedWitnessStore() {
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // PROTO BUFFER
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ private SignedWitnessStore(List list) {
+ list.forEach(item -> map.put(new P2PDataStorage.ByteArray(item.getHash()), item));
+ }
+
+ public Message toProtoMessage() {
+ return protobuf.PersistableEnvelope.newBuilder()
+ .setSignedWitnessStore(getBuilder())
+ .build();
+ }
+
+ private protobuf.SignedWitnessStore.Builder getBuilder() {
+ final List protoList = map.values().stream()
+ .map(payload -> (SignedWitness) payload)
+ .map(SignedWitness::toProtoSignedWitness)
+ .collect(Collectors.toList());
+ return protobuf.SignedWitnessStore.newBuilder().addAllItems(protoList);
+ }
+
+ public static PersistableEnvelope fromProto(protobuf.SignedWitnessStore proto) {
+ List list = proto.getItemsList().stream()
+ .map(SignedWitness::fromProto).collect(Collectors.toList());
+ return new SignedWitnessStore(list);
+ }
+
+ public boolean containsKey(P2PDataStorage.ByteArray hash) {
+ return map.containsKey(hash);
+ }
+}
diff --git a/core/src/main/java/bisq/core/payment/AccountAgeRestrictions.java b/core/src/main/java/bisq/core/account/witness/AccountAgeRestrictions.java
similarity index 85%
rename from core/src/main/java/bisq/core/payment/AccountAgeRestrictions.java
rename to core/src/main/java/bisq/core/account/witness/AccountAgeRestrictions.java
index 85dd82cef34..04c6ab2af43 100644
--- a/core/src/main/java/bisq/core/payment/AccountAgeRestrictions.java
+++ b/core/src/main/java/bisq/core/account/witness/AccountAgeRestrictions.java
@@ -15,11 +15,12 @@
* along with Bisq. If not, see .
*/
-package bisq.core.payment;
+package bisq.core.account.witness;
import bisq.core.offer.Offer;
import bisq.core.offer.OfferPayload;
import bisq.core.offer.OfferRestrictions;
+import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.trade.Trade;
@@ -32,7 +33,7 @@
@Slf4j
public class AccountAgeRestrictions {
- public static final long SAFE_ACCOUNT_AGE_DATE = Utilities.getUTCDate(2019, GregorianCalendar.MARCH, 1).getTime();
+ private static final long SAFE_ACCOUNT_AGE_DATE = Utilities.getUTCDate(2019, GregorianCalendar.MARCH, 1).getTime();
public static boolean isMakersAccountAgeImmature(AccountAgeWitnessService accountAgeWitnessService, Offer offer) {
long accountCreationDate = new Date().getTime() - accountAgeWitnessService.getMakersAccountAge(offer, new Date());
@@ -54,7 +55,7 @@ public static long getMyTradeLimitAtCreateOffer(AccountAgeWitnessService account
String currencyCode,
OfferPayload.Direction direction) {
if (direction == OfferPayload.Direction.BUY &&
- PaymentMethod.hasChargebackRisk(paymentAccount.getPaymentMethod()) &&
+ PaymentMethod.hasChargebackRisk(paymentAccount.getPaymentMethod(), currencyCode) &&
AccountAgeRestrictions.isMyAccountAgeImmature(accountAgeWitnessService, paymentAccount)) {
return OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value;
} else {
@@ -67,15 +68,18 @@ public static long getMyTradeLimitAtTakeOffer(AccountAgeWitnessService accountAg
Offer offer,
String currencyCode,
OfferPayload.Direction direction) {
- if (direction == OfferPayload.Direction.BUY && PaymentMethod.hasChargebackRisk(paymentAccount.getPaymentMethod()) &&
+ if (direction == OfferPayload.Direction.BUY &&
+ PaymentMethod.hasChargebackRisk(paymentAccount.getPaymentMethod(), currencyCode) &&
AccountAgeRestrictions.isMakersAccountAgeImmature(accountAgeWitnessService, offer)) {
// Taker is seller
return OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value;
- } else if (direction == OfferPayload.Direction.SELL && PaymentMethod.hasChargebackRisk(paymentAccount.getPaymentMethod()) &&
+ } else if (direction == OfferPayload.Direction.SELL &&
+ PaymentMethod.hasChargebackRisk(paymentAccount.getPaymentMethod(), currencyCode) &&
AccountAgeRestrictions.isMyAccountAgeImmature(accountAgeWitnessService, paymentAccount)) {
// Taker is buyer
return OfferRestrictions.TOLERATED_SMALL_TRADE_AMOUNT.value;
} else {
+ // Offers with no chargeback risk or mature buyer accounts
return accountAgeWitnessService.getMyTradeLimit(paymentAccount, currencyCode);
}
}
diff --git a/core/src/main/java/bisq/core/payment/AccountAgeWitness.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitness.java
similarity index 81%
rename from core/src/main/java/bisq/core/payment/AccountAgeWitness.java
rename to core/src/main/java/bisq/core/account/witness/AccountAgeWitness.java
index 78660248a55..76afa35807a 100644
--- a/core/src/main/java/bisq/core/payment/AccountAgeWitness.java
+++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitness.java
@@ -15,23 +15,20 @@
* along with bisq. If not, see .
*/
-package bisq.core.payment;
+package bisq.core.account.witness;
import bisq.network.p2p.storage.P2PDataStorage;
-import bisq.network.p2p.storage.payload.CapabilityRequiringPayload;
import bisq.network.p2p.storage.payload.DateTolerantPayload;
import bisq.network.p2p.storage.payload.LazyProcessedPayload;
import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
-import bisq.common.app.Capabilities;
-import bisq.common.app.Capability;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
+import java.time.Clock;
+
import java.util.Date;
import java.util.concurrent.TimeUnit;
@@ -43,7 +40,7 @@
// so only the newly added objects since the last release will be retrieved over the P2P network.
@Slf4j
@Value
-public class AccountAgeWitness implements LazyProcessedPayload, PersistableNetworkPayload, PersistableEnvelope, DateTolerantPayload, CapabilityRequiringPayload {
+public class AccountAgeWitness implements LazyProcessedPayload, PersistableNetworkPayload, PersistableEnvelope, DateTolerantPayload {
private static final long TOLERANCE = TimeUnit.DAYS.toMillis(1);
private final byte[] hash; // Ripemd160(Sha256(concatenated accountHash, signature and sigPubKey)); 20 bytes
@@ -61,18 +58,18 @@ public AccountAgeWitness(byte[] hash,
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.PersistableNetworkPayload toProtoMessage() {
- final PB.AccountAgeWitness.Builder builder = PB.AccountAgeWitness.newBuilder()
+ public protobuf.PersistableNetworkPayload toProtoMessage() {
+ final protobuf.AccountAgeWitness.Builder builder = protobuf.AccountAgeWitness.newBuilder()
.setHash(ByteString.copyFrom(hash))
.setDate(date);
- return PB.PersistableNetworkPayload.newBuilder().setAccountAgeWitness(builder).build();
+ return protobuf.PersistableNetworkPayload.newBuilder().setAccountAgeWitness(builder).build();
}
- public PB.AccountAgeWitness toProtoAccountAgeWitness() {
+ public protobuf.AccountAgeWitness toProtoAccountAgeWitness() {
return toProtoMessage().getAccountAgeWitness();
}
- public static AccountAgeWitness fromProto(PB.AccountAgeWitness proto) {
+ public static AccountAgeWitness fromProto(protobuf.AccountAgeWitness proto) {
byte[] hash = proto.getHash().toByteArray();
if (hash.length != 20) {
log.warn("We got a a hash which is not 20 bytes");
@@ -89,7 +86,7 @@ public static AccountAgeWitness fromProto(PB.AccountAgeWitness proto) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public boolean isDateInTolerance() {
+ public boolean isDateInTolerance(Clock clock) {
// We don't allow older or newer then 1 day.
// Preventing forward dating is also important to protect against a sophisticated attack
return Math.abs(new Date().getTime() - date) <= TOLERANCE;
@@ -100,12 +97,6 @@ public boolean verifyHashSize() {
return hash.length == 20;
}
- // Pre 0.6 version don't know the new message type and throw an error which leads to disconnecting the peer.
- @Override
- public Capabilities getRequiredCapabilities() {
- return new Capabilities(Capability.ACCOUNT_AGE_WITNESS);
- }
-
@Override
public byte[] getHash() {
return hash;
diff --git a/core/src/main/java/bisq/core/payment/AccountAgeWitnessService.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java
similarity index 97%
rename from core/src/main/java/bisq/core/payment/AccountAgeWitnessService.java
rename to core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java
index 547a9401a35..74f7d276d3e 100644
--- a/core/src/main/java/bisq/core/payment/AccountAgeWitnessService.java
+++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessService.java
@@ -15,10 +15,12 @@
* along with bisq. If not, see .
*/
-package bisq.core.payment;
+package bisq.core.account.witness;
import bisq.core.locale.CurrencyUtil;
import bisq.core.offer.Offer;
+import bisq.core.payment.AssetAccount;
+import bisq.core.payment.PaymentAccount;
import bisq.core.payment.payload.PaymentAccountPayload;
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.trade.Trade;
@@ -63,7 +65,6 @@
public class AccountAgeWitnessService {
private static final Date RELEASE = Utilities.getUTCDate(2017, GregorianCalendar.NOVEMBER, 11);
public static final Date FULL_ACTIVATION = Utilities.getUTCDate(2018, GregorianCalendar.FEBRUARY, 15);
- public static final long SAFE_ACCOUNT_AGE_DATE = Utilities.getUTCDate(2019, GregorianCalendar.MARCH, 15).getTime();
public enum AccountAge {
LESS_ONE_MONTH,
@@ -178,7 +179,7 @@ private Optional getWitnessByHash(byte[] hash) {
if (!containsKey)
log.debug("hash not found in accountAgeWitnessMap");
- return accountAgeWitnessMap.containsKey(hashAsByteArray) ? Optional.of(accountAgeWitnessMap.get(hashAsByteArray)) : Optional.empty();
+ return accountAgeWitnessMap.containsKey(hashAsByteArray) ? Optional.of(accountAgeWitnessMap.get(hashAsByteArray)) : Optional.empty();
}
private Optional getWitnessByHashAsHex(String hashAsHex) {
@@ -212,13 +213,9 @@ private long getTradeLimit(Coin maxTradeLimit, String currencyCode, Optional getAccountAgeCategory(accountAge))
+ .map(accountAgeWitness -> getAccountAgeCategory(accountAge))
.orElse(AccountAge.LESS_ONE_MONTH);
- // TODO Fade in by date can be removed after feb 2018
- // We want to fade in the limit over 2 months to avoid that all users get limited to 25% of the limit when
- // we deploy that feature.
-
switch (accountAgeCategory) {
case TWO_MONTHS_OR_MORE:
factor = 1;
diff --git a/core/src/main/java/bisq/core/payment/AccountAgeWitnessStorageService.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStorageService.java
similarity index 95%
rename from core/src/main/java/bisq/core/payment/AccountAgeWitnessStorageService.java
rename to core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStorageService.java
index 437014d9797..b55e9fb1de2 100644
--- a/core/src/main/java/bisq/core/payment/AccountAgeWitnessStorageService.java
+++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStorageService.java
@@ -15,7 +15,7 @@
* along with Bisq. If not, see .
*/
-package bisq.core.payment;
+package bisq.core.account.witness;
import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
@@ -84,6 +84,6 @@ protected void readStore() {
super.readStore();
checkArgument(store instanceof AccountAgeWitnessStore,
"Store is not instance of AccountAgeWitnessStore. That can happen if the ProtoBuffer " +
- "file got changed. We clear the data store and recreated it again.");
+ "file got changed. We cleared the data store and recreated it again.");
}
}
diff --git a/core/src/main/java/bisq/core/payment/AccountAgeWitnessStore.java b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStore.java
similarity index 86%
rename from core/src/main/java/bisq/core/payment/AccountAgeWitnessStore.java
rename to core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStore.java
index 9493be42a4e..e25f73e28b8 100644
--- a/core/src/main/java/bisq/core/payment/AccountAgeWitnessStore.java
+++ b/core/src/main/java/bisq/core/account/witness/AccountAgeWitnessStore.java
@@ -15,15 +15,13 @@
* along with Bisq. If not, see .
*/
-package bisq.core.payment;
+package bisq.core.account.witness;
import bisq.network.p2p.storage.P2PDataStorage;
import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
import bisq.common.proto.persistable.PersistableEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import java.util.List;
@@ -58,20 +56,20 @@ private AccountAgeWitnessStore(List list) {
}
public Message toProtoMessage() {
- return PB.PersistableEnvelope.newBuilder()
+ return protobuf.PersistableEnvelope.newBuilder()
.setAccountAgeWitnessStore(getBuilder())
.build();
}
- private PB.AccountAgeWitnessStore.Builder getBuilder() {
- final List protoList = map.values().stream()
+ private protobuf.AccountAgeWitnessStore.Builder getBuilder() {
+ final List protoList = map.values().stream()
.map(payload -> (AccountAgeWitness) payload)
.map(AccountAgeWitness::toProtoAccountAgeWitness)
.collect(Collectors.toList());
- return PB.AccountAgeWitnessStore.newBuilder().addAllItems(protoList);
+ return protobuf.AccountAgeWitnessStore.newBuilder().addAllItems(protoList);
}
- public static PersistableEnvelope fromProto(PB.AccountAgeWitnessStore proto) {
+ public static PersistableEnvelope fromProto(protobuf.AccountAgeWitnessStore proto) {
List list = proto.getItemsList().stream()
.map(AccountAgeWitness::fromProto).collect(Collectors.toList());
return new AccountAgeWitnessStore(list);
diff --git a/core/src/main/java/bisq/core/alert/Alert.java b/core/src/main/java/bisq/core/alert/Alert.java
index 4081b231f26..080c8272517 100644
--- a/core/src/main/java/bisq/core/alert/Alert.java
+++ b/core/src/main/java/bisq/core/alert/Alert.java
@@ -24,8 +24,6 @@
import bisq.common.crypto.Sig;
import bisq.common.util.ExtraDataMapValidator;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import org.springframework.util.CollectionUtils;
@@ -98,20 +96,26 @@ public Alert(String message,
}
@Override
- public PB.StoragePayload toProtoMessage() {
+ public protobuf.StoragePayload toProtoMessage() {
checkNotNull(ownerPubKeyBytes, "storagePublicKeyBytes must not be null");
checkNotNull(signatureAsBase64, "signatureAsBase64 must not be null");
- final PB.Alert.Builder builder = PB.Alert.newBuilder()
+ protobuf.Alert.Builder builder = protobuf.Alert.newBuilder()
.setMessage(message)
.setIsUpdateInfo(isUpdateInfo)
.setVersion(version)
.setOwnerPubKeyBytes(ByteString.copyFrom(ownerPubKeyBytes))
.setSignatureAsBase64(signatureAsBase64);
Optional.ofNullable(getExtraDataMap()).ifPresent(builder::putAllExtraData);
- return PB.StoragePayload.newBuilder().setAlert(builder).build();
+ return protobuf.StoragePayload.newBuilder().setAlert(builder).build();
}
- public static Alert fromProto(PB.Alert proto) {
+ @Nullable
+ public static Alert fromProto(protobuf.Alert proto) {
+ // We got in dev testing sometimes an empty protobuf Alert. Not clear why that happened but as it causes an
+ // exception and corrupted user db file we prefer to set it to null.
+ if (proto.getSignatureAsBase64().isEmpty())
+ return null;
+
return new Alert(proto.getMessage(),
proto.getIsUpdateInfo(),
proto.getVersion(),
diff --git a/core/src/main/java/bisq/core/alert/PrivateNotificationMessage.java b/core/src/main/java/bisq/core/alert/PrivateNotificationMessage.java
index 4aeb529256c..25820ef903f 100644
--- a/core/src/main/java/bisq/core/alert/PrivateNotificationMessage.java
+++ b/core/src/main/java/bisq/core/alert/PrivateNotificationMessage.java
@@ -23,8 +23,6 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.EqualsAndHashCode;
import lombok.Value;
@@ -57,16 +55,16 @@ private PrivateNotificationMessage(PrivateNotificationPayload privateNotificatio
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setPrivateNotificationMessage(PB.PrivateNotificationMessage.newBuilder()
+ .setPrivateNotificationMessage(protobuf.PrivateNotificationMessage.newBuilder()
.setPrivateNotificationPayload(privateNotificationPayload.toProtoMessage())
.setSenderNodeAddress(senderNodeAddress.toProtoMessage())
.setUid(uid))
.build();
}
- public static PrivateNotificationMessage fromProto(PB.PrivateNotificationMessage proto, int messageVersion) {
+ public static PrivateNotificationMessage fromProto(protobuf.PrivateNotificationMessage proto, int messageVersion) {
return new PrivateNotificationMessage(PrivateNotificationPayload.fromProto(proto.getPrivateNotificationPayload()),
NodeAddress.fromProto(proto.getSenderNodeAddress()),
proto.getUid(),
diff --git a/core/src/main/java/bisq/core/alert/PrivateNotificationPayload.java b/core/src/main/java/bisq/core/alert/PrivateNotificationPayload.java
index 2e01065ac1a..2c29647878c 100644
--- a/core/src/main/java/bisq/core/alert/PrivateNotificationPayload.java
+++ b/core/src/main/java/bisq/core/alert/PrivateNotificationPayload.java
@@ -21,8 +21,6 @@
import bisq.common.proto.network.NetworkPayload;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import java.security.PublicKey;
@@ -63,17 +61,17 @@ private PrivateNotificationPayload(String message, String signatureAsBase64, byt
sigPublicKey = Sig.getPublicKeyFromBytes(sigPublicKeyBytes);
}
- public static PrivateNotificationPayload fromProto(PB.PrivateNotificationPayload proto) {
+ public static PrivateNotificationPayload fromProto(protobuf.PrivateNotificationPayload proto) {
return new PrivateNotificationPayload(proto.getMessage(),
proto.getSignatureAsBase64(),
proto.getSigPublicKeyBytes().toByteArray());
}
@Override
- public PB.PrivateNotificationPayload toProtoMessage() {
+ public protobuf.PrivateNotificationPayload toProtoMessage() {
checkNotNull(sigPublicKeyBytes, "sigPublicKeyBytes must not be null");
checkNotNull(signatureAsBase64, "signatureAsBase64 must not be null");
- return PB.PrivateNotificationPayload.newBuilder()
+ return protobuf.PrivateNotificationPayload.newBuilder()
.setMessage(message)
.setSignatureAsBase64(signatureAsBase64)
.setSigPublicKeyBytes(ByteString.copyFrom(sigPublicKeyBytes))
diff --git a/core/src/main/java/bisq/core/app/AvoidStandbyModeService.java b/core/src/main/java/bisq/core/app/AvoidStandbyModeService.java
index 36badeaecd5..bf9a733718e 100644
--- a/core/src/main/java/bisq/core/app/AvoidStandbyModeService.java
+++ b/core/src/main/java/bisq/core/app/AvoidStandbyModeService.java
@@ -20,6 +20,7 @@
import bisq.core.user.Preferences;
import javax.inject.Inject;
+import javax.inject.Singleton;
import org.apache.commons.io.IOUtils;
@@ -40,6 +41,7 @@
import javax.sound.sampled.SourceDataLine;
@Slf4j
+@Singleton
public class AvoidStandbyModeService {
private final Preferences preferences;
private volatile boolean isStopped;
diff --git a/core/src/main/java/bisq/core/app/BisqEnvironment.java b/core/src/main/java/bisq/core/app/BisqEnvironment.java
index 59319dd525b..fdc211ad583 100644
--- a/core/src/main/java/bisq/core/app/BisqEnvironment.java
+++ b/core/src/main/java/bisq/core/app/BisqEnvironment.java
@@ -191,13 +191,12 @@ public static boolean isDaoActivated(Environment environment) {
@Getter
protected List bannedSeedNodes, bannedBtcNodes, bannedPriceRelayNodes;
- protected final String btcNodes, seedNodes, ignoreDevMsg, useDevPrivilegeKeys, useDevMode, useTorForBtc, rpcUser,
- rpcPassword, rpcPort, rpcBlockNotificationPort, dumpBlockchainData, fullDaoNode,
+ protected final String btcNodes, seedNodes, ignoreDevMsg, useDevPrivilegeKeys, useDevMode, useTorForBtc, rpcUser, rpcPassword,
+ rpcHost, rpcPort, rpcBlockNotificationPort, rpcBlockNotificationHost, dumpBlockchainData, fullDaoNode,
banList, dumpStatistics, maxMemory, socks5ProxyBtcAddress,
torRcFile, torRcOptions, externalTorControlPort, externalTorPassword, externalTorCookieFile,
- socks5ProxyHttpAddress, useAllProvidedNodes, numConnectionForBtc, genesisTxId, genesisBlockHeight,
- genesisTotalSupply, referralId, daoActivated, msgThrottlePerSec, msgThrottlePer10Sec, sendMsgThrottleTrigger,
- sendMsgThrottleSleep, ignoreLocalBtcNode;
+ socks5ProxyHttpAddress, useAllProvidedNodes, numConnectionForBtc, genesisTxId, genesisBlockHeight, genesisTotalSupply,
+ referralId, daoActivated, msgThrottlePerSec, msgThrottlePer10Sec, sendMsgThrottleTrigger, sendMsgThrottleSleep, ignoreLocalBtcNode;
protected final boolean externalTorUseSafeCookieAuthentication, torStreamIsolation;
@@ -306,12 +305,18 @@ public BisqEnvironment(PropertySource commandLineProperties) {
rpcPassword = commandLineProperties.containsProperty(DaoOptionKeys.RPC_PASSWORD) ?
(String) commandLineProperties.getProperty(DaoOptionKeys.RPC_PASSWORD) :
"";
+ rpcHost = commandLineProperties.containsProperty(DaoOptionKeys.RPC_HOST) ?
+ (String) commandLineProperties.getProperty(DaoOptionKeys.RPC_HOST) :
+ "";
rpcPort = commandLineProperties.containsProperty(DaoOptionKeys.RPC_PORT) ?
(String) commandLineProperties.getProperty(DaoOptionKeys.RPC_PORT) :
"";
rpcBlockNotificationPort = commandLineProperties.containsProperty(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_PORT) ?
(String) commandLineProperties.getProperty(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_PORT) :
"";
+ rpcBlockNotificationHost = commandLineProperties.containsProperty(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_HOST) ?
+ (String) commandLineProperties.getProperty(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_HOST) :
+ "";
dumpBlockchainData = commandLineProperties.containsProperty(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA) ?
(String) commandLineProperties.getProperty(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA) :
"";
@@ -504,8 +509,10 @@ private PropertySource> defaultProperties() {
setProperty(DaoOptionKeys.RPC_USER, rpcUser);
setProperty(DaoOptionKeys.RPC_PASSWORD, rpcPassword);
+ setProperty(DaoOptionKeys.RPC_HOST, rpcHost);
setProperty(DaoOptionKeys.RPC_PORT, rpcPort);
setProperty(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_PORT, rpcBlockNotificationPort);
+ setProperty(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_HOST, rpcBlockNotificationHost);
setProperty(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA, dumpBlockchainData);
setProperty(DaoOptionKeys.FULL_DAO_NODE, fullDaoNode);
setProperty(DaoOptionKeys.GENESIS_TX_ID, genesisTxId);
diff --git a/core/src/main/java/bisq/core/app/BisqExecutable.java b/core/src/main/java/bisq/core/app/BisqExecutable.java
index 28805139198..f5935a54067 100644
--- a/core/src/main/java/bisq/core/app/BisqExecutable.java
+++ b/core/src/main/java/bisq/core/app/BisqExecutable.java
@@ -17,7 +17,6 @@
package bisq.core.app;
-import bisq.core.arbitration.ArbitratorManager;
import bisq.core.btc.BtcOptionKeys;
import bisq.core.btc.setup.RegTestHost;
import bisq.core.btc.setup.WalletsSetup;
@@ -29,6 +28,7 @@
import bisq.core.offer.OpenOfferManager;
import bisq.core.setup.CorePersistedDataHost;
import bisq.core.setup.CoreSetup;
+import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
import bisq.core.trade.TradeManager;
import bisq.network.NetworkOptionKeys;
@@ -42,8 +42,6 @@
import bisq.common.handlers.ResultHandler;
import bisq.common.proto.persistable.PersistedDataHost;
import bisq.common.setup.GracefulShutDownHandler;
-import bisq.common.storage.CorruptedDatabaseFilesHandler;
-import bisq.common.storage.Storage;
import org.springframework.core.env.JOptCommandLinePropertySource;
@@ -232,8 +230,6 @@ protected Injector getInjector() {
protected void applyInjector() {
setupDevEnv();
- setCorruptedDataBaseFilesHandler();
-
setupPersistedDataHosts(injector);
}
@@ -242,20 +238,15 @@ protected void setupDevEnv() {
DevEnv.setDaoActivated(BisqEnvironment.isDaoActivated(bisqEnvironment));
}
- private void setCorruptedDataBaseFilesHandler() {
- CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler = injector.getInstance(CorruptedDatabaseFilesHandler.class);
- Storage.setCorruptedDatabaseFilesHandler(corruptedDatabaseFilesHandler);
- }
-
protected void setupPersistedDataHosts(Injector injector) {
try {
PersistedDataHost.apply(CorePersistedDataHost.getPersistedDataHosts(injector));
} catch (Throwable t) {
+ log.error("Error at PersistedDataHost.apply: {}", t.toString(), t);
// If we are in dev mode we want to get the exception if some db files are corrupted
// We need to delay it as the stage is not created yet and so popups would not be shown.
if (DevEnv.isDevMode())
UserThread.runAfter(() -> {
- log.error("Error at PersistedDataHost.apply: {}", t.toString());
throw t;
}, 2);
}
@@ -290,12 +281,14 @@ public void gracefulShutDown(ResultHandler resultHandler) {
injector.getInstance(TradeManager.class).shutDown();
injector.getInstance(DaoSetup.class).shutDown();
injector.getInstance(OpenOfferManager.class).shutDown(() -> {
+ log.info("OpenOfferManager shutdown completed");
injector.getInstance(P2PService.class).shutDown(() -> {
+ log.info("P2PService shutdown completed");
injector.getInstance(WalletsSetup.class).shutDownComplete.addListener((ov, o, n) -> {
+ log.info("WalletsSetup shutdown completed");
module.close(injector);
- log.debug("Graceful shutdown completed");
resultHandler.handleResult();
-
+ log.info("Graceful shutdown completed. Exiting now.");
System.exit(0);
});
injector.getInstance(WalletsSetup.class).shutDown();
@@ -541,6 +534,10 @@ protected void customizeOptionParsing(OptionParser parser) {
"Bitcoind rpc password")
.withRequiredArg();
+ parser.accepts(DaoOptionKeys.RPC_HOST,
+ "Bitcoind rpc host")
+ .withRequiredArg();
+
parser.accepts(DaoOptionKeys.RPC_PORT,
"Bitcoind rpc port")
.withRequiredArg();
@@ -549,6 +546,10 @@ protected void customizeOptionParsing(OptionParser parser) {
"Bitcoind rpc port for block notifications")
.withRequiredArg();
+ parser.accepts(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_HOST,
+ "Bitcoind rpc accepted incoming host for block notifications")
+ .withRequiredArg();
+
parser.accepts(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA,
format("If set to true the blockchain data from RPC requests to Bitcoin Core are " +
"stored as json file in the data dir. (default: %s)", "false"))
diff --git a/core/src/main/java/bisq/core/app/BisqSetup.java b/core/src/main/java/bisq/core/app/BisqSetup.java
index cbeeca5f08a..a77eafa8768 100644
--- a/core/src/main/java/bisq/core/app/BisqSetup.java
+++ b/core/src/main/java/bisq/core/app/BisqSetup.java
@@ -17,12 +17,12 @@
package bisq.core.app;
+import bisq.core.account.sign.SignedWitnessService;
+import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.alert.Alert;
import bisq.core.alert.AlertManager;
import bisq.core.alert.PrivateNotificationManager;
import bisq.core.alert.PrivateNotificationPayload;
-import bisq.core.arbitration.ArbitratorManager;
-import bisq.core.arbitration.DisputeManager;
import bisq.core.btc.Balances;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.setup.WalletsSetup;
@@ -41,11 +41,15 @@
import bisq.core.notifications.alerts.market.MarketAlerts;
import bisq.core.notifications.alerts.price.PriceAlert;
import bisq.core.offer.OpenOfferManager;
-import bisq.core.payment.AccountAgeWitnessService;
import bisq.core.payment.PaymentAccount;
import bisq.core.payment.TradeLimits;
import bisq.core.provider.fee.FeeService;
import bisq.core.provider.price.PriceFeedService;
+import bisq.core.support.dispute.arbitration.ArbitrationManager;
+import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
+import bisq.core.support.dispute.mediation.MediationManager;
+import bisq.core.support.dispute.mediation.mediator.MediatorManager;
+import bisq.core.support.traderchat.TraderChatManager;
import bisq.core.trade.TradeManager;
import bisq.core.trade.statistics.AssetTradeActivityCheck;
import bisq.core.trade.statistics.TradeStatisticsManager;
@@ -58,7 +62,7 @@
import bisq.network.p2p.P2PService;
import bisq.network.p2p.peers.keepalive.messages.Ping;
-import bisq.common.Clock;
+import bisq.common.ClockWatcher;
import bisq.common.Timer;
import bisq.common.UserThread;
import bisq.common.app.DevEnv;
@@ -72,6 +76,7 @@
import org.bitcoinj.core.Coin;
import javax.inject.Inject;
+import javax.inject.Singleton;
import com.google.common.net.InetAddresses;
@@ -109,6 +114,7 @@
import javax.annotation.Nullable;
@Slf4j
+@Singleton
public class BisqSetup {
public interface BisqSetupCompleteListener {
void onSetupComplete();
@@ -124,23 +130,27 @@ public interface BisqSetupCompleteListener {
private final Balances balances;
private final PriceFeedService priceFeedService;
private final ArbitratorManager arbitratorManager;
+ private final MediatorManager mediatorManager;
private final P2PService p2PService;
private final TradeManager tradeManager;
private final OpenOfferManager openOfferManager;
- private final DisputeManager disputeManager;
+ private final ArbitrationManager arbitrationManager;
+ private final MediationManager mediationManager;
+ private final TraderChatManager traderChatManager;
private final Preferences preferences;
private final User user;
private final AlertManager alertManager;
private final PrivateNotificationManager privateNotificationManager;
private final FilterManager filterManager;
private final TradeStatisticsManager tradeStatisticsManager;
- private final Clock clock;
+ private final ClockWatcher clockWatcher;
private final FeeService feeService;
private final DaoSetup daoSetup;
private final EncryptionService encryptionService;
private final KeyRing keyRing;
private final BisqEnvironment bisqEnvironment;
private final AccountAgeWitnessService accountAgeWitnessService;
+ private final SignedWitnessService signedWitnessService;
private final MobileNotificationService mobileNotificationService;
private final MyOfferTakenEvents myOfferTakenEvents;
private final TradeEvents tradeEvents;
@@ -202,23 +212,27 @@ public BisqSetup(P2PNetworkSetup p2PNetworkSetup,
Balances balances,
PriceFeedService priceFeedService,
ArbitratorManager arbitratorManager,
+ MediatorManager mediatorManager,
P2PService p2PService,
TradeManager tradeManager,
OpenOfferManager openOfferManager,
- DisputeManager disputeManager,
+ ArbitrationManager arbitrationManager,
+ MediationManager mediationManager,
+ TraderChatManager traderChatManager,
Preferences preferences,
User user,
AlertManager alertManager,
PrivateNotificationManager privateNotificationManager,
FilterManager filterManager,
TradeStatisticsManager tradeStatisticsManager,
- Clock clock,
+ ClockWatcher clockWatcher,
FeeService feeService,
DaoSetup daoSetup,
EncryptionService encryptionService,
KeyRing keyRing,
BisqEnvironment bisqEnvironment,
AccountAgeWitnessService accountAgeWitnessService,
+ SignedWitnessService signedWitnessService,
MobileNotificationService mobileNotificationService,
MyOfferTakenEvents myOfferTakenEvents,
TradeEvents tradeEvents,
@@ -242,23 +256,27 @@ public BisqSetup(P2PNetworkSetup p2PNetworkSetup,
this.balances = balances;
this.priceFeedService = priceFeedService;
this.arbitratorManager = arbitratorManager;
+ this.mediatorManager = mediatorManager;
this.p2PService = p2PService;
this.tradeManager = tradeManager;
this.openOfferManager = openOfferManager;
- this.disputeManager = disputeManager;
+ this.arbitrationManager = arbitrationManager;
+ this.mediationManager = mediationManager;
+ this.traderChatManager = traderChatManager;
this.preferences = preferences;
this.user = user;
this.alertManager = alertManager;
this.privateNotificationManager = privateNotificationManager;
this.filterManager = filterManager;
this.tradeStatisticsManager = tradeStatisticsManager;
- this.clock = clock;
+ this.clockWatcher = clockWatcher;
this.feeService = feeService;
this.daoSetup = daoSetup;
this.encryptionService = encryptionService;
this.keyRing = keyRing;
this.bisqEnvironment = bisqEnvironment;
this.accountAgeWitnessService = accountAgeWitnessService;
+ this.signedWitnessService = signedWitnessService;
this.mobileNotificationService = mobileNotificationService;
this.myOfferTakenEvents = myOfferTakenEvents;
this.tradeEvents = tradeEvents;
@@ -283,6 +301,11 @@ public void addBisqSetupCompleteListener(BisqSetupCompleteListener listener) {
}
public void start() {
+ if (log.isDebugEnabled()) {
+ UserThread.runPeriodically(() -> {
+ log.debug("1 second heartbeat");
+ }, 1);
+ }
maybeReSyncSPVChain();
maybeShowTac();
}
@@ -575,12 +598,15 @@ private void checkForLockedUpFunds() {
.filter(e -> tradeManager.getSetOfAllTradeIds().contains(e.getOfferId()) &&
e.getContext() == AddressEntry.Context.MULTI_SIG)
.forEach(e -> {
- final Coin balance = e.getCoinLockedInMultiSig();
- final String message = Res.get("popup.warning.lockedUpFunds",
- formatter.formatCoinWithCode(balance), e.getAddressString(), e.getOfferId());
- log.warn(message);
- if (lockedUpFundsHandler != null)
- lockedUpFundsHandler.accept(message);
+ Coin balance = e.getCoinLockedInMultiSig();
+ if (balance.isPositive()) {
+ String message = Res.get("popup.warning.lockedUpFunds",
+ formatter.formatCoinWithCode(balance), e.getAddressString(), e.getOfferId());
+ log.warn(message);
+ if (lockedUpFundsHandler != null) {
+ lockedUpFundsHandler.accept(message);
+ }
+ }
});
}
@@ -599,11 +625,13 @@ private void checkForCorrectOSArchitecture() {
private void initDomainServices() {
log.info("initDomainServices");
- clock.start();
+ clockWatcher.start();
tradeLimits.onAllServicesInitialized();
- disputeManager.onAllServicesInitialized();
+ arbitrationManager.onAllServicesInitialized();
+ mediationManager.onAllServicesInitialized();
+ traderChatManager.onAllServicesInitialized();
tradeManager.onAllServicesInitialized();
@@ -615,6 +643,7 @@ private void initDomainServices() {
balances.onAllServicesInitialized();
arbitratorManager.onAllServicesInitialized();
+ mediatorManager.onAllServicesInitialized();
alertManager.alertMessageProperty().addListener((observable, oldValue, newValue) ->
displayAlertIfPresent(newValue, false));
@@ -645,6 +674,7 @@ private void initDomainServices() {
assetService.onAllServicesInitialized();
accountAgeWitnessService.onAllServicesInitialized();
+ signedWitnessService.onAllServicesInitialized();
priceFeedService.setCurrencyCodeOnInit();
diff --git a/core/src/main/java/bisq/core/app/P2PNetworkSetup.java b/core/src/main/java/bisq/core/app/P2PNetworkSetup.java
index cbcda4bb3af..76527919dc4 100644
--- a/core/src/main/java/bisq/core/app/P2PNetworkSetup.java
+++ b/core/src/main/java/bisq/core/app/P2PNetworkSetup.java
@@ -28,6 +28,7 @@
import bisq.network.p2p.network.ConnectionListener;
import javax.inject.Inject;
+import javax.inject.Singleton;
import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.monadic.MonadicBinding;
@@ -44,6 +45,7 @@
import javax.annotation.Nullable;
+@Singleton
@Slf4j
public class P2PNetworkSetup {
private final PriceFeedService priceFeedService;
diff --git a/core/src/main/java/bisq/core/app/TorSetup.java b/core/src/main/java/bisq/core/app/TorSetup.java
index 238e23e97a4..669f570ee1c 100644
--- a/core/src/main/java/bisq/core/app/TorSetup.java
+++ b/core/src/main/java/bisq/core/app/TorSetup.java
@@ -25,6 +25,7 @@
import com.google.inject.name.Named;
import javax.inject.Inject;
+import javax.inject.Singleton;
import java.nio.file.Paths;
@@ -36,6 +37,7 @@
import javax.annotation.Nullable;
@Slf4j
+@Singleton
public class TorSetup {
private File torDir;
diff --git a/core/src/main/java/bisq/core/app/WalletAppSetup.java b/core/src/main/java/bisq/core/app/WalletAppSetup.java
index e89df28ab85..f9ad67f2fd8 100644
--- a/core/src/main/java/bisq/core/app/WalletAppSetup.java
+++ b/core/src/main/java/bisq/core/app/WalletAppSetup.java
@@ -28,6 +28,7 @@
import org.bitcoinj.store.ChainFileLockedException;
import javax.inject.Inject;
+import javax.inject.Singleton;
import org.fxmisc.easybind.EasyBind;
import org.fxmisc.easybind.monadic.MonadicBinding;
@@ -50,6 +51,7 @@
import javax.annotation.Nullable;
@Slf4j
+@Singleton
public class WalletAppSetup {
private final WalletsManager walletsManager;
private final WalletsSetup walletsSetup;
diff --git a/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java b/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java
index 07c74d7e760..8c9d54e20b2 100644
--- a/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java
+++ b/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java
@@ -17,10 +17,11 @@
package bisq.core.app.misc;
+import bisq.core.account.sign.SignedWitnessService;
+import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.app.SetupUtils;
import bisq.core.app.TorSetup;
import bisq.core.filter.FilterManager;
-import bisq.core.payment.AccountAgeWitnessService;
import bisq.core.trade.statistics.TradeStatisticsManager;
import bisq.network.crypto.EncryptionService;
@@ -46,6 +47,7 @@
public class AppSetupWithP2P extends AppSetup {
protected final P2PService p2PService;
protected final AccountAgeWitnessService accountAgeWitnessService;
+ private final SignedWitnessService signedWitnessService;
protected final FilterManager filterManager;
private final TorSetup torSetup;
protected BooleanProperty p2pNetWorkReady;
@@ -58,12 +60,14 @@ public AppSetupWithP2P(EncryptionService encryptionService,
P2PService p2PService,
TradeStatisticsManager tradeStatisticsManager,
AccountAgeWitnessService accountAgeWitnessService,
+ SignedWitnessService signedWitnessService,
FilterManager filterManager,
TorSetup torSetup) {
super(encryptionService, keyRing);
this.p2PService = p2PService;
this.tradeStatisticsManager = tradeStatisticsManager;
this.accountAgeWitnessService = accountAgeWitnessService;
+ this.signedWitnessService = signedWitnessService;
this.filterManager = filterManager;
this.torSetup = torSetup;
this.persistedDataHosts = new ArrayList<>();
@@ -184,6 +188,7 @@ protected void onBasicServicesInitialized() {
tradeStatisticsManager.onAllServicesInitialized();
accountAgeWitnessService.onAllServicesInitialized();
+ signedWitnessService.onAllServicesInitialized();
filterManager.onAllServicesInitialized();
}
diff --git a/core/src/main/java/bisq/core/app/misc/AppSetupWithP2PAndDAO.java b/core/src/main/java/bisq/core/app/misc/AppSetupWithP2PAndDAO.java
index 4a2a89c2953..0b0bfa36bd6 100644
--- a/core/src/main/java/bisq/core/app/misc/AppSetupWithP2PAndDAO.java
+++ b/core/src/main/java/bisq/core/app/misc/AppSetupWithP2PAndDAO.java
@@ -17,6 +17,8 @@
package bisq.core.app.misc;
+import bisq.core.account.sign.SignedWitnessService;
+import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.app.TorSetup;
import bisq.core.dao.DaoOptionKeys;
import bisq.core.dao.DaoSetup;
@@ -27,7 +29,6 @@
import bisq.core.dao.governance.proofofburn.MyProofOfBurnListService;
import bisq.core.dao.governance.proposal.MyProposalListService;
import bisq.core.filter.FilterManager;
-import bisq.core.payment.AccountAgeWitnessService;
import bisq.core.trade.statistics.TradeStatisticsManager;
import bisq.network.crypto.EncryptionService;
@@ -50,6 +51,7 @@ public AppSetupWithP2PAndDAO(EncryptionService encryptionService,
P2PService p2PService,
TradeStatisticsManager tradeStatisticsManager,
AccountAgeWitnessService accountAgeWitnessService,
+ SignedWitnessService signedWitnessService,
FilterManager filterManager,
DaoSetup daoSetup,
MyVoteListService myVoteListService,
@@ -65,6 +67,7 @@ public AppSetupWithP2PAndDAO(EncryptionService encryptionService,
p2PService,
tradeStatisticsManager,
accountAgeWitnessService,
+ signedWitnessService,
filterManager,
torSetup);
diff --git a/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java b/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java
index b7738439b86..9b637295035 100644
--- a/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java
+++ b/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java
@@ -20,11 +20,11 @@
import bisq.core.app.AppOptionKeys;
import bisq.core.app.BisqEnvironment;
import bisq.core.app.BisqExecutable;
-import bisq.core.arbitration.ArbitratorManager;
import bisq.core.btc.setup.WalletsSetup;
import bisq.core.btc.wallet.BsqWalletService;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.offer.OpenOfferManager;
+import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
import bisq.network.p2p.P2PService;
diff --git a/core/src/main/java/bisq/core/app/misc/ModuleForAppWithP2p.java b/core/src/main/java/bisq/core/app/misc/ModuleForAppWithP2p.java
index 35413918c2d..bf9050f2716 100644
--- a/core/src/main/java/bisq/core/app/misc/ModuleForAppWithP2p.java
+++ b/core/src/main/java/bisq/core/app/misc/ModuleForAppWithP2p.java
@@ -21,7 +21,6 @@
import bisq.core.app.AppOptionKeys;
import bisq.core.app.BisqEnvironment;
import bisq.core.app.TorSetup;
-import bisq.core.arbitration.ArbitratorModule;
import bisq.core.btc.BitcoinModule;
import bisq.core.dao.DaoModule;
import bisq.core.filter.FilterModule;
@@ -38,11 +37,13 @@
import bisq.network.p2p.network.BridgeAddressProvider;
import bisq.network.p2p.seed.SeedNodeRepository;
-import bisq.common.Clock;
+import bisq.common.ClockWatcher;
import bisq.common.CommonOptionKeys;
import bisq.common.app.AppModule;
import bisq.common.crypto.KeyRing;
import bisq.common.crypto.KeyStorage;
+import bisq.common.crypto.PubKeyRing;
+import bisq.common.crypto.PubKeyRingProvider;
import bisq.common.proto.network.NetworkProtoResolver;
import bisq.common.proto.persistable.PersistenceProtoResolver;
import bisq.common.storage.Storage;
@@ -69,7 +70,7 @@ protected void configure() {
bind(KeyStorage.class).in(Singleton.class);
bind(KeyRing.class).in(Singleton.class);
bind(User.class).in(Singleton.class);
- bind(Clock.class).in(Singleton.class);
+ bind(ClockWatcher.class).in(Singleton.class);
bind(NetworkProtoResolver.class).to(CoreNetworkProtoResolver.class).in(Singleton.class);
bind(PersistenceProtoResolver.class).to(CorePersistenceProtoResolver.class).in(Singleton.class);
bind(Preferences.class).in(Singleton.class);
@@ -96,13 +97,14 @@ protected void configure() {
// ordering is used for shut down sequence
install(tradeModule());
install(encryptionServiceModule());
- install(arbitratorModule());
install(offerModule());
install(p2pModule());
install(bitcoinModule());
install(daoModule());
install(alertModule());
install(filterModule());
+ bind(PubKeyRing.class).toProvider(PubKeyRingProvider.class);
+
}
protected void configEnvironment() {
@@ -117,10 +119,6 @@ protected EncryptionServiceModule encryptionServiceModule() {
return new EncryptionServiceModule(environment);
}
- protected ArbitratorModule arbitratorModule() {
- return new ArbitratorModule(environment);
- }
-
protected AlertModule alertModule() {
return new AlertModule(environment);
}
diff --git a/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java b/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java
deleted file mode 100644
index f9809d6c489..00000000000
--- a/core/src/main/java/bisq/core/arbitration/ArbitratorManager.java
+++ /dev/null
@@ -1,375 +0,0 @@
-/*
- * 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 .
- */
-
-package bisq.core.arbitration;
-
-import bisq.core.app.AppOptionKeys;
-import bisq.core.filter.FilterManager;
-import bisq.core.user.Preferences;
-import bisq.core.user.User;
-
-import bisq.network.p2p.BootstrapListener;
-import bisq.network.p2p.NodeAddress;
-import bisq.network.p2p.P2PService;
-import bisq.network.p2p.storage.HashMapChangedListener;
-import bisq.network.p2p.storage.payload.ProtectedStorageEntry;
-
-import bisq.common.Timer;
-import bisq.common.UserThread;
-import bisq.common.app.DevEnv;
-import bisq.common.crypto.KeyRing;
-import bisq.common.handlers.ErrorMessageHandler;
-import bisq.common.handlers.ResultHandler;
-import bisq.common.util.Utilities;
-
-import org.bitcoinj.core.ECKey;
-import org.bitcoinj.core.Utils;
-
-import com.google.inject.Inject;
-import com.google.inject.name.Named;
-
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableMap;
-
-import java.security.PublicKey;
-import java.security.SignatureException;
-
-import java.math.BigInteger;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.concurrent.TimeUnit;
-import java.util.function.Function;
-import java.util.stream.Collectors;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import org.jetbrains.annotations.NotNull;
-
-import javax.annotation.Nullable;
-
-import static org.bitcoinj.core.Utils.HEX;
-
-public class ArbitratorManager {
- private static final Logger log = LoggerFactory.getLogger(ArbitratorManager.class);
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Static
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- private static final long REPUBLISH_MILLIS = Arbitrator.TTL / 2;
- private static final long RETRY_REPUBLISH_SEC = 5;
- private static final long REPEATED_REPUBLISH_AT_STARTUP_SEC = 60;
-
- private final List publicKeys;
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Instance fields
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- private final KeyRing keyRing;
- private final ArbitratorService arbitratorService;
- private final User user;
- private final Preferences preferences;
- private final FilterManager filterManager;
- private final ObservableMap arbitratorsObservableMap = FXCollections.observableHashMap();
- private List persistedAcceptedArbitrators;
- private Timer republishArbitratorTimer, retryRepublishArbitratorTimer;
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Constructor
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- @Inject
- public ArbitratorManager(KeyRing keyRing,
- ArbitratorService arbitratorService,
- User user,
- Preferences preferences,
- FilterManager filterManager,
- @Named(AppOptionKeys.USE_DEV_PRIVILEGE_KEYS) boolean useDevPrivilegeKeys) {
- this.keyRing = keyRing;
- this.arbitratorService = arbitratorService;
- this.user = user;
- this.preferences = preferences;
- this.filterManager = filterManager;
- publicKeys = useDevPrivilegeKeys ?
- Collections.unmodifiableList(Collections.singletonList(DevEnv.DEV_PRIVILEGE_PUB_KEY)) :
- Collections.unmodifiableList(Arrays.asList(
- "0365c6af94681dbee69de1851f98d4684063bf5c2d64b1c73ed5d90434f375a054",
- "031c502a60f9dbdb5ae5e438a79819e4e1f417211dd537ac12c9bc23246534c4bd",
- "02c1e5a242387b6d5319ce27246cea6edaaf51c3550591b528d2578a4753c56c2c",
- "025c319faf7067d9299590dd6c97fe7e56cd4dac61205ccee1cd1fc390142390a2",
- "038f6e24c2bfe5d51d0a290f20a9a657c270b94ef2b9c12cd15ca3725fa798fc55",
- "0255256ff7fb615278c4544a9bbd3f5298b903b8a011cd7889be19b6b1c45cbefe",
- "024a3a37289f08c910fbd925ebc72b946f33feaeff451a4738ee82037b4cda2e95",
- "02a88b75e9f0f8afba1467ab26799dcc38fd7a6468fb2795444b425eb43e2c10bd",
- "02349a51512c1c04c67118386f4d27d768c5195a83247c150a4b722d161722ba81",
- "03f718a2e0dc672c7cdec0113e72c3322efc70412bb95870750d25c32cd98de17d",
- "028ff47ee2c56e66313928975c58fa4f1b19a0f81f3a96c4e9c9c3c6768075509e",
- "02b517c0cbc3a49548f448ddf004ed695c5a1c52ec110be1bfd65fa0ca0761c94b",
- "03df837a3a0f3d858e82f3356b71d1285327f101f7c10b404abed2abc1c94e7169",
- "0203a90fb2ab698e524a5286f317a183a84327b8f8c3f7fa4a98fec9e1cefd6b72",
- "023c99cc073b851c892d8c43329ca3beb5d2213ee87111af49884e3ce66cbd5ba5"
- ));
- }
-
- public void shutDown() {
- stopRepublishArbitratorTimer();
- stopRetryRepublishArbitratorTimer();
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // API
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- public void onAllServicesInitialized() {
- arbitratorService.addHashSetChangedListener(new HashMapChangedListener() {
- @Override
- public void onAdded(ProtectedStorageEntry data) {
- if (data.getProtectedStoragePayload() instanceof Arbitrator)
- updateArbitratorMap();
- }
-
- @Override
- public void onRemoved(ProtectedStorageEntry data) {
- if (data.getProtectedStoragePayload() instanceof Arbitrator) {
- updateArbitratorMap();
- final Arbitrator arbitrator = (Arbitrator) data.getProtectedStoragePayload();
- user.removeAcceptedArbitrator(arbitrator);
- user.removeAcceptedMediator(getMediator(arbitrator));
- }
- }
- });
-
- persistedAcceptedArbitrators = new ArrayList<>(user.getAcceptedArbitrators());
- user.clearAcceptedArbitrators();
-
- // TODO we mirror arbitrator data for mediator as long we have not impl. it in the UI
- user.clearAcceptedMediators();
-
- if (user.getRegisteredArbitrator() != null) {
- P2PService p2PService = arbitratorService.getP2PService();
- if (p2PService.isBootstrapped())
- startRepublishArbitrator();
- else
- p2PService.addP2PServiceListener(new BootstrapListener() {
- @Override
- public void onUpdatedDataReceived() {
- startRepublishArbitrator();
- }
- });
- }
-
- filterManager.filterProperty().addListener((observable, oldValue, newValue) -> updateArbitratorMap());
-
- updateArbitratorMap();
- }
-
- private void startRepublishArbitrator() {
- if (republishArbitratorTimer == null) {
- republishArbitratorTimer = UserThread.runPeriodically(this::republishArbitrator, REPUBLISH_MILLIS, TimeUnit.MILLISECONDS);
- UserThread.runAfter(this::republishArbitrator, REPEATED_REPUBLISH_AT_STARTUP_SEC);
- republishArbitrator();
- }
- }
-
- public void updateArbitratorMap() {
- Map map = arbitratorService.getArbitrators();
- arbitratorsObservableMap.clear();
- Map filtered = map.values().stream()
- .filter(e -> {
- final String pubKeyAsHex = Utils.HEX.encode(e.getRegistrationPubKey());
- final boolean isInPublicKeyInList = isPublicKeyInList(pubKeyAsHex);
- if (!isInPublicKeyInList) {
- if (DevEnv.DEV_PRIVILEGE_PUB_KEY.equals(pubKeyAsHex))
- log.info("We got the DEV_PRIVILEGE_PUB_KEY in our list of publicKeys. RegistrationPubKey={}, nodeAddress={}",
- Utilities.bytesAsHexString(e.getRegistrationPubKey()),
- e.getNodeAddress().getFullAddress());
- else
- log.warn("We got an arbitrator which is not in our list of publicKeys. RegistrationPubKey={}, nodeAddress={}",
- Utilities.bytesAsHexString(e.getRegistrationPubKey()),
- e.getNodeAddress().getFullAddress());
- }
- final boolean isSigValid = verifySignature(e.getPubKeyRing().getSignaturePubKey(),
- e.getRegistrationPubKey(),
- e.getRegistrationSignature());
- if (!isSigValid)
- log.warn("Sig check for arbitrator failed. Arbitrator=", e.toString());
-
- return isInPublicKeyInList && isSigValid;
- })
- .collect(Collectors.toMap(Arbitrator::getNodeAddress, Function.identity()));
-
- arbitratorsObservableMap.putAll(filtered);
- arbitratorsObservableMap.values().stream()
- .filter(persistedAcceptedArbitrators::contains)
- .forEach(a -> {
- user.addAcceptedArbitrator(a);
- user.addAcceptedMediator(getMediator(a)
- );
- });
-
- // We keep the domain with storing the arbitrators in user as it might be still useful for mediators
- arbitratorsObservableMap.values().forEach(a -> {
- user.addAcceptedArbitrator(a);
- user.addAcceptedMediator(getMediator(a)
- );
- });
-
- log.info("Available arbitrators: {}", arbitratorsObservableMap.keySet());
- }
-
- // TODO we mirror arbitrator data for mediator as long we have not impl. it in the UI
- @NotNull
- public static Mediator getMediator(Arbitrator arbitrator) {
- return new Mediator(arbitrator.getNodeAddress(),
- arbitrator.getPubKeyRing(),
- arbitrator.getLanguageCodes(),
- arbitrator.getRegistrationDate(),
- arbitrator.getRegistrationPubKey(),
- arbitrator.getRegistrationSignature(),
- arbitrator.getEmailAddress(),
- null,
- arbitrator.getExtraDataMap());
- }
-
- public void addArbitrator(Arbitrator arbitrator, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
- user.setRegisteredArbitrator(arbitrator);
- arbitratorsObservableMap.put(arbitrator.getNodeAddress(), arbitrator);
- arbitratorService.addArbitrator(arbitrator,
- () -> {
- log.debug("Arbitrator successfully saved in P2P network");
- resultHandler.handleResult();
-
- if (arbitratorsObservableMap.size() > 0)
- UserThread.runAfter(this::updateArbitratorMap, 100, TimeUnit.MILLISECONDS);
- },
- errorMessageHandler::handleErrorMessage);
- }
-
- public void removeArbitrator(ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
- Arbitrator registeredArbitrator = user.getRegisteredArbitrator();
- if (registeredArbitrator != null) {
- user.setRegisteredArbitrator(null);
- arbitratorsObservableMap.remove(registeredArbitrator.getNodeAddress());
- arbitratorService.removeArbitrator(registeredArbitrator,
- () -> {
- log.debug("Arbitrator successfully removed from P2P network");
- resultHandler.handleResult();
- },
- errorMessageHandler::handleErrorMessage);
- }
- }
-
- public ObservableMap getArbitratorsObservableMap() {
- return arbitratorsObservableMap;
- }
-
- // A private key is handed over to selected arbitrators for registration.
- // An invited arbitrator will sign at registration his storageSignaturePubKey with that private key and attach the signature and pubKey to his data.
- // Other users will check the signature with the list of public keys hardcoded in the app.
- public String signStorageSignaturePubKey(ECKey key) {
- String keyToSignAsHex = Utils.HEX.encode(keyRing.getPubKeyRing().getSignaturePubKey().getEncoded());
- return key.signMessage(keyToSignAsHex);
- }
-
- @Nullable
- public ECKey getRegistrationKey(String privKeyBigIntString) {
- try {
- return ECKey.fromPrivate(new BigInteger(1, HEX.decode(privKeyBigIntString)));
- } catch (Throwable t) {
- return null;
- }
- }
-
- public boolean isPublicKeyInList(String pubKeyAsHex) {
- return publicKeys.contains(pubKeyAsHex);
- }
-
- public boolean isArbitratorAvailableForLanguage(String languageCode) {
- return arbitratorsObservableMap.values().stream().anyMatch(arbitrator ->
- arbitrator.getLanguageCodes().stream().anyMatch(lc -> lc.equals(languageCode)));
- }
-
- public List getArbitratorLanguages(List nodeAddresses) {
- return arbitratorsObservableMap.values().stream()
- .filter(arbitrator -> nodeAddresses.stream().anyMatch(nodeAddress -> nodeAddress.equals(arbitrator.getNodeAddress())))
- .flatMap(arbitrator -> arbitrator.getLanguageCodes().stream())
- .distinct()
- .collect(Collectors.toList());
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Private
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- private void republishArbitrator() {
- Arbitrator registeredArbitrator = user.getRegisteredArbitrator();
- if (registeredArbitrator != null) {
- addArbitrator(registeredArbitrator,
- this::updateArbitratorMap,
- errorMessage -> {
- if (retryRepublishArbitratorTimer == null)
- retryRepublishArbitratorTimer = UserThread.runPeriodically(() -> {
- stopRetryRepublishArbitratorTimer();
- republishArbitrator();
- }, RETRY_REPUBLISH_SEC);
- }
- );
- }
- }
-
- private boolean verifySignature(PublicKey storageSignaturePubKey, byte[] registrationPubKey, String signature) {
- String keyToSignAsHex = Utils.HEX.encode(storageSignaturePubKey.getEncoded());
- try {
- ECKey key = ECKey.fromPublicOnly(registrationPubKey);
- key.verifyMessage(keyToSignAsHex, signature);
- return true;
- } catch (SignatureException e) {
- log.warn("verifySignature failed");
- return false;
- }
- }
-
-
- private void stopRetryRepublishArbitratorTimer() {
- if (retryRepublishArbitratorTimer != null) {
- retryRepublishArbitratorTimer.stop();
- retryRepublishArbitratorTimer = null;
- }
- }
-
- private void stopRepublishArbitratorTimer() {
- if (republishArbitratorTimer != null) {
- republishArbitratorTimer.stop();
- republishArbitratorTimer = null;
- }
- }
-
- public Optional getArbitratorByNodeAddress(NodeAddress nodeAddress) {
- return arbitratorsObservableMap.containsKey(nodeAddress) ?
- Optional.of(arbitratorsObservableMap.get(nodeAddress)) :
- Optional.empty();
- }
-}
diff --git a/core/src/main/java/bisq/core/arbitration/ArbitratorService.java b/core/src/main/java/bisq/core/arbitration/ArbitratorService.java
deleted file mode 100644
index 8e781cc5c10..00000000000
--- a/core/src/main/java/bisq/core/arbitration/ArbitratorService.java
+++ /dev/null
@@ -1,123 +0,0 @@
-/*
- * 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 .
- */
-
-package bisq.core.arbitration;
-
-import bisq.core.app.BisqEnvironment;
-import bisq.core.filter.FilterManager;
-
-import bisq.network.p2p.NodeAddress;
-import bisq.network.p2p.P2PService;
-import bisq.network.p2p.storage.HashMapChangedListener;
-
-import bisq.common.app.DevEnv;
-import bisq.common.handlers.ErrorMessageHandler;
-import bisq.common.handlers.ResultHandler;
-import bisq.common.util.Utilities;
-
-import javax.inject.Inject;
-
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-/**
- * Used to store arbitrators profile and load map of arbitrators
- */
-public class ArbitratorService {
- private static final Logger log = LoggerFactory.getLogger(ArbitratorService.class);
-
- private final P2PService p2PService;
- private final FilterManager filterManager;
-
- interface ArbitratorMapResultHandler {
- void handleResult(Map arbitratorsMap);
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Constructor
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- @Inject
- public ArbitratorService(P2PService p2PService, FilterManager filterManager) {
- this.p2PService = p2PService;
- this.filterManager = filterManager;
- }
-
- public void addHashSetChangedListener(HashMapChangedListener hashMapChangedListener) {
- p2PService.addHashSetChangedListener(hashMapChangedListener);
- }
-
- public void addArbitrator(Arbitrator arbitrator, final ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
- log.debug("addArbitrator arbitrator.hashCode() " + arbitrator.hashCode());
- if (!BisqEnvironment.getBaseCurrencyNetwork().isMainnet() ||
- !Utilities.encodeToHex(arbitrator.getRegistrationPubKey()).equals(DevEnv.DEV_PRIVILEGE_PUB_KEY)) {
- boolean result = p2PService.addProtectedStorageEntry(arbitrator, true);
- if (result) {
- log.trace("Add arbitrator to network was successful. Arbitrator.hashCode() = " + arbitrator.hashCode());
- resultHandler.handleResult();
- } else {
- errorMessageHandler.handleErrorMessage("Add arbitrator failed");
- }
- } else {
- log.error("Attempt to publish dev arbitrator on mainnet.");
- errorMessageHandler.handleErrorMessage("Add arbitrator failed. Attempt to publish dev arbitrator on mainnet.");
- }
- }
-
- public void removeArbitrator(Arbitrator arbitrator, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
- log.debug("removeArbitrator arbitrator.hashCode() " + arbitrator.hashCode());
- if (p2PService.removeData(arbitrator, true)) {
- log.trace("Remove arbitrator from network was successful. Arbitrator.hashCode() = " + arbitrator.hashCode());
- resultHandler.handleResult();
- } else {
- errorMessageHandler.handleErrorMessage("Remove arbitrator failed");
- }
- }
-
- P2PService getP2PService() {
- return p2PService;
- }
-
- public Map getArbitrators() {
- final List bannedArbitrators = filterManager.getFilter() != null ? filterManager.getFilter().getArbitrators() : null;
- if (bannedArbitrators != null)
- log.warn("bannedArbitrators=" + bannedArbitrators);
- Set arbitratorSet = p2PService.getDataMap().values().stream()
- .filter(data -> data.getProtectedStoragePayload() instanceof Arbitrator)
- .map(data -> (Arbitrator) data.getProtectedStoragePayload())
- .filter(a -> bannedArbitrators == null ||
- !bannedArbitrators.contains(a.getNodeAddress().getFullAddress()))
- .collect(Collectors.toSet());
-
- Map map = new HashMap<>();
- for (Arbitrator arbitrator : arbitratorSet) {
- NodeAddress arbitratorNodeAddress = arbitrator.getNodeAddress();
- if (!map.containsKey(arbitratorNodeAddress))
- map.put(arbitratorNodeAddress, arbitrator);
- else
- log.warn("arbitratorAddress already exist in arbitrator map. Seems an arbitrator object is already registered with the same address.");
- }
- return map;
- }
-}
diff --git a/core/src/main/java/bisq/core/arbitration/DisputeManager.java b/core/src/main/java/bisq/core/arbitration/DisputeManager.java
deleted file mode 100644
index ed1a665bd5d..00000000000
--- a/core/src/main/java/bisq/core/arbitration/DisputeManager.java
+++ /dev/null
@@ -1,1157 +0,0 @@
-/*
- * 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 .
- */
-
-package bisq.core.arbitration;
-
-import bisq.core.arbitration.messages.DisputeCommunicationMessage;
-import bisq.core.arbitration.messages.DisputeMessage;
-import bisq.core.arbitration.messages.DisputeResultMessage;
-import bisq.core.arbitration.messages.OpenNewDisputeMessage;
-import bisq.core.arbitration.messages.PeerOpenedDisputeMessage;
-import bisq.core.arbitration.messages.PeerPublishedDisputePayoutTxMessage;
-import bisq.core.btc.exceptions.TransactionVerificationException;
-import bisq.core.btc.exceptions.TxBroadcastException;
-import bisq.core.btc.exceptions.WalletException;
-import bisq.core.btc.setup.WalletsSetup;
-import bisq.core.btc.wallet.BtcWalletService;
-import bisq.core.btc.wallet.TradeWalletService;
-import bisq.core.btc.wallet.TxBroadcaster;
-import bisq.core.locale.Res;
-import bisq.core.offer.OpenOffer;
-import bisq.core.offer.OpenOfferManager;
-import bisq.core.trade.Contract;
-import bisq.core.trade.Tradable;
-import bisq.core.trade.Trade;
-import bisq.core.trade.TradeManager;
-import bisq.core.trade.closed.ClosedTradableManager;
-
-import bisq.network.p2p.AckMessage;
-import bisq.network.p2p.AckMessageSourceType;
-import bisq.network.p2p.BootstrapListener;
-import bisq.network.p2p.DecryptedMessageWithPubKey;
-import bisq.network.p2p.NodeAddress;
-import bisq.network.p2p.P2PService;
-import bisq.network.p2p.SendMailboxMessageListener;
-
-import bisq.common.Timer;
-import bisq.common.UserThread;
-import bisq.common.app.Version;
-import bisq.common.crypto.KeyRing;
-import bisq.common.crypto.PubKeyRing;
-import bisq.common.handlers.FaultHandler;
-import bisq.common.handlers.ResultHandler;
-import bisq.common.proto.network.NetworkEnvelope;
-import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.proto.persistable.PersistenceProtoResolver;
-import bisq.common.storage.Storage;
-import bisq.common.util.Tuple2;
-
-import org.bitcoinj.core.AddressFormatException;
-import org.bitcoinj.core.Transaction;
-import org.bitcoinj.crypto.DeterministicKey;
-
-import com.google.inject.Inject;
-
-import javax.inject.Named;
-
-import org.fxmisc.easybind.EasyBind;
-import org.fxmisc.easybind.Subscription;
-
-import javafx.beans.property.IntegerProperty;
-import javafx.beans.property.SimpleIntegerProperty;
-
-import javafx.collections.ListChangeListener;
-import javafx.collections.ObservableList;
-
-import java.io.File;
-
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.UUID;
-import java.util.concurrent.CopyOnWriteArraySet;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-
-import lombok.Getter;
-
-import javax.annotation.Nullable;
-
-public class DisputeManager implements PersistedDataHost {
- private static final Logger log = LoggerFactory.getLogger(DisputeManager.class);
-
- private final TradeWalletService tradeWalletService;
- private final BtcWalletService walletService;
- private final WalletsSetup walletsSetup;
- private final TradeManager tradeManager;
- private final ClosedTradableManager closedTradableManager;
- private final OpenOfferManager openOfferManager;
- private final P2PService p2PService;
- private final KeyRing keyRing;
- private final Storage disputeStorage;
- private DisputeList disputes;
- private final String disputeInfo;
- private final CopyOnWriteArraySet decryptedMailboxMessageWithPubKeys = new CopyOnWriteArraySet<>();
- private final CopyOnWriteArraySet decryptedDirectMessageWithPubKeys = new CopyOnWriteArraySet<>();
- private final Map openDisputes;
- private final Map closedDisputes;
- private final Map delayMsgMap = new HashMap<>();
-
- private final Map disputeIsClosedSubscriptionsMap = new HashMap<>();
- @Getter
- private final IntegerProperty numOpenDisputes = new SimpleIntegerProperty();
- private boolean servicesInitialized;
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Constructor
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- @Inject
- public DisputeManager(P2PService p2PService,
- TradeWalletService tradeWalletService,
- BtcWalletService walletService,
- WalletsSetup walletsSetup,
- TradeManager tradeManager,
- ClosedTradableManager closedTradableManager,
- OpenOfferManager openOfferManager,
- KeyRing keyRing,
- PersistenceProtoResolver persistenceProtoResolver,
- @Named(Storage.STORAGE_DIR) File storageDir) {
- this.p2PService = p2PService;
- this.tradeWalletService = tradeWalletService;
- this.walletService = walletService;
- this.walletsSetup = walletsSetup;
- this.tradeManager = tradeManager;
- this.closedTradableManager = closedTradableManager;
- this.openOfferManager = openOfferManager;
- this.keyRing = keyRing;
-
- disputeStorage = new Storage<>(storageDir, persistenceProtoResolver);
-
- openDisputes = new HashMap<>();
- closedDisputes = new HashMap<>();
-
- disputeInfo = Res.get("support.initialInfo");
-
- // We get first the message handler called then the onBootstrapped
- p2PService.addDecryptedDirectMessageListener((decryptedMessageWithPubKey, senderAddress) -> {
- decryptedDirectMessageWithPubKeys.add(decryptedMessageWithPubKey);
- tryApplyMessages();
- });
- p2PService.addDecryptedMailboxListener((decryptedMessageWithPubKey, senderAddress) -> {
- decryptedMailboxMessageWithPubKeys.add(decryptedMessageWithPubKey);
- tryApplyMessages();
- });
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // API
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- @Override
- public void readPersisted() {
- disputes = new DisputeList(disputeStorage);
- disputes.readPersisted();
- disputes.stream().forEach(dispute -> dispute.setStorage(disputeStorage));
- }
-
- public void onAllServicesInitialized() {
- servicesInitialized = true;
- p2PService.addP2PServiceListener(new BootstrapListener() {
- @Override
- public void onUpdatedDataReceived() {
- tryApplyMessages();
- }
- });
-
- walletsSetup.downloadPercentageProperty().addListener((observable, oldValue, newValue) -> {
- if (walletsSetup.isDownloadComplete())
- tryApplyMessages();
- });
-
- walletsSetup.numPeersProperty().addListener((observable, oldValue, newValue) -> {
- if (walletsSetup.hasSufficientPeersForBroadcast())
- tryApplyMessages();
- });
-
- tryApplyMessages();
-
- cleanupDisputes();
-
- disputes.getList().addListener((ListChangeListener) change -> {
- change.next();
- onDisputesChangeListener(change.getAddedSubList(), change.getRemoved());
- });
- onDisputesChangeListener(disputes.getList(), null);
- }
-
- private void onDisputesChangeListener(List extends Dispute> addedList, @Nullable List extends Dispute> removedList) {
- if (removedList != null) {
- removedList.forEach(dispute -> {
- String id = dispute.getId();
- if (disputeIsClosedSubscriptionsMap.containsKey(id)) {
- disputeIsClosedSubscriptionsMap.get(id).unsubscribe();
- disputeIsClosedSubscriptionsMap.remove(id);
- }
- });
- }
- addedList.forEach(dispute -> {
- String id = dispute.getId();
- Subscription disputeStateSubscription = EasyBind.subscribe(dispute.isClosedProperty(),
- isClosed -> {
- // We get the event before the list gets updated, so we execute on next frame
- UserThread.execute(() -> {
- int openDisputes = disputes.getList().stream()
- .filter(e -> !e.isClosed())
- .collect(Collectors.toList()).size();
- numOpenDisputes.set(openDisputes);
- });
- });
- disputeIsClosedSubscriptionsMap.put(id, disputeStateSubscription);
- });
- }
-
- public void cleanupDisputes() {
- disputes.stream().forEach(dispute -> {
- dispute.setStorage(disputeStorage);
- if (dispute.isClosed())
- closedDisputes.put(dispute.getTradeId(), dispute);
- else
- openDisputes.put(dispute.getTradeId(), dispute);
- });
-
- // If we have duplicate disputes we close the second one (might happen if both traders opened a dispute and arbitrator
- // was offline, so could not forward msg to other peer, then the arbitrator might have 4 disputes open for 1 trade)
- openDisputes.forEach((key, openDispute) -> {
- if (closedDisputes.containsKey(key)) {
- final Dispute closedDispute = closedDisputes.get(key);
- // We need to check if is from the same peer, we don't want to close the peers dispute
- if (closedDispute.getTraderId() == openDispute.getTraderId()) {
- openDispute.setIsClosed(true);
- tradeManager.closeDisputedTrade(openDispute.getTradeId());
- }
- }
- });
- }
-
- private void tryApplyMessages() {
- if (isReadyForTxBroadcast())
- applyMessages();
- }
-
- private boolean isReadyForTxBroadcast() {
- // Some messages can't be handled until all the services are properly initialized.
- // In particular it's not possible to complete the signing of a dispute payout
- // by an encrypted wallet until after it's been decrypted.
- return p2PService.isBootstrapped() &&
- walletsSetup.isDownloadComplete() &&
- walletsSetup.hasSufficientPeersForBroadcast() &&
- servicesInitialized;
- }
-
- private void applyMessages() {
- decryptedDirectMessageWithPubKeys.forEach(decryptedMessageWithPubKey -> {
- NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope();
- if (networkEnvelope instanceof DisputeMessage) {
- dispatchMessage((DisputeMessage) networkEnvelope);
- } else if (networkEnvelope instanceof AckMessage) {
- processAckMessage((AckMessage) networkEnvelope, null);
- }
- });
- decryptedDirectMessageWithPubKeys.clear();
-
- decryptedMailboxMessageWithPubKeys.forEach(decryptedMessageWithPubKey -> {
- NetworkEnvelope networkEnvelope = decryptedMessageWithPubKey.getNetworkEnvelope();
- log.debug("decryptedMessageWithPubKey.message " + networkEnvelope);
- if (networkEnvelope instanceof DisputeMessage) {
- dispatchMessage((DisputeMessage) networkEnvelope);
- p2PService.removeEntryFromMailbox(decryptedMessageWithPubKey);
- } else if (networkEnvelope instanceof AckMessage) {
- processAckMessage((AckMessage) networkEnvelope, decryptedMessageWithPubKey);
- }
- });
- decryptedMailboxMessageWithPubKeys.clear();
- }
-
- private void processAckMessage(AckMessage ackMessage, @Nullable DecryptedMessageWithPubKey decryptedMessageWithPubKey) {
- if (ackMessage.getSourceType() == AckMessageSourceType.DISPUTE_MESSAGE) {
- if (ackMessage.isSuccess()) {
- log.info("Received AckMessage for {} with tradeId {} and uid {}",
- ackMessage.getSourceMsgClassName(), ackMessage.getSourceId(), ackMessage.getSourceUid());
- } else {
- log.warn("Received AckMessage with error state for {} with tradeId {} and errorMessage={}",
- ackMessage.getSourceMsgClassName(), ackMessage.getSourceId(), ackMessage.getErrorMessage());
- }
-
- disputes.getList().stream()
- .flatMap(dispute -> dispute.getDisputeCommunicationMessages().stream())
- .filter(msg -> msg.getUid().equals(ackMessage.getSourceUid()))
- .forEach(msg -> {
- if (ackMessage.isSuccess())
- msg.setAcknowledged(true);
- else
- msg.setAckError(ackMessage.getErrorMessage());
- });
- disputes.persist();
-
- if (decryptedMessageWithPubKey != null)
- p2PService.removeEntryFromMailbox(decryptedMessageWithPubKey);
- }
- }
-
- private void dispatchMessage(DisputeMessage message) {
- log.info("Received {} with tradeId {} and uid {}",
- message.getClass().getSimpleName(), message.getTradeId(), message.getUid());
-
- if (message instanceof OpenNewDisputeMessage)
- onOpenNewDisputeMessage((OpenNewDisputeMessage) message);
- else if (message instanceof PeerOpenedDisputeMessage)
- onPeerOpenedDisputeMessage((PeerOpenedDisputeMessage) message);
- else if (message instanceof DisputeCommunicationMessage)
- onDisputeDirectMessage((DisputeCommunicationMessage) message);
- else if (message instanceof DisputeResultMessage)
- onDisputeResultMessage((DisputeResultMessage) message);
- else if (message instanceof PeerPublishedDisputePayoutTxMessage)
- onDisputedPayoutTxMessage((PeerPublishedDisputePayoutTxMessage) message);
- else
- log.warn("Unsupported message at dispatchMessage.\nmessage=" + message);
- }
-
- public void sendOpenNewDisputeMessage(Dispute dispute, boolean reOpen, ResultHandler resultHandler, FaultHandler faultHandler) {
- if (!disputes.contains(dispute)) {
- final Optional storedDisputeOptional = findDispute(dispute.getTradeId(), dispute.getTraderId());
- if (!storedDisputeOptional.isPresent() || reOpen) {
- String sysMsg = dispute.isSupportTicket() ?
- Res.get("support.youOpenedTicket", disputeInfo, Version.VERSION)
- : Res.get("support.youOpenedDispute", disputeInfo, Version.VERSION);
-
- DisputeCommunicationMessage disputeCommunicationMessage = new DisputeCommunicationMessage(
- dispute.getTradeId(),
- keyRing.getPubKeyRing().hashCode(),
- false,
- Res.get("support.systemMsg", sysMsg),
- p2PService.getAddress()
- );
- disputeCommunicationMessage.setSystemMessage(true);
- dispute.addDisputeCommunicationMessage(disputeCommunicationMessage);
- if (!reOpen) {
- disputes.add(dispute);
- }
-
- NodeAddress peersNodeAddress = dispute.getContract().getArbitratorNodeAddress();
- OpenNewDisputeMessage openNewDisputeMessage = new OpenNewDisputeMessage(dispute, p2PService.getAddress(),
- UUID.randomUUID().toString());
- log.info("Send {} to peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
- "disputeCommunicationMessage.uid={}",
- openNewDisputeMessage.getClass().getSimpleName(), peersNodeAddress,
- openNewDisputeMessage.getTradeId(), openNewDisputeMessage.getUid(),
- disputeCommunicationMessage.getUid());
- p2PService.sendEncryptedMailboxMessage(peersNodeAddress,
- dispute.getArbitratorPubKeyRing(),
- openNewDisputeMessage,
- new SendMailboxMessageListener() {
- @Override
- public void onArrived() {
- log.info("{} arrived at peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
- "disputeCommunicationMessage.uid={}",
- openNewDisputeMessage.getClass().getSimpleName(), peersNodeAddress,
- openNewDisputeMessage.getTradeId(), openNewDisputeMessage.getUid(),
- disputeCommunicationMessage.getUid());
-
- // We use the disputeCommunicationMessage wrapped inside the openNewDisputeMessage for
- // the state, as that is displayed to the user and we only persist that msg
- disputeCommunicationMessage.setArrived(true);
- disputes.persist();
- resultHandler.handleResult();
- }
-
- @Override
- public void onStoredInMailbox() {
- log.info("{} stored in mailbox for peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
- "disputeCommunicationMessage.uid={}",
- openNewDisputeMessage.getClass().getSimpleName(), peersNodeAddress,
- openNewDisputeMessage.getTradeId(), openNewDisputeMessage.getUid(),
- disputeCommunicationMessage.getUid());
-
- // We use the disputeCommunicationMessage wrapped inside the openNewDisputeMessage for
- // the state, as that is displayed to the user and we only persist that msg
- disputeCommunicationMessage.setStoredInMailbox(true);
- disputes.persist();
- resultHandler.handleResult();
- }
-
- @Override
- public void onFault(String errorMessage) {
- log.error("{} failed: Peer {}. tradeId={}, openNewDisputeMessage.uid={}, " +
- "disputeCommunicationMessage.uid={}, errorMessage={}",
- openNewDisputeMessage.getClass().getSimpleName(), peersNodeAddress,
- openNewDisputeMessage.getTradeId(), openNewDisputeMessage.getUid(),
- disputeCommunicationMessage.getUid(), errorMessage);
-
- // We use the disputeCommunicationMessage wrapped inside the openNewDisputeMessage for
- // the state, as that is displayed to the user and we only persist that msg
- disputeCommunicationMessage.setSendMessageError(errorMessage);
- disputes.persist();
- faultHandler.handleFault("Sending dispute message failed: " +
- errorMessage, new MessageDeliveryFailedException());
- }
- }
- );
- } else {
- final String msg = "We got a dispute already open for that trade and trading peer.\n" +
- "TradeId = " + dispute.getTradeId();
- log.warn(msg);
- faultHandler.handleFault(msg, new DisputeAlreadyOpenException());
- }
- } else {
- final String msg = "We got a dispute msg what we have already stored. TradeId = " + dispute.getTradeId();
- log.warn(msg);
- faultHandler.handleFault(msg, new DisputeAlreadyOpenException());
- }
- }
-
- // arbitrator sends that to trading peer when he received openDispute request
- private String sendPeerOpenedDisputeMessage(Dispute disputeFromOpener, Contract contractFromOpener, PubKeyRing pubKeyRing) {
- Dispute dispute = new Dispute(
- disputeStorage,
- disputeFromOpener.getTradeId(),
- pubKeyRing.hashCode(),
- !disputeFromOpener.isDisputeOpenerIsBuyer(),
- !disputeFromOpener.isDisputeOpenerIsMaker(),
- pubKeyRing,
- disputeFromOpener.getTradeDate().getTime(),
- contractFromOpener,
- disputeFromOpener.getContractHash(),
- disputeFromOpener.getDepositTxSerialized(),
- disputeFromOpener.getPayoutTxSerialized(),
- disputeFromOpener.getDepositTxId(),
- disputeFromOpener.getPayoutTxId(),
- disputeFromOpener.getContractAsJson(),
- disputeFromOpener.getMakerContractSignature(),
- disputeFromOpener.getTakerContractSignature(),
- disputeFromOpener.getArbitratorPubKeyRing(),
- disputeFromOpener.isSupportTicket()
- );
- final Optional storedDisputeOptional = findDispute(dispute.getTradeId(), dispute.getTraderId());
- if (!storedDisputeOptional.isPresent()) {
- String sysMsg = dispute.isSupportTicket() ?
- Res.get("support.peerOpenedTicket", disputeInfo)
- : Res.get("support.peerOpenedDispute", disputeInfo);
- DisputeCommunicationMessage disputeCommunicationMessage = new DisputeCommunicationMessage(
- dispute.getTradeId(),
- keyRing.getPubKeyRing().hashCode(),
- false,
- Res.get("support.systemMsg", sysMsg),
- p2PService.getAddress()
- );
- disputeCommunicationMessage.setSystemMessage(true);
- dispute.addDisputeCommunicationMessage(disputeCommunicationMessage);
- disputes.add(dispute);
-
- // we mirrored dispute already!
- Contract contract = dispute.getContract();
- PubKeyRing peersPubKeyRing = dispute.isDisputeOpenerIsBuyer() ? contract.getBuyerPubKeyRing() : contract.getSellerPubKeyRing();
- NodeAddress peersNodeAddress = dispute.isDisputeOpenerIsBuyer() ? contract.getBuyerNodeAddress() : contract.getSellerNodeAddress();
- PeerOpenedDisputeMessage peerOpenedDisputeMessage = new PeerOpenedDisputeMessage(dispute,
- p2PService.getAddress(),
- UUID.randomUUID().toString());
- log.info("Send {} to peer {}. tradeId={}, peerOpenedDisputeMessage.uid={}, " +
- "disputeCommunicationMessage.uid={}",
- peerOpenedDisputeMessage.getClass().getSimpleName(), peersNodeAddress,
- peerOpenedDisputeMessage.getTradeId(), peerOpenedDisputeMessage.getUid(),
- disputeCommunicationMessage.getUid());
- p2PService.sendEncryptedMailboxMessage(peersNodeAddress,
- peersPubKeyRing,
- peerOpenedDisputeMessage,
- new SendMailboxMessageListener() {
- @Override
- public void onArrived() {
- log.info("{} arrived at peer {}. tradeId={}, peerOpenedDisputeMessage.uid={}, " +
- "disputeCommunicationMessage.uid={}",
- peerOpenedDisputeMessage.getClass().getSimpleName(), peersNodeAddress,
- peerOpenedDisputeMessage.getTradeId(), peerOpenedDisputeMessage.getUid(),
- disputeCommunicationMessage.getUid());
-
- // We use the disputeCommunicationMessage wrapped inside the peerOpenedDisputeMessage for
- // the state, as that is displayed to the user and we only persist that msg
- disputeCommunicationMessage.setArrived(true);
- disputes.persist();
- }
-
- @Override
- public void onStoredInMailbox() {
- log.info("{} stored in mailbox for peer {}. tradeId={}, peerOpenedDisputeMessage.uid={}, " +
- "disputeCommunicationMessage.uid={}",
- peerOpenedDisputeMessage.getClass().getSimpleName(), peersNodeAddress,
- peerOpenedDisputeMessage.getTradeId(), peerOpenedDisputeMessage.getUid(),
- disputeCommunicationMessage.getUid());
-
- // We use the disputeCommunicationMessage wrapped inside the peerOpenedDisputeMessage for
- // the state, as that is displayed to the user and we only persist that msg
- disputeCommunicationMessage.setStoredInMailbox(true);
- disputes.persist();
- }
-
- @Override
- public void onFault(String errorMessage) {
- log.error("{} failed: Peer {}. tradeId={}, peerOpenedDisputeMessage.uid={}, " +
- "disputeCommunicationMessage.uid={}, errorMessage={}",
- peerOpenedDisputeMessage.getClass().getSimpleName(), peersNodeAddress,
- peerOpenedDisputeMessage.getTradeId(), peerOpenedDisputeMessage.getUid(),
- disputeCommunicationMessage.getUid(), errorMessage);
-
- // We use the disputeCommunicationMessage wrapped inside the peerOpenedDisputeMessage for
- // the state, as that is displayed to the user and we only persist that msg
- disputeCommunicationMessage.setSendMessageError(errorMessage);
- disputes.persist();
- }
- }
- );
- return null;
- } else {
- String msg = "We got a dispute already open for that trade and trading peer.\n" +
- "TradeId = " + dispute.getTradeId();
- log.warn(msg);
- return msg;
- }
- }
-
- // traders send msg to the arbitrator or arbitrator to 1 trader (trader to trader is not allowed)
- public DisputeCommunicationMessage sendDisputeDirectMessage(Dispute dispute, String text, ArrayList attachments) {
- DisputeCommunicationMessage message = new DisputeCommunicationMessage(
- dispute.getTradeId(),
- dispute.getTraderPubKeyRing().hashCode(),
- isTrader(dispute),
- text,
- p2PService.getAddress()
- );
-
- message.addAllAttachments(attachments);
- Tuple2 tuple = getNodeAddressPubKeyRingTuple(dispute);
- NodeAddress peersNodeAddress = tuple.first;
- PubKeyRing receiverPubKeyRing = tuple.second;
-
- if (isTrader(dispute) ||
- (isArbitrator(dispute) && !message.isSystemMessage()))
- dispute.addDisputeCommunicationMessage(message);
-
- if (receiverPubKeyRing != null) {
- log.info("Send {} to peer {}. tradeId={}, uid={}",
- message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
-
- p2PService.sendEncryptedMailboxMessage(peersNodeAddress,
- receiverPubKeyRing,
- message,
- new SendMailboxMessageListener() {
- @Override
- public void onArrived() {
- log.info("{} arrived at peer {}. tradeId={}, uid={}",
- message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
- message.setArrived(true);
- disputes.persist();
- }
-
- @Override
- public void onStoredInMailbox() {
- log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}",
- message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
- message.setStoredInMailbox(true);
- disputes.persist();
- }
-
- @Override
- public void onFault(String errorMessage) {
- log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}",
- message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage);
- message.setSendMessageError(errorMessage);
- disputes.persist();
- }
- }
- );
- }
-
- return message;
- }
-
- // arbitrator send result to trader
- public void sendDisputeResultMessage(DisputeResult disputeResult, Dispute dispute, String text) {
- DisputeCommunicationMessage disputeCommunicationMessage = new DisputeCommunicationMessage(
- dispute.getTradeId(),
- dispute.getTraderPubKeyRing().hashCode(),
- false,
- text,
- p2PService.getAddress()
- );
-
- dispute.addDisputeCommunicationMessage(disputeCommunicationMessage);
- disputeResult.setDisputeCommunicationMessage(disputeCommunicationMessage);
-
- NodeAddress peersNodeAddress;
- Contract contract = dispute.getContract();
- if (contract.getBuyerPubKeyRing().equals(dispute.getTraderPubKeyRing()))
- peersNodeAddress = contract.getBuyerNodeAddress();
- else
- peersNodeAddress = contract.getSellerNodeAddress();
- DisputeResultMessage disputeResultMessage = new DisputeResultMessage(disputeResult, p2PService.getAddress(),
- UUID.randomUUID().toString());
- log.info("Send {} to peer {}. tradeId={}, disputeResultMessage.uid={}, disputeCommunicationMessage.uid={}",
- disputeResultMessage.getClass().getSimpleName(), peersNodeAddress, disputeResultMessage.getTradeId(),
- disputeResultMessage.getUid(), disputeCommunicationMessage.getUid());
- p2PService.sendEncryptedMailboxMessage(peersNodeAddress,
- dispute.getTraderPubKeyRing(),
- disputeResultMessage,
- new SendMailboxMessageListener() {
- @Override
- public void onArrived() {
- log.info("{} arrived at peer {}. tradeId={}, disputeResultMessage.uid={}, " +
- "disputeCommunicationMessage.uid={}",
- disputeResultMessage.getClass().getSimpleName(), peersNodeAddress,
- disputeResultMessage.getTradeId(), disputeResultMessage.getUid(),
- disputeCommunicationMessage.getUid());
-
- // We use the disputeCommunicationMessage wrapped inside the disputeResultMessage for
- // the state, as that is displayed to the user and we only persist that msg
- disputeCommunicationMessage.setArrived(true);
- disputes.persist();
- }
-
- @Override
- public void onStoredInMailbox() {
- log.info("{} stored in mailbox for peer {}. tradeId={}, disputeResultMessage.uid={}, " +
- "disputeCommunicationMessage.uid={}",
- disputeResultMessage.getClass().getSimpleName(), peersNodeAddress,
- disputeResultMessage.getTradeId(), disputeResultMessage.getUid(),
- disputeCommunicationMessage.getUid());
-
- // We use the disputeCommunicationMessage wrapped inside the disputeResultMessage for
- // the state, as that is displayed to the user and we only persist that msg
- disputeCommunicationMessage.setStoredInMailbox(true);
- disputes.persist();
- }
-
- @Override
- public void onFault(String errorMessage) {
- log.error("{} failed: Peer {}. tradeId={}, disputeResultMessage.uid={}, " +
- "disputeCommunicationMessage.uid={}, errorMessage={}",
- disputeResultMessage.getClass().getSimpleName(), peersNodeAddress,
- disputeResultMessage.getTradeId(), disputeResultMessage.getUid(),
- disputeCommunicationMessage.getUid(), errorMessage);
-
- // We use the disputeCommunicationMessage wrapped inside the disputeResultMessage for
- // the state, as that is displayed to the user and we only persist that msg
- disputeCommunicationMessage.setSendMessageError(errorMessage);
- disputes.persist();
- }
- }
- );
- }
-
- // winner (or buyer in case of 50/50) sends tx to other peer
- private void sendPeerPublishedPayoutTxMessage(Transaction transaction, Dispute dispute, Contract contract) {
- PubKeyRing peersPubKeyRing = dispute.isDisputeOpenerIsBuyer() ? contract.getSellerPubKeyRing() : contract.getBuyerPubKeyRing();
- NodeAddress peersNodeAddress = dispute.isDisputeOpenerIsBuyer() ? contract.getSellerNodeAddress() : contract.getBuyerNodeAddress();
- log.trace("sendPeerPublishedPayoutTxMessage to peerAddress " + peersNodeAddress);
- final PeerPublishedDisputePayoutTxMessage message = new PeerPublishedDisputePayoutTxMessage(transaction.bitcoinSerialize(),
- dispute.getTradeId(),
- p2PService.getAddress(),
- UUID.randomUUID().toString());
- log.info("Send {} to peer {}. tradeId={}, uid={}",
- message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
- p2PService.sendEncryptedMailboxMessage(peersNodeAddress,
- peersPubKeyRing,
- message,
- new SendMailboxMessageListener() {
- @Override
- public void onArrived() {
- log.info("{} arrived at peer {}. tradeId={}, uid={}",
- message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
- }
-
- @Override
- public void onStoredInMailbox() {
- log.info("{} stored in mailbox for peer {}. tradeId={}, uid={}",
- message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid());
- }
-
- @Override
- public void onFault(String errorMessage) {
- log.error("{} failed: Peer {}. tradeId={}, uid={}, errorMessage={}",
- message.getClass().getSimpleName(), peersNodeAddress, message.getTradeId(), message.getUid(), errorMessage);
- }
- }
- );
- }
-
- private void sendAckMessage(DisputeMessage disputeMessage, PubKeyRing peersPubKeyRing,
- boolean result, @Nullable String errorMessage) {
- String tradeId = disputeMessage.getTradeId();
- String uid = disputeMessage.getUid();
- AckMessage ackMessage = new AckMessage(p2PService.getNetworkNode().getNodeAddress(),
- AckMessageSourceType.DISPUTE_MESSAGE,
- disputeMessage.getClass().getSimpleName(),
- uid,
- tradeId,
- result,
- errorMessage);
- final NodeAddress peersNodeAddress = disputeMessage.getSenderNodeAddress();
- log.info("Send AckMessage for {} to peer {}. tradeId={}, uid={}",
- ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, uid);
- p2PService.sendEncryptedMailboxMessage(
- peersNodeAddress,
- peersPubKeyRing,
- ackMessage,
- new SendMailboxMessageListener() {
- @Override
- public void onArrived() {
- log.info("AckMessage for {} arrived at peer {}. tradeId={}, uid={}",
- ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, uid);
- }
-
- @Override
- public void onStoredInMailbox() {
- log.info("AckMessage for {} stored in mailbox for peer {}. tradeId={}, uid={}",
- ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, uid);
- }
-
- @Override
- public void onFault(String errorMessage) {
- log.error("AckMessage for {} failed. Peer {}. tradeId={}, uid={}, errorMessage={}",
- ackMessage.getSourceMsgClassName(), peersNodeAddress, tradeId, uid, errorMessage);
- }
- }
- );
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Incoming message
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- // arbitrator receives that from trader who opens dispute
- private void onOpenNewDisputeMessage(OpenNewDisputeMessage openNewDisputeMessage) {
- String errorMessage;
- Dispute dispute = openNewDisputeMessage.getDispute();
- Contract contractFromOpener = dispute.getContract();
- PubKeyRing peersPubKeyRing = dispute.isDisputeOpenerIsBuyer() ? contractFromOpener.getSellerPubKeyRing() : contractFromOpener.getBuyerPubKeyRing();
- if (isArbitrator(dispute)) {
- if (!disputes.contains(dispute)) {
- final Optional storedDisputeOptional = findDispute(dispute.getTradeId(), dispute.getTraderId());
- if (!storedDisputeOptional.isPresent()) {
- dispute.setStorage(disputeStorage);
- disputes.add(dispute);
- errorMessage = sendPeerOpenedDisputeMessage(dispute, contractFromOpener, peersPubKeyRing);
- } else {
- errorMessage = "We got a dispute already open for that trade and trading peer.\n" +
- "TradeId = " + dispute.getTradeId();
- log.warn(errorMessage);
- }
- } else {
- errorMessage = "We got a dispute msg what we have already stored. TradeId = " + dispute.getTradeId();
- log.warn(errorMessage);
- }
- } else {
- errorMessage = "Trader received openNewDisputeMessage. That must never happen.";
- log.error(errorMessage);
- }
-
- // We use the DisputeCommunicationMessage not the openNewDisputeMessage for the ACK
- ObservableList messages = openNewDisputeMessage.getDispute().getDisputeCommunicationMessages();
- if (!messages.isEmpty()) {
- DisputeCommunicationMessage msg = messages.get(0);
- PubKeyRing sendersPubKeyRing = dispute.isDisputeOpenerIsBuyer() ? contractFromOpener.getBuyerPubKeyRing() : contractFromOpener.getSellerPubKeyRing();
- sendAckMessage(msg, sendersPubKeyRing, errorMessage == null, errorMessage);
- }
- }
-
- // not dispute requester receives that from arbitrator
- private void onPeerOpenedDisputeMessage(PeerOpenedDisputeMessage peerOpenedDisputeMessage) {
- String errorMessage;
- Dispute dispute = peerOpenedDisputeMessage.getDispute();
- if (!isArbitrator(dispute)) {
- if (!disputes.contains(dispute)) {
- final Optional storedDisputeOptional = findDispute(dispute.getTradeId(), dispute.getTraderId());
- if (!storedDisputeOptional.isPresent()) {
- dispute.setStorage(disputeStorage);
- disputes.add(dispute);
- Optional tradeOptional = tradeManager.getTradeById(dispute.getTradeId());
- tradeOptional.ifPresent(trade -> trade.setDisputeState(Trade.DisputeState.DISPUTE_STARTED_BY_PEER));
- errorMessage = null;
- } else {
- errorMessage = "We got a dispute already open for that trade and trading peer.\n" +
- "TradeId = " + dispute.getTradeId();
- log.warn(errorMessage);
- }
- } else {
- errorMessage = "We got a dispute msg what we have already stored. TradeId = " + dispute.getTradeId();
- log.warn(errorMessage);
- }
- } else {
- errorMessage = "Arbitrator received peerOpenedDisputeMessage. That must never happen.";
- log.error(errorMessage);
- }
-
- // We use the DisputeCommunicationMessage not the peerOpenedDisputeMessage for the ACK
- ObservableList messages = peerOpenedDisputeMessage.getDispute().getDisputeCommunicationMessages();
- if (!messages.isEmpty()) {
- DisputeCommunicationMessage msg = messages.get(0);
- sendAckMessage(msg, dispute.getArbitratorPubKeyRing(), errorMessage == null, errorMessage);
- }
-
- sendAckMessage(peerOpenedDisputeMessage, dispute.getArbitratorPubKeyRing(), errorMessage == null, errorMessage);
- }
-
- // A trader can receive a msg from the arbitrator or the arbitrator from a trader. Trader to trader is not allowed.
- private void onDisputeDirectMessage(DisputeCommunicationMessage disputeCommunicationMessage) {
- final String tradeId = disputeCommunicationMessage.getTradeId();
- final String uid = disputeCommunicationMessage.getUid();
- Optional disputeOptional = findDispute(tradeId, disputeCommunicationMessage.getTraderId());
- if (!disputeOptional.isPresent()) {
- log.debug("We got a disputeCommunicationMessage but we don't have a matching dispute. TradeId = " + tradeId);
- if (!delayMsgMap.containsKey(uid)) {
- Timer timer = UserThread.runAfter(() -> onDisputeDirectMessage(disputeCommunicationMessage), 1);
- delayMsgMap.put(uid, timer);
- } else {
- String msg = "We got a disputeCommunicationMessage after we already repeated to apply the message after a delay. That should never happen. TradeId = " + tradeId;
- log.warn(msg);
- }
- return;
- }
-
- cleanupRetryMap(uid);
- Dispute dispute = disputeOptional.get();
- Tuple2 tuple = getNodeAddressPubKeyRingTuple(dispute);
- PubKeyRing receiverPubKeyRing = tuple.second;
-
- if (!dispute.getDisputeCommunicationMessages().contains(disputeCommunicationMessage))
- dispute.addDisputeCommunicationMessage(disputeCommunicationMessage);
- else
- log.warn("We got a disputeCommunicationMessage what we have already stored. TradeId = " + tradeId);
-
- // We never get a errorMessage in that method (only if we cannot resolve the receiverPubKeyRing but then we
- // cannot send it anyway)
- if (receiverPubKeyRing != null)
- sendAckMessage(disputeCommunicationMessage, receiverPubKeyRing, true, null);
- }
-
- // We get that message at both peers. The dispute object is in context of the trader
- private void onDisputeResultMessage(DisputeResultMessage disputeResultMessage) {
- String errorMessage = null;
- boolean success = false;
- PubKeyRing arbitratorsPubKeyRing = null;
- DisputeResult disputeResult = disputeResultMessage.getDisputeResult();
-
- if (isArbitrator(disputeResult)) {
- log.error("Arbitrator received disputeResultMessage. That must never happen.");
- return;
- }
-
- final String tradeId = disputeResult.getTradeId();
- Optional disputeOptional = findDispute(tradeId, disputeResult.getTraderId());
- final String uid = disputeResultMessage.getUid();
- if (!disputeOptional.isPresent()) {
- log.debug("We got a dispute result msg but we don't have a matching dispute. " +
- "That might happen when we get the disputeResultMessage before the dispute was created. " +
- "We try again after 2 sec. to apply the disputeResultMessage. TradeId = " + tradeId);
- if (!delayMsgMap.containsKey(uid)) {
- // We delay2 sec. to be sure the comm. msg gets added first
- Timer timer = UserThread.runAfter(() -> onDisputeResultMessage(disputeResultMessage), 2);
- delayMsgMap.put(uid, timer);
- } else {
- log.warn("We got a dispute result msg after we already repeated to apply the message after a delay. " +
- "That should never happen. TradeId = " + tradeId);
- }
- return;
- }
- Dispute dispute = disputeOptional.get();
- try {
- cleanupRetryMap(uid);
- arbitratorsPubKeyRing = dispute.getArbitratorPubKeyRing();
- DisputeCommunicationMessage disputeCommunicationMessage = disputeResult.getDisputeCommunicationMessage();
- if (!dispute.getDisputeCommunicationMessages().contains(disputeCommunicationMessage))
- dispute.addDisputeCommunicationMessage(disputeCommunicationMessage);
- else if (disputeCommunicationMessage != null)
- log.warn("We got a dispute mail msg what we have already stored. TradeId = " + disputeCommunicationMessage.getTradeId());
-
- dispute.setIsClosed(true);
-
- if (dispute.disputeResultProperty().get() != null)
- log.warn("We got already a dispute result. That should only happen if a dispute needs to be closed " +
- "again because the first close did not succeed. TradeId = " + tradeId);
-
- dispute.setDisputeResult(disputeResult);
-
- // We need to avoid publishing the tx from both traders as it would create problems with zero confirmation withdrawals
- // There would be different transactions if both sign and publish (signers: once buyer+arb, once seller+arb)
- // The tx publisher is the winner or in case both get 50% the buyer, as the buyer has more inventive to publish the tx as he receives
- // more BTC as he has deposited
- final Contract contract = dispute.getContract();
-
- boolean isBuyer = keyRing.getPubKeyRing().equals(contract.getBuyerPubKeyRing());
- DisputeResult.Winner publisher = disputeResult.getWinner();
-
- // Sometimes the user who receives the trade amount is never online, so we might want to
- // let the loser publish the tx. When the winner comes online he gets his funds as it was published by the other peer.
- // Default isLoserPublisher is set to false
- if (disputeResult.isLoserPublisher()) {
- // we invert the logic
- if (publisher == DisputeResult.Winner.BUYER)
- publisher = DisputeResult.Winner.SELLER;
- else if (publisher == DisputeResult.Winner.SELLER)
- publisher = DisputeResult.Winner.BUYER;
- }
-
- if ((isBuyer && publisher == DisputeResult.Winner.BUYER)
- || (!isBuyer && publisher == DisputeResult.Winner.SELLER)) {
-
- final Optional tradeOptional = tradeManager.getTradeById(tradeId);
- Transaction payoutTx = null;
- if (tradeOptional.isPresent()) {
- payoutTx = tradeOptional.get().getPayoutTx();
- } else {
- final Optional tradableOptional = closedTradableManager.getTradableById(tradeId);
- if (tradableOptional.isPresent() && tradableOptional.get() instanceof Trade) {
- payoutTx = ((Trade) tradableOptional.get()).getPayoutTx();
- }
- }
-
- if (payoutTx == null) {
- if (dispute.getDepositTxSerialized() != null) {
- byte[] multiSigPubKey = isBuyer ? contract.getBuyerMultiSigPubKey() : contract.getSellerMultiSigPubKey();
- DeterministicKey multiSigKeyPair = walletService.getMultiSigKeyPair(dispute.getTradeId(), multiSigPubKey);
- Transaction signedDisputedPayoutTx = tradeWalletService.traderSignAndFinalizeDisputedPayoutTx(
- dispute.getDepositTxSerialized(),
- disputeResult.getArbitratorSignature(),
- disputeResult.getBuyerPayoutAmount(),
- disputeResult.getSellerPayoutAmount(),
- contract.getBuyerPayoutAddressString(),
- contract.getSellerPayoutAddressString(),
- multiSigKeyPair,
- contract.getBuyerMultiSigPubKey(),
- contract.getSellerMultiSigPubKey(),
- disputeResult.getArbitratorPubKey()
- );
- Transaction committedDisputedPayoutTx = tradeWalletService.addTxToWallet(signedDisputedPayoutTx);
- tradeWalletService.broadcastTx(committedDisputedPayoutTx, new TxBroadcaster.Callback() {
- @Override
- public void onSuccess(Transaction transaction) {
- // after successful publish we send peer the tx
-
- dispute.setDisputePayoutTxId(transaction.getHashAsString());
- sendPeerPublishedPayoutTxMessage(transaction, dispute, contract);
-
- // set state after payout as we call swapTradeEntryToAvailableEntry
- if (tradeManager.getTradeById(dispute.getTradeId()).isPresent())
- tradeManager.closeDisputedTrade(dispute.getTradeId());
- else {
- Optional openOfferOptional = openOfferManager.getOpenOfferById(dispute.getTradeId());
- openOfferOptional.ifPresent(openOffer -> openOfferManager.closeOpenOffer(openOffer.getOffer()));
- }
- }
-
- @Override
- public void onFailure(TxBroadcastException exception) {
- log.error(exception.getMessage());
- }
- }, 15);
-
- success = true;
- } else {
- errorMessage = "DepositTx is null. TradeId = " + tradeId;
- log.warn(errorMessage);
- success = false;
- }
- } else {
- log.warn("We got already a payout tx. That might be the case if the other peer did not get the " +
- "payout tx and opened a dispute. TradeId = " + tradeId);
- dispute.setDisputePayoutTxId(payoutTx.getHashAsString());
- sendPeerPublishedPayoutTxMessage(payoutTx, dispute, contract);
-
- success = true;
- }
-
- } else {
- log.trace("We don't publish the tx as we are not the winning party.");
- // Clean up tangling trades
- if (dispute.disputeResultProperty().get() != null &&
- dispute.isClosed() &&
- tradeManager.getTradeById(dispute.getTradeId()).isPresent()) {
- tradeManager.closeDisputedTrade(dispute.getTradeId());
- }
-
- success = true;
- }
- } catch (TransactionVerificationException e) {
- errorMessage = "Error at traderSignAndFinalizeDisputedPayoutTx " + e.toString();
- log.error(errorMessage, e);
- success = false;
-
- // We prefer to close the dispute in that case. If there was no deposit tx and a random tx was used
- // we get a TransactionVerificationException. No reason to keep that dispute open...
- if (tradeManager.getTradeById(dispute.getTradeId()).isPresent())
- tradeManager.closeDisputedTrade(dispute.getTradeId());
- else {
- Optional openOfferOptional = openOfferManager.getOpenOfferById(dispute.getTradeId());
- openOfferOptional.ifPresent(openOffer -> openOfferManager.closeOpenOffer(openOffer.getOffer()));
- }
- dispute.setIsClosed(true);
-
- throw new RuntimeException(errorMessage);
- } catch (AddressFormatException | WalletException e) {
- errorMessage = "Error at traderSignAndFinalizeDisputedPayoutTx " + e.toString();
- log.error(errorMessage, e);
- success = false;
- throw new RuntimeException(errorMessage);
- } finally {
- if (arbitratorsPubKeyRing != null) {
- // We use the disputeCommunicationMessage as we only persist those not the disputeResultMessage.
- // If we would use the disputeResultMessage we could not lookup for the msg when we receive the AckMessage.
- DisputeCommunicationMessage disputeCommunicationMessage = disputeResultMessage.getDisputeResult().getDisputeCommunicationMessage();
- sendAckMessage(disputeCommunicationMessage, arbitratorsPubKeyRing, success, errorMessage);
- }
- }
- }
-
- // Losing trader or in case of 50/50 the seller gets the tx sent from the winner or buyer
- private void onDisputedPayoutTxMessage(PeerPublishedDisputePayoutTxMessage peerPublishedDisputePayoutTxMessage) {
- final String uid = peerPublishedDisputePayoutTxMessage.getUid();
- final String tradeId = peerPublishedDisputePayoutTxMessage.getTradeId();
- Optional disputeOptional = findOwnDispute(tradeId);
- if (!disputeOptional.isPresent()) {
- log.debug("We got a peerPublishedPayoutTxMessage but we don't have a matching dispute. TradeId = " + tradeId);
- if (!delayMsgMap.containsKey(uid)) {
- // We delay 3 sec. to be sure the close msg gets added first
- Timer timer = UserThread.runAfter(() -> onDisputedPayoutTxMessage(peerPublishedDisputePayoutTxMessage), 3);
- delayMsgMap.put(uid, timer);
- } else {
- log.warn("We got a peerPublishedPayoutTxMessage after we already repeated to apply the message after a delay. " +
- "That should never happen. TradeId = " + tradeId);
- }
- return;
- }
-
- Dispute dispute = disputeOptional.get();
- final Contract contract = dispute.getContract();
- PubKeyRing ownPubKeyRing = keyRing.getPubKeyRing();
- boolean isBuyer = ownPubKeyRing.equals(contract.getBuyerPubKeyRing());
- PubKeyRing peersPubKeyRing = isBuyer ? contract.getSellerPubKeyRing() : contract.getBuyerPubKeyRing();
-
- cleanupRetryMap(uid);
- Transaction walletTx = tradeWalletService.addTxToWallet(peerPublishedDisputePayoutTxMessage.getTransaction());
- dispute.setDisputePayoutTxId(walletTx.getHashAsString());
- BtcWalletService.printTx("Disputed payoutTx received from peer", walletTx);
-
- // We can only send the ack msg if we have the peersPubKeyRing which requires the dispute
- sendAckMessage(peerPublishedDisputePayoutTxMessage, peersPubKeyRing, true, null);
- }
-
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Getters
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- public Storage getDisputeStorage() {
- return disputeStorage;
- }
-
- public ObservableList getDisputesAsObservableList() {
- return disputes.getList();
- }
-
- public boolean isTrader(Dispute dispute) {
- return keyRing.getPubKeyRing().equals(dispute.getTraderPubKeyRing());
- }
-
- private boolean isArbitrator(Dispute dispute) {
- return keyRing.getPubKeyRing().equals(dispute.getArbitratorPubKeyRing());
- }
-
- private boolean isArbitrator(DisputeResult disputeResult) {
- return Arrays.equals(disputeResult.getArbitratorPubKey(),
- walletService.getArbitratorAddressEntry().getPubKey());
- }
-
- public String getNrOfDisputes(boolean isBuyer, Contract contract) {
- return String.valueOf(getDisputesAsObservableList().stream()
- .filter(e -> {
- Contract contract1 = e.getContract();
- if (contract1 == null)
- return false;
-
- if (isBuyer) {
- NodeAddress buyerNodeAddress = contract1.getBuyerNodeAddress();
- return buyerNodeAddress != null && buyerNodeAddress.equals(contract.getBuyerNodeAddress());
- } else {
- NodeAddress sellerNodeAddress = contract1.getSellerNodeAddress();
- return sellerNodeAddress != null && sellerNodeAddress.equals(contract.getSellerNodeAddress());
- }
- })
- .collect(Collectors.toSet()).size());
- }
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // Utils
- ///////////////////////////////////////////////////////////////////////////////////////////
-
-
- private Tuple2 getNodeAddressPubKeyRingTuple(Dispute dispute) {
- PubKeyRing receiverPubKeyRing = null;
- NodeAddress peerNodeAddress = null;
- if (isTrader(dispute)) {
- receiverPubKeyRing = dispute.getArbitratorPubKeyRing();
- peerNodeAddress = dispute.getContract().getArbitratorNodeAddress();
- } else if (isArbitrator(dispute)) {
- receiverPubKeyRing = dispute.getTraderPubKeyRing();
- Contract contract = dispute.getContract();
- if (contract.getBuyerPubKeyRing().equals(receiverPubKeyRing))
- peerNodeAddress = contract.getBuyerNodeAddress();
- else
- peerNodeAddress = contract.getSellerNodeAddress();
- } else {
- log.error("That must not happen. Trader cannot communicate to other trader.");
- }
- return new Tuple2<>(peerNodeAddress, receiverPubKeyRing);
- }
-
- private Optional findDispute(String tradeId, int traderId) {
- return disputes.stream().filter(e -> e.getTradeId().equals(tradeId) && e.getTraderId() == traderId).findAny();
- }
-
- public Optional findOwnDispute(String tradeId) {
- return getDisputeStream(tradeId).findAny();
- }
-
- private Stream getDisputeStream(String tradeId) {
- return disputes.stream().filter(e -> e.getTradeId().equals(tradeId));
- }
-
- private void cleanupRetryMap(String uid) {
- if (delayMsgMap.containsKey(uid)) {
- Timer timer = delayMsgMap.remove(uid);
- if (timer != null)
- timer.stop();
- }
- }
-
-}
diff --git a/core/src/main/java/bisq/core/btc/model/AddressEntry.java b/core/src/main/java/bisq/core/btc/model/AddressEntry.java
index 5a2455dfc81..eb8512a9b6d 100644
--- a/core/src/main/java/bisq/core/btc/model/AddressEntry.java
+++ b/core/src/main/java/bisq/core/btc/model/AddressEntry.java
@@ -23,8 +23,6 @@
import bisq.common.proto.persistable.PersistablePayload;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import org.bitcoinj.core.Address;
@@ -119,7 +117,7 @@ private AddressEntry(byte[] pubKey,
this.coinLockedInMultiSig = coinLockedInMultiSig.value;
}
- public static AddressEntry fromProto(PB.AddressEntry proto) {
+ public static AddressEntry fromProto(protobuf.AddressEntry proto) {
return new AddressEntry(proto.getPubKey().toByteArray(),
proto.getPubKeyHash().toByteArray(),
ProtoUtil.enumFromProto(AddressEntry.Context.class, proto.getContext().name()),
@@ -128,11 +126,11 @@ public static AddressEntry fromProto(PB.AddressEntry proto) {
}
@Override
- public PB.AddressEntry toProtoMessage() {
- PB.AddressEntry.Builder builder = PB.AddressEntry.newBuilder()
+ public protobuf.AddressEntry toProtoMessage() {
+ protobuf.AddressEntry.Builder builder = protobuf.AddressEntry.newBuilder()
.setPubKey(ByteString.copyFrom(pubKey))
.setPubKeyHash(ByteString.copyFrom(pubKeyHash))
- .setContext(PB.AddressEntry.Context.valueOf(context.name()))
+ .setContext(protobuf.AddressEntry.Context.valueOf(context.name()))
.setCoinLockedInMultiSig(coinLockedInMultiSig);
Optional.ofNullable(offerId).ifPresent(builder::setOfferId);
return builder.build();
diff --git a/core/src/main/java/bisq/core/btc/model/AddressEntryList.java b/core/src/main/java/bisq/core/btc/model/AddressEntryList.java
index 6cb1bffc12b..52926ab6aef 100644
--- a/core/src/main/java/bisq/core/btc/model/AddressEntryList.java
+++ b/core/src/main/java/bisq/core/btc/model/AddressEntryList.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistedDataHost;
import bisq.common.storage.Storage;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.bitcoinj.core.Transaction;
@@ -73,7 +71,7 @@ private AddressEntryList(List list) {
this.list = list;
}
- public static AddressEntryList fromProto(PB.AddressEntryList proto) {
+ public static AddressEntryList fromProto(protobuf.AddressEntryList proto) {
return new AddressEntryList(new ArrayList<>(proto.getAddressEntryList().stream().map(AddressEntry::fromProto).collect(Collectors.toList())));
}
@@ -81,12 +79,12 @@ public static AddressEntryList fromProto(PB.AddressEntryList proto) {
public Message toProtoMessage() {
// We clone list as we got ConcurrentModificationExceptions
List clone = new ArrayList<>(list);
- List addressEntries = clone.stream()
+ List addressEntries = clone.stream()
.map(AddressEntry::toProtoMessage)
.collect(Collectors.toList());
- return PB.PersistableEnvelope.newBuilder()
- .setAddressEntryList(PB.AddressEntryList.newBuilder()
+ return protobuf.PersistableEnvelope.newBuilder()
+ .setAddressEntryList(protobuf.AddressEntryList.newBuilder()
.addAllAddressEntry(addressEntries))
.build();
}
diff --git a/core/src/main/java/bisq/core/btc/model/RawTransactionInput.java b/core/src/main/java/bisq/core/btc/model/RawTransactionInput.java
index 895c061c1fd..ef4d52116cb 100644
--- a/core/src/main/java/bisq/core/btc/model/RawTransactionInput.java
+++ b/core/src/main/java/bisq/core/btc/model/RawTransactionInput.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistablePayload;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import lombok.EqualsAndHashCode;
@@ -44,15 +42,15 @@ public RawTransactionInput(long index, byte[] parentTransaction, long value) {
}
@Override
- public PB.RawTransactionInput toProtoMessage() {
- return PB.RawTransactionInput.newBuilder()
+ public protobuf.RawTransactionInput toProtoMessage() {
+ return protobuf.RawTransactionInput.newBuilder()
.setIndex(index)
.setParentTransaction(ByteString.copyFrom(parentTransaction))
.setValue(value)
.build();
}
- public static RawTransactionInput fromProto(PB.RawTransactionInput proto) {
+ public static RawTransactionInput fromProto(protobuf.RawTransactionInput proto) {
return new RawTransactionInput(proto.getIndex(), proto.getParentTransaction().toByteArray(), proto.getValue());
}
diff --git a/core/src/main/java/bisq/core/btc/nodes/BtcNodes.java b/core/src/main/java/bisq/core/btc/nodes/BtcNodes.java
index b97030bf250..79057fa129b 100644
--- a/core/src/main/java/bisq/core/btc/nodes/BtcNodes.java
+++ b/core/src/main/java/bisq/core/btc/nodes/BtcNodes.java
@@ -77,6 +77,10 @@ public List getProvidedBtcNodes() {
// sgeisler
new BtcNode("bcwat.ch", "z33nukt7ngik3cpe.onion", "5.189.166.193", BtcNode.DEFAULT_PORT, "@sgeisler"),
+ // wiz
+ new BtcNode("node100.hnl.wiz.biz", "22tg6ufbwz6o3l2u.onion", "103.99.168.100", BtcNode.DEFAULT_PORT, "@wiz"),
+ new BtcNode("node130.hnl.wiz.biz", "jiuuuislm7ooesic.onion", "103.99.168.130", BtcNode.DEFAULT_PORT, "@wiz"),
+
// others
new BtcNode("btc.jochen-hoenicke.de", "sslnjjhnmwllysv4.onion", "88.198.39.205", BtcNode.DEFAULT_PORT, "@jhoenicke"),
new BtcNode("bitcoin4-fullnode.csg.uzh.ch", null, "192.41.136.217", BtcNode.DEFAULT_PORT, "@tbocek") // requested onion
diff --git a/core/src/main/java/bisq/core/btc/wallet/BsqWalletService.java b/core/src/main/java/bisq/core/btc/wallet/BsqWalletService.java
index 49018f8bca9..b8ccad5aba0 100644
--- a/core/src/main/java/bisq/core/btc/wallet/BsqWalletService.java
+++ b/core/src/main/java/bisq/core/btc/wallet/BsqWalletService.java
@@ -35,6 +35,8 @@
import bisq.core.provider.fee.FeeService;
import bisq.core.user.Preferences;
+import bisq.common.UserThread;
+
import org.bitcoinj.core.Address;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.BlockChain;
@@ -57,15 +59,14 @@
import javax.inject.Inject;
-import javafx.collections.FXCollections;
-import javafx.collections.ObservableList;
-
+import java.util.ArrayList;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
import java.util.concurrent.CopyOnWriteArraySet;
+import java.util.concurrent.TimeUnit;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -80,12 +81,20 @@
@Slf4j
public class BsqWalletService extends WalletService implements DaoStateListener {
+
+ public interface WalletTransactionsChangeListener {
+
+ void onWalletTransactionsChange();
+ }
+
private final BsqCoinSelector bsqCoinSelector;
private final NonBsqCoinSelector nonBsqCoinSelector;
private final DaoStateService daoStateService;
private final UnconfirmedBsqChangeOutputListService unconfirmedBsqChangeOutputListService;
- private final ObservableList walletTransactions = FXCollections.observableArrayList();
+ private final List walletTransactions = new ArrayList<>();
private final CopyOnWriteArraySet bsqBalanceListeners = new CopyOnWriteArraySet<>();
+ private final List walletTransactionsChangeListeners = new ArrayList<>();
+ private boolean updateBsqWalletTransactionsPending;
// balance of non BSQ satoshis
@Getter
@@ -152,7 +161,13 @@ public void onReorganize(Wallet wallet) {
@Override
public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) {
- updateBsqWalletTransactions();
+ // We are only interested in updates from unconfirmed txs and confirmed txs at the
+ // time when it gets into a block. Otherwise we would get called
+ // updateBsqWalletTransactions for each tx as the block depth changes for all.
+ if (tx.getConfidence().getDepthInBlocks() <= 1 &&
+ daoStateService.isParseBlockChainComplete()) {
+ updateBsqWalletTransactions();
+ }
unconfirmedBsqChangeOutputListService.onTransactionConfidenceChanged(tx);
}
@@ -215,6 +230,7 @@ String getWalletAsString(boolean includePrivKeys) {
///////////////////////////////////////////////////////////////////////////////////////////
private void updateBsqBalance() {
+ long ts = System.currentTimeMillis();
unverifiedBalance = Coin.valueOf(
getTransactions(false).stream()
.filter(tx -> tx.getConfidence().getConfidenceType() == PENDING)
@@ -246,7 +262,7 @@ private void updateBsqBalance() {
}
return false;
})
- .mapToLong(in -> in != null ? in.getValue().value : 0)
+ .mapToLong(in -> in.getValue() != null ? in.getValue().value : 0)
.sum();
return outputs - lockedInputs;
})
@@ -289,6 +305,7 @@ private void updateBsqBalance() {
bsqBalanceListeners.forEach(e -> e.onUpdateBalances(availableConfirmedBalance, availableNonBsqBalance, unverifiedBalance,
unconfirmedChangeBalance, lockedForVotingBalance, lockupBondsBalance, unlockingBondsBalance));
+ log.info("updateBsqBalance took {} ms", System.currentTimeMillis() - ts);
}
public void addBsqBalanceListener(BsqBalanceListener listener) {
@@ -299,13 +316,21 @@ public void removeBsqBalanceListener(BsqBalanceListener listener) {
bsqBalanceListeners.remove(listener);
}
+ public void addWalletTransactionsChangeListener(WalletTransactionsChangeListener listener) {
+ walletTransactionsChangeListeners.add(listener);
+ }
+
+ public void removeWalletTransactionsChangeListener(WalletTransactionsChangeListener listener) {
+ walletTransactionsChangeListeners.remove(listener);
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////
// BSQ TransactionOutputs and Transactions
///////////////////////////////////////////////////////////////////////////////////////////
- public ObservableList getWalletTransactions() {
- return walletTransactions;
+ public List getClonedWalletTransactions() {
+ return new ArrayList<>(walletTransactions);
}
public Stream getPendingWalletTransactionsStream() {
@@ -314,9 +339,21 @@ public Stream getPendingWalletTransactionsStream() {
}
private void updateBsqWalletTransactions() {
- walletTransactions.setAll(getTransactions(false));
if (daoStateService.isParseBlockChainComplete()) {
- updateBsqBalance();
+ // We get called updateBsqWalletTransactions multiple times from onWalletChanged, onTransactionConfidenceChanged
+ // and from onParseBlockCompleteAfterBatchProcessing. But as updateBsqBalance is an expensive operation we do
+ // not want to call it in a short interval series so we use a flag and a delay to not call it multiple times
+ // in a 100 ms period.
+ if (!updateBsqWalletTransactionsPending) {
+ updateBsqWalletTransactionsPending = true;
+ UserThread.runAfter(() -> {
+ walletTransactions.clear();
+ walletTransactions.addAll(getTransactions(false));
+ walletTransactionsChangeListeners.forEach(WalletTransactionsChangeListener::onWalletTransactionsChange);
+ updateBsqBalance();
+ updateBsqWalletTransactionsPending = false;
+ }, 100, TimeUnit.MILLISECONDS);
+ }
}
}
@@ -434,7 +471,7 @@ public Coin getValueSentToMeForTransaction(Transaction transaction) throws Scrip
}
public Optional isWalletTransaction(String txId) {
- return getWalletTransactions().stream().filter(e -> e.getHashAsString().equals(txId)).findAny();
+ return walletTransactions.stream().filter(e -> e.getHashAsString().equals(txId)).findAny();
}
@@ -553,7 +590,10 @@ private Transaction getPreparedBurnFeeTx(Coin fee, boolean requireChangeOutput)
return tx;
}
- private void addInputsAndChangeOutputForTx(Transaction tx, Coin fee, BsqCoinSelector bsqCoinSelector, boolean requireChangeOutput)
+ private void addInputsAndChangeOutputForTx(Transaction tx,
+ Coin fee,
+ BsqCoinSelector bsqCoinSelector,
+ boolean requireChangeOutput)
throws InsufficientBsqException {
Coin requiredInput;
// If our fee is less then dust limit we increase it so we are sure to not get any dust output.
diff --git a/core/src/main/java/bisq/core/btc/wallet/TradeWalletService.java b/core/src/main/java/bisq/core/btc/wallet/TradeWalletService.java
index 3db2070e5d4..dab65b733ac 100644
--- a/core/src/main/java/bisq/core/btc/wallet/TradeWalletService.java
+++ b/core/src/main/java/bisq/core/btc/wallet/TradeWalletService.java
@@ -341,7 +341,10 @@ public Transaction completeBsqTradingFeeTx(Transaction preparedBsqTx,
* @return A data container holding the inputs, the output value and address
* @throws TransactionVerificationException
*/
- public InputsAndChangeOutput takerCreatesDepositsTxInputs(Transaction takeOfferFeeTx, Coin inputAmount, Coin txFee, Address takersAddress) throws
+ public InputsAndChangeOutput takerCreatesDepositsTxInputs(Transaction takeOfferFeeTx,
+ Coin inputAmount,
+ Coin txFee,
+ Address takersAddress) throws
TransactionVerificationException {
log.debug("takerCreatesDepositsTxInputs called");
log.debug("inputAmount {}", inputAmount.toFriendlyString());
@@ -793,7 +796,112 @@ public Transaction sellerSignsAndFinalizesPayoutTx(Transaction depositTx,
///////////////////////////////////////////////////////////////////////////////////////////
- // Dispute
+ // Mediation
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ public byte[] signMediatedPayoutTx(Transaction depositTx,
+ Coin buyerPayoutAmount,
+ Coin sellerPayoutAmount,
+ String buyerPayoutAddressString,
+ String sellerPayoutAddressString,
+ DeterministicKey myMultiSigKeyPair,
+ byte[] buyerPubKey,
+ byte[] sellerPubKey,
+ byte[] arbitratorPubKey)
+ throws AddressFormatException, TransactionVerificationException {
+ log.trace("signMediatedPayoutTx called");
+ log.trace("depositTx {}", depositTx.toString());
+ log.trace("buyerPayoutAmount {}", buyerPayoutAmount.toFriendlyString());
+ log.trace("sellerPayoutAmount {}", sellerPayoutAmount.toFriendlyString());
+ log.trace("buyerPayoutAddressString {}", buyerPayoutAddressString);
+ log.trace("sellerPayoutAddressString {}", sellerPayoutAddressString);
+ log.trace("multiSigKeyPair (not displayed for security reasons)");
+ log.trace("buyerPubKey HEX=" + ECKey.fromPublicOnly(buyerPubKey).getPublicKeyAsHex());
+ log.trace("sellerPubKey HEX=" + ECKey.fromPublicOnly(sellerPubKey).getPublicKeyAsHex());
+ log.trace("arbitratorPubKey HEX=" + ECKey.fromPublicOnly(arbitratorPubKey).getPublicKeyAsHex());
+ Transaction preparedPayoutTx = createPayoutTx(depositTx,
+ buyerPayoutAmount,
+ sellerPayoutAmount,
+ buyerPayoutAddressString,
+ sellerPayoutAddressString);
+ // MS redeemScript
+ Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
+ // MS output from prev. tx is index 0
+ Sha256Hash sigHash = preparedPayoutTx.hashForSignature(0, redeemScript, Transaction.SigHash.ALL, false);
+ checkNotNull(myMultiSigKeyPair, "myMultiSigKeyPair must not be null");
+ if (myMultiSigKeyPair.isEncrypted())
+ checkNotNull(aesKey);
+
+ ECKey.ECDSASignature mySignature = myMultiSigKeyPair.sign(sigHash, aesKey).toCanonicalised();
+
+ WalletService.printTx("prepared mediated payoutTx for sig creation", preparedPayoutTx);
+
+ WalletService.verifyTransaction(preparedPayoutTx);
+
+ return mySignature.encodeToDER();
+ }
+
+ public Transaction finalizeMediatedPayoutTx(Transaction depositTx,
+ byte[] buyerSignature,
+ byte[] sellerSignature,
+ Coin buyerPayoutAmount,
+ Coin sellerPayoutAmount,
+ String buyerPayoutAddressString,
+ String sellerPayoutAddressString,
+ DeterministicKey multiSigKeyPair,
+ byte[] buyerPubKey,
+ byte[] sellerPubKey,
+ byte[] arbitratorPubKey)
+ throws AddressFormatException, TransactionVerificationException, WalletException {
+ log.trace("finalizeMediatedPayoutTx called");
+ log.trace("depositTx {}", depositTx.toString());
+ log.trace("buyerSignature r {}", ECKey.ECDSASignature.decodeFromDER(buyerSignature).r.toString());
+ log.trace("buyerSignature s {}", ECKey.ECDSASignature.decodeFromDER(buyerSignature).s.toString());
+ log.trace("sellerSignature r {}", ECKey.ECDSASignature.decodeFromDER(sellerSignature).r.toString());
+ log.trace("sellerSignature s {}", ECKey.ECDSASignature.decodeFromDER(sellerSignature).s.toString());
+ log.trace("buyerPayoutAmount {}", buyerPayoutAmount.toFriendlyString());
+ log.trace("sellerPayoutAmount {}", sellerPayoutAmount.toFriendlyString());
+ log.trace("buyerPayoutAddressString {}", buyerPayoutAddressString);
+ log.trace("sellerPayoutAddressString {}", sellerPayoutAddressString);
+ log.trace("multiSigKeyPair (not displayed for security reasons)");
+ log.trace("buyerPubKey {}", ECKey.fromPublicOnly(buyerPubKey).toString());
+ log.trace("sellerPubKey {}", ECKey.fromPublicOnly(sellerPubKey).toString());
+ log.trace("arbitratorPubKey {}", ECKey.fromPublicOnly(arbitratorPubKey).toString());
+
+ Transaction payoutTx = createPayoutTx(depositTx,
+ buyerPayoutAmount,
+ sellerPayoutAmount,
+ buyerPayoutAddressString,
+ sellerPayoutAddressString);
+ // MS redeemScript
+ Script redeemScript = getMultiSigRedeemScript(buyerPubKey, sellerPubKey, arbitratorPubKey);
+ // MS output from prev. tx is index 0
+ checkNotNull(multiSigKeyPair, "multiSigKeyPair must not be null");
+
+ TransactionSignature buyerTxSig = new TransactionSignature(ECKey.ECDSASignature.decodeFromDER(buyerSignature),
+ Transaction.SigHash.ALL, false);
+ TransactionSignature sellerTxSig = new TransactionSignature(ECKey.ECDSASignature.decodeFromDER(sellerSignature),
+ Transaction.SigHash.ALL, false);
+
+ // Take care of order of signatures. Need to be reversed here. See comment below at getMultiSigRedeemScript (arbitrator, seller, buyer)
+ Script inputScript = ScriptBuilder.createP2SHMultiSigInputScript(ImmutableList.of(sellerTxSig, buyerTxSig), redeemScript);
+
+ TransactionInput input = payoutTx.getInput(0);
+ input.setScriptSig(inputScript);
+
+ WalletService.printTx("mediated payoutTx", payoutTx);
+
+ WalletService.verifyTransaction(payoutTx);
+ WalletService.checkWalletConsistency(wallet);
+ WalletService.checkScriptSig(payoutTx, input, 0);
+ checkNotNull(input.getConnectedOutput(), "input.getConnectedOutput() must not be null");
+ input.verify(input.getConnectedOutput());
+ return payoutTx;
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Arbitration
///////////////////////////////////////////////////////////////////////////////////////////
/**
@@ -1127,7 +1235,9 @@ private byte[] getScriptProgram(Transaction makersDepositTx, int i) throws Trans
}
@NotNull
- private TransactionInput getTransactionInput(Transaction depositTx, byte[] scriptProgram, RawTransactionInput rawTransactionInput) {
+ private TransactionInput getTransactionInput(Transaction depositTx,
+ byte[] scriptProgram,
+ RawTransactionInput rawTransactionInput) {
return new TransactionInput(params,
depositTx,
scriptProgram,
@@ -1191,7 +1301,10 @@ private void signInput(Transaction transaction, TransactionInput input, int inpu
}
}
- private void addAvailableInputsAndChangeOutputs(Transaction transaction, Address address, Address changeAddress, Coin txFee) throws WalletException {
+ private void addAvailableInputsAndChangeOutputs(Transaction transaction,
+ Address address,
+ Address changeAddress,
+ Coin txFee) throws WalletException {
SendRequest sendRequest = null;
try {
// Lets let the framework do the work to find the right inputs
diff --git a/core/src/main/java/bisq/core/dao/DaoModule.java b/core/src/main/java/bisq/core/dao/DaoModule.java
index c1bf6e32425..4ed2d8b4518 100644
--- a/core/src/main/java/bisq/core/dao/DaoModule.java
+++ b/core/src/main/java/bisq/core/dao/DaoModule.java
@@ -225,9 +225,12 @@ protected void configure() {
// Options
bindConstant().annotatedWith(named(DaoOptionKeys.RPC_USER)).to(environment.getRequiredProperty(DaoOptionKeys.RPC_USER));
bindConstant().annotatedWith(named(DaoOptionKeys.RPC_PASSWORD)).to(environment.getRequiredProperty(DaoOptionKeys.RPC_PASSWORD));
+ bindConstant().annotatedWith(named(DaoOptionKeys.RPC_HOST)).to(environment.getRequiredProperty(DaoOptionKeys.RPC_HOST));
bindConstant().annotatedWith(named(DaoOptionKeys.RPC_PORT)).to(environment.getRequiredProperty(DaoOptionKeys.RPC_PORT));
bindConstant().annotatedWith(named(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_PORT))
.to(environment.getRequiredProperty(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_PORT));
+ bindConstant().annotatedWith(named(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_HOST))
+ .to(environment.getRequiredProperty(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_HOST));
bindConstant().annotatedWith(named(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA))
.to(environment.getRequiredProperty(DaoOptionKeys.DUMP_BLOCKCHAIN_DATA));
bindConstant().annotatedWith(named(DaoOptionKeys.FULL_DAO_NODE))
diff --git a/core/src/main/java/bisq/core/dao/DaoOptionKeys.java b/core/src/main/java/bisq/core/dao/DaoOptionKeys.java
index 945fd51adad..7829dcaf36d 100644
--- a/core/src/main/java/bisq/core/dao/DaoOptionKeys.java
+++ b/core/src/main/java/bisq/core/dao/DaoOptionKeys.java
@@ -25,6 +25,8 @@ public class DaoOptionKeys {
public static final String RPC_PASSWORD = "rpcPassword";
public static final String RPC_PORT = "rpcPort";
public static final String RPC_BLOCK_NOTIFICATION_PORT = "rpcBlockNotificationPort";
+ public static final String RPC_BLOCK_NOTIFICATION_HOST = "rpcBlockNotificationHost";
+ public static final String RPC_HOST = "rpcHost";
public static final String DUMP_BLOCKCHAIN_DATA = "dumpBlockchainData";
public static final String FULL_DAO_NODE = "fullDaoNode";
diff --git a/core/src/main/java/bisq/core/dao/governance/blindvote/BlindVote.java b/core/src/main/java/bisq/core/dao/governance/blindvote/BlindVote.java
index 6e2f1f8ac46..071682e4277 100644
--- a/core/src/main/java/bisq/core/dao/governance/blindvote/BlindVote.java
+++ b/core/src/main/java/bisq/core/dao/governance/blindvote/BlindVote.java
@@ -24,8 +24,6 @@
import bisq.common.util.ExtraDataMapValidator;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import org.springframework.util.CollectionUtils;
@@ -87,13 +85,13 @@ public BlindVote(byte[] encryptedVotes,
// Used for sending over the network
@Override
- public PB.BlindVote toProtoMessage() {
+ public protobuf.BlindVote toProtoMessage() {
return getBuilder().build();
}
@NotNull
- public PB.BlindVote.Builder getBuilder() {
- PB.BlindVote.Builder builder = PB.BlindVote.newBuilder();
+ public protobuf.BlindVote.Builder getBuilder() {
+ protobuf.BlindVote.Builder builder = protobuf.BlindVote.newBuilder();
builder.setEncryptedVotes(ByteString.copyFrom(encryptedVotes))
.setTxId(txId)
.setStake(stake)
@@ -103,7 +101,7 @@ public PB.BlindVote.Builder getBuilder() {
return builder;
}
- public static BlindVote fromProto(PB.BlindVote proto) {
+ public static BlindVote fromProto(protobuf.BlindVote proto) {
return new BlindVote(proto.getEncryptedVotes().toByteArray(),
proto.getTxId(),
proto.getStake(),
diff --git a/core/src/main/java/bisq/core/dao/governance/blindvote/MyBlindVoteList.java b/core/src/main/java/bisq/core/dao/governance/blindvote/MyBlindVoteList.java
index a66f610ced3..47dca594eb0 100644
--- a/core/src/main/java/bisq/core/dao/governance/blindvote/MyBlindVoteList.java
+++ b/core/src/main/java/bisq/core/dao/governance/blindvote/MyBlindVoteList.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistableList;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import java.util.ArrayList;
@@ -53,15 +51,15 @@ public MyBlindVoteList(List list) {
@Override
public Message toProtoMessage() {
- return PB.PersistableEnvelope.newBuilder()
- .setMyBlindVoteList(PB.MyBlindVoteList.newBuilder()
+ return protobuf.PersistableEnvelope.newBuilder()
+ .setMyBlindVoteList(protobuf.MyBlindVoteList.newBuilder()
.addAllBlindVote(getList().stream()
.map(BlindVote::toProtoMessage)
.collect(Collectors.toList())))
.build();
}
- public static PersistableEnvelope fromProto(PB.MyBlindVoteList proto) {
+ public static PersistableEnvelope fromProto(protobuf.MyBlindVoteList proto) {
return new MyBlindVoteList(new ArrayList<>(proto.getBlindVoteList().stream()
.map(BlindVote::fromProto)
.collect(Collectors.toList())));
diff --git a/core/src/main/java/bisq/core/dao/governance/blindvote/VoteWithProposalTxId.java b/core/src/main/java/bisq/core/dao/governance/blindvote/VoteWithProposalTxId.java
index 5e98471b5c4..1c60733fcf7 100644
--- a/core/src/main/java/bisq/core/dao/governance/blindvote/VoteWithProposalTxId.java
+++ b/core/src/main/java/bisq/core/dao/governance/blindvote/VoteWithProposalTxId.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Optional;
import lombok.Value;
@@ -50,19 +48,19 @@ public class VoteWithProposalTxId implements PersistablePayload {
// Used for sending over the network
@Override
- public PB.VoteWithProposalTxId toProtoMessage() {
+ public protobuf.VoteWithProposalTxId toProtoMessage() {
return getBuilder().build();
}
@NotNull
- private PB.VoteWithProposalTxId.Builder getBuilder() {
- final PB.VoteWithProposalTxId.Builder builder = PB.VoteWithProposalTxId.newBuilder()
+ private protobuf.VoteWithProposalTxId.Builder getBuilder() {
+ final protobuf.VoteWithProposalTxId.Builder builder = protobuf.VoteWithProposalTxId.newBuilder()
.setProposalTxId(proposalTxId);
- Optional.ofNullable(vote).ifPresent(e -> builder.setVote((PB.Vote) e.toProtoMessage()));
+ Optional.ofNullable(vote).ifPresent(e -> builder.setVote((protobuf.Vote) e.toProtoMessage()));
return builder;
}
- public static VoteWithProposalTxId fromProto(PB.VoteWithProposalTxId proto) {
+ public static VoteWithProposalTxId fromProto(protobuf.VoteWithProposalTxId proto) {
return new VoteWithProposalTxId(proto.getProposalTxId(),
proto.hasVote() ? Vote.fromProto(proto.getVote()) : null);
}
diff --git a/core/src/main/java/bisq/core/dao/governance/blindvote/VoteWithProposalTxIdList.java b/core/src/main/java/bisq/core/dao/governance/blindvote/VoteWithProposalTxIdList.java
index e3afee90fdd..247235faab0 100644
--- a/core/src/main/java/bisq/core/dao/governance/blindvote/VoteWithProposalTxIdList.java
+++ b/core/src/main/java/bisq/core/dao/governance/blindvote/VoteWithProposalTxIdList.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistableList;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.InvalidProtocolBufferException;
import java.util.ArrayList;
@@ -52,22 +50,22 @@ public class VoteWithProposalTxIdList extends PersistableList list = proto.getItemList().stream()
.map(VoteWithProposalTxId::fromProto).collect(Collectors.toCollection(ArrayList::new));
return new VoteWithProposalTxIdList(list);
diff --git a/core/src/main/java/bisq/core/dao/governance/blindvote/network/messages/RepublishGovernanceDataRequest.java b/core/src/main/java/bisq/core/dao/governance/blindvote/network/messages/RepublishGovernanceDataRequest.java
index 420677bb86f..258149a5fc5 100644
--- a/core/src/main/java/bisq/core/dao/governance/blindvote/network/messages/RepublishGovernanceDataRequest.java
+++ b/core/src/main/java/bisq/core/dao/governance/blindvote/network/messages/RepublishGovernanceDataRequest.java
@@ -25,11 +25,11 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.EqualsAndHashCode;
import lombok.Getter;
+
+// This message is sent only to full DAO nodes
@EqualsAndHashCode(callSuper = true)
@Getter
public final class RepublishGovernanceDataRequest extends NetworkEnvelope implements DirectMessage, CapabilityRequiringPayload {
@@ -48,13 +48,13 @@ private RepublishGovernanceDataRequest(int messageVersion) {
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setRepublishGovernanceDataRequest(PB.RepublishGovernanceDataRequest.newBuilder())
+ .setRepublishGovernanceDataRequest(protobuf.RepublishGovernanceDataRequest.newBuilder())
.build();
}
- public static NetworkEnvelope fromProto(PB.RepublishGovernanceDataRequest proto, int messageVersion) {
+ public static NetworkEnvelope fromProto(protobuf.RepublishGovernanceDataRequest proto, int messageVersion) {
return new RepublishGovernanceDataRequest(messageVersion);
}
diff --git a/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVotePayload.java b/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVotePayload.java
index 468484fae89..923bd4e043c 100644
--- a/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVotePayload.java
+++ b/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVotePayload.java
@@ -20,21 +20,14 @@
import bisq.core.dao.governance.ConsensusCritical;
import bisq.core.dao.governance.blindvote.BlindVote;
-import bisq.network.p2p.storage.payload.CapabilityRequiringPayload;
import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
-import bisq.common.app.Capabilities;
-import bisq.common.app.Capability;
import bisq.common.crypto.Hash;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
-import java.util.concurrent.TimeUnit;
-
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@@ -50,8 +43,7 @@
@Slf4j
@Getter
@EqualsAndHashCode
-public final class BlindVotePayload implements PersistableNetworkPayload, PersistableEnvelope,
- CapabilityRequiringPayload, ConsensusCritical {
+public final class BlindVotePayload implements PersistableNetworkPayload, PersistableEnvelope, ConsensusCritical {
private final BlindVote blindVote;
protected final byte[] hash; // 20 byte
@@ -69,23 +61,23 @@ private BlindVotePayload(BlindVote blindVote, byte[] hash) {
this.hash = hash;
}
- private PB.BlindVotePayload.Builder getBlindVoteBuilder() {
- return PB.BlindVotePayload.newBuilder()
+ private protobuf.BlindVotePayload.Builder getBlindVoteBuilder() {
+ return protobuf.BlindVotePayload.newBuilder()
.setBlindVote(blindVote.toProtoMessage())
.setHash(ByteString.copyFrom(hash));
}
@Override
- public PB.PersistableNetworkPayload toProtoMessage() {
- return PB.PersistableNetworkPayload.newBuilder().setBlindVotePayload(getBlindVoteBuilder()).build();
+ public protobuf.PersistableNetworkPayload toProtoMessage() {
+ return protobuf.PersistableNetworkPayload.newBuilder().setBlindVotePayload(getBlindVoteBuilder()).build();
}
- public PB.BlindVotePayload toProtoBlindVotePayload() {
+ public protobuf.BlindVotePayload toProtoBlindVotePayload() {
return getBlindVoteBuilder().build();
}
- public static BlindVotePayload fromProto(PB.BlindVotePayload proto) {
+ public static BlindVotePayload fromProto(protobuf.BlindVotePayload proto) {
return new BlindVotePayload(BlindVote.fromProto(proto.getBlindVote()),
proto.getHash().toByteArray());
}
@@ -105,16 +97,6 @@ public byte[] getHash() {
return hash;
}
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // CapabilityRequiringPayload
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- @Override
- public Capabilities getRequiredCapabilities() {
- return new Capabilities(Capability.BLIND_VOTE);
- }
-
@Override
public String toString() {
return "BlindVotePayload{" +
diff --git a/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVoteStore.java b/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVoteStore.java
index 7a125c1ac8f..e7f11038065 100644
--- a/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVoteStore.java
+++ b/core/src/main/java/bisq/core/dao/governance/blindvote/storage/BlindVoteStore.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistableEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import java.util.List;
@@ -58,20 +56,20 @@ private BlindVoteStore(List list) {
}
public Message toProtoMessage() {
- return PB.PersistableEnvelope.newBuilder()
+ return protobuf.PersistableEnvelope.newBuilder()
.setBlindVoteStore(getBuilder())
.build();
}
- private PB.BlindVoteStore.Builder getBuilder() {
- final List protoList = map.values().stream()
+ private protobuf.BlindVoteStore.Builder getBuilder() {
+ final List protoList = map.values().stream()
.map(payload -> (BlindVotePayload) payload)
.map(BlindVotePayload::toProtoBlindVotePayload)
.collect(Collectors.toList());
- return PB.BlindVoteStore.newBuilder().addAllItems(protoList);
+ return protobuf.BlindVoteStore.newBuilder().addAllItems(protoList);
}
- public static PersistableEnvelope fromProto(PB.BlindVoteStore proto) {
+ public static PersistableEnvelope fromProto(protobuf.BlindVoteStore proto) {
List list = proto.getItemsList().stream()
.map(BlindVotePayload::fromProto).collect(Collectors.toList());
return new BlindVoteStore(list);
diff --git a/core/src/main/java/bisq/core/dao/governance/bond/BondRepository.java b/core/src/main/java/bisq/core/dao/governance/bond/BondRepository.java
index 19b4336076f..d3f69b79a09 100644
--- a/core/src/main/java/bisq/core/dao/governance/bond/BondRepository.java
+++ b/core/src/main/java/bisq/core/dao/governance/bond/BondRepository.java
@@ -35,7 +35,6 @@
import javax.inject.Inject;
import javafx.collections.FXCollections;
-import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import java.util.Arrays;
@@ -55,7 +54,8 @@
* unconfirmed txs.
*/
@Slf4j
-public abstract class BondRepository implements DaoSetupService {
+public abstract class BondRepository implements DaoSetupService,
+ BsqWalletService.WalletTransactionsChangeListener {
///////////////////////////////////////////////////////////////////////////////////////////
// Static
@@ -161,7 +161,7 @@ public void onParseBlockCompleteAfterBatchProcessing(Block block) {
update();
}
});
- bsqWalletService.getWalletTransactions().addListener((ListChangeListener) c -> update());
+ bsqWalletService.addWalletTransactionsChangeListener(this);
}
@Override
@@ -170,6 +170,16 @@ public void start() {
}
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // BsqWalletService.WalletTransactionsChangeListener
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ @Override
+ public void onWalletTransactionsChange() {
+ update();
+ }
+
+
///////////////////////////////////////////////////////////////////////////////////////////
// API
///////////////////////////////////////////////////////////////////////////////////////////
@@ -188,13 +198,14 @@ public List getActiveBonds() {
// Protected
///////////////////////////////////////////////////////////////////////////////////////////
- abstract protected T createBond(R bondedAsset);
+ protected abstract T createBond(R bondedAsset);
- abstract protected void updateBond(T bond, R bondedAsset, TxOutput lockupTxOutput);
+ protected abstract void updateBond(T bond, R bondedAsset, TxOutput lockupTxOutput);
- abstract protected Stream getBondedAssetStream();
+ protected abstract Stream getBondedAssetStream();
protected void update() {
+ log.debug("update");
getBondedAssetStream().forEach(bondedAsset -> {
String uid = bondedAsset.getUid();
bondByUidMap.putIfAbsent(uid, createBond(bondedAsset));
diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputationRepository.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputationRepository.java
index 4fc97d47540..0de193ba97d 100644
--- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputationRepository.java
+++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyBondedReputationRepository.java
@@ -26,12 +26,9 @@
import bisq.core.dao.state.DaoStateService;
import bisq.core.dao.state.model.blockchain.Block;
-import org.bitcoinj.core.Transaction;
-
import javax.inject.Inject;
import javafx.collections.FXCollections;
-import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import java.util.Arrays;
@@ -50,7 +47,7 @@
* unconfirmed txs.
*/
@Slf4j
-public class MyBondedReputationRepository implements DaoSetupService {
+public class MyBondedReputationRepository implements DaoSetupService, BsqWalletService.WalletTransactionsChangeListener {
private final DaoStateService daoStateService;
private final BsqWalletService bsqWalletService;
private final MyReputationListService myReputationListService;
@@ -84,7 +81,7 @@ public void onParseBlockCompleteAfterBatchProcessing(Block block) {
update();
}
});
- bsqWalletService.getWalletTransactions().addListener((ListChangeListener) c -> update());
+ bsqWalletService.addWalletTransactionsChangeListener(this);
}
@Override
@@ -92,11 +89,22 @@ public void start() {
}
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // BsqWalletService.WalletTransactionsChangeListener
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ @Override
+ public void onWalletTransactionsChange() {
+ update();
+ }
+
+
///////////////////////////////////////////////////////////////////////////////////////////
// Private
///////////////////////////////////////////////////////////////////////////////////////////
private void update() {
+ log.debug("update");
// It can be that the same salt/hash is in several lockupTxs, so we use the bondByLockupTxIdMap to eliminate
// duplicates by the collection algorithm.
Map bondByLockupTxIdMap = new HashMap<>();
diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputation.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputation.java
index f0a7eee04be..f4bef01ac41 100644
--- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputation.java
+++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputation.java
@@ -24,8 +24,6 @@
import bisq.common.proto.persistable.PersistablePayload;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import java.util.Arrays;
@@ -69,14 +67,14 @@ private MyReputation(String uid, byte[] salt) {
}
@Override
- public PB.MyReputation toProtoMessage() {
- return PB.MyReputation.newBuilder()
+ public protobuf.MyReputation toProtoMessage() {
+ return protobuf.MyReputation.newBuilder()
.setUid(uid)
.setSalt(ByteString.copyFrom(salt))
.build();
}
- public static MyReputation fromProto(PB.MyReputation proto) {
+ public static MyReputation fromProto(protobuf.MyReputation proto) {
return new MyReputation(proto.getUid(), proto.getSalt().toByteArray());
}
diff --git a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationList.java b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationList.java
index 5e426e999a1..729ef5ae314 100644
--- a/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationList.java
+++ b/core/src/main/java/bisq/core/dao/governance/bond/reputation/MyReputationList.java
@@ -19,8 +19,6 @@
import bisq.common.proto.persistable.PersistableList;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -47,18 +45,18 @@ private MyReputationList(List list) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.PersistableEnvelope toProtoMessage() {
- return PB.PersistableEnvelope.newBuilder().setMyReputationList(getBuilder()).build();
+ public protobuf.PersistableEnvelope toProtoMessage() {
+ return protobuf.PersistableEnvelope.newBuilder().setMyReputationList(getBuilder()).build();
}
- private PB.MyReputationList.Builder getBuilder() {
- return PB.MyReputationList.newBuilder()
+ private protobuf.MyReputationList.Builder getBuilder() {
+ return protobuf.MyReputationList.newBuilder()
.addAllMyReputation(getList().stream()
.map(MyReputation::toProtoMessage)
.collect(Collectors.toList()));
}
- public static MyReputationList fromProto(PB.MyReputationList proto) {
+ public static MyReputationList fromProto(protobuf.MyReputationList proto) {
return new MyReputationList(new ArrayList<>(proto.getMyReputationList().stream()
.map(MyReputation::fromProto)
.collect(Collectors.toList())));
diff --git a/core/src/main/java/bisq/core/dao/governance/bond/role/BondedRolesRepository.java b/core/src/main/java/bisq/core/dao/governance/bond/role/BondedRolesRepository.java
index 2f25d972eca..8176565d0ed 100644
--- a/core/src/main/java/bisq/core/dao/governance/bond/role/BondedRolesRepository.java
+++ b/core/src/main/java/bisq/core/dao/governance/bond/role/BondedRolesRepository.java
@@ -60,7 +60,7 @@ public BondedRolesRepository(DaoStateService daoStateService, BsqWalletService b
///////////////////////////////////////////////////////////////////////////////////////////
public boolean isMyRole(Role role) {
- Set myWalletTransactionIds = bsqWalletService.getWalletTransactions().stream()
+ Set myWalletTransactionIds = bsqWalletService.getClonedWalletTransactions().stream()
.map(Transaction::getHashAsString)
.collect(Collectors.toSet());
return getAcceptedBondedRoleProposalStream()
diff --git a/core/src/main/java/bisq/core/dao/governance/myvote/MyVote.java b/core/src/main/java/bisq/core/dao/governance/myvote/MyVote.java
index 507eaaadb70..6036bc62602 100644
--- a/core/src/main/java/bisq/core/dao/governance/myvote/MyVote.java
+++ b/core/src/main/java/bisq/core/dao/governance/myvote/MyVote.java
@@ -29,8 +29,6 @@
import bisq.common.util.JsonExclude;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import javax.crypto.SecretKey;
@@ -101,8 +99,8 @@ private MyVote(int height,
}
@Override
- public PB.MyVote toProtoMessage() {
- final PB.MyVote.Builder builder = PB.MyVote.newBuilder()
+ public protobuf.MyVote toProtoMessage() {
+ final protobuf.MyVote.Builder builder = protobuf.MyVote.newBuilder()
.setHeight(height)
.setBlindVote(blindVote.getBuilder())
.setBallotList(ballotList.getBuilder())
@@ -112,7 +110,7 @@ public PB.MyVote toProtoMessage() {
return builder.build();
}
- public static MyVote fromProto(PB.MyVote proto) {
+ public static MyVote fromProto(protobuf.MyVote proto) {
return new MyVote(proto.getHeight(),
BallotList.fromProto(proto.getBallotList()),
proto.getSecretKeyEncoded().toByteArray(),
diff --git a/core/src/main/java/bisq/core/dao/governance/myvote/MyVoteList.java b/core/src/main/java/bisq/core/dao/governance/myvote/MyVoteList.java
index 169aeb21e03..ef66f624c99 100644
--- a/core/src/main/java/bisq/core/dao/governance/myvote/MyVoteList.java
+++ b/core/src/main/java/bisq/core/dao/governance/myvote/MyVoteList.java
@@ -20,8 +20,6 @@
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistableList;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import java.util.ArrayList;
@@ -47,15 +45,15 @@ private MyVoteList(List list) {
@Override
public Message toProtoMessage() {
- return PB.PersistableEnvelope.newBuilder()
- .setMyVoteList(PB.MyVoteList.newBuilder()
+ return protobuf.PersistableEnvelope.newBuilder()
+ .setMyVoteList(protobuf.MyVoteList.newBuilder()
.addAllMyVote(getList().stream()
.map(MyVote::toProtoMessage)
.collect(Collectors.toList())))
.build();
}
- public static PersistableEnvelope fromProto(PB.MyVoteList proto) {
+ public static PersistableEnvelope fromProto(protobuf.MyVoteList proto) {
return new MyVoteList(new ArrayList<>(proto.getMyVoteList().stream()
.map(MyVote::fromProto)
.collect(Collectors.toList())));
diff --git a/core/src/main/java/bisq/core/dao/governance/param/Param.java b/core/src/main/java/bisq/core/dao/governance/param/Param.java
index 81fa09ede95..9d7fb1568ba 100644
--- a/core/src/main/java/bisq/core/dao/governance/param/Param.java
+++ b/core/src/main/java/bisq/core/dao/governance/param/Param.java
@@ -22,8 +22,6 @@
import bisq.common.proto.ProtoUtil;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.Getter;
import lombok.extern.slf4j.Slf4j;
@@ -61,6 +59,8 @@ public enum Param {
// Might need adjustment if BSQ/BTC rate changes.
DEFAULT_MAKER_FEE_BSQ("0.50", ParamType.BSQ, 5, 5), // ~ 0.01% of trade amount
DEFAULT_TAKER_FEE_BSQ("1.5", ParamType.BSQ, 5, 5),
+ // Min fee is the smallest fee allowed for a trade. If the default fee would be less than min fee the
+ // min fee is used instead.
// 0.03 BSQ (3 satoshi) for a 1 BTC trade. 0.05 USD if 1 BSQ = 1 USD, 10 % of the BTC fee
MIN_MAKER_FEE_BSQ("0.03", ParamType.BSQ, 5, 5), // 0.0003%.
MIN_TAKER_FEE_BSQ("0.03", ParamType.BSQ, 5, 5),
@@ -239,7 +239,7 @@ public enum Param {
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- public static Param fromProto(PB.ChangeParamProposal proposalProto) {
+ public static Param fromProto(protobuf.ChangeParamProposal proposalProto) {
Param param;
try {
param = ProtoUtil.enumFromProto(Param.class, proposalProto.getParam());
diff --git a/core/src/main/java/bisq/core/dao/governance/period/PeriodService.java b/core/src/main/java/bisq/core/dao/governance/period/PeriodService.java
index 18ea9b61912..dfe18cb07a5 100644
--- a/core/src/main/java/bisq/core/dao/governance/period/PeriodService.java
+++ b/core/src/main/java/bisq/core/dao/governance/period/PeriodService.java
@@ -32,7 +32,7 @@
import javax.annotation.Nullable;
@Slf4j
-public final class PeriodService {
+public class PeriodService {
private final DaoStateService daoStateService;
diff --git a/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurn.java b/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurn.java
index 25317d7c8e1..7902741a9cf 100644
--- a/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurn.java
+++ b/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurn.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistablePayload;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.common.base.Charsets;
import java.util.Objects;
@@ -56,14 +54,14 @@ public MyProofOfBurn(String txId, String preImage) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.MyProofOfBurn toProtoMessage() {
- return PB.MyProofOfBurn.newBuilder()
+ public protobuf.MyProofOfBurn toProtoMessage() {
+ return protobuf.MyProofOfBurn.newBuilder()
.setTxId(txId)
.setPreImage(preImage)
.build();
}
- public static MyProofOfBurn fromProto(PB.MyProofOfBurn proto) {
+ public static MyProofOfBurn fromProto(protobuf.MyProofOfBurn proto) {
return new MyProofOfBurn(proto.getTxId(), proto.getPreImage());
}
diff --git a/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurnList.java b/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurnList.java
index a5d6c0ce997..ed0fb32e16a 100644
--- a/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurnList.java
+++ b/core/src/main/java/bisq/core/dao/governance/proofofburn/MyProofOfBurnList.java
@@ -19,8 +19,6 @@
import bisq.common.proto.persistable.PersistableList;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -47,18 +45,18 @@ private MyProofOfBurnList(List list) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.PersistableEnvelope toProtoMessage() {
- return PB.PersistableEnvelope.newBuilder().setMyProofOfBurnList(getBuilder()).build();
+ public protobuf.PersistableEnvelope toProtoMessage() {
+ return protobuf.PersistableEnvelope.newBuilder().setMyProofOfBurnList(getBuilder()).build();
}
- private PB.MyProofOfBurnList.Builder getBuilder() {
- return PB.MyProofOfBurnList.newBuilder()
+ private protobuf.MyProofOfBurnList.Builder getBuilder() {
+ return protobuf.MyProofOfBurnList.newBuilder()
.addAllMyProofOfBurn(getList().stream()
.map(MyProofOfBurn::toProtoMessage)
.collect(Collectors.toList()));
}
- public static MyProofOfBurnList fromProto(PB.MyProofOfBurnList proto) {
+ public static MyProofOfBurnList fromProto(protobuf.MyProofOfBurnList proto) {
return new MyProofOfBurnList(new ArrayList<>(proto.getMyProofOfBurnList().stream()
.map(MyProofOfBurn::fromProto)
.collect(Collectors.toList())));
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalList.java b/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalList.java
index 948d18f14d0..5ec0126d36b 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalList.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalList.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistableList;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -50,18 +48,18 @@ public MyProposalList(List list) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.PersistableEnvelope toProtoMessage() {
- return PB.PersistableEnvelope.newBuilder().setMyProposalList(getBuilder()).build();
+ public protobuf.PersistableEnvelope toProtoMessage() {
+ return protobuf.PersistableEnvelope.newBuilder().setMyProposalList(getBuilder()).build();
}
- private PB.MyProposalList.Builder getBuilder() {
- return PB.MyProposalList.newBuilder()
+ private protobuf.MyProposalList.Builder getBuilder() {
+ return protobuf.MyProposalList.newBuilder()
.addAllProposal(getList().stream()
.map(Proposal::toProtoMessage)
.collect(Collectors.toList()));
}
- public static MyProposalList fromProto(PB.MyProposalList proto) {
+ public static MyProposalList fromProto(protobuf.MyProposalList proto) {
return new MyProposalList(new ArrayList<>(proto.getProposalList().stream()
.map(Proposal::fromProto)
.collect(Collectors.toList())));
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalListService.java b/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalListService.java
index 0357ce7958e..d0933144c56 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalListService.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/MyProposalListService.java
@@ -32,7 +32,7 @@
import bisq.common.UserThread;
import bisq.common.app.DevEnv;
-import bisq.common.crypto.KeyRing;
+import bisq.common.crypto.PubKeyRing;
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ResultHandler;
import bisq.common.proto.persistable.PersistedDataHost;
@@ -85,14 +85,14 @@ public MyProposalListService(P2PService p2PService,
PeriodService periodService,
WalletsManager walletsManager,
Storage storage,
- KeyRing keyRing) {
+ PubKeyRing pubKeyRing) {
this.p2PService = p2PService;
this.daoStateService = daoStateService;
this.periodService = periodService;
this.walletsManager = walletsManager;
this.storage = storage;
- signaturePubKey = keyRing.getPubKeyRing().getSignaturePubKey();
+ signaturePubKey = pubKeyRing.getSignaturePubKey();
numConnectedPeersListener = (observable, oldValue, newValue) -> rePublishMyProposalsOnceWellConnected();
daoStateService.addDaoStateListener(this);
@@ -239,8 +239,8 @@ private void persist() {
}
private boolean canRemoveProposal(Proposal proposal, DaoStateService daoStateService, PeriodService periodService) {
- boolean inPhase = periodService.isInPhase(daoStateService.getChainHeight(), DaoPhase.Phase.PROPOSAL);
- return isMine(proposal) && inPhase;
+ boolean inProposalPhase = periodService.isInPhase(daoStateService.getChainHeight(), DaoPhase.Phase.PROPOSAL);
+ return isMine(proposal) && inProposalPhase;
}
}
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/ProposalValidator.java b/core/src/main/java/bisq/core/dao/governance/proposal/ProposalValidator.java
index e0f0118b1cc..2f7d97a7f5a 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/ProposalValidator.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/ProposalValidator.java
@@ -114,7 +114,7 @@ private boolean isValid(Proposal proposal, boolean allowUnconfirmed) {
if (isTxConfirmed) {
int txHeight = optionalTx.get().getBlockHeight();
if (!periodService.isTxInCorrectCycle(txHeight, chainHeight)) {
- log.debug("Tx is not in current cycle. proposal.getTxId()={}", proposal.getTxId());
+ log.trace("Tx is not in current cycle. proposal.getTxId()={}", proposal.getTxId());
return false;
}
if (!periodService.isInPhase(txHeight, DaoPhase.Phase.PROPOSAL)) {
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/param/ChangeParamValidator.java b/core/src/main/java/bisq/core/dao/governance/proposal/param/ChangeParamValidator.java
index e209bc204f7..626d30a5186 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/param/ChangeParamValidator.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/param/ChangeParamValidator.java
@@ -63,9 +63,13 @@ public ChangeParamValidator(DaoStateService daoStateService, PeriodService perio
public void validateDataFields(Proposal proposal) throws ProposalValidationException {
try {
super.validateDataFields(proposal);
- ChangeParamProposal changeParamProposal = (ChangeParamProposal) proposal;
- validateParamValue(changeParamProposal.getParam(), changeParamProposal.getParamValue(), getBlockHeight(proposal));
- checkArgument(changeParamProposal.getParamValue().length() <= 200, "ParamValue must not exceed 200 chars");
+
+ // Only once parsing is complete we can check for param changes
+ if (daoStateService.isParseBlockChainComplete()) {
+ ChangeParamProposal changeParamProposal = (ChangeParamProposal) proposal;
+ validateParamValue(changeParamProposal.getParam(), changeParamProposal.getParamValue(), getBlockHeight(proposal));
+ checkArgument(changeParamProposal.getParamValue().length() <= 200, "ParamValue must not exceed 200 chars");
+ }
} catch (ProposalValidationException e) {
throw e;
} catch (Throwable throwable) {
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalPayload.java b/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalPayload.java
index c6fa08a6c64..04a4eaa71f5 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalPayload.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalPayload.java
@@ -20,17 +20,12 @@
import bisq.core.dao.governance.ConsensusCritical;
import bisq.core.dao.state.model.governance.Proposal;
-import bisq.network.p2p.storage.payload.CapabilityRequiringPayload;
import bisq.network.p2p.storage.payload.PersistableNetworkPayload;
-import bisq.common.app.Capabilities;
-import bisq.common.app.Capability;
import bisq.common.crypto.Hash;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import lombok.Value;
@@ -45,8 +40,7 @@
@Immutable
@Slf4j
@Value
-public class ProposalPayload implements PersistableNetworkPayload, PersistableEnvelope,
- CapabilityRequiringPayload, ConsensusCritical {
+public class ProposalPayload implements PersistableNetworkPayload, PersistableEnvelope, ConsensusCritical {
private final Proposal proposal;
protected final byte[] hash; // 20 byte
@@ -64,25 +58,25 @@ private ProposalPayload(Proposal proposal, byte[] hash) {
this.hash = hash;
}
- private PB.ProposalPayload.Builder getProposalBuilder() {
- return PB.ProposalPayload.newBuilder()
+ private protobuf.ProposalPayload.Builder getProposalBuilder() {
+ return protobuf.ProposalPayload.newBuilder()
.setProposal(proposal.toProtoMessage())
.setHash(ByteString.copyFrom(hash));
}
@Override
- public PB.PersistableNetworkPayload toProtoMessage() {
- return PB.PersistableNetworkPayload.newBuilder()
+ public protobuf.PersistableNetworkPayload toProtoMessage() {
+ return protobuf.PersistableNetworkPayload.newBuilder()
.setProposalPayload(getProposalBuilder())
.build();
}
- public PB.ProposalPayload toProtoProposalPayload() {
+ public protobuf.ProposalPayload toProtoProposalPayload() {
return getProposalBuilder().build();
}
- public static ProposalPayload fromProto(PB.ProposalPayload proto) {
+ public static ProposalPayload fromProto(protobuf.ProposalPayload proto) {
return new ProposalPayload(Proposal.fromProto(proto.getProposal()),
proto.getHash().toByteArray());
}
@@ -102,16 +96,6 @@ public byte[] getHash() {
return hash;
}
-
- ///////////////////////////////////////////////////////////////////////////////////////////
- // CapabilityRequiringPayload
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- @Override
- public Capabilities getRequiredCapabilities() {
- return new Capabilities(Capability.PROPOSAL);
- }
-
@Override
public String toString() {
return "ProposalPayload{" +
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalStore.java b/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalStore.java
index b73e9ef0300..cd18dc8274b 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalStore.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/storage/appendonly/ProposalStore.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistableEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import java.util.List;
@@ -58,20 +56,20 @@ private ProposalStore(List list) {
}
public Message toProtoMessage() {
- return PB.PersistableEnvelope.newBuilder()
+ return protobuf.PersistableEnvelope.newBuilder()
.setProposalStore(getBuilder())
.build();
}
- private PB.ProposalStore.Builder getBuilder() {
- final List protoList = map.values().stream()
+ private protobuf.ProposalStore.Builder getBuilder() {
+ final List protoList = map.values().stream()
.map(payload -> (ProposalPayload) payload)
.map(ProposalPayload::toProtoProposalPayload)
.collect(Collectors.toList());
- return PB.ProposalStore.newBuilder().addAllItems(protoList);
+ return protobuf.ProposalStore.newBuilder().addAllItems(protoList);
}
- public static PersistableEnvelope fromProto(PB.ProposalStore proto) {
+ public static PersistableEnvelope fromProto(protobuf.ProposalStore proto) {
List list = proto.getItemsList().stream()
.map(ProposalPayload::fromProto).collect(Collectors.toList());
return new ProposalStore(list);
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalPayload.java b/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalPayload.java
index 38b993f1e6d..6ea17a819d1 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalPayload.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalPayload.java
@@ -19,19 +19,14 @@
import bisq.core.dao.state.model.governance.Proposal;
-import bisq.network.p2p.storage.payload.CapabilityRequiringPayload;
import bisq.network.p2p.storage.payload.ExpirablePayload;
import bisq.network.p2p.storage.payload.LazyProcessedPayload;
import bisq.network.p2p.storage.payload.ProtectedStoragePayload;
-import bisq.common.app.Capabilities;
-import bisq.common.app.Capability;
import bisq.common.crypto.Sig;
import bisq.common.proto.persistable.PersistablePayload;
import bisq.common.util.ExtraDataMapValidator;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import org.springframework.util.CollectionUtils;
@@ -61,7 +56,7 @@
@EqualsAndHashCode
@FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE)
public class TempProposalPayload implements LazyProcessedPayload, ProtectedStoragePayload,
- ExpirablePayload, CapabilityRequiringPayload, PersistablePayload {
+ ExpirablePayload, PersistablePayload {
protected final Proposal proposal;
protected final byte[] ownerPubKeyEncoded;
@@ -94,8 +89,8 @@ private TempProposalPayload(Proposal proposal,
ownerPubKey = Sig.getPublicKeyFromBytes(ownerPubKeyEncoded);
}
- private PB.TempProposalPayload.Builder getTempProposalPayloadBuilder() {
- final PB.TempProposalPayload.Builder builder = PB.TempProposalPayload.newBuilder()
+ private protobuf.TempProposalPayload.Builder getTempProposalPayloadBuilder() {
+ final protobuf.TempProposalPayload.Builder builder = protobuf.TempProposalPayload.newBuilder()
.setProposal(proposal.getProposalBuilder())
.setOwnerPubKeyEncoded(ByteString.copyFrom(ownerPubKeyEncoded));
Optional.ofNullable(extraDataMap).ifPresent(builder::putAllExtraData);
@@ -103,11 +98,11 @@ private PB.TempProposalPayload.Builder getTempProposalPayloadBuilder() {
}
@Override
- public PB.StoragePayload toProtoMessage() {
- return PB.StoragePayload.newBuilder().setTempProposalPayload(getTempProposalPayloadBuilder()).build();
+ public protobuf.StoragePayload toProtoMessage() {
+ return protobuf.StoragePayload.newBuilder().setTempProposalPayload(getTempProposalPayloadBuilder()).build();
}
- public static TempProposalPayload fromProto(PB.TempProposalPayload proto) {
+ public static TempProposalPayload fromProto(protobuf.TempProposalPayload proto) {
return new TempProposalPayload(Proposal.fromProto(proto.getProposal()),
proto.getOwnerPubKeyEncoded().toByteArray(),
CollectionUtils.isEmpty(proto.getExtraDataMap()) ? null : proto.getExtraDataMap());
@@ -124,16 +119,6 @@ public PublicKey getOwnerPubKey() {
}
- ///////////////////////////////////////////////////////////////////////////////////////////
- // CapabilityRequiringPayload
- ///////////////////////////////////////////////////////////////////////////////////////////
-
- @Override
- public Capabilities getRequiredCapabilities() {
- return new Capabilities(Capability.PROPOSAL);
- }
-
-
///////////////////////////////////////////////////////////////////////////////////////////
// ExpirablePayload
///////////////////////////////////////////////////////////////////////////////////////////
diff --git a/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalStore.java b/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalStore.java
index fa497be8201..81ef3c05908 100644
--- a/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalStore.java
+++ b/core/src/main/java/bisq/core/dao/governance/proposal/storage/temp/TempProposalStore.java
@@ -23,8 +23,6 @@
import bisq.common.proto.network.NetworkProtoResolver;
import bisq.common.proto.persistable.PersistableEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import javax.inject.Inject;
@@ -62,19 +60,19 @@ private TempProposalStore(List list) {
}
public Message toProtoMessage() {
- return PB.PersistableEnvelope.newBuilder()
+ return protobuf.PersistableEnvelope.newBuilder()
.setTempProposalStore(getBuilder())
.build();
}
- private PB.TempProposalStore.Builder getBuilder() {
- final List protoList = map.values().stream()
+ private protobuf.TempProposalStore.Builder getBuilder() {
+ final List protoList = map.values().stream()
.map(ProtectedStorageEntry::toProtectedStorageEntry)
.collect(Collectors.toList());
- return PB.TempProposalStore.newBuilder().addAllItems(protoList);
+ return protobuf.TempProposalStore.newBuilder().addAllItems(protoList);
}
- public static PersistableEnvelope fromProto(PB.TempProposalStore proto, NetworkProtoResolver networkProtoResolver) {
+ public static PersistableEnvelope fromProto(protobuf.TempProposalStore proto, NetworkProtoResolver networkProtoResolver) {
List list = proto.getItemsList().stream()
.map(entry -> ProtectedStorageEntry.fromProto(entry, networkProtoResolver))
.collect(Collectors.toList());
diff --git a/core/src/main/java/bisq/core/dao/monitoring/BlindVoteStateMonitoringService.java b/core/src/main/java/bisq/core/dao/monitoring/BlindVoteStateMonitoringService.java
index 797a6ebf833..01ae89c8521 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/BlindVoteStateMonitoringService.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/BlindVoteStateMonitoringService.java
@@ -157,7 +157,14 @@ public void onDaoStateChanged(Block block) {
System.currentTimeMillis() - ts);
}
}
- maybeUpdateHashChain(blockHeight);
+
+ long ts = System.currentTimeMillis();
+ boolean updated = maybeUpdateHashChain(blockHeight);
+ if (updated) {
+ log.info("updateHashChain for block {} took {} ms",
+ blockHeight,
+ System.currentTimeMillis() - ts);
+ }
}
@SuppressWarnings("Duplicates")
@@ -241,11 +248,11 @@ public void removeListener(Listener listener) {
// Private
///////////////////////////////////////////////////////////////////////////////////////////
- private void maybeUpdateHashChain(int blockHeight) {
+ private boolean maybeUpdateHashChain(int blockHeight) {
// We use first block in blind vote phase to create the hash of our blindVotes. We prefer to wait as long as
// possible to increase the chance that we have received all blindVotes.
if (!isFirstBlockOfBlindVotePhase(blockHeight)) {
- return;
+ return false;
}
periodService.getCycle(blockHeight).ifPresent(cycle -> {
@@ -281,9 +288,12 @@ private void maybeUpdateHashChain(int blockHeight) {
UserThread.runAfter(() -> blindVoteStateNetworkService.broadcastMyStateHash(myBlindVoteStateHash), delayInSec);
}
});
+ return true;
}
- private boolean processPeersBlindVoteStateHash(BlindVoteStateHash blindVoteStateHash, Optional peersNodeAddress, boolean notifyListeners) {
+ private boolean processPeersBlindVoteStateHash(BlindVoteStateHash blindVoteStateHash,
+ Optional peersNodeAddress,
+ boolean notifyListeners) {
AtomicBoolean changed = new AtomicBoolean(false);
AtomicBoolean inConflictWithNonSeedNode = new AtomicBoolean(this.isInConflictWithNonSeedNode);
AtomicBoolean inConflictWithSeedNode = new AtomicBoolean(this.isInConflictWithSeedNode);
diff --git a/core/src/main/java/bisq/core/dao/monitoring/DaoStateMonitoringService.java b/core/src/main/java/bisq/core/dao/monitoring/DaoStateMonitoringService.java
index d0846e11b54..843b2f570d0 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/DaoStateMonitoringService.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/DaoStateMonitoringService.java
@@ -117,6 +117,8 @@ public interface Listener {
);
private boolean checkpointFailed;
private boolean ignoreDevMsg;
+ private int numCalls;
+ private long accumulatedDuration;
private final File storageDir;
@@ -176,6 +178,12 @@ public void onParseBlockChainComplete() {
if (!ignoreDevMsg) {
verifyCheckpoints();
}
+
+ log.info("ParseBlockChainComplete: Accumulated updateHashChain() calls for {} block took {} ms " +
+ "({} ms in average / block)",
+ numCalls,
+ accumulatedDuration,
+ (int) ((double) accumulatedDuration / (double) numCalls));
}
@Override
@@ -277,6 +285,7 @@ public void removeListener(Listener listener) {
///////////////////////////////////////////////////////////////////////////////////////////
private void updateHashChain(Block block) {
+ long ts = System.currentTimeMillis();
byte[] prevHash;
int height = block.getHeight();
if (daoStateBlockChain.isEmpty()) {
@@ -316,6 +325,13 @@ private void updateHashChain(Block block) {
int delayInSec = 5 + new Random().nextInt(10);
UserThread.runAfter(() -> daoStateNetworkService.broadcastMyStateHash(myDaoStateHash), delayInSec);
}
+ long duration = System.currentTimeMillis() - ts;
+ // We don't want to spam the output. We log accumulated time after parsing is completed.
+ log.trace("updateHashChain for block {} took {} ms",
+ block.getHeight(),
+ duration);
+ accumulatedDuration += duration;
+ numCalls++;
}
private boolean processPeersDaoStateHash(DaoStateHash daoStateHash, Optional peersNodeAddress,
diff --git a/core/src/main/java/bisq/core/dao/monitoring/ProposalStateMonitoringService.java b/core/src/main/java/bisq/core/dao/monitoring/ProposalStateMonitoringService.java
index 1e610d5a21f..9b7863cf734 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/ProposalStateMonitoringService.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/ProposalStateMonitoringService.java
@@ -160,7 +160,13 @@ public void onDaoStateChanged(Block block) {
System.currentTimeMillis() - ts);
}
}
- maybeUpdateHashChain(blockHeight);
+ long ts = System.currentTimeMillis();
+ boolean updated = maybeUpdateHashChain(blockHeight);
+ if (updated) {
+ log.info("updateHashChain for block {} took {} ms",
+ blockHeight,
+ System.currentTimeMillis() - ts);
+ }
}
@SuppressWarnings("Duplicates")
diff --git a/core/src/main/java/bisq/core/dao/monitoring/model/BlindVoteStateHash.java b/core/src/main/java/bisq/core/dao/monitoring/model/BlindVoteStateHash.java
index 4ac39908b14..79a59032c71 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/model/BlindVoteStateHash.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/model/BlindVoteStateHash.java
@@ -18,8 +18,6 @@
package bisq.core.dao.monitoring.model;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import lombok.EqualsAndHashCode;
@@ -41,15 +39,15 @@ public BlindVoteStateHash(int cycleStartBlockHeight, byte[] hash, byte[] prevHas
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.BlindVoteStateHash toProtoMessage() {
- return PB.BlindVoteStateHash.newBuilder()
+ public protobuf.BlindVoteStateHash toProtoMessage() {
+ return protobuf.BlindVoteStateHash.newBuilder()
.setHeight(height)
.setHash(ByteString.copyFrom(hash))
.setPrevHash(ByteString.copyFrom(prevHash))
.setNumBlindVotes(numBlindVotes).build();
}
- public static BlindVoteStateHash fromProto(PB.BlindVoteStateHash proto) {
+ public static BlindVoteStateHash fromProto(protobuf.BlindVoteStateHash proto) {
return new BlindVoteStateHash(proto.getHeight(),
proto.getHash().toByteArray(),
proto.getPrevHash().toByteArray(),
diff --git a/core/src/main/java/bisq/core/dao/monitoring/model/DaoStateHash.java b/core/src/main/java/bisq/core/dao/monitoring/model/DaoStateHash.java
index db5e0c1bc69..e0e7f5e403a 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/model/DaoStateHash.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/model/DaoStateHash.java
@@ -17,7 +17,6 @@
package bisq.core.dao.monitoring.model;
-import io.bisq.generated.protobuffer.PB;
import com.google.protobuf.ByteString;
@@ -35,14 +34,14 @@ public DaoStateHash(int height, byte[] hash, byte[] prevHash) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.DaoStateHash toProtoMessage() {
- return PB.DaoStateHash.newBuilder()
+ public protobuf.DaoStateHash toProtoMessage() {
+ return protobuf.DaoStateHash.newBuilder()
.setHeight(height)
.setHash(ByteString.copyFrom(hash))
.setPrevHash(ByteString.copyFrom(prevHash)).build();
}
- public static DaoStateHash fromProto(PB.DaoStateHash proto) {
+ public static DaoStateHash fromProto(protobuf.DaoStateHash proto) {
return new DaoStateHash(proto.getHeight(),
proto.getHash().toByteArray(),
proto.getPrevHash().toByteArray());
diff --git a/core/src/main/java/bisq/core/dao/monitoring/model/ProposalStateHash.java b/core/src/main/java/bisq/core/dao/monitoring/model/ProposalStateHash.java
index 147170096d9..dc2ccdeabfe 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/model/ProposalStateHash.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/model/ProposalStateHash.java
@@ -18,8 +18,6 @@
package bisq.core.dao.monitoring.model;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import lombok.EqualsAndHashCode;
@@ -41,15 +39,15 @@ public ProposalStateHash(int cycleStartBlockHeight, byte[] hash, byte[] prevHash
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.ProposalStateHash toProtoMessage() {
- return PB.ProposalStateHash.newBuilder()
+ public protobuf.ProposalStateHash toProtoMessage() {
+ return protobuf.ProposalStateHash.newBuilder()
.setHeight(height)
.setHash(ByteString.copyFrom(hash))
.setPrevHash(ByteString.copyFrom(prevHash))
.setNumProposals(numProposals).build();
}
- public static ProposalStateHash fromProto(PB.ProposalStateHash proto) {
+ public static ProposalStateHash fromProto(protobuf.ProposalStateHash proto) {
return new ProposalStateHash(proto.getHeight(),
proto.getHash().toByteArray(),
proto.getPrevHash().toByteArray(),
diff --git a/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetBlindVoteStateHashesRequest.java b/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetBlindVoteStateHashesRequest.java
index aeb6c417849..7505c3f9c44 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetBlindVoteStateHashesRequest.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetBlindVoteStateHashesRequest.java
@@ -20,8 +20,6 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -42,15 +40,15 @@ private GetBlindVoteStateHashesRequest(int height, int nonce, int messageVersion
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setGetBlindVoteStateHashesRequest(PB.GetBlindVoteStateHashesRequest.newBuilder()
+ .setGetBlindVoteStateHashesRequest(protobuf.GetBlindVoteStateHashesRequest.newBuilder()
.setHeight(height)
.setNonce(nonce))
.build();
}
- public static NetworkEnvelope fromProto(PB.GetBlindVoteStateHashesRequest proto, int messageVersion) {
+ public static NetworkEnvelope fromProto(protobuf.GetBlindVoteStateHashesRequest proto, int messageVersion) {
return new GetBlindVoteStateHashesRequest(proto.getHeight(), proto.getNonce(), messageVersion);
}
}
diff --git a/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetBlindVoteStateHashesResponse.java b/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetBlindVoteStateHashesResponse.java
index a3e849d2877..6dd65027742 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetBlindVoteStateHashesResponse.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetBlindVoteStateHashesResponse.java
@@ -22,8 +22,6 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -50,9 +48,9 @@ private GetBlindVoteStateHashesResponse(List stateHashes,
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setGetBlindVoteStateHashesResponse(PB.GetBlindVoteStateHashesResponse.newBuilder()
+ .setGetBlindVoteStateHashesResponse(protobuf.GetBlindVoteStateHashesResponse.newBuilder()
.addAllStateHashes(stateHashes.stream()
.map(BlindVoteStateHash::toProtoMessage)
.collect(Collectors.toList()))
@@ -60,7 +58,7 @@ public PB.NetworkEnvelope toProtoNetworkEnvelope() {
.build();
}
- public static NetworkEnvelope fromProto(PB.GetBlindVoteStateHashesResponse proto, int messageVersion) {
+ public static NetworkEnvelope fromProto(protobuf.GetBlindVoteStateHashesResponse proto, int messageVersion) {
return new GetBlindVoteStateHashesResponse(proto.getStateHashesList().isEmpty() ?
new ArrayList<>() :
proto.getStateHashesList().stream()
diff --git a/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetDaoStateHashesRequest.java b/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetDaoStateHashesRequest.java
index d86ae1ee2f5..c9dc3af4821 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetDaoStateHashesRequest.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetDaoStateHashesRequest.java
@@ -20,8 +20,6 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -42,15 +40,15 @@ private GetDaoStateHashesRequest(int height, int nonce, int messageVersion) {
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setGetDaoStateHashesRequest(PB.GetDaoStateHashesRequest.newBuilder()
+ .setGetDaoStateHashesRequest(protobuf.GetDaoStateHashesRequest.newBuilder()
.setHeight(height)
.setNonce(nonce))
.build();
}
- public static NetworkEnvelope fromProto(PB.GetDaoStateHashesRequest proto, int messageVersion) {
+ public static NetworkEnvelope fromProto(protobuf.GetDaoStateHashesRequest proto, int messageVersion) {
return new GetDaoStateHashesRequest(proto.getHeight(), proto.getNonce(), messageVersion);
}
}
diff --git a/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetDaoStateHashesResponse.java b/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetDaoStateHashesResponse.java
index 83998072927..7582e73c317 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetDaoStateHashesResponse.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetDaoStateHashesResponse.java
@@ -22,8 +22,6 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -50,9 +48,9 @@ private GetDaoStateHashesResponse(List daoStateHashes,
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setGetDaoStateHashesResponse(PB.GetDaoStateHashesResponse.newBuilder()
+ .setGetDaoStateHashesResponse(protobuf.GetDaoStateHashesResponse.newBuilder()
.addAllStateHashes(stateHashes.stream()
.map(DaoStateHash::toProtoMessage)
.collect(Collectors.toList()))
@@ -60,7 +58,7 @@ public PB.NetworkEnvelope toProtoNetworkEnvelope() {
.build();
}
- public static NetworkEnvelope fromProto(PB.GetDaoStateHashesResponse proto, int messageVersion) {
+ public static NetworkEnvelope fromProto(protobuf.GetDaoStateHashesResponse proto, int messageVersion) {
return new GetDaoStateHashesResponse(proto.getStateHashesList().isEmpty() ?
new ArrayList<>() :
proto.getStateHashesList().stream()
diff --git a/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetProposalStateHashesRequest.java b/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetProposalStateHashesRequest.java
index e32895b7c1d..34f80ad39b1 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetProposalStateHashesRequest.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetProposalStateHashesRequest.java
@@ -20,8 +20,6 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -42,15 +40,15 @@ private GetProposalStateHashesRequest(int height, int nonce, int messageVersion)
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setGetProposalStateHashesRequest(PB.GetProposalStateHashesRequest.newBuilder()
+ .setGetProposalStateHashesRequest(protobuf.GetProposalStateHashesRequest.newBuilder()
.setHeight(height)
.setNonce(nonce))
.build();
}
- public static NetworkEnvelope fromProto(PB.GetProposalStateHashesRequest proto, int messageVersion) {
+ public static NetworkEnvelope fromProto(protobuf.GetProposalStateHashesRequest proto, int messageVersion) {
return new GetProposalStateHashesRequest(proto.getHeight(), proto.getNonce(), messageVersion);
}
}
diff --git a/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetProposalStateHashesResponse.java b/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetProposalStateHashesResponse.java
index 485ee25d4ec..1056594c606 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetProposalStateHashesResponse.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/network/messages/GetProposalStateHashesResponse.java
@@ -22,8 +22,6 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -50,9 +48,9 @@ private GetProposalStateHashesResponse(List proposalStateHash
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setGetProposalStateHashesResponse(PB.GetProposalStateHashesResponse.newBuilder()
+ .setGetProposalStateHashesResponse(protobuf.GetProposalStateHashesResponse.newBuilder()
.addAllStateHashes(stateHashes.stream()
.map(ProposalStateHash::toProtoMessage)
.collect(Collectors.toList()))
@@ -60,7 +58,7 @@ public PB.NetworkEnvelope toProtoNetworkEnvelope() {
.build();
}
- public static NetworkEnvelope fromProto(PB.GetProposalStateHashesResponse proto, int messageVersion) {
+ public static NetworkEnvelope fromProto(protobuf.GetProposalStateHashesResponse proto, int messageVersion) {
return new GetProposalStateHashesResponse(proto.getStateHashesList().isEmpty() ?
new ArrayList<>() :
proto.getStateHashesList().stream()
diff --git a/core/src/main/java/bisq/core/dao/monitoring/network/messages/NewBlindVoteStateHashMessage.java b/core/src/main/java/bisq/core/dao/monitoring/network/messages/NewBlindVoteStateHashMessage.java
index 8e4449b6c60..986371ce582 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/network/messages/NewBlindVoteStateHashMessage.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/network/messages/NewBlindVoteStateHashMessage.java
@@ -24,8 +24,6 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -46,14 +44,14 @@ private NewBlindVoteStateHashMessage(BlindVoteStateHash stateHash, int messageVe
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setNewBlindVoteStateHashMessage(PB.NewBlindVoteStateHashMessage.newBuilder()
+ .setNewBlindVoteStateHashMessage(protobuf.NewBlindVoteStateHashMessage.newBuilder()
.setStateHash(stateHash.toProtoMessage()))
.build();
}
- public static NetworkEnvelope fromProto(PB.NewBlindVoteStateHashMessage proto, int messageVersion) {
+ public static NetworkEnvelope fromProto(protobuf.NewBlindVoteStateHashMessage proto, int messageVersion) {
return new NewBlindVoteStateHashMessage(BlindVoteStateHash.fromProto(proto.getStateHash()), messageVersion);
}
diff --git a/core/src/main/java/bisq/core/dao/monitoring/network/messages/NewDaoStateHashMessage.java b/core/src/main/java/bisq/core/dao/monitoring/network/messages/NewDaoStateHashMessage.java
index 5300031865b..adc3523e448 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/network/messages/NewDaoStateHashMessage.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/network/messages/NewDaoStateHashMessage.java
@@ -24,8 +24,6 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -46,14 +44,14 @@ private NewDaoStateHashMessage(DaoStateHash daoStateHash, int messageVersion) {
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setNewDaoStateHashMessage(PB.NewDaoStateHashMessage.newBuilder()
+ .setNewDaoStateHashMessage(protobuf.NewDaoStateHashMessage.newBuilder()
.setStateHash(stateHash.toProtoMessage()))
.build();
}
- public static NetworkEnvelope fromProto(PB.NewDaoStateHashMessage proto, int messageVersion) {
+ public static NetworkEnvelope fromProto(protobuf.NewDaoStateHashMessage proto, int messageVersion) {
return new NewDaoStateHashMessage(DaoStateHash.fromProto(proto.getStateHash()), messageVersion);
}
diff --git a/core/src/main/java/bisq/core/dao/monitoring/network/messages/NewProposalStateHashMessage.java b/core/src/main/java/bisq/core/dao/monitoring/network/messages/NewProposalStateHashMessage.java
index 4e9485fdffd..eaf38180a2f 100644
--- a/core/src/main/java/bisq/core/dao/monitoring/network/messages/NewProposalStateHashMessage.java
+++ b/core/src/main/java/bisq/core/dao/monitoring/network/messages/NewProposalStateHashMessage.java
@@ -24,8 +24,6 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.EqualsAndHashCode;
import lombok.Getter;
@@ -46,14 +44,14 @@ private NewProposalStateHashMessage(ProposalStateHash proposalStateHash, int mes
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setNewProposalStateHashMessage(PB.NewProposalStateHashMessage.newBuilder()
+ .setNewProposalStateHashMessage(protobuf.NewProposalStateHashMessage.newBuilder()
.setStateHash(stateHash.toProtoMessage()))
.build();
}
- public static NetworkEnvelope fromProto(PB.NewProposalStateHashMessage proto, int messageVersion) {
+ public static NetworkEnvelope fromProto(protobuf.NewProposalStateHashMessage proto, int messageVersion) {
return new NewProposalStateHashMessage(ProposalStateHash.fromProto(proto.getStateHash()), messageVersion);
}
diff --git a/core/src/main/java/bisq/core/dao/node/BsqNode.java b/core/src/main/java/bisq/core/dao/node/BsqNode.java
index d0168beafed..042bd84ba40 100644
--- a/core/src/main/java/bisq/core/dao/node/BsqNode.java
+++ b/core/src/main/java/bisq/core/dao/node/BsqNode.java
@@ -202,7 +202,7 @@ protected int getStartBlockHeight() {
return startBlockHeight;
}
- abstract protected void startParseBlocks();
+ protected abstract void startParseBlocks();
protected void onParseBlockChainComplete() {
log.info("onParseBlockChainComplete");
diff --git a/core/src/main/java/bisq/core/dao/node/BsqNodeProvider.java b/core/src/main/java/bisq/core/dao/node/BsqNodeProvider.java
index c5c2302db4b..ad03966af3c 100644
--- a/core/src/main/java/bisq/core/dao/node/BsqNodeProvider.java
+++ b/core/src/main/java/bisq/core/dao/node/BsqNodeProvider.java
@@ -45,9 +45,10 @@ public BsqNodeProvider(LiteNode bsqLiteNode,
!preferences.getRpcPw().isEmpty() &&
preferences.getBlockNotifyPort() > 0;
boolean daoFullNode = preferences.isDaoFullNode();
- if (daoFullNode && !rpcDataSet)
- log.warn("daoFullNode is set but RPC user and pw are missing");
-
+ if (daoFullNode && !rpcDataSet) {
+ log.warn("daoFullNode is set in preferences but RPC user and pw are missing. We reset daoFullNode in preferences to false.");
+ preferences.setDaoFullNode(false);
+ }
bsqNode = daoFullNode && rpcDataSet ? bsqFullNode : bsqLiteNode;
}
}
diff --git a/core/src/main/java/bisq/core/dao/node/full/RawBlock.java b/core/src/main/java/bisq/core/dao/node/full/RawBlock.java
index 40101ed6655..686ecb2dbe7 100644
--- a/core/src/main/java/bisq/core/dao/node/full/RawBlock.java
+++ b/core/src/main/java/bisq/core/dao/node/full/RawBlock.java
@@ -22,8 +22,6 @@
import bisq.common.proto.network.NetworkPayload;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
@@ -75,16 +73,16 @@ public static RawBlock fromBlock(Block block) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.BaseBlock toProtoMessage() {
- PB.RawBlock.Builder builder = PB.RawBlock.newBuilder()
+ public protobuf.BaseBlock toProtoMessage() {
+ protobuf.RawBlock.Builder builder = protobuf.RawBlock.newBuilder()
.addAllRawTxs(rawTxs.stream()
.map(RawTx::toProtoMessage)
.collect(Collectors.toList()));
return getBaseBlockBuilder().setRawBlock(builder).build();
}
- public static RawBlock fromProto(PB.BaseBlock proto) {
- PB.RawBlock rawBlockProto = proto.getRawBlock();
+ public static RawBlock fromProto(protobuf.BaseBlock proto) {
+ protobuf.RawBlock rawBlockProto = proto.getRawBlock();
ImmutableList rawTxs = rawBlockProto.getRawTxsList().isEmpty() ?
ImmutableList.copyOf(new ArrayList<>()) :
ImmutableList.copyOf(rawBlockProto.getRawTxsList().stream()
diff --git a/core/src/main/java/bisq/core/dao/node/full/RawTx.java b/core/src/main/java/bisq/core/dao/node/full/RawTx.java
index 464e6432cf9..301f56eb0e3 100644
--- a/core/src/main/java/bisq/core/dao/node/full/RawTx.java
+++ b/core/src/main/java/bisq/core/dao/node/full/RawTx.java
@@ -24,8 +24,6 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkPayload;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
@@ -102,21 +100,21 @@ private RawTx(String txVersion,
}
@Override
- public PB.BaseTx toProtoMessage() {
- final PB.RawTx.Builder builder = PB.RawTx.newBuilder()
+ public protobuf.BaseTx toProtoMessage() {
+ final protobuf.RawTx.Builder builder = protobuf.RawTx.newBuilder()
.addAllRawTxOutputs(rawTxOutputs.stream()
.map(RawTxOutput::toProtoMessage)
.collect(Collectors.toList()));
return getBaseTxBuilder().setRawTx(builder).build();
}
- public static RawTx fromProto(PB.BaseTx protoBaseTx) {
+ public static RawTx fromProto(protobuf.BaseTx protoBaseTx) {
ImmutableList txInputs = protoBaseTx.getTxInputsList().isEmpty() ?
ImmutableList.copyOf(new ArrayList<>()) :
ImmutableList.copyOf(protoBaseTx.getTxInputsList().stream()
.map(TxInput::fromProto)
.collect(Collectors.toList()));
- PB.RawTx protoRawTx = protoBaseTx.getRawTx();
+ protobuf.RawTx protoRawTx = protoBaseTx.getRawTx();
ImmutableList outputs = protoRawTx.getRawTxOutputsList().isEmpty() ?
ImmutableList.copyOf(new ArrayList<>()) :
ImmutableList.copyOf(protoRawTx.getRawTxOutputsList().stream()
diff --git a/core/src/main/java/bisq/core/dao/node/full/RawTxOutput.java b/core/src/main/java/bisq/core/dao/node/full/RawTxOutput.java
index 9b20cc577ce..2d5599b2fbb 100644
--- a/core/src/main/java/bisq/core/dao/node/full/RawTxOutput.java
+++ b/core/src/main/java/bisq/core/dao/node/full/RawTxOutput.java
@@ -23,8 +23,6 @@
import bisq.common.proto.network.NetworkPayload;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.EqualsAndHashCode;
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
@@ -73,11 +71,11 @@ public RawTxOutput(int index,
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.BaseTxOutput toProtoMessage() {
- return getRawTxOutputBuilder().setRawTxOutput(PB.RawTxOutput.newBuilder()).build();
+ public protobuf.BaseTxOutput toProtoMessage() {
+ return getRawTxOutputBuilder().setRawTxOutput(protobuf.RawTxOutput.newBuilder()).build();
}
- public static RawTxOutput fromProto(PB.BaseTxOutput proto) {
+ public static RawTxOutput fromProto(protobuf.BaseTxOutput proto) {
return new RawTxOutput(proto.getIndex(),
proto.getValue(),
proto.getTxId(),
diff --git a/core/src/main/java/bisq/core/dao/node/full/RpcService.java b/core/src/main/java/bisq/core/dao/node/full/RpcService.java
index 1c43396e3e3..af3c5f86655 100644
--- a/core/src/main/java/bisq/core/dao/node/full/RpcService.java
+++ b/core/src/main/java/bisq/core/dao/node/full/RpcService.java
@@ -72,8 +72,10 @@
public class RpcService {
private final String rpcUser;
private final String rpcPassword;
+ private final String rpcHost;
private final String rpcPort;
- private final int blockNotifyPort;
+ private final String rpcBlockPort;
+ private final String rpcBlockHost;
private BtcdClient client;
private BtcdDaemon daemon;
@@ -90,22 +92,28 @@ public class RpcService {
@SuppressWarnings("WeakerAccess")
@Inject
public RpcService(Preferences preferences,
- @Named(DaoOptionKeys.RPC_PORT) String rpcPort) {
+ @Named(DaoOptionKeys.RPC_HOST) String rpcHost,
+ @Named(DaoOptionKeys.RPC_PORT) String rpcPort,
+ @Named(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_PORT) String rpcBlockPort,
+ @Named(DaoOptionKeys.RPC_BLOCK_NOTIFICATION_HOST) String rpcBlockHost) {
this.rpcUser = preferences.getRpcUser();
this.rpcPassword = preferences.getRpcPw();
- this.blockNotifyPort = preferences.getBlockNotifyPort();
// mainnet is 8332, testnet 18332, regtest 18443
+ boolean isHostSet = rpcHost != null && !rpcHost.isEmpty();
boolean isPortSet = rpcPort != null && !rpcPort.isEmpty();
boolean isMainnet = BisqEnvironment.getBaseCurrencyNetwork().isMainnet();
boolean isTestnet = BisqEnvironment.getBaseCurrencyNetwork().isTestnet();
boolean isDaoBetaNet = BisqEnvironment.getBaseCurrencyNetwork().isDaoBetaNet();
+ this.rpcHost = isHostSet ? rpcHost : "127.0.0.1";
this.rpcPort = isPortSet ? rpcPort :
isMainnet || isDaoBetaNet ? "8332" :
isTestnet ? "18332" :
- "18443"; // regtest
-
- log.info("Version of btcd-cli4j library: {}", BtcdCli4jVersion.VERSION);
+ "18443"; // regtest
+ boolean isBlockPortSet = rpcBlockPort != null && !rpcBlockPort.isEmpty();
+ boolean isBlockHostSet = rpcBlockHost != null && !rpcBlockHost.isEmpty();
+ this.rpcBlockPort = isBlockPortSet ? rpcBlockPort : "5125";
+ this.rpcBlockHost = isBlockHostSet ? rpcBlockHost : "127.0.0.1";
}
@@ -116,17 +124,23 @@ public RpcService(Preferences preferences,
void setup(ResultHandler resultHandler, Consumer errorHandler) {
ListenableFuture future = executor.submit(() -> {
try {
+ log.info("Starting RPCService with btcd-cli4j version {} on {}:{} with user {}, " +
+ "listening for blocknotify on port {} from {}",
+ BtcdCli4jVersion.VERSION, this.rpcHost, this.rpcPort, this.rpcUser, this.rpcBlockPort,
+ this.rpcBlockHost);
+
long startTs = System.currentTimeMillis();
PoolingHttpClientConnectionManager cm = new PoolingHttpClientConnectionManager();
CloseableHttpClient httpProvider = HttpClients.custom().setConnectionManager(cm).build();
Properties nodeConfig = new Properties();
nodeConfig.setProperty("node.bitcoind.rpc.protocol", "http");
- nodeConfig.setProperty("node.bitcoind.rpc.host", "127.0.0.1");
+ nodeConfig.setProperty("node.bitcoind.rpc.host", rpcHost);
nodeConfig.setProperty("node.bitcoind.rpc.auth_scheme", "Basic");
nodeConfig.setProperty("node.bitcoind.rpc.user", rpcUser);
nodeConfig.setProperty("node.bitcoind.rpc.password", rpcPassword);
nodeConfig.setProperty("node.bitcoind.rpc.port", rpcPort);
- nodeConfig.setProperty("node.bitcoind.notification.block.port", String.valueOf(blockNotifyPort));
+ nodeConfig.setProperty("node.bitcoind.notification.block.port", rpcBlockPort);
+ nodeConfig.setProperty("node.bitcoind.notification.block.host", rpcBlockHost);
nodeConfig.setProperty("node.bitcoind.notification.alert.port", String.valueOf(bisq.network.p2p.Utils.findFreeSystemPort()));
nodeConfig.setProperty("node.bitcoind.notification.wallet.port", String.valueOf(bisq.network.p2p.Utils.findFreeSystemPort()));
@@ -245,7 +259,8 @@ public void onFailure(@NotNull Throwable throwable) {
// Private
///////////////////////////////////////////////////////////////////////////////////////////
- private RawTx getTxFromRawTransaction(RawTransaction rawBtcTx, com.neemre.btcdcli4j.core.domain.RawBlock rawBtcBlock) {
+ private RawTx getTxFromRawTransaction(RawTransaction rawBtcTx,
+ com.neemre.btcdcli4j.core.domain.RawBlock rawBtcBlock) {
String txId = rawBtcTx.getTxId();
long blockTime = rawBtcBlock.getTime() * 1000; // We convert block time from sec to ms
int blockHeight = rawBtcBlock.getHeight();
@@ -277,7 +292,7 @@ private RawTx getTxFromRawTransaction(RawTransaction rawBtcTx, com.neemre.btcdcl
.filter(e -> e != null && e.getN() != null && e.getValue() != null && e.getScriptPubKey() != null)
.map(rawBtcTxOutput -> {
byte[] opReturnData = null;
- com.neemre.btcdcli4j.core.domain.PubKeyScript scriptPubKey = rawBtcTxOutput.getScriptPubKey();
+ com.neemre.btcdcli4j.core.domain.PubKeyScript scriptPubKey = rawBtcTxOutput.getScriptPubKey();
if (ScriptTypes.NULL_DATA.equals(scriptPubKey.getType()) && scriptPubKey.getAsm() != null) {
String[] chunks = scriptPubKey.getAsm().split(" ");
// We get on testnet a lot of "OP_RETURN 0" data, so we filter those away
@@ -297,10 +312,10 @@ private RawTx getTxFromRawTransaction(RawTransaction rawBtcTx, com.neemre.btcdcl
// We don't support raw MS which are the only case where scriptPubKey.getAddresses()>1
String address = scriptPubKey.getAddresses() != null &&
scriptPubKey.getAddresses().size() == 1 ? scriptPubKey.getAddresses().get(0) : null;
- PubKeyScript pubKeyScript = new PubKeyScript(scriptPubKey);
- return new RawTxOutput(rawBtcTxOutput.getN(),
- rawBtcTxOutput.getValue().movePointRight(8).longValue(),
- rawBtcTx.getTxId(),
+ PubKeyScript pubKeyScript = new PubKeyScript(scriptPubKey);
+ return new RawTxOutput(rawBtcTxOutput.getN(),
+ rawBtcTxOutput.getValue().movePointRight(8).longValue(),
+ rawBtcTx.getTxId(),
pubKeyScript,
address,
opReturnData,
diff --git a/core/src/main/java/bisq/core/dao/node/lite/LiteNode.java b/core/src/main/java/bisq/core/dao/node/lite/LiteNode.java
index d6fd1a64cb6..a51c5a11235 100644
--- a/core/src/main/java/bisq/core/dao/node/lite/LiteNode.java
+++ b/core/src/main/java/bisq/core/dao/node/lite/LiteNode.java
@@ -88,9 +88,6 @@ public void start() {
liteNodeNetworkService.start();
bsqWalletService.addNewBestBlockListener(block -> {
- int height = block.getHeight();
- log.info("New block at height {} from bsqWalletService", height);
-
// Check if we are done with parsing
if (!daoStateService.isParseBlockChainComplete())
return;
@@ -100,6 +97,9 @@ public void start() {
checkForBlockReceivedTimer.stop();
}
+ int height = block.getHeight();
+ log.info("New block at height {} from bsqWalletService", height);
+
// We expect to receive the new BSQ block from the network shortly after BitcoinJ has been aware of it.
// If we don't receive it we request it manually from seed nodes
checkForBlockReceivedTimer = UserThread.runAfter(() -> {
@@ -199,7 +199,7 @@ private void onRequestedBlocksReceived(List blockList, Runnable onPars
runDelayedBatchProcessing(new ArrayList<>(blockList),
() -> {
- log.info("Parsing {} blocks took {} seconds.", blockList.size(), (System.currentTimeMillis() - ts) / 1000d);
+ log.debug("Parsing {} blocks took {} seconds.", blockList.size(), (System.currentTimeMillis() - ts) / 1000d);
if (daoStateService.getChainHeight() < bsqWalletService.getBestChainHeight()) {
liteNodeNetworkService.requestBlocks(getStartBlockHeight());
} else {
@@ -229,7 +229,7 @@ private void runDelayedBatchProcessing(List blocks, Runnable resultHan
// We received a new block
private void onNewBlockReceived(RawBlock block) {
int blockHeight = block.getHeight();
- log.info("onNewBlockReceived: block at height {}, hash={}", blockHeight, block.getHash());
+ log.debug("onNewBlockReceived: block at height {}, hash={}", blockHeight, block.getHash());
// We only update chainTipHeight if we get a newer block
if (blockHeight > chainTipHeight)
diff --git a/core/src/main/java/bisq/core/dao/node/lite/network/LiteNodeNetworkService.java b/core/src/main/java/bisq/core/dao/node/lite/network/LiteNodeNetworkService.java
index 7b5c345d7fa..2cb081834f6 100644
--- a/core/src/main/java/bisq/core/dao/node/lite/network/LiteNodeNetworkService.java
+++ b/core/src/main/java/bisq/core/dao/node/lite/network/LiteNodeNetworkService.java
@@ -143,6 +143,10 @@ public void addListener(Listener listener) {
listeners.add(listener);
}
+ /**
+ *
+ * @param startBlockHeight Block height from where we expect new blocks (current block height in bsqState + 1)
+ */
public void requestBlocks(int startBlockHeight) {
lastRequestedBlockHeight = startBlockHeight;
Optional connectionToSeedNodeOptional = networkNode.getConfirmedConnections().stream()
@@ -231,8 +235,8 @@ public void onMessage(NetworkEnvelope networkEnvelope, Connection connection) {
List txIds = newBlockBroadcastMessage.getBlock().getRawTxs().stream().map(BaseTx::getId).collect(Collectors.toList());
String extBlockId = newBlockBroadcastMessage.getBlock().getHash() + ":" + txIds;
if (!receivedBlocks.contains(extBlockId)) {
- log.info("We received a new message from peer {} and broadcast it to our peers. extBlockId={}",
- connection.getPeersNodeAddressOptional(), extBlockId);
+ log.debug("We received a new message from peer {} and broadcast it to our peers. extBlockId={}",
+ connection.getPeersNodeAddressOptional().orElse(null), extBlockId);
receivedBlocks.add(extBlockId);
broadcaster.broadcast(newBlockBroadcastMessage, networkNode.getNodeAddress(), null, false);
listeners.forEach(listener -> listener.onNewBlockReceived(newBlockBroadcastMessage));
@@ -259,7 +263,7 @@ private void requestBlocks(NodeAddress peersNodeAddress, int startBlockHeight) {
new RequestBlocksHandler.Listener() {
@Override
public void onComplete(GetBlocksResponse getBlocksResponse) {
- log.info("requestBlocksHandler of outbound connection complete. nodeAddress={}",
+ log.debug("requestBlocksHandler of outbound connection complete. nodeAddress={}",
peersNodeAddress);
stopRetryTimer();
diff --git a/core/src/main/java/bisq/core/dao/node/messages/GetBlocksRequest.java b/core/src/main/java/bisq/core/dao/node/messages/GetBlocksRequest.java
index 4d180ccabef..d78ffdf37d3 100644
--- a/core/src/main/java/bisq/core/dao/node/messages/GetBlocksRequest.java
+++ b/core/src/main/java/bisq/core/dao/node/messages/GetBlocksRequest.java
@@ -21,15 +21,11 @@
import bisq.network.p2p.NodeAddress;
import bisq.network.p2p.SendersNodeAddressMessage;
import bisq.network.p2p.SupportedCapabilitiesMessage;
-import bisq.network.p2p.storage.payload.CapabilityRequiringPayload;
import bisq.common.app.Capabilities;
-import bisq.common.app.Capability;
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Optional;
import lombok.EqualsAndHashCode;
@@ -38,11 +34,17 @@
import javax.annotation.Nullable;
+// TODO We remove CapabilityRequiringPayload as it would cause problems if the lite node connects to a new seed node and
+// they have not exchanged capabilities already. We need to improve capability handling the we can re-enable it again.
+// As this message is sent any only to seed nodes it does not has any effect. Even if a lite node receives it it will be
+// simply ignored.
+
+// This message is sent only to full DAO nodes
@EqualsAndHashCode(callSuper = true)
@Getter
@Slf4j
public final class GetBlocksRequest extends NetworkEnvelope implements DirectMessage, SendersNodeAddressMessage,
- CapabilityRequiringPayload, SupportedCapabilitiesMessage {
+ /*CapabilityRequiringPayload, */SupportedCapabilitiesMessage {
private final int fromBlockHeight;
private final int nonce;
@@ -82,8 +84,8 @@ private GetBlocksRequest(int fromBlockHeight,
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
- PB.GetBlocksRequest.Builder builder = PB.GetBlocksRequest.newBuilder()
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
+ protobuf.GetBlocksRequest.Builder builder = protobuf.GetBlocksRequest.newBuilder()
.setFromBlockHeight(fromBlockHeight)
.setNonce(nonce);
Optional.ofNullable(senderNodeAddress).ifPresent(e -> builder.setSenderNodeAddress(e.toProtoMessage()));
@@ -91,8 +93,8 @@ public PB.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder().setGetBlocksRequest(builder).build();
}
- public static NetworkEnvelope fromProto(PB.GetBlocksRequest proto, int messageVersion) {
- PB.NodeAddress protoNodeAddress = proto.getSenderNodeAddress();
+ public static NetworkEnvelope fromProto(protobuf.GetBlocksRequest proto, int messageVersion) {
+ protobuf.NodeAddress protoNodeAddress = proto.getSenderNodeAddress();
NodeAddress senderNodeAddress = protoNodeAddress.getHostName().isEmpty() ?
null :
NodeAddress.fromProto(protoNodeAddress);
@@ -106,10 +108,10 @@ public static NetworkEnvelope fromProto(PB.GetBlocksRequest proto, int messageVe
messageVersion);
}
- @Override
- public Capabilities getRequiredCapabilities() {
- return new Capabilities(Capability.DAO_FULL_NODE);
- }
+// @Override
+// public Capabilities getRequiredCapabilities() {
+// return new Capabilities(Capability.DAO_FULL_NODE);
+// }
@Override
public String toString() {
diff --git a/core/src/main/java/bisq/core/dao/node/messages/GetBlocksResponse.java b/core/src/main/java/bisq/core/dao/node/messages/GetBlocksResponse.java
index 12454a2bdaa..87f814fdee6 100644
--- a/core/src/main/java/bisq/core/dao/node/messages/GetBlocksResponse.java
+++ b/core/src/main/java/bisq/core/dao/node/messages/GetBlocksResponse.java
@@ -25,8 +25,6 @@
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -58,9 +56,9 @@ private GetBlocksResponse(List blocks, int requestNonce, int messageVe
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setGetBlocksResponse(PB.GetBlocksResponse.newBuilder()
+ .setGetBlocksResponse(protobuf.GetBlocksResponse.newBuilder()
.addAllRawBlocks(blocks.stream()
.map(RawBlock::toProtoMessage)
.collect(Collectors.toList()))
@@ -68,7 +66,7 @@ public PB.NetworkEnvelope toProtoNetworkEnvelope() {
.build();
}
- public static NetworkEnvelope fromProto(PB.GetBlocksResponse proto, int messageVersion) {
+ public static NetworkEnvelope fromProto(protobuf.GetBlocksResponse proto, int messageVersion) {
List list = proto.getRawBlocksList().stream()
.map(RawBlock::fromProto)
.collect(Collectors.toList());
diff --git a/core/src/main/java/bisq/core/dao/node/messages/NewBlockBroadcastMessage.java b/core/src/main/java/bisq/core/dao/node/messages/NewBlockBroadcastMessage.java
index ed8ae157e0a..658ace48e02 100644
--- a/core/src/main/java/bisq/core/dao/node/messages/NewBlockBroadcastMessage.java
+++ b/core/src/main/java/bisq/core/dao/node/messages/NewBlockBroadcastMessage.java
@@ -20,21 +20,21 @@
import bisq.core.dao.node.full.RawBlock;
import bisq.network.p2p.storage.messages.BroadcastMessage;
-import bisq.network.p2p.storage.payload.CapabilityRequiringPayload;
-import bisq.common.app.Capabilities;
-import bisq.common.app.Capability;
import bisq.common.app.Version;
import bisq.common.proto.network.NetworkEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.EqualsAndHashCode;
import lombok.Getter;
+// We remove the CapabilityRequiringPayload interface to avoid risks that new BSQ blocks are not well distributed in
+// case the capability is not exchanged at the time when the message is sent. We need to improve the capability handling
+// so that we can be sure that we know the actual capability of the peer.
+
+// This message is sent only to lite DAO nodes (full nodes get block from their local bitcoind)
@EqualsAndHashCode(callSuper = true)
@Getter
-public final class NewBlockBroadcastMessage extends BroadcastMessage implements CapabilityRequiringPayload {
+public final class NewBlockBroadcastMessage extends BroadcastMessage /*implements CapabilityRequiringPayload*/ {
private final RawBlock block;
public NewBlockBroadcastMessage(RawBlock block) {
@@ -52,20 +52,20 @@ private NewBlockBroadcastMessage(RawBlock block, int messageVersion) {
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
return getNetworkEnvelopeBuilder()
- .setNewBlockBroadcastMessage(PB.NewBlockBroadcastMessage.newBuilder()
+ .setNewBlockBroadcastMessage(protobuf.NewBlockBroadcastMessage.newBuilder()
.setRawBlock(block.toProtoMessage()))
.build();
}
- public static NetworkEnvelope fromProto(PB.NewBlockBroadcastMessage proto, int messageVersion) {
+ public static NetworkEnvelope fromProto(protobuf.NewBlockBroadcastMessage proto, int messageVersion) {
return new NewBlockBroadcastMessage(RawBlock.fromProto(proto.getRawBlock()),
messageVersion);
}
- @Override
- public Capabilities getRequiredCapabilities() {
- return new Capabilities(Capability.RECEIVE_BSQ_BLOCK);
- }
+// @Override
+// public Capabilities getRequiredCapabilities() {
+// return new Capabilities(Capability.RECEIVE_BSQ_BLOCK);
+// }
}
diff --git a/core/src/main/java/bisq/core/dao/node/parser/BlockParser.java b/core/src/main/java/bisq/core/dao/node/parser/BlockParser.java
index 5cb3d8e17fb..a1b7409bf2b 100644
--- a/core/src/main/java/bisq/core/dao/node/parser/BlockParser.java
+++ b/core/src/main/java/bisq/core/dao/node/parser/BlockParser.java
@@ -80,7 +80,7 @@ public BlockParser(TxParser txParser,
*/
public Block parseBlock(RawBlock rawBlock) throws BlockHashNotConnectingException, BlockHeightNotConnectingException {
int blockHeight = rawBlock.getHeight();
- log.debug("Parse block at height={} ", blockHeight);
+ log.trace("Parse block at height={} ", blockHeight);
validateIfBlockIsConnecting(rawBlock);
diff --git a/core/src/main/java/bisq/core/dao/node/parser/TxParser.java b/core/src/main/java/bisq/core/dao/node/parser/TxParser.java
index 57c0cf11816..42be945a632 100644
--- a/core/src/main/java/bisq/core/dao/node/parser/TxParser.java
+++ b/core/src/main/java/bisq/core/dao/node/parser/TxParser.java
@@ -385,7 +385,7 @@ static TxType evaluateTxType(TempTx tempTx, Optional optionalOpRet
}
// TRANSFER_BSQ has no fee, no opReturn and no UNLOCK_OUTPUT at first output
- log.debug("No burned fee and no OP_RETURN, so this is a TRANSFER_BSQ tx.");
+ log.trace("No burned fee and no OP_RETURN, so this is a TRANSFER_BSQ tx.");
return TxType.TRANSFER_BSQ;
}
diff --git a/core/src/main/java/bisq/core/dao/state/DaoStateSnapshotService.java b/core/src/main/java/bisq/core/dao/state/DaoStateSnapshotService.java
index 9dc29217c85..df98840cd02 100644
--- a/core/src/main/java/bisq/core/dao/state/DaoStateSnapshotService.java
+++ b/core/src/main/java/bisq/core/dao/state/DaoStateSnapshotService.java
@@ -98,7 +98,7 @@ public void maybeCreateSnapshot(Block block) {
LinkedList clonedDaoStateHashChain = new LinkedList<>(daoStateHashChainSnapshotCandidate);
daoStateStorageService.persist(clonedDaoState, clonedDaoStateHashChain);
- log.info("Saved snapshotCandidate with height {} to Disc at height {} took {} ms",
+ log.debug("Saved snapshotCandidate with height {} to Disc at height {} took {} ms",
daoStateSnapshotCandidate.getChainHeight(), chainHeight, System.currentTimeMillis() - ts);
}
@@ -107,7 +107,7 @@ public void maybeCreateSnapshot(Block block) {
daoStateSnapshotCandidate = daoStateService.getClone();
daoStateHashChainSnapshotCandidate = new LinkedList<>(daoStateMonitoringService.getDaoStateHashChain());
- log.info("Cloned new snapshotCandidate at height {} took {} ms", chainHeight, System.currentTimeMillis() - ts);
+ log.debug("Cloned new snapshotCandidate at height {} took {} ms", chainHeight, System.currentTimeMillis() - ts);
}
}
@@ -119,7 +119,7 @@ public void applySnapshot(boolean fromReorg) {
int chainHeightOfPersisted = persistedBsqState.getChainHeight();
if (!blocks.isEmpty()) {
int heightOfLastBlock = blocks.getLast().getHeight();
- log.info("applySnapshot from persistedBsqState daoState with height of last block {}", heightOfLastBlock);
+ log.debug("applySnapshot from persistedBsqState daoState with height of last block {}", heightOfLastBlock);
if (isValidHeight(heightOfLastBlock)) {
if (chainHeightOfLastApplySnapshot != chainHeightOfPersisted) {
chainHeightOfLastApplySnapshot = chainHeightOfPersisted;
diff --git a/core/src/main/java/bisq/core/dao/state/DaoStateStore.java b/core/src/main/java/bisq/core/dao/state/DaoStateStore.java
index 8e74c7cfa1a..a0a28e66004 100644
--- a/core/src/main/java/bisq/core/dao/state/DaoStateStore.java
+++ b/core/src/main/java/bisq/core/dao/state/DaoStateStore.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistableEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import java.util.LinkedList;
@@ -59,17 +57,17 @@ public class DaoStateStore implements PersistableEnvelope {
public Message toProtoMessage() {
checkNotNull(daoState, "daoState must not be null when toProtoMessage is invoked");
- PB.DaoStateStore.Builder builder = PB.DaoStateStore.newBuilder()
+ protobuf.DaoStateStore.Builder builder = protobuf.DaoStateStore.newBuilder()
.setDaoState(daoState.getBsqStateBuilder())
.addAllDaoStateHash(daoStateHashChain.stream()
.map(DaoStateHash::toProtoMessage)
.collect(Collectors.toList()));
- return PB.PersistableEnvelope.newBuilder()
+ return protobuf.PersistableEnvelope.newBuilder()
.setDaoStateStore(builder)
.build();
}
- public static PersistableEnvelope fromProto(PB.DaoStateStore proto) {
+ public static PersistableEnvelope fromProto(protobuf.DaoStateStore proto) {
LinkedList daoStateHashList = proto.getDaoStateHashList().isEmpty() ?
new LinkedList<>() :
new LinkedList<>(proto.getDaoStateHashList().stream()
diff --git a/core/src/main/java/bisq/core/dao/state/model/DaoState.java b/core/src/main/java/bisq/core/dao/state/model/DaoState.java
index e06a7b20a63..7d0cf31a66c 100644
--- a/core/src/main/java/bisq/core/dao/state/model/DaoState.java
+++ b/core/src/main/java/bisq/core/dao/state/model/DaoState.java
@@ -29,8 +29,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import javax.inject.Inject;
@@ -154,14 +152,14 @@ public Message toProtoMessage() {
return getBsqStateBuilder().build();
}
- public PB.DaoState.Builder getBsqStateBuilder() {
+ public protobuf.DaoState.Builder getBsqStateBuilder() {
return getBsqStateBuilderExcludingBlocks().addAllBlocks(blocks.stream()
.map(Block::toProtoMessage)
.collect(Collectors.toList()));
}
- private PB.DaoState.Builder getBsqStateBuilderExcludingBlocks() {
- PB.DaoState.Builder builder = PB.DaoState.newBuilder();
+ private protobuf.DaoState.Builder getBsqStateBuilderExcludingBlocks() {
+ protobuf.DaoState.Builder builder = protobuf.DaoState.newBuilder();
builder.setChainHeight(chainHeight)
.addAllCycles(cycles.stream().map(Cycle::toProtoMessage).collect(Collectors.toList()))
.putAllUnspentTxOutputMap(unspentTxOutputMap.entrySet().stream()
@@ -177,7 +175,7 @@ private PB.DaoState.Builder getBsqStateBuilderExcludingBlocks() {
return builder;
}
- public static DaoState fromProto(PB.DaoState proto) {
+ public static DaoState fromProto(protobuf.DaoState proto) {
LinkedList blocks = proto.getBlocksList().stream()
.map(Block::fromProto)
.collect(Collectors.toCollection(LinkedList::new));
diff --git a/core/src/main/java/bisq/core/dao/state/model/blockchain/BaseBlock.java b/core/src/main/java/bisq/core/dao/state/model/blockchain/BaseBlock.java
index e9a2dd8fae0..d993cdfaba3 100644
--- a/core/src/main/java/bisq/core/dao/state/model/blockchain/BaseBlock.java
+++ b/core/src/main/java/bisq/core/dao/state/model/blockchain/BaseBlock.java
@@ -19,8 +19,6 @@
import bisq.core.dao.state.model.ImmutableDaoStateModel;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Optional;
import lombok.Data;
@@ -53,8 +51,8 @@ protected BaseBlock(int height, long time, String hash, @SuppressWarnings("Nulla
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- protected PB.BaseBlock.Builder getBaseBlockBuilder() {
- PB.BaseBlock.Builder builder = PB.BaseBlock.newBuilder()
+ protected protobuf.BaseBlock.Builder getBaseBlockBuilder() {
+ protobuf.BaseBlock.Builder builder = protobuf.BaseBlock.newBuilder()
.setHeight(height)
.setTime(time)
.setHash(hash);
diff --git a/core/src/main/java/bisq/core/dao/state/model/blockchain/BaseTx.java b/core/src/main/java/bisq/core/dao/state/model/blockchain/BaseTx.java
index 37960e22268..19c9754808d 100644
--- a/core/src/main/java/bisq/core/dao/state/model/blockchain/BaseTx.java
+++ b/core/src/main/java/bisq/core/dao/state/model/blockchain/BaseTx.java
@@ -19,8 +19,6 @@
import bisq.core.dao.state.model.ImmutableDaoStateModel;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.common.collect.ImmutableList;
import java.util.stream.Collectors;
@@ -69,8 +67,8 @@ protected BaseTx(String txVersion,
this.txInputs = txInputs;
}
- protected PB.BaseTx.Builder getBaseTxBuilder() {
- return PB.BaseTx.newBuilder()
+ protected protobuf.BaseTx.Builder getBaseTxBuilder() {
+ return protobuf.BaseTx.newBuilder()
.setTxVersion(txVersion)
.setId(id)
.setBlockHeight(blockHeight)
diff --git a/core/src/main/java/bisq/core/dao/state/model/blockchain/BaseTxOutput.java b/core/src/main/java/bisq/core/dao/state/model/blockchain/BaseTxOutput.java
index 6175ade740d..39c8c223349 100644
--- a/core/src/main/java/bisq/core/dao/state/model/blockchain/BaseTxOutput.java
+++ b/core/src/main/java/bisq/core/dao/state/model/blockchain/BaseTxOutput.java
@@ -22,8 +22,6 @@
import bisq.common.util.JsonExclude;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import java.util.Optional;
@@ -77,8 +75,8 @@ protected BaseTxOutput(int index,
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- protected PB.BaseTxOutput.Builder getRawTxOutputBuilder() {
- final PB.BaseTxOutput.Builder builder = PB.BaseTxOutput.newBuilder()
+ protected protobuf.BaseTxOutput.Builder getRawTxOutputBuilder() {
+ final protobuf.BaseTxOutput.Builder builder = protobuf.BaseTxOutput.newBuilder()
.setIndex(index)
.setValue(value)
.setTxId(txId)
diff --git a/core/src/main/java/bisq/core/dao/state/model/blockchain/Block.java b/core/src/main/java/bisq/core/dao/state/model/blockchain/Block.java
index 3c047556494..2763b74c69f 100644
--- a/core/src/main/java/bisq/core/dao/state/model/blockchain/Block.java
+++ b/core/src/main/java/bisq/core/dao/state/model/blockchain/Block.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
@@ -73,16 +71,16 @@ private Block(int height,
@Override
- public PB.BaseBlock toProtoMessage() {
- PB.Block.Builder builder = PB.Block.newBuilder()
+ public protobuf.BaseBlock toProtoMessage() {
+ protobuf.Block.Builder builder = protobuf.Block.newBuilder()
.addAllTxs(txs.stream()
.map(Tx::toProtoMessage)
.collect(Collectors.toList()));
return getBaseBlockBuilder().setBlock(builder).build();
}
- public static Block fromProto(PB.BaseBlock proto) {
- PB.Block blockProto = proto.getBlock();
+ public static Block fromProto(protobuf.BaseBlock proto) {
+ protobuf.Block blockProto = proto.getBlock();
ImmutableList txs = blockProto.getTxsList().isEmpty() ?
ImmutableList.copyOf(new ArrayList<>()) :
ImmutableList.copyOf(blockProto.getTxsList().stream()
diff --git a/core/src/main/java/bisq/core/dao/state/model/blockchain/PubKeyScript.java b/core/src/main/java/bisq/core/dao/state/model/blockchain/PubKeyScript.java
index 40152888844..a3b6750ff1f 100644
--- a/core/src/main/java/bisq/core/dao/state/model/blockchain/PubKeyScript.java
+++ b/core/src/main/java/bisq/core/dao/state/model/blockchain/PubKeyScript.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.common.collect.ImmutableList;
import java.util.Objects;
@@ -58,8 +56,8 @@ public PubKeyScript(com.neemre.btcdcli4j.core.domain.PubKeyScript scriptPubKey)
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- public PB.PubKeyScript toProtoMessage() {
- final PB.PubKeyScript.Builder builder = PB.PubKeyScript.newBuilder()
+ public protobuf.PubKeyScript toProtoMessage() {
+ final protobuf.PubKeyScript.Builder builder = protobuf.PubKeyScript.newBuilder()
.setReqSigs(reqSigs)
.setScriptType(scriptType.toProtoMessage())
.setAsm(asm)
@@ -68,7 +66,7 @@ public PB.PubKeyScript toProtoMessage() {
return builder.build();
}
- public static PubKeyScript fromProto(PB.PubKeyScript proto) {
+ public static PubKeyScript fromProto(protobuf.PubKeyScript proto) {
return new PubKeyScript(proto.getReqSigs(),
ScriptType.fromProto(proto.getScriptType()),
proto.getAddressesList().isEmpty() ? null : ImmutableList.copyOf(proto.getAddressesList()),
diff --git a/core/src/main/java/bisq/core/dao/state/model/blockchain/ScriptType.java b/core/src/main/java/bisq/core/dao/state/model/blockchain/ScriptType.java
index b09bec6760e..173f78ce11a 100644
--- a/core/src/main/java/bisq/core/dao/state/model/blockchain/ScriptType.java
+++ b/core/src/main/java/bisq/core/dao/state/model/blockchain/ScriptType.java
@@ -21,8 +21,6 @@
import bisq.common.proto.ProtoUtil;
-import io.bisq.generated.protobuffer.PB;
-
import com.fasterxml.jackson.annotation.JsonCreator;
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import com.fasterxml.jackson.annotation.JsonInclude;
@@ -77,11 +75,11 @@ public static ScriptType forName(String name) {
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- public static ScriptType fromProto(PB.ScriptType scriptType) {
+ public static ScriptType fromProto(protobuf.ScriptType scriptType) {
return ProtoUtil.enumFromProto(ScriptType.class, scriptType.name());
}
- public PB.ScriptType toProtoMessage() {
- return PB.ScriptType.valueOf(name());
+ public protobuf.ScriptType toProtoMessage() {
+ return protobuf.ScriptType.valueOf(name());
}
}
diff --git a/core/src/main/java/bisq/core/dao/state/model/blockchain/SpentInfo.java b/core/src/main/java/bisq/core/dao/state/model/blockchain/SpentInfo.java
index 8c3f0033cc8..fb01985ae29 100644
--- a/core/src/main/java/bisq/core/dao/state/model/blockchain/SpentInfo.java
+++ b/core/src/main/java/bisq/core/dao/state/model/blockchain/SpentInfo.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.Value;
import javax.annotation.concurrent.Immutable;
@@ -40,14 +38,14 @@ public final class SpentInfo implements PersistablePayload, ImmutableDaoStateMod
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- public static SpentInfo fromProto(PB.SpentInfo proto) {
+ public static SpentInfo fromProto(protobuf.SpentInfo proto) {
return new SpentInfo(proto.getBlockHeight(),
proto.getTxId(),
proto.getInputIndex());
}
- public PB.SpentInfo toProtoMessage() {
- return PB.SpentInfo.newBuilder()
+ public protobuf.SpentInfo toProtoMessage() {
+ return protobuf.SpentInfo.newBuilder()
.setBlockHeight(blockHeight)
.setTxId(txId)
.setInputIndex(inputIndex)
diff --git a/core/src/main/java/bisq/core/dao/state/model/blockchain/Tx.java b/core/src/main/java/bisq/core/dao/state/model/blockchain/Tx.java
index 63ca99189a5..48c1d4979e8 100644
--- a/core/src/main/java/bisq/core/dao/state/model/blockchain/Tx.java
+++ b/core/src/main/java/bisq/core/dao/state/model/blockchain/Tx.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.common.collect.ImmutableList;
import java.util.ArrayList;
@@ -93,8 +91,8 @@ private Tx(String txVersion,
}
@Override
- public PB.BaseTx toProtoMessage() {
- final PB.Tx.Builder builder = PB.Tx.newBuilder()
+ public protobuf.BaseTx toProtoMessage() {
+ final protobuf.Tx.Builder builder = protobuf.Tx.newBuilder()
.addAllTxOutputs(txOutputs.stream()
.map(TxOutput::toProtoMessage)
.collect(Collectors.toList()))
@@ -103,13 +101,13 @@ public PB.BaseTx toProtoMessage() {
return getBaseTxBuilder().setTx(builder).build();
}
- public static Tx fromProto(PB.BaseTx protoBaseTx) {
+ public static Tx fromProto(protobuf.BaseTx protoBaseTx) {
ImmutableList txInputs = protoBaseTx.getTxInputsList().isEmpty() ?
ImmutableList.copyOf(new ArrayList<>()) :
ImmutableList.copyOf(protoBaseTx.getTxInputsList().stream()
.map(TxInput::fromProto)
.collect(Collectors.toList()));
- PB.Tx protoTx = protoBaseTx.getTx();
+ protobuf.Tx protoTx = protoBaseTx.getTx();
ImmutableList outputs = protoTx.getTxOutputsList().isEmpty() ?
ImmutableList.copyOf(new ArrayList<>()) :
ImmutableList.copyOf(protoTx.getTxOutputsList().stream()
diff --git a/core/src/main/java/bisq/core/dao/state/model/blockchain/TxInput.java b/core/src/main/java/bisq/core/dao/state/model/blockchain/TxInput.java
index 608fe5f5840..0ebcddf937f 100644
--- a/core/src/main/java/bisq/core/dao/state/model/blockchain/TxInput.java
+++ b/core/src/main/java/bisq/core/dao/state/model/blockchain/TxInput.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Optional;
import lombok.EqualsAndHashCode;
@@ -57,8 +55,8 @@ public TxInput(String connectedTxOutputTxId, int connectedTxOutputIndex, @Nullab
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- public PB.TxInput toProtoMessage() {
- final PB.TxInput.Builder builder = PB.TxInput.newBuilder()
+ public protobuf.TxInput toProtoMessage() {
+ final protobuf.TxInput.Builder builder = protobuf.TxInput.newBuilder()
.setConnectedTxOutputTxId(connectedTxOutputTxId)
.setConnectedTxOutputIndex(connectedTxOutputIndex);
@@ -67,7 +65,7 @@ public PB.TxInput toProtoMessage() {
return builder.build();
}
- public static TxInput fromProto(PB.TxInput proto) {
+ public static TxInput fromProto(protobuf.TxInput proto) {
return new TxInput(proto.getConnectedTxOutputTxId(),
proto.getConnectedTxOutputIndex(),
proto.getPubKey().isEmpty() ? null : proto.getPubKey());
diff --git a/core/src/main/java/bisq/core/dao/state/model/blockchain/TxOutput.java b/core/src/main/java/bisq/core/dao/state/model/blockchain/TxOutput.java
index ae9c59a729a..4cdc953661a 100644
--- a/core/src/main/java/bisq/core/dao/state/model/blockchain/TxOutput.java
+++ b/core/src/main/java/bisq/core/dao/state/model/blockchain/TxOutput.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Objects;
import lombok.Data;
@@ -90,16 +88,16 @@ private TxOutput(int index,
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.BaseTxOutput toProtoMessage() {
- PB.TxOutput.Builder builder = PB.TxOutput.newBuilder()
+ public protobuf.BaseTxOutput toProtoMessage() {
+ protobuf.TxOutput.Builder builder = protobuf.TxOutput.newBuilder()
.setTxOutputType(txOutputType.toProtoMessage())
.setLockTime(lockTime)
.setUnlockBlockHeight(unlockBlockHeight);
return getRawTxOutputBuilder().setTxOutput(builder).build();
}
- public static TxOutput fromProto(PB.BaseTxOutput proto) {
- PB.TxOutput protoTxOutput = proto.getTxOutput();
+ public static TxOutput fromProto(protobuf.BaseTxOutput proto) {
+ protobuf.TxOutput protoTxOutput = proto.getTxOutput();
return new TxOutput(proto.getIndex(),
proto.getValue(),
proto.getTxId(),
diff --git a/core/src/main/java/bisq/core/dao/state/model/blockchain/TxOutputType.java b/core/src/main/java/bisq/core/dao/state/model/blockchain/TxOutputType.java
index 498c984746e..51bfbd01971 100644
--- a/core/src/main/java/bisq/core/dao/state/model/blockchain/TxOutputType.java
+++ b/core/src/main/java/bisq/core/dao/state/model/blockchain/TxOutputType.java
@@ -21,8 +21,6 @@
import bisq.common.proto.ProtoUtil;
-import io.bisq.generated.protobuffer.PB;
-
import javax.annotation.concurrent.Immutable;
@Immutable
@@ -53,11 +51,11 @@ public enum TxOutputType implements ImmutableDaoStateModel {
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- public static TxOutputType fromProto(PB.TxOutputType txOutputType) {
+ public static TxOutputType fromProto(protobuf.TxOutputType txOutputType) {
return ProtoUtil.enumFromProto(TxOutputType.class, txOutputType.name());
}
- public PB.TxOutputType toProtoMessage() {
- return PB.TxOutputType.valueOf(name());
+ public protobuf.TxOutputType toProtoMessage() {
+ return protobuf.TxOutputType.valueOf(name());
}
}
diff --git a/core/src/main/java/bisq/core/dao/state/model/blockchain/TxType.java b/core/src/main/java/bisq/core/dao/state/model/blockchain/TxType.java
index 5083ae9690a..21e8f6f1617 100644
--- a/core/src/main/java/bisq/core/dao/state/model/blockchain/TxType.java
+++ b/core/src/main/java/bisq/core/dao/state/model/blockchain/TxType.java
@@ -21,8 +21,6 @@
import bisq.common.proto.ProtoUtil;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.Getter;
import javax.annotation.Nullable;
@@ -64,11 +62,11 @@ public enum TxType implements ImmutableDaoStateModel {
}
@Nullable
- public static TxType fromProto(PB.TxType txType) {
+ public static TxType fromProto(protobuf.TxType txType) {
return ProtoUtil.enumFromProto(TxType.class, txType.name());
}
- public PB.TxType toProtoMessage() {
- return PB.TxType.valueOf(name());
+ public protobuf.TxType toProtoMessage() {
+ return protobuf.TxType.valueOf(name());
}
}
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/Ballot.java b/core/src/main/java/bisq/core/dao/state/model/governance/Ballot.java
index b3b48e7f5c3..7a8ad920789 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/Ballot.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/Ballot.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Optional;
import lombok.EqualsAndHashCode;
@@ -70,14 +68,14 @@ public Ballot(Proposal proposal, @Nullable Vote vote) {
}
@Override
- public PB.Ballot toProtoMessage() {
- final PB.Ballot.Builder builder = PB.Ballot.newBuilder()
+ public protobuf.Ballot toProtoMessage() {
+ final protobuf.Ballot.Builder builder = protobuf.Ballot.newBuilder()
.setProposal(proposal.getProposalBuilder());
- Optional.ofNullable(vote).ifPresent(e -> builder.setVote((PB.Vote) e.toProtoMessage()));
+ Optional.ofNullable(vote).ifPresent(e -> builder.setVote((protobuf.Vote) e.toProtoMessage()));
return builder.build();
}
- public static Ballot fromProto(PB.Ballot proto) {
+ public static Ballot fromProto(protobuf.Ballot proto) {
return new Ballot(Proposal.fromProto(proto.getProposal()),
proto.hasVote() ? Vote.fromProto(proto.getVote()) : null);
}
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/BallotList.java b/core/src/main/java/bisq/core/dao/state/model/governance/BallotList.java
index 6d7b10e5059..b5a4651a1a7 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/BallotList.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/BallotList.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistableList;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
@@ -53,18 +51,18 @@ public BallotList() {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.PersistableEnvelope toProtoMessage() {
- return PB.PersistableEnvelope.newBuilder().setBallotList(getBuilder()).build();
+ public protobuf.PersistableEnvelope toProtoMessage() {
+ return protobuf.PersistableEnvelope.newBuilder().setBallotList(getBuilder()).build();
}
- public PB.BallotList.Builder getBuilder() {
- return PB.BallotList.newBuilder()
+ public protobuf.BallotList.Builder getBuilder() {
+ return protobuf.BallotList.newBuilder()
.addAllBallot(getList().stream()
.map(Ballot::toProtoMessage)
.collect(Collectors.toList()));
}
- public static BallotList fromProto(PB.BallotList proto) {
+ public static BallotList fromProto(protobuf.BallotList proto) {
return new BallotList(new ArrayList<>(proto.getBallotList().stream()
.map(Ballot::fromProto)
.collect(Collectors.toList())));
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/ChangeParamProposal.java b/core/src/main/java/bisq/core/dao/state/model/governance/ChangeParamProposal.java
index b78decf2cf5..4fc6c5c9431 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/ChangeParamProposal.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/ChangeParamProposal.java
@@ -24,8 +24,6 @@
import bisq.common.app.Version;
-import io.bisq.generated.protobuffer.PB;
-
import org.springframework.util.CollectionUtils;
import java.util.Date;
@@ -84,15 +82,15 @@ private ChangeParamProposal(String name,
}
@Override
- public PB.Proposal.Builder getProposalBuilder() {
- final PB.ChangeParamProposal.Builder builder = PB.ChangeParamProposal.newBuilder()
+ public protobuf.Proposal.Builder getProposalBuilder() {
+ final protobuf.ChangeParamProposal.Builder builder = protobuf.ChangeParamProposal.newBuilder()
.setParam(param.name())
.setParamValue(paramValue);
return super.getProposalBuilder().setChangeParamProposal(builder);
}
- public static ChangeParamProposal fromProto(PB.Proposal proto) {
- final PB.ChangeParamProposal proposalProto = proto.getChangeParamProposal();
+ public static ChangeParamProposal fromProto(protobuf.Proposal proto) {
+ final protobuf.ChangeParamProposal proposalProto = proto.getChangeParamProposal();
return new ChangeParamProposal(proto.getName(),
proto.getLink(),
Param.fromProto(proposalProto),
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/CompensationProposal.java b/core/src/main/java/bisq/core/dao/state/model/governance/CompensationProposal.java
index 45d749923f4..fd5f5270a7b 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/CompensationProposal.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/CompensationProposal.java
@@ -26,8 +26,6 @@
import bisq.common.app.Version;
-import io.bisq.generated.protobuffer.PB;
-
import org.bitcoinj.core.Address;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.Coin;
@@ -91,15 +89,15 @@ private CompensationProposal(String name,
}
@Override
- public PB.Proposal.Builder getProposalBuilder() {
- final PB.CompensationProposal.Builder builder = PB.CompensationProposal.newBuilder()
+ public protobuf.Proposal.Builder getProposalBuilder() {
+ final protobuf.CompensationProposal.Builder builder = protobuf.CompensationProposal.newBuilder()
.setBsqAddress(bsqAddress)
.setRequestedBsq(requestedBsq);
return super.getProposalBuilder().setCompensationProposal(builder);
}
- public static CompensationProposal fromProto(PB.Proposal proto) {
- final PB.CompensationProposal proposalProto = proto.getCompensationProposal();
+ public static CompensationProposal fromProto(protobuf.Proposal proto) {
+ final protobuf.CompensationProposal proposalProto = proto.getCompensationProposal();
return new CompensationProposal(proto.getName(),
proto.getLink(),
proposalProto.getBsqAddress(),
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/ConfiscateBondProposal.java b/core/src/main/java/bisq/core/dao/state/model/governance/ConfiscateBondProposal.java
index 38eb9ef320d..be88a09adf7 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/ConfiscateBondProposal.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/ConfiscateBondProposal.java
@@ -24,8 +24,6 @@
import bisq.common.app.Version;
-import io.bisq.generated.protobuffer.PB;
-
import org.springframework.util.CollectionUtils;
import java.util.Date;
@@ -79,14 +77,14 @@ private ConfiscateBondProposal(String name,
}
@Override
- public PB.Proposal.Builder getProposalBuilder() {
- final PB.ConfiscateBondProposal.Builder builder = PB.ConfiscateBondProposal.newBuilder()
+ public protobuf.Proposal.Builder getProposalBuilder() {
+ final protobuf.ConfiscateBondProposal.Builder builder = protobuf.ConfiscateBondProposal.newBuilder()
.setLockupTxId(lockupTxId);
return super.getProposalBuilder().setConfiscateBondProposal(builder);
}
- public static ConfiscateBondProposal fromProto(PB.Proposal proto) {
- final PB.ConfiscateBondProposal proposalProto = proto.getConfiscateBondProposal();
+ public static ConfiscateBondProposal fromProto(protobuf.Proposal proto) {
+ final protobuf.ConfiscateBondProposal proposalProto = proto.getConfiscateBondProposal();
return new ConfiscateBondProposal(proto.getName(),
proto.getLink(),
proposalProto.getLockupTxId(),
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/Cycle.java b/core/src/main/java/bisq/core/dao/state/model/governance/Cycle.java
index 8e5e7971dfa..a1066757a09 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/Cycle.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/Cycle.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.common.collect.ImmutableList;
import java.util.Optional;
@@ -59,8 +57,8 @@ public Cycle(int heightOfFirstBlock, ImmutableList daoPhaseList) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.Cycle toProtoMessage() {
- return PB.Cycle.newBuilder()
+ public protobuf.Cycle toProtoMessage() {
+ return protobuf.Cycle.newBuilder()
.setHeightOfFirstLock(heightOfFirstBlock)
.addAllDaoPhase(daoPhaseList.stream()
.map(DaoPhase::toProtoMessage)
@@ -68,7 +66,7 @@ public PB.Cycle toProtoMessage() {
.build();
}
- public static Cycle fromProto(PB.Cycle proto) {
+ public static Cycle fromProto(protobuf.Cycle proto) {
final ImmutableList daoPhaseList = ImmutableList.copyOf(proto.getDaoPhaseList().stream()
.map(DaoPhase::fromProto)
.collect(Collectors.toList()));
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/DaoPhase.java b/core/src/main/java/bisq/core/dao/state/model/governance/DaoPhase.java
index 5ae7e13ff1d..4902c99f708 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/DaoPhase.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/DaoPhase.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Objects;
import lombok.Value;
@@ -71,14 +69,14 @@ public DaoPhase(Phase phase, int duration) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.DaoPhase toProtoMessage() {
- return PB.DaoPhase.newBuilder()
+ public protobuf.DaoPhase toProtoMessage() {
+ return protobuf.DaoPhase.newBuilder()
.setPhaseOrdinal(phase.ordinal())
.setDuration(duration)
.build();
}
- public static DaoPhase fromProto(PB.DaoPhase proto) {
+ public static DaoPhase fromProto(protobuf.DaoPhase proto) {
int ordinal = proto.getPhaseOrdinal();
if (ordinal >= Phase.values().length) {
log.warn("We tried to access a ordinal outside of the DaoPhase.Phase enum bounds and set it to " +
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/DecryptedBallotsWithMerits.java b/core/src/main/java/bisq/core/dao/state/model/governance/DecryptedBallotsWithMerits.java
index 3c811a5593a..489ba012f75 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/DecryptedBallotsWithMerits.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/DecryptedBallotsWithMerits.java
@@ -24,8 +24,6 @@
import bisq.common.proto.persistable.PersistablePayload;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import java.util.Optional;
@@ -67,12 +65,12 @@ public DecryptedBallotsWithMerits(byte[] hashOfBlindVoteList, String blindVoteTx
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.DecryptedBallotsWithMerits toProtoMessage() {
+ public protobuf.DecryptedBallotsWithMerits toProtoMessage() {
return getBuilder().build();
}
- private PB.DecryptedBallotsWithMerits.Builder getBuilder() {
- return PB.DecryptedBallotsWithMerits.newBuilder()
+ private protobuf.DecryptedBallotsWithMerits.Builder getBuilder() {
+ return protobuf.DecryptedBallotsWithMerits.newBuilder()
.setHashOfBlindVoteList(ByteString.copyFrom(hashOfBlindVoteList))
.setBlindVoteTxId(blindVoteTxId)
.setVoteRevealTxId(voteRevealTxId)
@@ -81,7 +79,7 @@ private PB.DecryptedBallotsWithMerits.Builder getBuilder() {
.setMeritList(meritList.getBuilder());
}
- public static DecryptedBallotsWithMerits fromProto(PB.DecryptedBallotsWithMerits proto) {
+ public static DecryptedBallotsWithMerits fromProto(protobuf.DecryptedBallotsWithMerits proto) {
return new DecryptedBallotsWithMerits(proto.getHashOfBlindVoteList().toByteArray(),
proto.getBlindVoteTxId(),
proto.getVoteRevealTxId(),
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/EvaluatedProposal.java b/core/src/main/java/bisq/core/dao/state/model/governance/EvaluatedProposal.java
index d20a9f81e54..c06bba00534 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/EvaluatedProposal.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/EvaluatedProposal.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.Value;
import javax.annotation.concurrent.Immutable;
@@ -44,14 +42,14 @@ public EvaluatedProposal(boolean isAccepted, ProposalVoteResult proposalVoteResu
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.EvaluatedProposal toProtoMessage() {
- PB.EvaluatedProposal.Builder builder = PB.EvaluatedProposal.newBuilder()
+ public protobuf.EvaluatedProposal toProtoMessage() {
+ protobuf.EvaluatedProposal.Builder builder = protobuf.EvaluatedProposal.newBuilder()
.setIsAccepted(isAccepted)
.setProposalVoteResult(proposalVoteResult.toProtoMessage());
return builder.build();
}
- public static EvaluatedProposal fromProto(PB.EvaluatedProposal proto) {
+ public static EvaluatedProposal fromProto(protobuf.EvaluatedProposal proto) {
return new EvaluatedProposal(proto.getIsAccepted(),
ProposalVoteResult.fromProto(proto.getProposalVoteResult()));
}
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/GenericProposal.java b/core/src/main/java/bisq/core/dao/state/model/governance/GenericProposal.java
index 92002f559f5..90070bc4f0e 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/GenericProposal.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/GenericProposal.java
@@ -24,8 +24,6 @@
import bisq.common.app.Version;
-import io.bisq.generated.protobuffer.PB;
-
import org.springframework.util.CollectionUtils;
import java.util.Date;
@@ -74,12 +72,12 @@ private GenericProposal(String name,
}
@Override
- public PB.Proposal.Builder getProposalBuilder() {
- final PB.GenericProposal.Builder builder = PB.GenericProposal.newBuilder();
+ public protobuf.Proposal.Builder getProposalBuilder() {
+ final protobuf.GenericProposal.Builder builder = protobuf.GenericProposal.newBuilder();
return super.getProposalBuilder().setGenericProposal(builder);
}
- public static GenericProposal fromProto(PB.Proposal proto) {
+ public static GenericProposal fromProto(protobuf.Proposal proto) {
return new GenericProposal(proto.getName(),
proto.getLink(),
(byte) proto.getVersion(),
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/Issuance.java b/core/src/main/java/bisq/core/dao/state/model/governance/Issuance.java
index 93db97114c7..45888ac7222 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/Issuance.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/Issuance.java
@@ -23,8 +23,6 @@
import bisq.common.proto.network.NetworkPayload;
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Objects;
import java.util.Optional;
@@ -63,8 +61,8 @@ public Issuance(String txId, int chainHeight, long amount, @Nullable String pubK
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- public PB.Issuance toProtoMessage() {
- final PB.Issuance.Builder builder = PB.Issuance.newBuilder()
+ public protobuf.Issuance toProtoMessage() {
+ final protobuf.Issuance.Builder builder = protobuf.Issuance.newBuilder()
.setTxId(txId)
.setChainHeight(chainHeight)
.setAmount(amount)
@@ -73,7 +71,7 @@ public PB.Issuance toProtoMessage() {
return builder.build();
}
- public static Issuance fromProto(PB.Issuance proto) {
+ public static Issuance fromProto(protobuf.Issuance proto) {
return new Issuance(proto.getTxId(),
proto.getChainHeight(),
proto.getAmount(),
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/Merit.java b/core/src/main/java/bisq/core/dao/state/model/governance/Merit.java
index 5068c0d61b2..7b449934b36 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/Merit.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/Merit.java
@@ -24,8 +24,6 @@
import bisq.common.proto.persistable.PersistablePayload;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import lombok.EqualsAndHashCode;
@@ -52,14 +50,14 @@ public Merit(Issuance issuance, byte[] signature) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.Merit toProtoMessage() {
- final PB.Merit.Builder builder = PB.Merit.newBuilder()
+ public protobuf.Merit toProtoMessage() {
+ final protobuf.Merit.Builder builder = protobuf.Merit.newBuilder()
.setIssuance(issuance.toProtoMessage())
.setSignature(ByteString.copyFrom(signature));
return builder.build();
}
- public static Merit fromProto(PB.Merit proto) {
+ public static Merit fromProto(protobuf.Merit proto) {
return new Merit(Issuance.fromProto(proto.getIssuance()),
proto.getSignature().toByteArray());
}
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/MeritList.java b/core/src/main/java/bisq/core/dao/state/model/governance/MeritList.java
index 1ef0a26874a..d70507e46fb 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/MeritList.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/MeritList.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistableList;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.InvalidProtocolBufferException;
import java.util.ArrayList;
@@ -50,24 +48,24 @@ public MeritList(List list) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.MeritList toProtoMessage() {
+ public protobuf.MeritList toProtoMessage() {
return getBuilder().build();
}
- public PB.MeritList.Builder getBuilder() {
- return PB.MeritList.newBuilder()
+ public protobuf.MeritList.Builder getBuilder() {
+ return protobuf.MeritList.newBuilder()
.addAllMerit(getList().stream()
.map(Merit::toProtoMessage)
.collect(Collectors.toList()));
}
- public static MeritList fromProto(PB.MeritList proto) {
+ public static MeritList fromProto(protobuf.MeritList proto) {
return new MeritList(new ArrayList<>(proto.getMeritList().stream()
.map(Merit::fromProto)
.collect(Collectors.toList())));
}
public static MeritList getMeritListFromBytes(byte[] bytes) throws InvalidProtocolBufferException {
- return MeritList.fromProto(PB.MeritList.parseFrom(bytes));
+ return MeritList.fromProto(protobuf.MeritList.parseFrom(bytes));
}
}
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/ParamChange.java b/core/src/main/java/bisq/core/dao/state/model/governance/ParamChange.java
index 285a757ed4e..622d3272f1d 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/ParamChange.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/ParamChange.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.Value;
import javax.annotation.concurrent.Immutable;
@@ -50,15 +48,15 @@ public ParamChange(String paramName, String value, int activationHeight) {
@Override
- public PB.ParamChange toProtoMessage() {
- return PB.ParamChange.newBuilder()
+ public protobuf.ParamChange toProtoMessage() {
+ return protobuf.ParamChange.newBuilder()
.setParamName(paramName)
.setParamValue(value)
.setActivationHeight(activationHeight)
.build();
}
- public static ParamChange fromProto(PB.ParamChange proto) {
+ public static ParamChange fromProto(protobuf.ParamChange proto) {
return new ParamChange(proto.getParamName(),
proto.getParamValue(),
proto.getActivationHeight());
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/Proposal.java b/core/src/main/java/bisq/core/dao/state/model/governance/Proposal.java
index 395b29c9597..585ffd9bc84 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/Proposal.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/Proposal.java
@@ -28,8 +28,6 @@
import bisq.common.proto.persistable.PersistablePayload;
import bisq.common.util.ExtraDataMapValidator;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Date;
import java.util.Map;
import java.util.Optional;
@@ -79,8 +77,8 @@ protected Proposal(String name,
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- public PB.Proposal.Builder getProposalBuilder() {
- final PB.Proposal.Builder builder = PB.Proposal.newBuilder()
+ public protobuf.Proposal.Builder getProposalBuilder() {
+ final protobuf.Proposal.Builder builder = protobuf.Proposal.newBuilder()
.setName(name)
.setLink(link)
.setVersion(version)
@@ -91,11 +89,11 @@ public PB.Proposal.Builder getProposalBuilder() {
}
@Override
- public PB.Proposal toProtoMessage() {
+ public protobuf.Proposal toProtoMessage() {
return getProposalBuilder().build();
}
- public static Proposal fromProto(PB.Proposal proto) {
+ public static Proposal fromProto(protobuf.Proposal proto) {
switch (proto.getMessageCase()) {
case COMPENSATION_PROPOSAL:
return CompensationProposal.fromProto(proto);
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/ProposalVoteResult.java b/core/src/main/java/bisq/core/dao/state/model/governance/ProposalVoteResult.java
index 67dcc693215..765c97e9d6e 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/ProposalVoteResult.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/ProposalVoteResult.java
@@ -21,8 +21,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
@@ -57,8 +55,8 @@ public ProposalVoteResult(Proposal proposal, long stakeOfAcceptedVotes, long sta
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.ProposalVoteResult toProtoMessage() {
- PB.ProposalVoteResult.Builder builder = PB.ProposalVoteResult.newBuilder()
+ public protobuf.ProposalVoteResult toProtoMessage() {
+ protobuf.ProposalVoteResult.Builder builder = protobuf.ProposalVoteResult.newBuilder()
.setProposal(proposal.toProtoMessage())
.setStakeOfAcceptedVotes(stakeOfAcceptedVotes)
.setStakeOfRejectedVotes(stakeOfRejectedVotes)
@@ -68,7 +66,7 @@ public PB.ProposalVoteResult toProtoMessage() {
return builder.build();
}
- public static ProposalVoteResult fromProto(PB.ProposalVoteResult proto) {
+ public static ProposalVoteResult fromProto(protobuf.ProposalVoteResult proto) {
return new ProposalVoteResult(Proposal.fromProto(proto.getProposal()),
proto.getStakeOfAcceptedVotes(),
proto.getStakeOfRejectedVotes(),
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/ReimbursementProposal.java b/core/src/main/java/bisq/core/dao/state/model/governance/ReimbursementProposal.java
index 40146666101..23efd4e7046 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/ReimbursementProposal.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/ReimbursementProposal.java
@@ -26,8 +26,6 @@
import bisq.common.app.Version;
-import io.bisq.generated.protobuffer.PB;
-
import org.bitcoinj.core.Address;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.Coin;
@@ -91,15 +89,15 @@ private ReimbursementProposal(String name,
}
@Override
- public PB.Proposal.Builder getProposalBuilder() {
- final PB.ReimbursementProposal.Builder builder = PB.ReimbursementProposal.newBuilder()
+ public protobuf.Proposal.Builder getProposalBuilder() {
+ final protobuf.ReimbursementProposal.Builder builder = protobuf.ReimbursementProposal.newBuilder()
.setBsqAddress(bsqAddress)
.setRequestedBsq(requestedBsq);
return super.getProposalBuilder().setReimbursementProposal(builder);
}
- public static ReimbursementProposal fromProto(PB.Proposal proto) {
- final PB.ReimbursementProposal proposalProto = proto.getReimbursementProposal();
+ public static ReimbursementProposal fromProto(protobuf.Proposal proto) {
+ final protobuf.ReimbursementProposal proposalProto = proto.getReimbursementProposal();
return new ReimbursementProposal(proto.getName(),
proto.getLink(),
proposalProto.getBsqAddress(),
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/RemoveAssetProposal.java b/core/src/main/java/bisq/core/dao/state/model/governance/RemoveAssetProposal.java
index f4452e10163..ccd34c555ca 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/RemoveAssetProposal.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/RemoveAssetProposal.java
@@ -24,8 +24,6 @@
import bisq.common.app.Version;
-import io.bisq.generated.protobuffer.PB;
-
import org.springframework.util.CollectionUtils;
import java.util.Date;
@@ -80,14 +78,14 @@ private RemoveAssetProposal(String name,
}
@Override
- public PB.Proposal.Builder getProposalBuilder() {
- final PB.RemoveAssetProposal.Builder builder = PB.RemoveAssetProposal.newBuilder()
+ public protobuf.Proposal.Builder getProposalBuilder() {
+ final protobuf.RemoveAssetProposal.Builder builder = protobuf.RemoveAssetProposal.newBuilder()
.setTickerSymbol(tickerSymbol);
return super.getProposalBuilder().setRemoveAssetProposal(builder);
}
- public static RemoveAssetProposal fromProto(PB.Proposal proto) {
- final PB.RemoveAssetProposal proposalProto = proto.getRemoveAssetProposal();
+ public static RemoveAssetProposal fromProto(protobuf.Proposal proto) {
+ final protobuf.RemoveAssetProposal proposalProto = proto.getRemoveAssetProposal();
return new RemoveAssetProposal(proto.getName(),
proto.getLink(),
proposalProto.getTickerSymbol(),
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/Role.java b/core/src/main/java/bisq/core/dao/state/model/governance/Role.java
index 34f1d18e6f0..a133b0b0c89 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/Role.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/Role.java
@@ -26,8 +26,6 @@
import bisq.common.proto.network.NetworkPayload;
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Objects;
import java.util.UUID;
@@ -79,8 +77,8 @@ private Role(String uid,
}
@Override
- public PB.Role toProtoMessage() {
- PB.Role.Builder builder = PB.Role.newBuilder()
+ public protobuf.Role toProtoMessage() {
+ protobuf.Role.Builder builder = protobuf.Role.newBuilder()
.setUid(uid)
.setName(name)
.setLink(link)
@@ -88,7 +86,7 @@ public PB.Role toProtoMessage() {
return builder.build();
}
- public static Role fromProto(PB.Role proto) {
+ public static Role fromProto(protobuf.Role proto) {
return new Role(proto.getUid(),
proto.getName(),
proto.getLink(),
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/RoleProposal.java b/core/src/main/java/bisq/core/dao/state/model/governance/RoleProposal.java
index c4caa7adb68..48a6d3b137f 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/RoleProposal.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/RoleProposal.java
@@ -24,8 +24,6 @@
import bisq.common.app.Version;
-import io.bisq.generated.protobuffer.PB;
-
import org.springframework.util.CollectionUtils;
import java.util.Date;
@@ -85,16 +83,16 @@ private RoleProposal(String name,
}
@Override
- public PB.Proposal.Builder getProposalBuilder() {
- final PB.RoleProposal.Builder builder = PB.RoleProposal.newBuilder()
+ public protobuf.Proposal.Builder getProposalBuilder() {
+ final protobuf.RoleProposal.Builder builder = protobuf.RoleProposal.newBuilder()
.setRole(role.toProtoMessage())
.setRequiredBondUnit(requiredBondUnit)
.setUnlockTime(unlockTime);
return super.getProposalBuilder().setRoleProposal(builder);
}
- public static RoleProposal fromProto(PB.Proposal proto) {
- final PB.RoleProposal proposalProto = proto.getRoleProposal();
+ public static RoleProposal fromProto(protobuf.Proposal proto) {
+ final protobuf.RoleProposal proposalProto = proto.getRoleProposal();
return new RoleProposal(proto.getName(),
proto.getLink(),
Role.fromProto(proposalProto.getRole()),
diff --git a/core/src/main/java/bisq/core/dao/state/model/governance/Vote.java b/core/src/main/java/bisq/core/dao/state/model/governance/Vote.java
index eff5f0a1ced..cb29cfbadd6 100644
--- a/core/src/main/java/bisq/core/dao/state/model/governance/Vote.java
+++ b/core/src/main/java/bisq/core/dao/state/model/governance/Vote.java
@@ -23,8 +23,6 @@
import bisq.common.proto.network.NetworkPayload;
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import lombok.Value;
@@ -46,12 +44,12 @@ public Vote(boolean accepted) {
@Override
public Message toProtoMessage() {
- return PB.Vote.newBuilder()
+ return protobuf.Vote.newBuilder()
.setAccepted(accepted)
.build();
}
- public static Vote fromProto(PB.Vote proto) {
+ public static Vote fromProto(protobuf.Vote proto) {
return new Vote(proto.getAccepted());
}
}
diff --git a/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedBsqChangeOutputList.java b/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedBsqChangeOutputList.java
index dd0de8147e3..141bc1a853a 100644
--- a/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedBsqChangeOutputList.java
+++ b/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedBsqChangeOutputList.java
@@ -20,8 +20,6 @@
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistableList;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import java.util.ArrayList;
@@ -48,13 +46,13 @@ private UnconfirmedBsqChangeOutputList(List list) {
@Override
public Message toProtoMessage() {
- return PB.PersistableEnvelope.newBuilder()
- .setUnconfirmedBsqChangeOutputList(PB.UnconfirmedBsqChangeOutputList.newBuilder()
+ return protobuf.PersistableEnvelope.newBuilder()
+ .setUnconfirmedBsqChangeOutputList(protobuf.UnconfirmedBsqChangeOutputList.newBuilder()
.addAllUnconfirmedTxOutput(getList().stream().map(UnconfirmedTxOutput::toProtoMessage).collect(Collectors.toList())))
.build();
}
- public static PersistableEnvelope fromProto(PB.UnconfirmedBsqChangeOutputList proto) {
+ public static PersistableEnvelope fromProto(protobuf.UnconfirmedBsqChangeOutputList proto) {
return new UnconfirmedBsqChangeOutputList(new ArrayList<>(proto.getUnconfirmedTxOutputList().stream()
.map(UnconfirmedTxOutput::fromProto)
.collect(Collectors.toList())));
diff --git a/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedTxOutput.java b/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedTxOutput.java
index ac047ad6cd2..28aa5250d35 100644
--- a/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedTxOutput.java
+++ b/core/src/main/java/bisq/core/dao/state/unconfirmed/UnconfirmedTxOutput.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import org.bitcoinj.core.Transaction;
import org.bitcoinj.core.TransactionOutput;
@@ -80,14 +78,14 @@ private UnconfirmedTxOutput(int index,
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- public PB.UnconfirmedTxOutput toProtoMessage() {
- return PB.UnconfirmedTxOutput.newBuilder()
+ public protobuf.UnconfirmedTxOutput toProtoMessage() {
+ return protobuf.UnconfirmedTxOutput.newBuilder()
.setIndex(index)
.setValue(value)
.setTxId(txId).build();
}
- public static UnconfirmedTxOutput fromProto(PB.UnconfirmedTxOutput proto) {
+ public static UnconfirmedTxOutput fromProto(protobuf.UnconfirmedTxOutput proto) {
return new UnconfirmedTxOutput(proto.getIndex(),
proto.getValue(),
proto.getTxId());
diff --git a/core/src/main/java/bisq/core/filter/Filter.java b/core/src/main/java/bisq/core/filter/Filter.java
index 3aeb68bb6a9..8d92fa17839 100644
--- a/core/src/main/java/bisq/core/filter/Filter.java
+++ b/core/src/main/java/bisq/core/filter/Filter.java
@@ -23,8 +23,6 @@
import bisq.common.crypto.Sig;
import bisq.common.util.ExtraDataMapValidator;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.ByteString;
import org.springframework.util.CollectionUtils;
@@ -96,6 +94,10 @@ public final class Filter implements ProtectedStoragePayload, ExpirablePayload {
@Nullable
private final String disableTradeBelowVersion;
+ // added in v1.1.6
+ @Nullable
+ private final List mediators;
+
public Filter(List bannedOfferIds,
List bannedNodeAddress,
List bannedPaymentAccounts,
@@ -108,7 +110,8 @@ public Filter(List bannedOfferIds,
@Nullable List btcNodes,
boolean disableDao,
@Nullable String disableDaoBelowVersion,
- @Nullable String disableTradeBelowVersion) {
+ @Nullable String disableTradeBelowVersion,
+ @Nullable List mediators) {
this.bannedOfferIds = bannedOfferIds;
this.bannedNodeAddress = bannedNodeAddress;
this.bannedPaymentAccounts = bannedPaymentAccounts;
@@ -122,6 +125,7 @@ public Filter(List bannedOfferIds,
this.disableDao = disableDao;
this.disableDaoBelowVersion = disableDaoBelowVersion;
this.disableTradeBelowVersion = disableTradeBelowVersion;
+ this.mediators = mediators;
}
@@ -145,7 +149,8 @@ public Filter(List bannedOfferIds,
@Nullable String disableTradeBelowVersion,
String signatureAsBase64,
byte[] ownerPubKeyBytes,
- @Nullable Map extraDataMap) {
+ @Nullable Map extraDataMap,
+ @Nullable List mediators) {
this(bannedOfferIds,
bannedNodeAddress,
bannedPaymentAccounts,
@@ -158,7 +163,8 @@ public Filter(List bannedOfferIds,
btcNodes,
disableDao,
disableDaoBelowVersion,
- disableTradeBelowVersion);
+ disableTradeBelowVersion,
+ mediators);
this.signatureAsBase64 = signatureAsBase64;
this.ownerPubKeyBytes = ownerPubKeyBytes;
this.extraDataMap = ExtraDataMapValidator.getValidatedExtraDataMap(extraDataMap);
@@ -167,13 +173,13 @@ public Filter(List bannedOfferIds,
}
@Override
- public PB.StoragePayload toProtoMessage() {
+ public protobuf.StoragePayload toProtoMessage() {
checkNotNull(signatureAsBase64, "signatureAsBase64 must nto be null");
checkNotNull(ownerPubKeyBytes, "ownerPubKeyBytes must nto be null");
- List paymentAccountFilterList = bannedPaymentAccounts.stream()
+ List paymentAccountFilterList = bannedPaymentAccounts.stream()
.map(PaymentAccountFilter::toProtoMessage)
.collect(Collectors.toList());
- final PB.Filter.Builder builder = PB.Filter.newBuilder()
+ final protobuf.Filter.Builder builder = protobuf.Filter.newBuilder()
.addAllBannedOfferIds(bannedOfferIds)
.addAllBannedNodeAddress(bannedNodeAddress)
.addAllBannedPaymentAccounts(paymentAccountFilterList)
@@ -191,11 +197,12 @@ public PB.StoragePayload toProtoMessage() {
Optional.ofNullable(disableDaoBelowVersion).ifPresent(builder::setDisableDaoBelowVersion);
Optional.ofNullable(disableTradeBelowVersion).ifPresent(builder::setDisableTradeBelowVersion);
Optional.ofNullable(extraDataMap).ifPresent(builder::putAllExtraData);
+ Optional.ofNullable(mediators).ifPresent(builder::addAllMediators);
- return PB.StoragePayload.newBuilder().setFilter(builder).build();
+ return protobuf.StoragePayload.newBuilder().setFilter(builder).build();
}
- public static Filter fromProto(PB.Filter proto) {
+ public static Filter fromProto(protobuf.Filter proto) {
return new Filter(new ArrayList<>(proto.getBannedOfferIdsList()),
new ArrayList<>(proto.getBannedNodeAddressList()),
proto.getBannedPaymentAccountsList().stream()
@@ -213,7 +220,8 @@ public static Filter fromProto(PB.Filter proto) {
proto.getDisableTradeBelowVersion().isEmpty() ? null : proto.getDisableTradeBelowVersion(),
proto.getSignatureAsBase64(),
proto.getOwnerPubKeyBytes().toByteArray(),
- CollectionUtils.isEmpty(proto.getExtraDataMap()) ? null : proto.getExtraDataMap());
+ CollectionUtils.isEmpty(proto.getExtraDataMap()) ? null : proto.getExtraDataMap(),
+ CollectionUtils.isEmpty(proto.getMediatorsList()) ? null : new ArrayList<>(proto.getMediatorsList()));
}
@@ -226,7 +234,7 @@ public long getTTL() {
return TimeUnit.DAYS.toMillis(180);
}
- public void setSigAndPubKey(String signatureAsBase64, PublicKey ownerPubKey) {
+ void setSigAndPubKey(String signatureAsBase64, PublicKey ownerPubKey) {
this.signatureAsBase64 = signatureAsBase64;
this.ownerPubKey = ownerPubKey;
diff --git a/core/src/main/java/bisq/core/filter/FilterManager.java b/core/src/main/java/bisq/core/filter/FilterManager.java
index f185f11c6ce..a29b43ce13c 100644
--- a/core/src/main/java/bisq/core/filter/FilterManager.java
+++ b/core/src/main/java/bisq/core/filter/FilterManager.java
@@ -38,8 +38,6 @@
import bisq.common.app.Version;
import bisq.common.crypto.KeyRing;
-import io.bisq.generated.protobuffer.PB;
-
import org.bitcoinj.core.ECKey;
import org.bitcoinj.core.Utils;
@@ -306,7 +304,7 @@ private boolean verifySignature(Filter filter) {
// We dont use full data from Filter as we are only interested in the filter data not the sig and keys
private String getHexFromData(Filter filter) {
- PB.Filter.Builder builder = PB.Filter.newBuilder()
+ protobuf.Filter.Builder builder = protobuf.Filter.newBuilder()
.addAllBannedOfferIds(filter.getBannedOfferIds())
.addAllBannedNodeAddress(filter.getBannedNodeAddress())
.addAllBannedPaymentAccounts(filter.getBannedPaymentAccounts().stream()
diff --git a/core/src/main/java/bisq/core/filter/PaymentAccountFilter.java b/core/src/main/java/bisq/core/filter/PaymentAccountFilter.java
index cb22b4ae6a3..0e8dca0f7fb 100644
--- a/core/src/main/java/bisq/core/filter/PaymentAccountFilter.java
+++ b/core/src/main/java/bisq/core/filter/PaymentAccountFilter.java
@@ -19,8 +19,6 @@
import bisq.common.proto.network.NetworkPayload;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.Value;
import lombok.extern.slf4j.Slf4j;
@@ -38,15 +36,15 @@ public PaymentAccountFilter(String paymentMethodId, String getMethodName, String
}
@Override
- public PB.PaymentAccountFilter toProtoMessage() {
- return PB.PaymentAccountFilter.newBuilder()
+ public protobuf.PaymentAccountFilter toProtoMessage() {
+ return protobuf.PaymentAccountFilter.newBuilder()
.setPaymentMethodId(paymentMethodId)
.setGetMethodName(getMethodName)
.setValue(value)
.build();
}
- public static PaymentAccountFilter fromProto(PB.PaymentAccountFilter proto) {
+ public static PaymentAccountFilter fromProto(protobuf.PaymentAccountFilter proto) {
return new PaymentAccountFilter(proto.getPaymentMethodId(),
proto.getGetMethodName(),
proto.getValue());
diff --git a/core/src/main/java/bisq/core/locale/Country.java b/core/src/main/java/bisq/core/locale/Country.java
index e9f384226a9..50e3f6b293c 100644
--- a/core/src/main/java/bisq/core/locale/Country.java
+++ b/core/src/main/java/bisq/core/locale/Country.java
@@ -19,8 +19,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import lombok.EqualsAndHashCode;
@@ -44,11 +42,11 @@ public Country(String code, String name, Region region) {
@Override
public Message toProtoMessage() {
- return PB.Country.newBuilder().setCode(code).setName(name)
- .setRegion(PB.Region.newBuilder().setCode(region.code).setName(region.name)).build();
+ return protobuf.Country.newBuilder().setCode(code).setName(name)
+ .setRegion(protobuf.Region.newBuilder().setCode(region.code).setName(region.name)).build();
}
- public static Country fromProto(PB.Country proto) {
+ public static Country fromProto(protobuf.Country proto) {
return new Country(proto.getCode(),
proto.getName(),
Region.fromProto(proto.getRegion()));
diff --git a/core/src/main/java/bisq/core/locale/CryptoCurrency.java b/core/src/main/java/bisq/core/locale/CryptoCurrency.java
index c71f2397881..14681b4cd78 100644
--- a/core/src/main/java/bisq/core/locale/CryptoCurrency.java
+++ b/core/src/main/java/bisq/core/locale/CryptoCurrency.java
@@ -17,7 +17,6 @@
package bisq.core.locale;
-import io.bisq.generated.protobuffer.PB;
import com.google.protobuf.Message;
@@ -51,12 +50,12 @@ public CryptoCurrency(String currencyCode,
@Override
public Message toProtoMessage() {
return getTradeCurrencyBuilder()
- .setCryptoCurrency(PB.CryptoCurrency.newBuilder()
+ .setCryptoCurrency(protobuf.CryptoCurrency.newBuilder()
.setIsAsset(isAsset))
.build();
}
- public static CryptoCurrency fromProto(PB.TradeCurrency proto) {
+ public static CryptoCurrency fromProto(protobuf.TradeCurrency proto) {
return new CryptoCurrency(proto.getCode(),
proto.getName(),
proto.getCryptoCurrency().getIsAsset());
diff --git a/core/src/main/java/bisq/core/locale/CurrencyUtil.java b/core/src/main/java/bisq/core/locale/CurrencyUtil.java
index 096766960b5..ac8a8350174 100644
--- a/core/src/main/java/bisq/core/locale/CurrencyUtil.java
+++ b/core/src/main/java/bisq/core/locale/CurrencyUtil.java
@@ -295,6 +295,19 @@ public static List getAllRevolutCurrencies() {
return currencies;
}
+ public static List getMatureMarketCurrencies() {
+ ArrayList currencies = new ArrayList<>(Arrays.asList(
+ new FiatCurrency("EUR"),
+ new FiatCurrency("USD"),
+ new FiatCurrency("GBP"),
+ new FiatCurrency("CAD"),
+ new FiatCurrency("AUD"),
+ new FiatCurrency("BRL")
+ ));
+ currencies.sort(Comparator.comparing(TradeCurrency::getCode));
+ return currencies;
+ }
+
public static boolean isFiatCurrency(String currencyCode) {
try {
return currencyCode != null
diff --git a/core/src/main/java/bisq/core/locale/FiatCurrency.java b/core/src/main/java/bisq/core/locale/FiatCurrency.java
index c01812d57fd..d51a444f758 100644
--- a/core/src/main/java/bisq/core/locale/FiatCurrency.java
+++ b/core/src/main/java/bisq/core/locale/FiatCurrency.java
@@ -17,7 +17,6 @@
package bisq.core.locale;
-import io.bisq.generated.protobuffer.PB;
import com.google.protobuf.Message;
@@ -59,14 +58,14 @@ public FiatCurrency(Currency currency, Locale locale) {
@Override
public Message toProtoMessage() {
- PB.Currency.Builder currencyBuilder = PB.Currency.newBuilder().setCurrencyCode(currency.getCurrencyCode());
- PB.FiatCurrency.Builder fiatCurrencyBuilder = PB.FiatCurrency.newBuilder().setCurrency(currencyBuilder);
+ protobuf.Currency.Builder currencyBuilder = protobuf.Currency.newBuilder().setCurrencyCode(currency.getCurrencyCode());
+ protobuf.FiatCurrency.Builder fiatCurrencyBuilder = protobuf.FiatCurrency.newBuilder().setCurrency(currencyBuilder);
return getTradeCurrencyBuilder()
.setFiatCurrency(fiatCurrencyBuilder)
.build();
}
- public static FiatCurrency fromProto(PB.TradeCurrency proto) {
+ public static FiatCurrency fromProto(protobuf.TradeCurrency proto) {
return new FiatCurrency(proto.getCode());
}
diff --git a/core/src/main/java/bisq/core/locale/GlobalSettings.java b/core/src/main/java/bisq/core/locale/GlobalSettings.java
index 3b680d4a664..8e0f86ff4a7 100644
--- a/core/src/main/java/bisq/core/locale/GlobalSettings.java
+++ b/core/src/main/java/bisq/core/locale/GlobalSettings.java
@@ -25,6 +25,7 @@
public class GlobalSettings {
private static boolean useAnimations = true;
+ private static boolean useDarkMode = false;
private static Locale locale;
private static final ObjectProperty localeProperty = new SimpleObjectProperty<>(locale);
private static TradeCurrency defaultTradeCurrency;
@@ -47,6 +48,10 @@ public static void setUseAnimations(boolean useAnimations) {
GlobalSettings.useAnimations = useAnimations;
}
+ public static void setUseDarkMode(boolean useDarkMode) {
+ GlobalSettings.useDarkMode = useDarkMode;
+ }
+
public static void setDefaultTradeCurrency(TradeCurrency fiatCurrency) {
GlobalSettings.defaultTradeCurrency = fiatCurrency;
}
diff --git a/core/src/main/java/bisq/core/locale/Region.java b/core/src/main/java/bisq/core/locale/Region.java
index 4ae8e0a5d91..3ffd3b8aad9 100644
--- a/core/src/main/java/bisq/core/locale/Region.java
+++ b/core/src/main/java/bisq/core/locale/Region.java
@@ -19,8 +19,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import lombok.EqualsAndHashCode;
@@ -42,10 +40,10 @@ public Region(String code, String name) {
@Override
public Message toProtoMessage() {
- return PB.Region.newBuilder().setCode(code).setName(name).build();
+ return protobuf.Region.newBuilder().setCode(code).setName(name).build();
}
- public static Region fromProto(PB.Region proto) {
+ public static Region fromProto(protobuf.Region proto) {
return new Region(proto.getCode(), proto.getName());
}
}
diff --git a/core/src/main/java/bisq/core/locale/TradeCurrency.java b/core/src/main/java/bisq/core/locale/TradeCurrency.java
index 8ff4c79e294..42741dadb19 100644
--- a/core/src/main/java/bisq/core/locale/TradeCurrency.java
+++ b/core/src/main/java/bisq/core/locale/TradeCurrency.java
@@ -20,8 +20,6 @@
import bisq.common.proto.ProtobufferRuntimeException;
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.EqualsAndHashCode;
import lombok.Getter;
import lombok.ToString;
@@ -47,7 +45,7 @@ public TradeCurrency(String code, String name) {
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- public static TradeCurrency fromProto(PB.TradeCurrency proto) {
+ public static TradeCurrency fromProto(protobuf.TradeCurrency proto) {
switch (proto.getMessageCase()) {
case FIAT_CURRENCY:
return FiatCurrency.fromProto(proto);
@@ -58,8 +56,8 @@ public static TradeCurrency fromProto(PB.TradeCurrency proto) {
}
}
- public PB.TradeCurrency.Builder getTradeCurrencyBuilder() {
- return PB.TradeCurrency.newBuilder()
+ public protobuf.TradeCurrency.Builder getTradeCurrencyBuilder() {
+ return protobuf.TradeCurrency.newBuilder()
.setCode(code)
.setName(name);
}
diff --git a/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeRepository.java b/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeRepository.java
index 6b3a021789f..790bf4e4548 100644
--- a/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeRepository.java
+++ b/core/src/main/java/bisq/core/network/p2p/seed/DefaultSeedNodeRepository.java
@@ -25,6 +25,7 @@
import javax.inject.Inject;
import javax.inject.Named;
+import javax.inject.Singleton;
import java.io.BufferedReader;
import java.io.InputStream;
@@ -43,11 +44,12 @@
// If a new BaseCurrencyNetwork type gets added we need to add the resource file for it as well!
@Slf4j
+@Singleton
public class DefaultSeedNodeRepository implements SeedNodeRepository {
//TODO add support for localhost addresses
private static final Pattern pattern = Pattern.compile("^([a-z0-9]+\\.onion:\\d+)");
private static final String ENDING = ".seednodes";
- private static final Collection cache = new HashSet<>();
+ private final Collection cache = new HashSet<>();
private final BisqEnvironment bisqEnvironment;
@Nullable
private final String seedNodes;
@@ -92,7 +94,7 @@ private void reload() {
log.info("Seed nodes: {}", cache);
} catch (Throwable t) {
- log.error(t.toString());
+ log.error("exception in DefaultSeedNodeRepository", t);
t.printStackTrace();
throw t;
}
diff --git a/core/src/main/java/bisq/core/notifications/MobileMessageEncryption.java b/core/src/main/java/bisq/core/notifications/MobileMessageEncryption.java
index 0b6195872b7..37ddfe88d41 100644
--- a/core/src/main/java/bisq/core/notifications/MobileMessageEncryption.java
+++ b/core/src/main/java/bisq/core/notifications/MobileMessageEncryption.java
@@ -18,6 +18,7 @@
package bisq.core.notifications;
import javax.inject.Inject;
+import javax.inject.Singleton;
import com.google.common.base.Charsets;
@@ -33,6 +34,7 @@
import lombok.extern.slf4j.Slf4j;
@Slf4j
+@Singleton
public class MobileMessageEncryption {
private SecretKeySpec keySpec;
private Cipher cipher;
diff --git a/core/src/main/java/bisq/core/notifications/MobileModel.java b/core/src/main/java/bisq/core/notifications/MobileModel.java
index ffd015afa0b..2c212e7e4e9 100644
--- a/core/src/main/java/bisq/core/notifications/MobileModel.java
+++ b/core/src/main/java/bisq/core/notifications/MobileModel.java
@@ -18,6 +18,7 @@
package bisq.core.notifications;
import javax.inject.Inject;
+import javax.inject.Singleton;
import com.google.common.annotations.VisibleForTesting;
@@ -29,6 +30,7 @@
@Data
@Slf4j
+@Singleton
public class MobileModel {
public static final String PHONE_SEPARATOR_ESCAPED = "\\|"; // see https://stackoverflow.com/questions/5675704/java-string-split-not-returning-the-right-values
public static final String PHONE_SEPARATOR_WRITING = "|";
diff --git a/core/src/main/java/bisq/core/notifications/MobileNotificationService.java b/core/src/main/java/bisq/core/notifications/MobileNotificationService.java
index 3b80e0f8940..e93845f0a44 100644
--- a/core/src/main/java/bisq/core/notifications/MobileNotificationService.java
+++ b/core/src/main/java/bisq/core/notifications/MobileNotificationService.java
@@ -29,6 +29,7 @@
import com.google.gson.Gson;
import com.google.inject.Inject;
+import com.google.inject.Singleton;
import javax.inject.Named;
@@ -54,6 +55,7 @@
import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
+@Singleton
public class MobileNotificationService {
// Used in Relay app to response of a success state. We won't want a code dependency just for that string so we keep it
// duplicated in relay and here. Must not be changed.
diff --git a/core/src/main/java/bisq/core/notifications/MobileNotificationValidator.java b/core/src/main/java/bisq/core/notifications/MobileNotificationValidator.java
index 95eab45fff7..5cf6f2aeb51 100644
--- a/core/src/main/java/bisq/core/notifications/MobileNotificationValidator.java
+++ b/core/src/main/java/bisq/core/notifications/MobileNotificationValidator.java
@@ -18,10 +18,12 @@
package bisq.core.notifications;
import javax.inject.Inject;
+import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
@Slf4j
+@Singleton
public class MobileNotificationValidator {
@Inject
public MobileNotificationValidator() {
diff --git a/core/src/main/java/bisq/core/notifications/alerts/DisputeMsgEvents.java b/core/src/main/java/bisq/core/notifications/alerts/DisputeMsgEvents.java
index e989317f770..6559d27c922 100644
--- a/core/src/main/java/bisq/core/notifications/alerts/DisputeMsgEvents.java
+++ b/core/src/main/java/bisq/core/notifications/alerts/DisputeMsgEvents.java
@@ -17,17 +17,18 @@
package bisq.core.notifications.alerts;
-import bisq.core.arbitration.Dispute;
-import bisq.core.arbitration.DisputeManager;
-import bisq.core.arbitration.messages.DisputeCommunicationMessage;
import bisq.core.locale.Res;
import bisq.core.notifications.MobileMessage;
import bisq.core.notifications.MobileMessageType;
import bisq.core.notifications.MobileNotificationService;
+import bisq.core.support.dispute.Dispute;
+import bisq.core.support.dispute.arbitration.ArbitrationManager;
+import bisq.core.support.messages.ChatMessage;
import bisq.network.p2p.P2PService;
import javax.inject.Inject;
+import javax.inject.Singleton;
import javafx.collections.ListChangeListener;
@@ -36,23 +37,26 @@
import lombok.extern.slf4j.Slf4j;
@Slf4j
+@Singleton
public class DisputeMsgEvents {
private final P2PService p2PService;
private final MobileNotificationService mobileNotificationService;
@Inject
- public DisputeMsgEvents(DisputeManager disputeManager, P2PService p2PService, MobileNotificationService mobileNotificationService) {
+ public DisputeMsgEvents(ArbitrationManager arbitrationManager,
+ P2PService p2PService,
+ MobileNotificationService mobileNotificationService) {
this.p2PService = p2PService;
this.mobileNotificationService = mobileNotificationService;
// We need to handle it here in the constructor otherwise we get repeated the messages sent.
- disputeManager.getDisputesAsObservableList().addListener((ListChangeListener) c -> {
+ arbitrationManager.getDisputesAsObservableList().addListener((ListChangeListener) c -> {
c.next();
if (c.wasAdded()) {
c.getAddedSubList().forEach(this::setDisputeListener);
}
});
- disputeManager.getDisputesAsObservableList().forEach(this::setDisputeListener);
+ arbitrationManager.getDisputesAsObservableList().forEach(this::setDisputeListener);
}
// We ignore that onAllServicesInitialized here
@@ -62,22 +66,22 @@ public void onAllServicesInitialized() {
private void setDisputeListener(Dispute dispute) {
//TODO use weak ref or remove listener
log.debug("We got a dispute added. id={}, tradeId={}", dispute.getId(), dispute.getTradeId());
- dispute.getDisputeCommunicationMessages().addListener((ListChangeListener) c -> {
- log.debug("We got a DisputeCommunicationMessage added. id={}, tradeId={}", dispute.getId(), dispute.getTradeId());
+ dispute.getChatMessages().addListener((ListChangeListener) c -> {
+ log.debug("We got a ChatMessage added. id={}, tradeId={}", dispute.getId(), dispute.getTradeId());
c.next();
if (c.wasAdded()) {
- c.getAddedSubList().forEach(this::setDisputeCommunicationMessage);
+ c.getAddedSubList().forEach(this::setChatMessage);
}
});
//TODO test
- if (!dispute.getDisputeCommunicationMessages().isEmpty())
- setDisputeCommunicationMessage(dispute.getDisputeCommunicationMessages().get(0));
+ if (!dispute.getChatMessages().isEmpty())
+ setChatMessage(dispute.getChatMessages().get(0));
}
- private void setDisputeCommunicationMessage(DisputeCommunicationMessage disputeMsg) {
+ private void setChatMessage(ChatMessage disputeMsg) {
// TODO we need to prevent to send msg for old dispute messages again at restart
- // Maybe we need a new property in DisputeCommunicationMessage
+ // Maybe we need a new property in ChatMessage
// As key is not set in initial iterations it seems we don't need an extra handling.
// the mailbox msg is set a bit later so that triggers a notification, but not the old messages.
diff --git a/core/src/main/java/bisq/core/notifications/alerts/MyOfferTakenEvents.java b/core/src/main/java/bisq/core/notifications/alerts/MyOfferTakenEvents.java
index 2ed8a7ebb7f..842dbadacc4 100644
--- a/core/src/main/java/bisq/core/notifications/alerts/MyOfferTakenEvents.java
+++ b/core/src/main/java/bisq/core/notifications/alerts/MyOfferTakenEvents.java
@@ -25,6 +25,7 @@
import bisq.core.offer.OpenOfferManager;
import javax.inject.Inject;
+import javax.inject.Singleton;
import javafx.collections.ListChangeListener;
@@ -33,6 +34,7 @@
import lombok.extern.slf4j.Slf4j;
@Slf4j
+@Singleton
public class MyOfferTakenEvents {
private final OpenOfferManager openOfferManager;
private final MobileNotificationService mobileNotificationService;
diff --git a/core/src/main/java/bisq/core/notifications/alerts/TradeEvents.java b/core/src/main/java/bisq/core/notifications/alerts/TradeEvents.java
index 43f51ec80e5..adef19d1b1c 100644
--- a/core/src/main/java/bisq/core/notifications/alerts/TradeEvents.java
+++ b/core/src/main/java/bisq/core/notifications/alerts/TradeEvents.java
@@ -28,6 +28,7 @@
import bisq.common.crypto.PubKeyRing;
import javax.inject.Inject;
+import javax.inject.Singleton;
import javafx.collections.ListChangeListener;
@@ -38,6 +39,7 @@
import lombok.extern.slf4j.Slf4j;
@Slf4j
+@Singleton
public class TradeEvents {
private final PubKeyRing pubKeyRing;
private final TradeManager tradeManager;
diff --git a/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlertFilter.java b/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlertFilter.java
index 48daa0419bd..dc34de9effe 100644
--- a/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlertFilter.java
+++ b/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlertFilter.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.ArrayList;
import java.util.List;
@@ -63,8 +61,8 @@ private MarketAlertFilter(PaymentAccount paymentAccount, int triggerValue, boole
}
@Override
- public PB.MarketAlertFilter toProtoMessage() {
- return PB.MarketAlertFilter.newBuilder()
+ public protobuf.MarketAlertFilter toProtoMessage() {
+ return protobuf.MarketAlertFilter.newBuilder()
.setPaymentAccount(paymentAccount.toProtoMessage())
.setTriggerValue(triggerValue)
.setIsBuyOffer(isBuyOffer)
@@ -72,7 +70,7 @@ public PB.MarketAlertFilter toProtoMessage() {
.build();
}
- public static MarketAlertFilter fromProto(PB.MarketAlertFilter proto, CoreProtoResolver coreProtoResolver) {
+ public static MarketAlertFilter fromProto(protobuf.MarketAlertFilter proto, CoreProtoResolver coreProtoResolver) {
List list = proto.getAlertIdsList().isEmpty() ?
new ArrayList<>() : new ArrayList<>(proto.getAlertIdsList());
return new MarketAlertFilter(PaymentAccount.fromProto(proto.getPaymentAccount(), coreProtoResolver),
diff --git a/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlerts.java b/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlerts.java
index ac2a70a4321..fad6fc2a2f1 100644
--- a/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlerts.java
+++ b/core/src/main/java/bisq/core/notifications/alerts/market/MarketAlerts.java
@@ -38,6 +38,7 @@
import org.bitcoinj.utils.Fiat;
import javax.inject.Inject;
+import javax.inject.Singleton;
import java.util.List;
import java.util.UUID;
@@ -45,6 +46,7 @@
import lombok.extern.slf4j.Slf4j;
@Slf4j
+@Singleton
public class MarketAlerts {
private final OfferBookService offerBookService;
private final MobileNotificationService mobileNotificationService;
diff --git a/core/src/main/java/bisq/core/notifications/alerts/price/PriceAlert.java b/core/src/main/java/bisq/core/notifications/alerts/price/PriceAlert.java
index c7b21aeabaf..f52a048f60e 100644
--- a/core/src/main/java/bisq/core/notifications/alerts/price/PriceAlert.java
+++ b/core/src/main/java/bisq/core/notifications/alerts/price/PriceAlert.java
@@ -33,10 +33,12 @@
import org.bitcoinj.utils.Fiat;
import javax.inject.Inject;
+import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
@Slf4j
+@Singleton
public class PriceAlert {
private final PriceFeedService priceFeedService;
private final MobileNotificationService mobileNotificationService;
diff --git a/core/src/main/java/bisq/core/notifications/alerts/price/PriceAlertFilter.java b/core/src/main/java/bisq/core/notifications/alerts/price/PriceAlertFilter.java
index 712a8d6182d..f14896f3ee6 100644
--- a/core/src/main/java/bisq/core/notifications/alerts/price/PriceAlertFilter.java
+++ b/core/src/main/java/bisq/core/notifications/alerts/price/PriceAlertFilter.java
@@ -19,8 +19,6 @@
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.Value;
@Value
@@ -41,14 +39,14 @@ public PriceAlertFilter(String currencyCode, long high, long low) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.PriceAlertFilter toProtoMessage() {
- return PB.PriceAlertFilter.newBuilder()
+ public protobuf.PriceAlertFilter toProtoMessage() {
+ return protobuf.PriceAlertFilter.newBuilder()
.setCurrencyCode(currencyCode)
.setHigh(high)
.setLow(low).build();
}
- public static PriceAlertFilter fromProto(PB.PriceAlertFilter proto) {
+ public static PriceAlertFilter fromProto(protobuf.PriceAlertFilter proto) {
return new PriceAlertFilter(proto.getCurrencyCode(), proto.getHigh(), proto.getLow());
}
}
diff --git a/core/src/main/java/bisq/core/offer/AvailabilityResult.java b/core/src/main/java/bisq/core/offer/AvailabilityResult.java
index 135afa9bf01..95895687037 100644
--- a/core/src/main/java/bisq/core/offer/AvailabilityResult.java
+++ b/core/src/main/java/bisq/core/offer/AvailabilityResult.java
@@ -25,5 +25,6 @@ public enum AvailabilityResult {
MARKET_PRICE_NOT_AVAILABLE,
NO_ARBITRATORS,
NO_MEDIATORS,
- USER_IGNORED
+ USER_IGNORED,
+ MISSING_MANDATORY_CAPABILITY
}
diff --git a/core/src/main/java/bisq/core/offer/Offer.java b/core/src/main/java/bisq/core/offer/Offer.java
index e76b4a541b3..d52bd9471e7 100644
--- a/core/src/main/java/bisq/core/offer/Offer.java
+++ b/core/src/main/java/bisq/core/offer/Offer.java
@@ -40,8 +40,6 @@
import bisq.common.util.MathUtils;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import org.bitcoinj.core.Coin;
import org.bitcoinj.utils.Fiat;
@@ -74,7 +72,8 @@ public class Offer implements NetworkPayload, PersistablePayload {
// Market price might be different at maker's and takers side so we need a bit of tolerance.
// The tolerance will get smaller once we have multiple price feeds avoiding fast price fluctuations
// from one provider.
- final static double PRICE_TOLERANCE = 0.01;
+ private final static double PRICE_TOLERANCE = 0.01;
+
///////////////////////////////////////////////////////////////////////////////////////////
// Enums
@@ -124,11 +123,11 @@ public Offer(OfferPayload offerPayload) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.Offer toProtoMessage() {
- return PB.Offer.newBuilder().setOfferPayload(offerPayload.toProtoMessage().getOfferPayload()).build();
+ public protobuf.Offer toProtoMessage() {
+ return protobuf.Offer.newBuilder().setOfferPayload(offerPayload.toProtoMessage().getOfferPayload()).build();
}
- public static Offer fromProto(PB.Offer proto) {
+ public static Offer fromProto(protobuf.Offer proto) {
return new Offer(OfferPayload.fromProto(proto.getOfferPayload()));
}
@@ -189,7 +188,7 @@ public Price getPrice() {
return null;
}
} else {
- log.debug("We don't have a market price.\n" +
+ log.trace("We don't have a market price. " +
"That case could only happen if you don't have a price feed.");
return null;
}
@@ -392,14 +391,6 @@ public String getId() {
return offerPayload.getId();
}
- public List getArbitratorNodeAddresses() {
- return offerPayload.getArbitratorNodeAddresses();
- }
-
- public List getMediatorNodeAddresses() {
- return offerPayload.getMediatorNodeAddresses();
- }
-
@Nullable
public List getAcceptedBankIds() {
return offerPayload.getAcceptedBankIds();
diff --git a/core/src/main/java/bisq/core/offer/OfferBookService.java b/core/src/main/java/bisq/core/offer/OfferBookService.java
index 71b9b9d6e3c..d99955d5327 100644
--- a/core/src/main/java/bisq/core/offer/OfferBookService.java
+++ b/core/src/main/java/bisq/core/offer/OfferBookService.java
@@ -28,6 +28,7 @@
import bisq.network.p2p.storage.payload.ProtectedStorageEntry;
import bisq.common.UserThread;
+import bisq.common.app.Capability;
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ResultHandler;
import bisq.common.storage.JsonFileManager;
@@ -42,6 +43,7 @@
import java.util.LinkedList;
import java.util.List;
+import java.util.Objects;
import java.util.stream.Collectors;
import org.slf4j.Logger;
@@ -91,8 +93,10 @@ public void onAdded(ProtectedStorageEntry data) {
if (data.getProtectedStoragePayload() instanceof OfferPayload) {
OfferPayload offerPayload = (OfferPayload) data.getProtectedStoragePayload();
Offer offer = new Offer(offerPayload);
- offer.setPriceFeedService(priceFeedService);
- listener.onAdded(offer);
+ if (showOffer(offer)) {
+ offer.setPriceFeedService(priceFeedService);
+ listener.onAdded(offer);
+ }
}
});
}
@@ -131,6 +135,11 @@ public void onRemoved(Offer offer) {
}
}
+ private boolean showOffer(Offer offer) {
+ return !OfferRestrictions.requiresUpdate() ||
+ OfferRestrictions.hasOfferMandatoryCapability(offer, Capability.MEDIATION);
+ }
+
///////////////////////////////////////////////////////////////////////////////////////////
// API
@@ -150,7 +159,9 @@ public void addOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHandl
}
}
- public void refreshTTL(OfferPayload offerPayload, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
+ public void refreshTTL(OfferPayload offerPayload,
+ ResultHandler resultHandler,
+ ErrorMessageHandler errorMessageHandler) {
if (filterManager.requireUpdateToNewVersionForTrading()) {
errorMessageHandler.handleErrorMessage(Res.get("popup.warning.mandatoryUpdate.trading"));
return;
@@ -164,15 +175,21 @@ public void refreshTTL(OfferPayload offerPayload, ResultHandler resultHandler, E
}
}
- public void activateOffer(Offer offer, @Nullable ResultHandler resultHandler, @Nullable ErrorMessageHandler errorMessageHandler) {
+ public void activateOffer(Offer offer,
+ @Nullable ResultHandler resultHandler,
+ @Nullable ErrorMessageHandler errorMessageHandler) {
addOffer(offer, resultHandler, errorMessageHandler);
}
- public void deactivateOffer(OfferPayload offerPayload, @Nullable ResultHandler resultHandler, @Nullable ErrorMessageHandler errorMessageHandler) {
+ public void deactivateOffer(OfferPayload offerPayload,
+ @Nullable ResultHandler resultHandler,
+ @Nullable ErrorMessageHandler errorMessageHandler) {
removeOffer(offerPayload, resultHandler, errorMessageHandler);
}
- public void removeOffer(OfferPayload offerPayload, @Nullable ResultHandler resultHandler, @Nullable ErrorMessageHandler errorMessageHandler) {
+ public void removeOffer(OfferPayload offerPayload,
+ @Nullable ResultHandler resultHandler,
+ @Nullable ErrorMessageHandler errorMessageHandler) {
if (p2PService.removeData(offerPayload, true)) {
if (resultHandler != null)
resultHandler.handleResult();
@@ -191,6 +208,7 @@ public List getOffers() {
offer.setPriceFeedService(priceFeedService);
return offer;
})
+ .filter(this::showOffer)
.collect(Collectors.toList());
}
@@ -236,7 +254,7 @@ private void doDumpStatistics() {
return null;
}
})
- .filter(e -> e != null)
+ .filter(Objects::nonNull)
.collect(Collectors.toList());
jsonFileManager.writeToDisc(Utilities.objectToJson(offerForJsonList), "offers_statistics");
}
diff --git a/core/src/main/java/bisq/core/offer/OfferPayload.java b/core/src/main/java/bisq/core/offer/OfferPayload.java
index d68aa7dec59..ea7ff0406d5 100644
--- a/core/src/main/java/bisq/core/offer/OfferPayload.java
+++ b/core/src/main/java/bisq/core/offer/OfferPayload.java
@@ -27,12 +27,11 @@
import bisq.common.util.ExtraDataMapValidator;
import bisq.common.util.JsonExclude;
-import io.bisq.generated.protobuffer.PB;
-
import org.springframework.util.CollectionUtils;
import java.security.PublicKey;
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;
@@ -63,21 +62,28 @@ public enum Direction {
BUY,
SELL;
- public static OfferPayload.Direction fromProto(PB.OfferPayload.Direction direction) {
+ public static OfferPayload.Direction fromProto(protobuf.OfferPayload.Direction direction) {
return ProtoUtil.enumFromProto(OfferPayload.Direction.class, direction.name());
}
- public static PB.OfferPayload.Direction toProtoMessage(Direction direction) {
- return PB.OfferPayload.Direction.valueOf(direction.name());
+ public static protobuf.OfferPayload.Direction toProtoMessage(Direction direction) {
+ return protobuf.OfferPayload.Direction.valueOf(direction.name());
}
}
// Keys for extra map
+ // Only set for fiat offers
public static final String ACCOUNT_AGE_WITNESS_HASH = "accountAgeWitnessHash";
public static final String REFERRAL_ID = "referralId";
+ // Only used in payment method F2F
public static final String F2F_CITY = "f2fCity";
public static final String F2F_EXTRA_INFO = "f2fExtraInfo";
+ // Comma separated list of ordinal of a bisq.common.app.Capability. E.g. ordinal of
+ // Capability.SIGNED_ACCOUNT_AGE_WITNESS is 11 and Capability.MEDIATION is 12 so if we want to signal that maker
+ // of the offer supports both capabilities we add "11, 12" to capabilities.
+ public static final String CAPABILITIES = "capabilities";
+
///////////////////////////////////////////////////////////////////////////////////////////
// Instance fields
@@ -107,7 +113,11 @@ public static PB.OfferPayload.Direction toProtoMessage(Direction direction) {
private final String baseCurrencyCode;
private final String counterCurrencyCode;
+ @Deprecated
+ // Not used anymore but we cannot set it Nullable or remove it to not break backward compatibility (diff. hash)
private final List arbitratorNodeAddresses;
+ @Deprecated
+ // Not used anymore but we cannot set it Nullable or remove it to not break backward compatibility (diff. hash)
private final List mediatorNodeAddresses;
private final String paymentMethodId;
private final String makerPaymentAccountId;
@@ -246,8 +256,8 @@ public OfferPayload(String id,
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.StoragePayload toProtoMessage() {
- PB.OfferPayload.Builder builder = PB.OfferPayload.newBuilder()
+ public protobuf.StoragePayload toProtoMessage() {
+ protobuf.OfferPayload.Builder builder = protobuf.OfferPayload.newBuilder()
.setId(id)
.setDate(date)
.setOwnerNodeAddress(ownerNodeAddress.toProtoMessage())
@@ -294,15 +304,15 @@ public PB.StoragePayload toProtoMessage() {
Optional.ofNullable(hashOfChallenge).ifPresent(builder::setHashOfChallenge);
Optional.ofNullable(extraDataMap).ifPresent(builder::putAllExtraData);
- return PB.StoragePayload.newBuilder().setOfferPayload(builder).build();
+ return protobuf.StoragePayload.newBuilder().setOfferPayload(builder).build();
}
- public static OfferPayload fromProto(PB.OfferPayload proto) {
+ public static OfferPayload fromProto(protobuf.OfferPayload proto) {
checkArgument(!proto.getOfferFeePaymentTxId().isEmpty(), "OfferFeePaymentTxId must be set in PB.OfferPayload");
List acceptedBankIds = proto.getAcceptedBankIdsList().isEmpty() ?
- null : proto.getAcceptedBankIdsList().stream().collect(Collectors.toList());
+ null : new ArrayList<>(proto.getAcceptedBankIdsList());
List acceptedCountryCodes = proto.getAcceptedCountryCodesList().isEmpty() ?
- null : proto.getAcceptedCountryCodesList().stream().collect(Collectors.toList());
+ null : new ArrayList<>(proto.getAcceptedCountryCodesList());
String hashOfChallenge = ProtoUtil.stringOrNullFromProto(proto.getHashOfChallenge());
Map extraDataMapMap = CollectionUtils.isEmpty(proto.getExtraDataMap()) ?
null : proto.getExtraDataMap();
@@ -390,8 +400,6 @@ public String toString() {
",\n minAmount=" + minAmount +
",\n baseCurrencyCode='" + baseCurrencyCode + '\'' +
",\n counterCurrencyCode='" + counterCurrencyCode + '\'' +
- ",\n arbitratorNodeAddresses=" + arbitratorNodeAddresses +
- ",\n mediatorNodeAddresses=" + mediatorNodeAddresses +
",\n paymentMethodId='" + paymentMethodId + '\'' +
",\n makerPaymentAccountId='" + makerPaymentAccountId + '\'' +
",\n offerFeePaymentTxId='" + offerFeePaymentTxId + '\'' +
diff --git a/core/src/main/java/bisq/core/offer/OfferRestrictions.java b/core/src/main/java/bisq/core/offer/OfferRestrictions.java
index 53905478992..d7b64580bd5 100644
--- a/core/src/main/java/bisq/core/offer/OfferRestrictions.java
+++ b/core/src/main/java/bisq/core/offer/OfferRestrictions.java
@@ -20,21 +20,37 @@
import bisq.core.payment.payload.PaymentMethod;
import bisq.core.trade.Trade;
+import bisq.common.app.Capabilities;
+import bisq.common.app.Capability;
+import bisq.common.util.Utilities;
+
import org.bitcoinj.core.Coin;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Map;
+
public class OfferRestrictions {
+ // The date when traders who have not updated cannot take offers from updated clients and their offers become
+ // invisible for updated clients.
+ private static final Date REQUIRE_UPDATE_DATE = Utilities.getUTCDate(2019, GregorianCalendar.SEPTEMBER, 19);
+
+ static boolean requiresUpdate() {
+ return new Date().after(REQUIRE_UPDATE_DATE);
+ }
+
public static Coin TOLERATED_SMALL_TRADE_AMOUNT = Coin.parseCoin("0.01");
public static boolean isOfferRisky(Offer offer) {
return offer != null &&
offer.isBuyOffer() &&
- PaymentMethod.hasChargebackRisk(offer.getPaymentMethod()) &&
+ PaymentMethod.hasChargebackRisk(offer.getPaymentMethod(), offer.getCurrencyCode()) &&
isMinTradeAmountRisky(offer);
}
public static boolean isSellOfferRisky(Offer offer) {
return offer != null &&
- PaymentMethod.hasChargebackRisk(offer.getPaymentMethod()) &&
+ PaymentMethod.hasChargebackRisk(offer.getPaymentMethod(), offer.getCurrencyCode()) &&
isMinTradeAmountRisky(offer);
}
@@ -44,7 +60,7 @@ public static boolean isTradeRisky(Trade trade) {
Offer offer = trade.getOffer();
return offer != null &&
- PaymentMethod.hasChargebackRisk(offer.getPaymentMethod()) &&
+ PaymentMethod.hasChargebackRisk(offer.getPaymentMethod(), offer.getCurrencyCode()) &&
trade.getTradeAmount() != null &&
isAmountRisky(trade.getTradeAmount());
}
@@ -53,7 +69,17 @@ public static boolean isMinTradeAmountRisky(Offer offer) {
return isAmountRisky(offer.getMinAmount());
}
- public static boolean isAmountRisky(Coin amount) {
+ private static boolean isAmountRisky(Coin amount) {
return amount.isGreaterThan(TOLERATED_SMALL_TRADE_AMOUNT);
}
+
+ static boolean hasOfferMandatoryCapability(Offer offer, Capability mandatoryCapability) {
+ Map extraDataMap = offer.getOfferPayload().getExtraDataMap();
+ if (extraDataMap != null && extraDataMap.containsKey(OfferPayload.CAPABILITIES)) {
+ String commaSeparatedOrdinals = extraDataMap.get(OfferPayload.CAPABILITIES);
+ Capabilities capabilities = Capabilities.fromStringList(commaSeparatedOrdinals);
+ return Capabilities.hasMandatoryCapability(capabilities, mandatoryCapability);
+ }
+ return false;
+ }
}
diff --git a/core/src/main/java/bisq/core/offer/OfferUtil.java b/core/src/main/java/bisq/core/offer/OfferUtil.java
index 14e30a62912..c987bd2e18f 100644
--- a/core/src/main/java/bisq/core/offer/OfferUtil.java
+++ b/core/src/main/java/bisq/core/offer/OfferUtil.java
@@ -17,6 +17,7 @@
package bisq.core.offer;
+import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.btc.wallet.BsqWalletService;
import bisq.core.btc.wallet.Restrictions;
import bisq.core.filter.FilterManager;
@@ -24,7 +25,6 @@
import bisq.core.locale.Res;
import bisq.core.monetary.Price;
import bisq.core.monetary.Volume;
-import bisq.core.payment.AccountAgeWitnessService;
import bisq.core.payment.F2FAccount;
import bisq.core.payment.PaymentAccount;
import bisq.core.provider.fee.FeeService;
@@ -38,6 +38,7 @@
import bisq.network.p2p.P2PService;
+import bisq.common.app.Capabilities;
import bisq.common.util.MathUtils;
import org.bitcoinj.core.Coin;
@@ -116,7 +117,9 @@ public static Coin getMakerFee(boolean isCurrencyForMakerFeeBtc, @Nullable Coin
* @param amount
* @return
*/
- public static boolean isCurrencyForMakerFeeBtc(Preferences preferences, BsqWalletService bsqWalletService, Coin amount) {
+ public static boolean isCurrencyForMakerFeeBtc(Preferences preferences,
+ BsqWalletService bsqWalletService,
+ Coin amount) {
boolean payFeeInBtc = preferences.getPayFeeInBtc();
boolean bsqForFeeAvailable = isBsqForMakerFeeAvailable(bsqWalletService, amount);
return payFeeInBtc || !bsqForFeeAvailable;
@@ -152,7 +155,9 @@ public static Coin getTakerFee(boolean isCurrencyForTakerFeeBtc, @Nullable Coin
}
}
- public static boolean isCurrencyForTakerFeeBtc(Preferences preferences, BsqWalletService bsqWalletService, Coin amount) {
+ public static boolean isCurrencyForTakerFeeBtc(Preferences preferences,
+ BsqWalletService bsqWalletService,
+ Coin amount) {
boolean payFeeInBtc = preferences.getPayFeeInBtc();
boolean bsqForFeeAvailable = isBsqForTakerFeeAvailable(bsqWalletService, amount);
return payFeeInBtc || !bsqForFeeAvailable;
@@ -278,10 +283,21 @@ static Coin getAdjustedAmount(Coin amount, Price price, long maxTradeLimit, int
public static Optional getFeeInUserFiatCurrency(Coin makerFee, boolean isCurrencyForMakerFeeBtc,
Preferences preferences, PriceFeedService priceFeedService,
BsqFormatter bsqFormatter) {
- // We use the users currency derived from his selected country.
- // We don't use the preferredTradeCurrency from preferences as that can be also set to an altcoin.
String countryCode = preferences.getUserCountry().code;
String userCurrencyCode = CurrencyUtil.getCurrencyByCountryCode(countryCode).getCode();
+ return getFeeInUserFiatCurrency(makerFee,
+ isCurrencyForMakerFeeBtc,
+ userCurrencyCode,
+ priceFeedService,
+ bsqFormatter);
+ }
+
+ public static Optional getFeeInUserFiatCurrency(Coin makerFee, boolean isCurrencyForMakerFeeBtc,
+ String userCurrencyCode, PriceFeedService priceFeedService,
+ BsqFormatter bsqFormatter) {
+ // We use the users currency derived from his selected country.
+ // We don't use the preferredTradeCurrency from preferences as that can be also set to an altcoin.
+
MarketPrice marketPrice = priceFeedService.getMarketPrice(userCurrencyCode);
if (marketPrice != null && makerFee != null) {
long marketPriceAsLong = MathUtils.roundDoubleToLong(MathUtils.scaleUpByPowerOf10(marketPrice.getPrice(), Fiat.SMALLEST_UNIT_EXPONENT));
@@ -306,7 +322,9 @@ public static Optional getFeeInUserFiatCurrency(Coin makerFee, boolean i
}
}
- public static String getFeeWithFiatAmount(Coin makerFeeAsCoin, Optional optionalFeeInFiat, BSFormatter formatter) {
+ public static String getFeeWithFiatAmount(Coin makerFeeAsCoin,
+ Optional optionalFeeInFiat,
+ BSFormatter formatter) {
String fee = makerFeeAsCoin != null ? formatter.formatCoinWithCode(makerFeeAsCoin) : Res.get("shared.na");
String feeInFiatAsString;
if (optionalFeeInFiat != null && optionalFeeInFiat.isPresent()) {
@@ -322,27 +340,24 @@ public static Map getExtraDataMap(AccountAgeWitnessService accou
ReferralIdService referralIdService,
PaymentAccount paymentAccount,
String currencyCode) {
- Map extraDataMap = null;
+ Map extraDataMap = new HashMap<>();
if (CurrencyUtil.isFiatCurrency(currencyCode)) {
- extraDataMap = new HashMap<>();
- final String myWitnessHashAsHex = accountAgeWitnessService.getMyWitnessHashAsHex(paymentAccount.getPaymentAccountPayload());
+ String myWitnessHashAsHex = accountAgeWitnessService.getMyWitnessHashAsHex(paymentAccount.getPaymentAccountPayload());
extraDataMap.put(OfferPayload.ACCOUNT_AGE_WITNESS_HASH, myWitnessHashAsHex);
}
if (referralIdService.getOptionalReferralId().isPresent()) {
- if (extraDataMap == null)
- extraDataMap = new HashMap<>();
extraDataMap.put(OfferPayload.REFERRAL_ID, referralIdService.getOptionalReferralId().get());
}
if (paymentAccount instanceof F2FAccount) {
- if (extraDataMap == null)
- extraDataMap = new HashMap<>();
extraDataMap.put(OfferPayload.F2F_CITY, ((F2FAccount) paymentAccount).getCity());
extraDataMap.put(OfferPayload.F2F_EXTRA_INFO, ((F2FAccount) paymentAccount).getExtraInfo());
}
- return extraDataMap;
+ extraDataMap.put(OfferPayload.CAPABILITIES, Capabilities.app.toStringList());
+
+ return extraDataMap.isEmpty() ? null : extraDataMap;
}
public static void validateOfferData(FilterManager filterManager,
diff --git a/core/src/main/java/bisq/core/offer/OpenOffer.java b/core/src/main/java/bisq/core/offer/OpenOffer.java
index 8505bdc85b4..2193b30752c 100644
--- a/core/src/main/java/bisq/core/offer/OpenOffer.java
+++ b/core/src/main/java/bisq/core/offer/OpenOffer.java
@@ -27,8 +27,6 @@
import bisq.common.proto.ProtoUtil;
import bisq.common.storage.Storage;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Date;
import java.util.Optional;
@@ -62,6 +60,10 @@ public enum State {
@Setter
@Nullable
private NodeAddress arbitratorNodeAddress;
+ @Getter
+ @Setter
+ @Nullable
+ private NodeAddress mediatorNodeAddress;
transient private Storage> storage;
@@ -75,30 +77,36 @@ public OpenOffer(Offer offer, Storage> storage) {
// PROTO BUFFER
///////////////////////////////////////////////////////////////////////////////////////////
- private OpenOffer(Offer offer, State state, @Nullable NodeAddress arbitratorNodeAddress) {
+ private OpenOffer(Offer offer,
+ State state,
+ @Nullable NodeAddress arbitratorNodeAddress,
+ @Nullable NodeAddress mediatorNodeAddress) {
this.offer = offer;
this.state = state;
this.arbitratorNodeAddress = arbitratorNodeAddress;
+ this.mediatorNodeAddress = mediatorNodeAddress;
if (this.state == State.RESERVED)
setState(State.AVAILABLE);
}
@Override
- public PB.Tradable toProtoMessage() {
- PB.OpenOffer.Builder builder = PB.OpenOffer.newBuilder()
+ public protobuf.Tradable toProtoMessage() {
+ protobuf.OpenOffer.Builder builder = protobuf.OpenOffer.newBuilder()
.setOffer(offer.toProtoMessage())
- .setState(PB.OpenOffer.State.valueOf(state.name()));
+ .setState(protobuf.OpenOffer.State.valueOf(state.name()));
Optional.ofNullable(arbitratorNodeAddress).ifPresent(nodeAddress -> builder.setArbitratorNodeAddress(nodeAddress.toProtoMessage()));
+ Optional.ofNullable(mediatorNodeAddress).ifPresent(nodeAddress -> builder.setMediatorNodeAddress(nodeAddress.toProtoMessage()));
- return PB.Tradable.newBuilder().setOpenOffer(builder).build();
+ return protobuf.Tradable.newBuilder().setOpenOffer(builder).build();
}
- public static Tradable fromProto(PB.OpenOffer proto) {
+ public static Tradable fromProto(protobuf.OpenOffer proto) {
return new OpenOffer(Offer.fromProto(proto.getOffer()),
ProtoUtil.enumFromProto(OpenOffer.State.class, proto.getState().name()),
- proto.hasArbitratorNodeAddress() ? NodeAddress.fromProto(proto.getArbitratorNodeAddress()) : null);
+ proto.hasArbitratorNodeAddress() ? NodeAddress.fromProto(proto.getArbitratorNodeAddress()) : null,
+ proto.hasMediatorNodeAddress() ? NodeAddress.fromProto(proto.getMediatorNodeAddress()) : null);
}
@@ -159,12 +167,15 @@ private void stopTimeout() {
}
}
+
@Override
public String toString() {
return "OpenOffer{" +
- "\n\toffer=" + offer +
- "\n\tstate=" + state +
- '}';
+ ",\n offer=" + offer +
+ ",\n state=" + state +
+ ",\n arbitratorNodeAddress=" + arbitratorNodeAddress +
+ ",\n mediatorNodeAddress=" + mediatorNodeAddress +
+ "\n}";
}
}
diff --git a/core/src/main/java/bisq/core/offer/OpenOfferManager.java b/core/src/main/java/bisq/core/offer/OpenOfferManager.java
index 5302a65df3c..6754512c6e1 100644
--- a/core/src/main/java/bisq/core/offer/OpenOfferManager.java
+++ b/core/src/main/java/bisq/core/offer/OpenOfferManager.java
@@ -17,17 +17,18 @@
package bisq.core.offer;
-import bisq.core.arbitration.ArbitratorManager;
import bisq.core.btc.wallet.BsqWalletService;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.btc.wallet.TradeWalletService;
import bisq.core.exceptions.TradePriceOutOfToleranceException;
-import bisq.core.offer.availability.ArbitratorSelection;
+import bisq.core.offer.availability.DisputeAgentSelection;
import bisq.core.offer.messages.OfferAvailabilityRequest;
import bisq.core.offer.messages.OfferAvailabilityResponse;
import bisq.core.offer.placeoffer.PlaceOfferModel;
import bisq.core.offer.placeoffer.PlaceOfferProtocol;
import bisq.core.provider.price.PriceFeedService;
+import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
+import bisq.core.support.dispute.mediation.mediator.MediatorManager;
import bisq.core.trade.TradableList;
import bisq.core.trade.closed.ClosedTradableManager;
import bisq.core.trade.handlers.TransactionResultHandler;
@@ -48,24 +49,22 @@
import bisq.common.Timer;
import bisq.common.UserThread;
+import bisq.common.app.Capabilities;
+import bisq.common.app.Capability;
import bisq.common.crypto.KeyRing;
import bisq.common.crypto.PubKeyRing;
import bisq.common.handlers.ErrorMessageHandler;
import bisq.common.handlers.ResultHandler;
import bisq.common.proto.network.NetworkEnvelope;
import bisq.common.proto.persistable.PersistedDataHost;
-import bisq.common.proto.persistable.PersistenceProtoResolver;
import bisq.common.storage.Storage;
import org.bitcoinj.core.Coin;
import javax.inject.Inject;
-import javax.inject.Named;
import javafx.collections.ObservableList;
-import java.io.File;
-
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
@@ -104,6 +103,7 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
private final Preferences preferences;
private final TradeStatisticsManager tradeStatisticsManager;
private final ArbitratorManager arbitratorManager;
+ private final MediatorManager mediatorManager;
private final Storage> openOfferTradableListStorage;
private final Map offersToBeEdited = new HashMap<>();
private boolean stopped;
@@ -115,7 +115,6 @@ public class OpenOfferManager implements PeerManager.Listener, DecryptedDirectMe
// Constructor, Initialization
///////////////////////////////////////////////////////////////////////////////////////////
- @SuppressWarnings("WeakerAccess")
@Inject
public OpenOfferManager(KeyRing keyRing,
User user,
@@ -127,10 +126,10 @@ public OpenOfferManager(KeyRing keyRing,
ClosedTradableManager closedTradableManager,
PriceFeedService priceFeedService,
Preferences preferences,
- PersistenceProtoResolver persistenceProtoResolver,
TradeStatisticsManager tradeStatisticsManager,
ArbitratorManager arbitratorManager,
- @Named(Storage.STORAGE_DIR) File storageDir) {
+ MediatorManager mediatorManager,
+ Storage> storage) {
this.keyRing = keyRing;
this.user = user;
this.p2PService = p2PService;
@@ -143,8 +142,9 @@ public OpenOfferManager(KeyRing keyRing,
this.preferences = preferences;
this.tradeStatisticsManager = tradeStatisticsManager;
this.arbitratorManager = arbitratorManager;
+ this.mediatorManager = mediatorManager;
- openOfferTradableListStorage = new Storage<>(storageDir, persistenceProtoResolver);
+ openOfferTradableListStorage = storage;
// In case the app did get killed the shutDown from the modules is not called, so we use a shutdown hook
Runtime.getRuntime().addShutdownHook(new Thread(() -> {
@@ -155,7 +155,10 @@ public OpenOfferManager(KeyRing keyRing,
@Override
public void readPersisted() {
openOffers = new TradableList<>(openOfferTradableListStorage, "OpenOffers");
- openOffers.forEach(e -> e.getOffer().setPriceFeedService(priceFeedService));
+ openOffers.forEach(e -> {
+ Offer offer = e.getOffer();
+ offer.setPriceFeedService(priceFeedService);
+ });
}
public void onAllServicesInitialized() {
@@ -187,8 +190,7 @@ private void cleanUpAddressEntries() {
});
}
- @SuppressWarnings("WeakerAccess")
- public void shutDown() {
+ private void shutDown() {
shutDown(null);
}
@@ -201,15 +203,14 @@ public void shutDown(@Nullable Runnable completeHandler) {
stopPeriodicRepublishOffersTimer();
stopRetryRepublishOffersTimer();
- log.debug("remove all open offers at shutDown");
// we remove own offers from offerbook when we go offline
// Normally we use a delay for broadcasting to the peers, but at shut down we want to get it fast out
-
- final int size = openOffers != null ? openOffers.size() : 0;
+ int size = openOffers != null ? openOffers.size() : 0;
+ log.info("Remove open offers at shutDown. Number of open offers: {}", size);
if (offerBookService.isBootstrapped() && size > 0) {
openOffers.forEach(openOffer -> offerBookService.removeOfferAtShutDown(openOffer.getOffer().getOfferPayload()));
if (completeHandler != null)
- UserThread.runAfter(completeHandler::run, size * 200 + 500, TimeUnit.MILLISECONDS);
+ UserThread.runAfter(completeHandler, size * 200 + 500, TimeUnit.MILLISECONDS);
} else {
if (completeHandler != null)
completeHandler.run();
@@ -220,7 +221,7 @@ public void removeAllOpenOffers(@Nullable Runnable completeHandler) {
removeOpenOffers(getObservableList(), completeHandler);
}
- public void removeOpenOffers(List openOffers, @Nullable Runnable completeHandler) {
+ private void removeOpenOffers(List openOffers, @Nullable Runnable completeHandler) {
final int size = openOffers.size();
// Copy list as we remove in the loop
List openOffersList = new ArrayList<>(openOffers);
@@ -228,7 +229,7 @@ public void removeOpenOffers(List openOffers, @Nullable Runnable comp
}, errorMessage -> {
}));
if (completeHandler != null)
- UserThread.runAfter(completeHandler::run, size * 200 + 500, TimeUnit.MILLISECONDS);
+ UserThread.runAfter(completeHandler, size * 200 + 500, TimeUnit.MILLISECONDS);
}
@@ -266,6 +267,8 @@ public void onDirectMessage(DecryptedMessageWithPubKey decryptedMessageWithPubKe
private void onBootstrapComplete() {
stopped = false;
+ maybeUpdatePersistedOffers();
+
// Republish means we send the complete offer object
republishOffers();
startPeriodicRepublishOffersTimer();
@@ -351,7 +354,7 @@ public void placeOffer(Offer offer,
log.debug("We have stopped already. We ignore that placeOfferProtocol.placeOffer.onResult call.");
}
},
- errorMessageHandler::handleErrorMessage
+ errorMessageHandler
);
placeOfferProtocol.placeOffer();
}
@@ -371,7 +374,9 @@ public void removeOffer(Offer offer, ResultHandler resultHandler, ErrorMessageHa
}
}
- public void activateOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
+ public void activateOpenOffer(OpenOffer openOffer,
+ ResultHandler resultHandler,
+ ErrorMessageHandler errorMessageHandler) {
if (!offersToBeEdited.containsKey(openOffer.getId())) {
Offer offer = openOffer.getOffer();
openOffer.setStorage(openOfferTradableListStorage);
@@ -387,7 +392,9 @@ public void activateOpenOffer(OpenOffer openOffer, ResultHandler resultHandler,
}
}
- public void deactivateOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
+ public void deactivateOpenOffer(OpenOffer openOffer,
+ ResultHandler resultHandler,
+ ErrorMessageHandler errorMessageHandler) {
Offer offer = openOffer.getOffer();
openOffer.setStorage(openOfferTradableListStorage);
offerBookService.deactivateOffer(offer.getOfferPayload(),
@@ -399,7 +406,9 @@ public void deactivateOpenOffer(OpenOffer openOffer, ResultHandler resultHandler
errorMessageHandler);
}
- public void removeOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
+ public void removeOpenOffer(OpenOffer openOffer,
+ ResultHandler resultHandler,
+ ErrorMessageHandler errorMessageHandler) {
if (!offersToBeEdited.containsKey(openOffer.getId())) {
Offer offer = openOffer.getOffer();
if (openOffer.isDeactivated()) {
@@ -415,7 +424,9 @@ public void removeOpenOffer(OpenOffer openOffer, ResultHandler resultHandler, Er
}
}
- public void editOpenOfferStart(OpenOffer openOffer, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
+ public void editOpenOfferStart(OpenOffer openOffer,
+ ResultHandler resultHandler,
+ ErrorMessageHandler errorMessageHandler) {
if (offersToBeEdited.containsKey(openOffer.getId())) {
log.warn("editOpenOfferStart called for an offer which is already in edit mode.");
resultHandler.handleResult();
@@ -428,7 +439,7 @@ public void editOpenOfferStart(OpenOffer openOffer, ResultHandler resultHandler,
resultHandler.handleResult();
} else {
deactivateOpenOffer(openOffer,
- () -> resultHandler.handleResult(),
+ resultHandler,
errorMessage -> {
offersToBeEdited.remove(openOffer.getId());
errorMessageHandler.handleErrorMessage(errorMessage);
@@ -436,7 +447,10 @@ public void editOpenOfferStart(OpenOffer openOffer, ResultHandler resultHandler,
}
}
- public void editOpenOfferPublish(Offer editedOffer, OpenOffer.State originalState, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
+ public void editOpenOfferPublish(Offer editedOffer,
+ OpenOffer.State originalState,
+ ResultHandler resultHandler,
+ ErrorMessageHandler errorMessageHandler) {
Optional openOfferOptional = getOpenOfferById(editedOffer.getId());
if (openOfferOptional.isPresent()) {
@@ -464,13 +478,14 @@ public void editOpenOfferPublish(Offer editedOffer, OpenOffer.State originalStat
}
}
- public void editOpenOfferCancel(OpenOffer openOffer, OpenOffer.State originalState, ResultHandler resultHandler, ErrorMessageHandler errorMessageHandler) {
+ public void editOpenOfferCancel(OpenOffer openOffer,
+ OpenOffer.State originalState,
+ ResultHandler resultHandler,
+ ErrorMessageHandler errorMessageHandler) {
if (offersToBeEdited.containsKey(openOffer.getId())) {
offersToBeEdited.remove(openOffer.getId());
if (originalState.equals(OpenOffer.State.AVAILABLE)) {
- activateOpenOffer(openOffer, () -> {
- resultHandler.handleResult();
- }, errorMessageHandler);
+ activateOpenOffer(openOffer, resultHandler, errorMessageHandler);
} else {
resultHandler.handleResult();
}
@@ -561,6 +576,7 @@ private void handleOfferAvailabilityRequest(OfferAvailabilityRequest request, No
Optional openOfferOptional = getOpenOfferById(request.offerId);
AvailabilityResult availabilityResult;
NodeAddress arbitratorNodeAddress = null;
+ NodeAddress mediatorNodeAddress = null;
if (openOfferOptional.isPresent()) {
OpenOffer openOffer = openOfferOptional.get();
if (openOffer.getState() == OpenOffer.State.AVAILABLE) {
@@ -570,23 +586,35 @@ private void handleOfferAvailabilityRequest(OfferAvailabilityRequest request, No
List acceptedArbitrators = user.getAcceptedArbitratorAddresses();
if (acceptedArbitrators != null && !acceptedArbitrators.isEmpty()) {
- arbitratorNodeAddress = ArbitratorSelection.getLeastUsedArbitrator(tradeStatisticsManager, arbitratorManager).getNodeAddress();
+ arbitratorNodeAddress = DisputeAgentSelection.getLeastUsedArbitrator(tradeStatisticsManager, arbitratorManager).getNodeAddress();
openOffer.setArbitratorNodeAddress(arbitratorNodeAddress);
- // Check also tradePrice to avoid failures after taker fee is paid caused by a too big difference
- // in trade price between the peers. Also here poor connectivity might cause market price API connection
- // losses and therefore an outdated market price.
- try {
- offer.checkTradePriceTolerance(request.getTakersTradePrice());
- } catch (TradePriceOutOfToleranceException e) {
- log.warn("Trade price check failed because takers price is outside out tolerance.");
- availabilityResult = AvailabilityResult.PRICE_OUT_OF_TOLERANCE;
- } catch (MarketPriceNotAvailableException e) {
- log.warn(e.getMessage());
- availabilityResult = AvailabilityResult.MARKET_PRICE_NOT_AVAILABLE;
- } catch (Throwable e) {
- log.warn("Trade price check failed. " + e.getMessage());
- availabilityResult = AvailabilityResult.UNKNOWN_FAILURE;
+ mediatorNodeAddress = DisputeAgentSelection.getLeastUsedMediator(tradeStatisticsManager, mediatorManager).getNodeAddress();
+ openOffer.setMediatorNodeAddress(mediatorNodeAddress);
+ Capabilities supportedCapabilities = request.getSupportedCapabilities();
+ if (!OfferRestrictions.requiresUpdate() ||
+ (supportedCapabilities != null &&
+ Capabilities.hasMandatoryCapability(supportedCapabilities, Capability.MEDIATION))) {
+ try {
+ // Check also tradePrice to avoid failures after taker fee is paid caused by a too big difference
+ // in trade price between the peers. Also here poor connectivity might cause market price API connection
+ // losses and therefore an outdated market price.
+ offer.checkTradePriceTolerance(request.getTakersTradePrice());
+ } catch (TradePriceOutOfToleranceException e) {
+ log.warn("Trade price check failed because takers price is outside out tolerance.");
+ availabilityResult = AvailabilityResult.PRICE_OUT_OF_TOLERANCE;
+ } catch (MarketPriceNotAvailableException e) {
+ log.warn(e.getMessage());
+ availabilityResult = AvailabilityResult.MARKET_PRICE_NOT_AVAILABLE;
+ } catch (Throwable e) {
+ log.warn("Trade price check failed. " + e.getMessage());
+ availabilityResult = AvailabilityResult.UNKNOWN_FAILURE;
+ }
+ } else {
+ log.warn("Taker has not mandatory capability MEDIATION");
+ // Because an old peer has not AvailabilityResult.MISSING_MANDATORY_CAPABILITY and we
+ // have not set the UNDEFINED fallback in AvailabilityResult the user will get a null value.
+ availabilityResult = AvailabilityResult.MISSING_MANDATORY_CAPABILITY;
}
} else {
log.warn("acceptedArbitrators is null or empty: acceptedArbitrators=" + acceptedArbitrators);
@@ -603,7 +631,10 @@ private void handleOfferAvailabilityRequest(OfferAvailabilityRequest request, No
availabilityResult = AvailabilityResult.OFFER_TAKEN;
}
- OfferAvailabilityResponse offerAvailabilityResponse = new OfferAvailabilityResponse(request.offerId, availabilityResult, arbitratorNodeAddress);
+ OfferAvailabilityResponse offerAvailabilityResponse = new OfferAvailabilityResponse(request.offerId,
+ availabilityResult,
+ arbitratorNodeAddress,
+ mediatorNodeAddress);
log.info("Send {} with offerId {} and uid {} to peer {}",
offerAvailabilityResponse.getClass().getSimpleName(), offerAvailabilityResponse.getOfferId(),
offerAvailabilityResponse.getUid(), peer);
@@ -614,14 +645,18 @@ private void handleOfferAvailabilityRequest(OfferAvailabilityRequest request, No
@Override
public void onArrived() {
log.info("{} arrived at peer: offerId={}; uid={}",
- offerAvailabilityResponse.getClass().getSimpleName(), offerAvailabilityResponse.getOfferId(), offerAvailabilityResponse.getUid());
+ offerAvailabilityResponse.getClass().getSimpleName(),
+ offerAvailabilityResponse.getOfferId(),
+ offerAvailabilityResponse.getUid());
}
@Override
public void onFault(String errorMessage) {
log.error("Sending {} failed: uid={}; peer={}; error={}",
- offerAvailabilityResponse.getClass().getSimpleName(), offerAvailabilityResponse.getUid(),
- peer, errorMessage);
+ offerAvailabilityResponse.getClass().getSimpleName(),
+ offerAvailabilityResponse.getUid(),
+ peer,
+ errorMessage);
}
});
result = true;
@@ -634,7 +669,10 @@ public void onFault(String errorMessage) {
}
}
- private void sendAckMessage(OfferAvailabilityRequest message, NodeAddress sender, boolean result, String errorMessage) {
+ private void sendAckMessage(OfferAvailabilityRequest message,
+ NodeAddress sender,
+ boolean result,
+ String errorMessage) {
String offerId = message.getOfferId();
String sourceUid = message.getUid();
AckMessage ackMessage = new AckMessage(p2PService.getNetworkNode().getNodeAddress(),
@@ -670,6 +708,98 @@ public void onFault(String errorMessage) {
}
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // Update persisted offer if a new capability is required after a software update
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ private void maybeUpdatePersistedOffers() {
+ // We need to clone to avoid ConcurrentModificationException
+ ArrayList openOffersClone = new ArrayList<>(openOffers.getList());
+ openOffersClone.forEach(openOffer -> {
+ Offer originalOffer = openOffer.getOffer();
+
+ OfferPayload originalOfferPayload = originalOffer.getOfferPayload();
+ // We added CAPABILITIES with entry for Capability.MEDIATION in v1.1.6 and want to rewrite a
+ // persisted offer after the user has updated to 1.1.6 so their offer will be accepted by the network.
+
+ if (!OfferRestrictions.hasOfferMandatoryCapability(originalOffer, Capability.MEDIATION)) {
+ // We rewrite our offer with the additional capabilities entry
+
+ Map originalExtraDataMap = originalOfferPayload.getExtraDataMap();
+ Map updatedExtraDataMap = new HashMap<>();
+
+ if (originalExtraDataMap != null) {
+ updatedExtraDataMap.putAll(originalExtraDataMap);
+ }
+
+ // We overwrite any entry with our current capabilities
+ updatedExtraDataMap.put(OfferPayload.CAPABILITIES, Capabilities.app.toStringList());
+
+ OfferPayload updatedPayload = new OfferPayload(originalOfferPayload.getId(),
+ originalOfferPayload.getDate(),
+ originalOfferPayload.getOwnerNodeAddress(),
+ originalOfferPayload.getPubKeyRing(),
+ originalOfferPayload.getDirection(),
+ originalOfferPayload.getPrice(),
+ originalOfferPayload.getMarketPriceMargin(),
+ originalOfferPayload.isUseMarketBasedPrice(),
+ originalOfferPayload.getAmount(),
+ originalOfferPayload.getMinAmount(),
+ originalOfferPayload.getBaseCurrencyCode(),
+ originalOfferPayload.getCounterCurrencyCode(),
+ originalOfferPayload.getArbitratorNodeAddresses(),
+ originalOfferPayload.getMediatorNodeAddresses(),
+ originalOfferPayload.getPaymentMethodId(),
+ originalOfferPayload.getMakerPaymentAccountId(),
+ originalOfferPayload.getOfferFeePaymentTxId(),
+ originalOfferPayload.getCountryCode(),
+ originalOfferPayload.getAcceptedCountryCodes(),
+ originalOfferPayload.getBankId(),
+ originalOfferPayload.getAcceptedBankIds(),
+ originalOfferPayload.getVersionNr(),
+ originalOfferPayload.getBlockHeightAtOfferCreation(),
+ originalOfferPayload.getTxFee(),
+ originalOfferPayload.getMakerFee(),
+ originalOfferPayload.isCurrencyForMakerFeeBtc(),
+ originalOfferPayload.getBuyerSecurityDeposit(),
+ originalOfferPayload.getSellerSecurityDeposit(),
+ originalOfferPayload.getMaxTradeLimit(),
+ originalOfferPayload.getMaxTradePeriod(),
+ originalOfferPayload.isUseAutoClose(),
+ originalOfferPayload.isUseReOpenAfterAutoClose(),
+ originalOfferPayload.getLowerClosePrice(),
+ originalOfferPayload.getUpperClosePrice(),
+ originalOfferPayload.isPrivateOffer(),
+ originalOfferPayload.getHashOfChallenge(),
+ updatedExtraDataMap,
+ originalOfferPayload.getProtocolVersion());
+
+ // Save states from original data to use the for updated
+ Offer.State originalOfferState = originalOffer.getState();
+ OpenOffer.State originalOpenOfferState = openOffer.getState();
+
+ // remove old offer
+ originalOffer.setState(Offer.State.REMOVED);
+ openOffer.setState(OpenOffer.State.CANCELED);
+ openOffer.setStorage(openOfferTradableListStorage);
+ openOffers.remove(openOffer);
+
+ // Create new Offer
+ Offer updatedOffer = new Offer(updatedPayload);
+ updatedOffer.setPriceFeedService(priceFeedService);
+ updatedOffer.setState(originalOfferState);
+
+ OpenOffer updatedOpenOffer = new OpenOffer(updatedOffer, openOfferTradableListStorage);
+ updatedOpenOffer.setState(originalOpenOfferState);
+ updatedOpenOffer.setStorage(openOfferTradableListStorage);
+ openOffers.add(updatedOpenOffer);
+
+ log.info("Converted offer to support new Capability.MEDIATION capability. id={}", originalOffer.getId());
+ }
+ });
+ }
+
+
///////////////////////////////////////////////////////////////////////////////////////////
// RepublishOffers, refreshOffers
///////////////////////////////////////////////////////////////////////////////////////////
diff --git a/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java b/core/src/main/java/bisq/core/offer/availability/DisputeAgentSelection.java
similarity index 50%
rename from core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java
rename to core/src/main/java/bisq/core/offer/availability/DisputeAgentSelection.java
index 4f34cefab01..bce44e6cbc6 100644
--- a/core/src/main/java/bisq/core/offer/availability/ArbitratorSelection.java
+++ b/core/src/main/java/bisq/core/offer/availability/DisputeAgentSelection.java
@@ -17,13 +17,15 @@
package bisq.core.offer.availability;
-import bisq.core.arbitration.Arbitrator;
-import bisq.core.arbitration.ArbitratorManager;
+import bisq.core.support.dispute.agent.DisputeAgent;
+import bisq.core.support.dispute.agent.DisputeAgentManager;
import bisq.core.trade.statistics.TradeStatistics2;
import bisq.core.trade.statistics.TradeStatisticsManager;
import bisq.common.util.Tuple2;
+import com.google.common.annotations.VisibleForTesting;
+
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
@@ -39,10 +41,25 @@
import static com.google.common.base.Preconditions.checkArgument;
@Slf4j
-public class ArbitratorSelection {
+public class DisputeAgentSelection {
+
+ public static T getLeastUsedArbitrator(TradeStatisticsManager tradeStatisticsManager,
+ DisputeAgentManager disputeAgentManager) {
+ return getLeastUsedDisputeAgent(tradeStatisticsManager,
+ disputeAgentManager,
+ TradeStatistics2.ARBITRATOR_ADDRESS);
+ }
+
+ public static T getLeastUsedMediator(TradeStatisticsManager tradeStatisticsManager,
+ DisputeAgentManager disputeAgentManager) {
+ return getLeastUsedDisputeAgent(tradeStatisticsManager,
+ disputeAgentManager,
+ TradeStatistics2.MEDIATOR_ADDRESS);
+ }
- public static Arbitrator getLeastUsedArbitrator(TradeStatisticsManager tradeStatisticsManager,
- ArbitratorManager arbitratorManager) {
+ private static T getLeastUsedDisputeAgent(TradeStatisticsManager tradeStatisticsManager,
+ DisputeAgentManager disputeAgentManager,
+ String extraMapKey) {
// We take last 100 entries from trade statistics
List list = new ArrayList<>(tradeStatisticsManager.getObservableTradeStatisticsSet());
list.sort(Comparator.comparing(TradeStatistics2::getTradeDate));
@@ -52,32 +69,33 @@ public static Arbitrator getLeastUsedArbitrator(TradeStatisticsManager tradeStat
list = list.subList(0, max);
}
- // We stored only first 4 chars of arbitrators onion address
+ // We stored only first 4 chars of disputeAgents onion address
List lastAddressesUsedInTrades = list.stream()
.filter(tradeStatistics2 -> tradeStatistics2.getExtraDataMap() != null)
- .map(tradeStatistics2 -> tradeStatistics2.getExtraDataMap().get(TradeStatistics2.ARBITRATOR_ADDRESS))
+ .map(tradeStatistics2 -> tradeStatistics2.getExtraDataMap().get(extraMapKey))
.filter(Objects::nonNull)
.collect(Collectors.toList());
- Set arbitrators = arbitratorManager.getArbitratorsObservableMap().values().stream()
- .map(arbitrator -> arbitrator.getNodeAddress().getFullAddress())
+ Set disputeAgents = disputeAgentManager.getObservableMap().values().stream()
+ .map(disputeAgent -> disputeAgent.getNodeAddress().getFullAddress())
.collect(Collectors.toSet());
- String result = getLeastUsedArbitrator(lastAddressesUsedInTrades, arbitrators);
+ String result = getLeastUsedDisputeAgent(lastAddressesUsedInTrades, disputeAgents);
- Optional optionalArbitrator = arbitratorManager.getArbitratorsObservableMap().values().stream()
+ Optional optionalDisputeAgent = disputeAgentManager.getObservableMap().values().stream()
.filter(e -> e.getNodeAddress().getFullAddress().equals(result))
.findAny();
- checkArgument(optionalArbitrator.isPresent(), "optionalArbitrator has to be present");
- return optionalArbitrator.get();
+ checkArgument(optionalDisputeAgent.isPresent(), "optionalDisputeAgent has to be present");
+ return optionalDisputeAgent.get();
}
- static String getLeastUsedArbitrator(List lastAddressesUsedInTrades, Set arbitrators) {
- checkArgument(!arbitrators.isEmpty(), "arbitrators must not be empty");
- List> arbitratorTuples = arbitrators.stream()
+ @VisibleForTesting
+ static String getLeastUsedDisputeAgent(List lastAddressesUsedInTrades, Set disputeAgents) {
+ checkArgument(!disputeAgents.isEmpty(), "disputeAgents must not be empty");
+ List> disputeAgentTuples = disputeAgents.stream()
.map(e -> new Tuple2<>(e, new AtomicInteger(0)))
.collect(Collectors.toList());
- arbitratorTuples.forEach(tuple -> {
+ disputeAgentTuples.forEach(tuple -> {
int count = (int) lastAddressesUsedInTrades.stream()
.filter(tuple.first::startsWith) // we use only first 4 chars for comparing
.mapToInt(e -> 1)
@@ -85,8 +103,8 @@ static String getLeastUsedArbitrator(List lastAddressesUsedInTrades, Set
tuple.second.set(count);
});
- arbitratorTuples.sort(Comparator.comparing(e -> e.first));
- arbitratorTuples.sort(Comparator.comparingInt(e -> e.second.get()));
- return arbitratorTuples.get(0).first;
+ disputeAgentTuples.sort(Comparator.comparing(e -> e.first));
+ disputeAgentTuples.sort(Comparator.comparingInt(e -> e.second.get()));
+ return disputeAgentTuples.get(0).first;
}
}
diff --git a/core/src/main/java/bisq/core/offer/availability/OfferAvailabilityModel.java b/core/src/main/java/bisq/core/offer/availability/OfferAvailabilityModel.java
index 982540b54c2..2b55c18813a 100644
--- a/core/src/main/java/bisq/core/offer/availability/OfferAvailabilityModel.java
+++ b/core/src/main/java/bisq/core/offer/availability/OfferAvailabilityModel.java
@@ -19,6 +19,8 @@
import bisq.core.offer.Offer;
import bisq.core.offer.messages.OfferAvailabilityResponse;
+import bisq.core.support.dispute.mediation.mediator.MediatorManager;
+import bisq.core.trade.statistics.TradeStatisticsManager;
import bisq.core.user.User;
import bisq.network.p2p.NodeAddress;
@@ -41,6 +43,10 @@ public class OfferAvailabilityModel implements Model {
private final P2PService p2PService;
@Getter
final private User user;
+ @Getter
+ private final MediatorManager mediatorManager;
+ @Getter
+ private final TradeStatisticsManager tradeStatisticsManager;
private NodeAddress peerNodeAddress; // maker
private OfferAvailabilityResponse message;
@Nullable
@@ -48,21 +54,32 @@ public class OfferAvailabilityModel implements Model {
@Getter
private NodeAddress selectedArbitrator;
+ // Added in v1.1.6
+ @Nullable
+ @Setter
+ @Getter
+ private NodeAddress selectedMediator;
+
+
public OfferAvailabilityModel(Offer offer,
PubKeyRing pubKeyRing,
P2PService p2PService,
- User user) {
+ User user,
+ MediatorManager mediatorManager,
+ TradeStatisticsManager tradeStatisticsManager) {
this.offer = offer;
this.pubKeyRing = pubKeyRing;
this.p2PService = p2PService;
this.user = user;
+ this.mediatorManager = mediatorManager;
+ this.tradeStatisticsManager = tradeStatisticsManager;
}
public NodeAddress getPeerNodeAddress() {
return peerNodeAddress;
}
- public void setPeerNodeAddress(NodeAddress peerNodeAddress) {
+ void setPeerNodeAddress(NodeAddress peerNodeAddress) {
this.peerNodeAddress = peerNodeAddress;
}
diff --git a/core/src/main/java/bisq/core/offer/availability/tasks/ProcessOfferAvailabilityResponse.java b/core/src/main/java/bisq/core/offer/availability/tasks/ProcessOfferAvailabilityResponse.java
index 2fddd54e62a..1690ddc34ae 100644
--- a/core/src/main/java/bisq/core/offer/availability/tasks/ProcessOfferAvailabilityResponse.java
+++ b/core/src/main/java/bisq/core/offer/availability/tasks/ProcessOfferAvailabilityResponse.java
@@ -19,24 +19,18 @@
import bisq.core.offer.AvailabilityResult;
import bisq.core.offer.Offer;
+import bisq.core.offer.availability.DisputeAgentSelection;
import bisq.core.offer.availability.OfferAvailabilityModel;
import bisq.core.offer.messages.OfferAvailabilityResponse;
-import bisq.core.trade.protocol.ArbitratorSelectionRule;
import bisq.network.p2p.NodeAddress;
import bisq.common.taskrunner.Task;
import bisq.common.taskrunner.TaskRunner;
-import com.google.common.collect.Lists;
-
-import java.util.List;
-import java.util.stream.Collectors;
-
import lombok.extern.slf4j.Slf4j;
import static com.google.common.base.Preconditions.checkArgument;
-import static com.google.common.base.Preconditions.checkNotNull;
@Slf4j
public class ProcessOfferAvailabilityResponse extends Task {
@@ -62,43 +56,14 @@ protected void run() {
offer.setState(Offer.State.AVAILABLE);
- NodeAddress selectedArbitrator = offerAvailabilityResponse.getArbitrator();
-
- if (selectedArbitrator != null) {
- model.setSelectedArbitrator(selectedArbitrator);
- complete();
- return;
- }
-
- // We have an offer from a maker who runs a pre 0.9 version.
- log.info("Maker has on old version and does not send the selected arbitrator in the offerAvailabilityResponse. " +
- "We use the old selection model instead with the supported arbitrators of the offers");
-
- List userArbitratorAddresses = model.getUser().getAcceptedArbitratorAddresses();
- checkNotNull(userArbitratorAddresses, "model.getUser().getAcceptedArbitratorAddresses() must not be null");
-
- List offerArbitratorNodeAddresses = offer.getArbitratorNodeAddresses();
-
- List matchingArbitrators = offerArbitratorNodeAddresses.stream()
- .filter(userArbitratorAddresses::contains)
- .collect(Collectors.toList());
-
- if (!matchingArbitrators.isEmpty()) {
- // We have at least one arbitrator which was used in the offer and is still available.
- try {
- model.setSelectedArbitrator(ArbitratorSelectionRule.select(Lists.newArrayList(matchingArbitrators), offer));
- complete();
- } catch (Throwable t) {
- failed("There is no arbitrator matching that offer. The maker has " +
- "not updated to the latest version and the arbitrators selected for that offer are not available anymore.");
- }
- } else {
- // If an arbitrator which was selected in the offer from an old version has revoked we would get a failed take-offer attempt
- // with lost trade fees. To avoid that we fail here after 1 week after the new rule is activated.
- // Because one arbitrator need to revoke his application and register new as he gets too many transactions already
- // we need to handle the planned revoke case.
- failed("You cannot take that offer because the maker has not updated to version 0.9.");
+ model.setSelectedArbitrator(offerAvailabilityResponse.getArbitrator());
+ NodeAddress mediator = offerAvailabilityResponse.getMediator();
+ if (mediator == null) {
+ // We do not get a mediator from old clients so we need to handle the null case.
+ mediator = DisputeAgentSelection.getLeastUsedMediator(model.getTradeStatisticsManager(), model.getMediatorManager()).getNodeAddress();
}
+ model.setSelectedMediator(mediator);
+ complete();
} catch (Throwable t) {
offer.setErrorMessage("An error occurred.\n" +
"Error message:\n"
diff --git a/core/src/main/java/bisq/core/offer/messages/OfferAvailabilityRequest.java b/core/src/main/java/bisq/core/offer/messages/OfferAvailabilityRequest.java
index 75c4905ec22..704f73c981d 100644
--- a/core/src/main/java/bisq/core/offer/messages/OfferAvailabilityRequest.java
+++ b/core/src/main/java/bisq/core/offer/messages/OfferAvailabilityRequest.java
@@ -23,13 +23,12 @@
import bisq.common.app.Version;
import bisq.common.crypto.PubKeyRing;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Optional;
import java.util.UUID;
import lombok.EqualsAndHashCode;
import lombok.Value;
+import lombok.extern.slf4j.Slf4j;
import javax.annotation.Nullable;
@@ -37,6 +36,7 @@
// to the trading peer
@EqualsAndHashCode(callSuper = true)
@Value
+@Slf4j
public final class OfferAvailabilityRequest extends OfferMessage implements SupportedCapabilitiesMessage {
private final PubKeyRing pubKeyRing;
private final long takersTradePrice;
@@ -72,8 +72,8 @@ private OfferAvailabilityRequest(String offerId,
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
- final PB.OfferAvailabilityRequest.Builder builder = PB.OfferAvailabilityRequest.newBuilder()
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
+ final protobuf.OfferAvailabilityRequest.Builder builder = protobuf.OfferAvailabilityRequest.newBuilder()
.setOfferId(offerId)
.setPubKeyRing(pubKeyRing.toProtoMessage())
.setTakersTradePrice(takersTradePrice);
@@ -86,7 +86,7 @@ public PB.NetworkEnvelope toProtoNetworkEnvelope() {
.build();
}
- public static OfferAvailabilityRequest fromProto(PB.OfferAvailabilityRequest proto, int messageVersion) {
+ public static OfferAvailabilityRequest fromProto(protobuf.OfferAvailabilityRequest proto, int messageVersion) {
return new OfferAvailabilityRequest(proto.getOfferId(),
PubKeyRing.fromProto(proto.getPubKeyRing()),
proto.getTakersTradePrice(),
diff --git a/core/src/main/java/bisq/core/offer/messages/OfferAvailabilityResponse.java b/core/src/main/java/bisq/core/offer/messages/OfferAvailabilityResponse.java
index 03ecfd275d4..f71713c7a01 100644
--- a/core/src/main/java/bisq/core/offer/messages/OfferAvailabilityResponse.java
+++ b/core/src/main/java/bisq/core/offer/messages/OfferAvailabilityResponse.java
@@ -27,8 +27,6 @@
import bisq.common.app.Version;
import bisq.common.proto.ProtoUtil;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.Optional;
import java.util.UUID;
@@ -46,17 +44,22 @@ public final class OfferAvailabilityResponse extends OfferMessage implements Sup
@Nullable
private final Capabilities supportedCapabilities;
- // Was introduced in v 0.9.0. Might be null if msg received from node with old version
- @Nullable
private final NodeAddress arbitrator;
+ // Was introduced in v 1.1.6. Might be null if msg received from node with old version
+ @Nullable
+ private final NodeAddress mediator;
- public OfferAvailabilityResponse(String offerId, AvailabilityResult availabilityResult, NodeAddress arbitrator) {
+ public OfferAvailabilityResponse(String offerId,
+ AvailabilityResult availabilityResult,
+ NodeAddress arbitrator,
+ NodeAddress mediator) {
this(offerId,
availabilityResult,
Capabilities.app,
Version.getP2PMessageVersion(),
UUID.randomUUID().toString(),
- arbitrator);
+ arbitrator,
+ mediator);
}
@@ -69,34 +72,38 @@ private OfferAvailabilityResponse(String offerId,
@Nullable Capabilities supportedCapabilities,
int messageVersion,
@Nullable String uid,
- @Nullable NodeAddress arbitrator) {
+ NodeAddress arbitrator,
+ @Nullable NodeAddress mediator) {
super(messageVersion, offerId, uid);
this.availabilityResult = availabilityResult;
this.supportedCapabilities = supportedCapabilities;
this.arbitrator = arbitrator;
+ this.mediator = mediator;
}
@Override
- public PB.NetworkEnvelope toProtoNetworkEnvelope() {
- final PB.OfferAvailabilityResponse.Builder builder = PB.OfferAvailabilityResponse.newBuilder()
+ public protobuf.NetworkEnvelope toProtoNetworkEnvelope() {
+ final protobuf.OfferAvailabilityResponse.Builder builder = protobuf.OfferAvailabilityResponse.newBuilder()
.setOfferId(offerId)
- .setAvailabilityResult(PB.AvailabilityResult.valueOf(availabilityResult.name()));
+ .setAvailabilityResult(protobuf.AvailabilityResult.valueOf(availabilityResult.name()))
+ .setArbitrator(arbitrator.toProtoMessage());
Optional.ofNullable(supportedCapabilities).ifPresent(e -> builder.addAllSupportedCapabilities(Capabilities.toIntList(supportedCapabilities)));
Optional.ofNullable(uid).ifPresent(e -> builder.setUid(uid));
- Optional.ofNullable(arbitrator).ifPresent(e -> builder.setArbitrator(arbitrator.toProtoMessage()));
+ Optional.ofNullable(mediator).ifPresent(e -> builder.setMediator(mediator.toProtoMessage()));
return getNetworkEnvelopeBuilder()
.setOfferAvailabilityResponse(builder)
.build();
}
- public static OfferAvailabilityResponse fromProto(PB.OfferAvailabilityResponse proto, int messageVersion) {
+ public static OfferAvailabilityResponse fromProto(protobuf.OfferAvailabilityResponse proto, int messageVersion) {
return new OfferAvailabilityResponse(proto.getOfferId(),
ProtoUtil.enumFromProto(AvailabilityResult.class, proto.getAvailabilityResult().name()),
Capabilities.fromIntList(proto.getSupportedCapabilitiesList()),
messageVersion,
proto.getUid().isEmpty() ? null : proto.getUid(),
- proto.hasArbitrator() ? NodeAddress.fromProto(proto.getArbitrator()) : null);
+ NodeAddress.fromProto(proto.getArbitrator()),
+ proto.hasMediator() ? NodeAddress.fromProto(proto.getMediator()) : null);
}
}
diff --git a/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java b/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java
index 6c67acf39d6..e63e31ecdf2 100644
--- a/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java
+++ b/core/src/main/java/bisq/core/offer/placeoffer/PlaceOfferModel.java
@@ -17,12 +17,12 @@
package bisq.core.offer.placeoffer;
-import bisq.core.arbitration.ArbitratorManager;
import bisq.core.btc.wallet.BsqWalletService;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.btc.wallet.TradeWalletService;
import bisq.core.offer.Offer;
import bisq.core.offer.OfferBookService;
+import bisq.core.support.dispute.arbitration.arbitrator.ArbitratorManager;
import bisq.core.trade.statistics.TradeStatisticsManager;
import bisq.core.user.User;
diff --git a/core/src/main/java/bisq/core/offer/placeoffer/tasks/CreateMakerFeeTx.java b/core/src/main/java/bisq/core/offer/placeoffer/tasks/CreateMakerFeeTx.java
index 6419a0b287c..f7e35d82a08 100644
--- a/core/src/main/java/bisq/core/offer/placeoffer/tasks/CreateMakerFeeTx.java
+++ b/core/src/main/java/bisq/core/offer/placeoffer/tasks/CreateMakerFeeTx.java
@@ -17,7 +17,6 @@
package bisq.core.offer.placeoffer.tasks;
-import bisq.core.arbitration.Arbitrator;
import bisq.core.btc.exceptions.TxBroadcastException;
import bisq.core.btc.model.AddressEntry;
import bisq.core.btc.wallet.BsqWalletService;
@@ -28,8 +27,9 @@
import bisq.core.dao.exceptions.DaoDisabledException;
import bisq.core.dao.state.model.blockchain.TxType;
import bisq.core.offer.Offer;
-import bisq.core.offer.availability.ArbitratorSelection;
+import bisq.core.offer.availability.DisputeAgentSelection;
import bisq.core.offer.placeoffer.PlaceOfferModel;
+import bisq.core.support.dispute.arbitration.arbitrator.Arbitrator;
import bisq.common.UserThread;
import bisq.common.taskrunner.Task;
@@ -47,7 +47,7 @@ public class CreateMakerFeeTx extends Task {
private static final Logger log = LoggerFactory.getLogger(CreateMakerFeeTx.class);
private Transaction tradeFeeTx = null;
- @SuppressWarnings({"WeakerAccess", "unused"})
+ @SuppressWarnings({"unused"})
public CreateMakerFeeTx(TaskRunner taskHandler, PlaceOfferModel model) {
super(taskHandler, model);
}
@@ -62,7 +62,7 @@ protected void run() {
String id = offer.getId();
BtcWalletService walletService = model.getWalletService();
- Arbitrator arbitrator = ArbitratorSelection.getLeastUsedArbitrator(model.getTradeStatisticsManager(),
+ Arbitrator arbitrator = DisputeAgentSelection.getLeastUsedArbitrator(model.getTradeStatisticsManager(),
model.getArbitratorManager());
Address fundingAddress = walletService.getOrCreateAddressEntry(id, AddressEntry.Context.OFFER_FUNDING).getAddress();
diff --git a/core/src/main/java/bisq/core/offer/placeoffer/tasks/ValidateOffer.java b/core/src/main/java/bisq/core/offer/placeoffer/tasks/ValidateOffer.java
index 8216c924f21..70701adc79c 100644
--- a/core/src/main/java/bisq/core/offer/placeoffer/tasks/ValidateOffer.java
+++ b/core/src/main/java/bisq/core/offer/placeoffer/tasks/ValidateOffer.java
@@ -83,8 +83,6 @@ protected void run() {
checkArgument(offer.getDate().getTime() > 0,
"Date must not be 0. date=" + offer.getDate().toString());
- checkNotNull(offer.getArbitratorNodeAddresses(), "Arbitrator is null");
- checkNotNull(offer.getMediatorNodeAddresses(), "Mediator is null");
checkNotNull(offer.getCurrencyCode(), "Currency is null");
checkNotNull(offer.getDirection(), "Direction is null");
checkNotNull(offer.getId(), "Id is null");
diff --git a/core/src/main/java/bisq/core/payment/ChargeBackRisk.java b/core/src/main/java/bisq/core/payment/ChargeBackRisk.java
new file mode 100644
index 00000000000..6faa91c9402
--- /dev/null
+++ b/core/src/main/java/bisq/core/payment/ChargeBackRisk.java
@@ -0,0 +1,29 @@
+/*
+ * 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 .
+ */
+
+package bisq.core.payment;
+
+import bisq.core.payment.payload.PaymentMethod;
+
+import javax.inject.Singleton;
+
+@Singleton
+public class ChargeBackRisk {
+ public boolean hasChargebackRisk(String id, String currencyCode) {
+ return PaymentMethod.hasChargebackRisk(id, currencyCode);
+ }
+}
diff --git a/core/src/main/java/bisq/core/payment/JapanBankAccount.java b/core/src/main/java/bisq/core/payment/JapanBankAccount.java
new file mode 100644
index 00000000000..b2d9fede114
--- /dev/null
+++ b/core/src/main/java/bisq/core/payment/JapanBankAccount.java
@@ -0,0 +1,124 @@
+/*
+ * 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 .
+ */
+
+package bisq.core.payment;
+
+import bisq.core.payment.payload.JapanBankAccountPayload;
+import bisq.core.payment.payload.PaymentAccountPayload;
+import bisq.core.payment.payload.PaymentMethod;
+import bisq.core.payment.payload.JapanBankAccountPayload;
+
+import org.jetbrains.annotations.NotNull;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import bisq.core.locale.Country;
+import bisq.core.locale.FiatCurrency;
+import bisq.core.payment.payload.JapanBankAccountPayload;
+
+public final class JapanBankAccount extends PaymentAccount
+{
+ public JapanBankAccount()
+ {
+ super(PaymentMethod.JAPAN_BANK);
+ setSingleTradeCurrency(new FiatCurrency("JPY"));
+ }
+
+ @Override
+ protected PaymentAccountPayload createPayload()
+ {
+ return new JapanBankAccountPayload(paymentMethod.getId(), id);
+ }
+
+ // bank code
+ public String getBankCode()
+ {
+ return ((JapanBankAccountPayload) paymentAccountPayload).getBankCode();
+ }
+ public void setBankCode(String bankCode)
+ {
+ if (bankCode == null) bankCode = "";
+ ((JapanBankAccountPayload) paymentAccountPayload).setBankCode(bankCode);
+ }
+
+ // bank name
+ public String getBankName()
+ {
+ return ((JapanBankAccountPayload) paymentAccountPayload).getBankName();
+ }
+ public void setBankName(String bankName)
+ {
+ if (bankName == null) bankName = "";
+ ((JapanBankAccountPayload) paymentAccountPayload).setBankName(bankName);
+ }
+
+ // branch code
+ public String getBankBranchCode()
+ {
+ return ((JapanBankAccountPayload) paymentAccountPayload).getBankBranchCode();
+ }
+ public void setBankBranchCode(String bankBranchCode)
+ {
+ if (bankBranchCode == null) bankBranchCode = "";
+ ((JapanBankAccountPayload) paymentAccountPayload).setBankBranchCode(bankBranchCode);
+ }
+
+ // branch name
+ public String getBankBranchName()
+ {
+ return ((JapanBankAccountPayload) paymentAccountPayload).getBankBranchName();
+ }
+ public void setBankBranchName(String bankBranchName)
+ {
+ if (bankBranchName == null) bankBranchName = "";
+ ((JapanBankAccountPayload) paymentAccountPayload).setBankBranchName(bankBranchName);
+ }
+
+ // account type
+ public String getBankAccountType()
+ {
+ return ((JapanBankAccountPayload) paymentAccountPayload).getBankAccountType();
+ }
+ public void setBankAccountType(String bankAccountType)
+ {
+ if (bankAccountType == null) bankAccountType = "";
+ ((JapanBankAccountPayload) paymentAccountPayload).setBankAccountType(bankAccountType);
+ }
+
+ // account number
+ public String getBankAccountNumber()
+ {
+ return ((JapanBankAccountPayload) paymentAccountPayload).getBankAccountNumber();
+ }
+ public void setBankAccountNumber(String bankAccountNumber)
+ {
+ if (bankAccountNumber == null) bankAccountNumber = "";
+ ((JapanBankAccountPayload) paymentAccountPayload).setBankAccountNumber(bankAccountNumber);
+ }
+
+ // account name
+ public String getBankAccountName()
+ {
+ return ((JapanBankAccountPayload) paymentAccountPayload).getBankAccountName();
+ }
+ public void setBankAccountName(String bankAccountName)
+ {
+ if (bankAccountName == null) bankAccountName = "";
+ ((JapanBankAccountPayload) paymentAccountPayload).setBankAccountName(bankAccountName);
+ }
+}
diff --git a/core/src/main/java/bisq/core/payment/PaymentAccount.java b/core/src/main/java/bisq/core/payment/PaymentAccount.java
index a0a9fdbc046..2a4b6bd354e 100644
--- a/core/src/main/java/bisq/core/payment/PaymentAccount.java
+++ b/core/src/main/java/bisq/core/payment/PaymentAccount.java
@@ -26,8 +26,6 @@
import bisq.common.proto.persistable.PersistablePayload;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
@@ -85,20 +83,20 @@ public void init() {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.PaymentAccount toProtoMessage() {
+ public protobuf.PaymentAccount toProtoMessage() {
checkNotNull(accountName, "accountName must not be null");
- PB.PaymentAccount.Builder builder = PB.PaymentAccount.newBuilder()
+ protobuf.PaymentAccount.Builder builder = protobuf.PaymentAccount.newBuilder()
.setPaymentMethod(paymentMethod.toProtoMessage())
.setId(id)
.setCreationDate(creationDate)
- .setPaymentAccountPayload((PB.PaymentAccountPayload) paymentAccountPayload.toProtoMessage())
+ .setPaymentAccountPayload((protobuf.PaymentAccountPayload) paymentAccountPayload.toProtoMessage())
.setAccountName(accountName)
- .addAllTradeCurrencies(ProtoUtil.collectionToProto(tradeCurrencies));
- Optional.ofNullable(selectedTradeCurrency).ifPresent(selectedTradeCurrency -> builder.setSelectedTradeCurrency((PB.TradeCurrency) selectedTradeCurrency.toProtoMessage()));
+ .addAllTradeCurrencies(ProtoUtil.collectionToProto(tradeCurrencies));
+ Optional.ofNullable(selectedTradeCurrency).ifPresent(selectedTradeCurrency -> builder.setSelectedTradeCurrency((protobuf.TradeCurrency) selectedTradeCurrency.toProtoMessage()));
return builder.build();
}
- public static PaymentAccount fromProto(PB.PaymentAccount proto, CoreProtoResolver coreProtoResolver) {
+ public static PaymentAccount fromProto(protobuf.PaymentAccount proto, CoreProtoResolver coreProtoResolver) {
PaymentAccount account = PaymentAccountFactory.getPaymentAccount(PaymentMethod.getPaymentMethodById(proto.getPaymentMethod().getId()));
account.getTradeCurrencies().clear();
account.setId(proto.getId());
diff --git a/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java b/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java
index 044967cd7a6..e858e01e3b0 100644
--- a/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java
+++ b/core/src/main/java/bisq/core/payment/PaymentAccountFactory.java
@@ -44,6 +44,8 @@ public static PaymentAccount getPaymentAccount(PaymentMethod paymentMethod) {
return new SameBankAccount();
case PaymentMethod.SPECIFIC_BANKS_ID:
return new SpecificBanksAccount();
+ case PaymentMethod.JAPAN_BANK_ID:
+ return new JapanBankAccount();
case PaymentMethod.ALI_PAY_ID:
return new AliPayAccount();
case PaymentMethod.WECHAT_PAY_ID:
diff --git a/core/src/main/java/bisq/core/payment/PaymentAccountList.java b/core/src/main/java/bisq/core/payment/PaymentAccountList.java
index 3965ea3ce44..edd21695389 100644
--- a/core/src/main/java/bisq/core/payment/PaymentAccountList.java
+++ b/core/src/main/java/bisq/core/payment/PaymentAccountList.java
@@ -22,8 +22,6 @@
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistableList;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import java.util.ArrayList;
@@ -41,13 +39,13 @@ public PaymentAccountList(List list) {
@Override
public Message toProtoMessage() {
- return PB.PersistableEnvelope.newBuilder()
- .setPaymentAccountList(PB.PaymentAccountList.newBuilder()
+ return protobuf.PersistableEnvelope.newBuilder()
+ .setPaymentAccountList(protobuf.PaymentAccountList.newBuilder()
.addAllPaymentAccount(getList().stream().map(PaymentAccount::toProtoMessage).collect(Collectors.toList())))
.build();
}
- public static PersistableEnvelope fromProto(PB.PaymentAccountList proto, CoreProtoResolver coreProtoResolver) {
+ public static PersistableEnvelope fromProto(protobuf.PaymentAccountList proto, CoreProtoResolver coreProtoResolver) {
return new PaymentAccountList(new ArrayList<>(proto.getPaymentAccountList().stream()
.map(e -> PaymentAccount.fromProto(e, coreProtoResolver))
.collect(Collectors.toList())));
diff --git a/core/src/main/java/bisq/core/payment/PaymentAccountUtil.java b/core/src/main/java/bisq/core/payment/PaymentAccountUtil.java
index 37c607b999e..b4bba4f4e76 100644
--- a/core/src/main/java/bisq/core/payment/PaymentAccountUtil.java
+++ b/core/src/main/java/bisq/core/payment/PaymentAccountUtil.java
@@ -17,6 +17,8 @@
package bisq.core.payment;
+import bisq.core.account.witness.AccountAgeRestrictions;
+import bisq.core.account.witness.AccountAgeWitnessService;
import bisq.core.locale.Country;
import bisq.core.offer.Offer;
import bisq.core.offer.OfferRestrictions;
@@ -65,7 +67,7 @@ public static boolean isSellOfferAndAllTakerPaymentAccountsForOfferImmature(Offe
private static boolean isTakerAccountForOfferMature(Offer offer,
PaymentAccount takerPaymentAccount,
AccountAgeWitnessService accountAgeWitnessService) {
- return !PaymentMethod.hasChargebackRisk(offer.getPaymentMethod()) ||
+ return !PaymentMethod.hasChargebackRisk(offer.getPaymentMethod(), offer.getCurrencyCode()) ||
!OfferRestrictions.isMinTradeAmountRisky(offer) ||
(isTakerPaymentAccountValidForOffer(offer, takerPaymentAccount) &&
!AccountAgeRestrictions.isMyAccountAgeImmature(accountAgeWitnessService, takerPaymentAccount));
@@ -82,7 +84,10 @@ public static boolean hasMakerAnyMatureAccountForBuyOffer(Collection.
+ */
+
+package bisq.core.payment.payload;
+
+import bisq.core.locale.Res;
+
+import com.google.protobuf.Message;
+
+import org.springframework.util.CollectionUtils;
+
+import java.nio.charset.Charset;
+
+import java.util.HashMap;
+import java.util.Map;
+
+import lombok.EqualsAndHashCode;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.ToString;
+import lombok.extern.slf4j.Slf4j;
+
+@EqualsAndHashCode(callSuper = true)
+@ToString
+@Setter
+@Getter
+@Slf4j
+public final class JapanBankAccountPayload extends PaymentAccountPayload {
+ // bank
+ private String bankName = "";
+ private String bankCode = "";
+ // branch
+ private String bankBranchName = "";
+ private String bankBranchCode = "";
+ // account
+ private String bankAccountType = "";
+ private String bankAccountName = "";
+ private String bankAccountNumber = "";
+
+ public JapanBankAccountPayload(String paymentMethod, String id) {
+ super(paymentMethod, id);
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // PROTO BUFFER
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ private JapanBankAccountPayload(String paymentMethod,
+ String id,
+ String bankName,
+ String bankCode,
+ String bankBranchName,
+ String bankBranchCode,
+ String bankAccountType,
+ String bankAccountName,
+ String bankAccountNumber,
+ long maxTradePeriod,
+ Map excludeFromJsonDataMap) {
+ super(paymentMethod,
+ id,
+ maxTradePeriod,
+ excludeFromJsonDataMap);
+
+ this.bankName = bankName;
+ this.bankCode = bankCode;
+ this.bankBranchName = bankBranchName;
+ this.bankBranchCode = bankBranchCode;
+ this.bankAccountType = bankAccountType;
+ this.bankAccountName = bankAccountName;
+ this.bankAccountNumber = bankAccountNumber;
+ }
+
+ @Override
+ public Message toProtoMessage() {
+ return getPaymentAccountPayloadBuilder()
+ .setJapanBankAccountPayload(
+ protobuf.JapanBankAccountPayload.newBuilder()
+ .setBankName(bankName)
+ .setBankCode(bankCode)
+ .setBankBranchName(bankBranchName)
+ .setBankBranchCode(bankBranchCode)
+ .setBankAccountType(bankAccountType)
+ .setBankAccountName(bankAccountName)
+ .setBankAccountNumber(bankAccountNumber)
+ ).build();
+ }
+
+ public static JapanBankAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
+ protobuf.JapanBankAccountPayload japanBankAccountPayload = proto.getJapanBankAccountPayload();
+ return new JapanBankAccountPayload(proto.getPaymentMethodId(),
+ proto.getId(),
+ japanBankAccountPayload.getBankName(),
+ japanBankAccountPayload.getBankCode(),
+ japanBankAccountPayload.getBankBranchName(),
+ japanBankAccountPayload.getBankBranchCode(),
+ japanBankAccountPayload.getBankAccountType(),
+ japanBankAccountPayload.getBankAccountName(),
+ japanBankAccountPayload.getBankAccountNumber(),
+ proto.getMaxTradePeriod(),
+ CollectionUtils.isEmpty(proto.getExcludeFromJsonDataMap()) ? null : new HashMap<>(proto.getExcludeFromJsonDataMap()));
+ }
+
+
+ ///////////////////////////////////////////////////////////////////////////////////////////
+ // API
+ ///////////////////////////////////////////////////////////////////////////////////////////
+
+ @Override
+ public String getPaymentDetails()
+ {
+ return Res.get(paymentMethodId) + " - " + getPaymentDetailsForTradePopup().replace("\n", ", ");
+ }
+
+ @Override
+ public String getPaymentDetailsForTradePopup()
+ {
+ return
+ Res.get("payment.japan.bank") + ": " + bankName + "(" + bankCode + ")\n" +
+ Res.get("payment.japan.branch") + ": " + bankBranchName + "(" + bankBranchCode + ")\n" +
+ Res.get("payment.japan.account") + ": " + bankAccountType + " " + bankAccountNumber + "\n" + Res.get("payment.japan.recipient") + ": " + bankAccountName;
+ }
+
+
+ @Override
+ public byte[] getAgeWitnessInputData() {
+ String all = this.bankName + this.bankBranchName + this.bankAccountType + this.bankAccountNumber + this.bankAccountName;
+ return super.getAgeWitnessInputData(all.getBytes(Charset.forName("UTF-8")));
+ }
+}
diff --git a/core/src/main/java/bisq/core/payment/payload/MoneyBeamAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/MoneyBeamAccountPayload.java
index e999d9de97b..855fac929cc 100644
--- a/core/src/main/java/bisq/core/payment/payload/MoneyBeamAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/MoneyBeamAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -69,12 +67,12 @@ private MoneyBeamAccountPayload(String paymentMethod,
@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
- .setMoneyBeamAccountPayload(PB.MoneyBeamAccountPayload.newBuilder()
+ .setMoneyBeamAccountPayload(protobuf.MoneyBeamAccountPayload.newBuilder()
.setAccountId(accountId))
.build();
}
- public static MoneyBeamAccountPayload fromProto(PB.PaymentAccountPayload proto) {
+ public static MoneyBeamAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new MoneyBeamAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getMoneyBeamAccountPayload().getAccountId(),
diff --git a/core/src/main/java/bisq/core/payment/payload/MoneyGramAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/MoneyGramAccountPayload.java
index 361e87361cf..e958633a7dd 100644
--- a/core/src/main/java/bisq/core/payment/payload/MoneyGramAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/MoneyGramAccountPayload.java
@@ -21,8 +21,6 @@
import bisq.core.locale.CountryUtil;
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -80,8 +78,8 @@ private MoneyGramAccountPayload(String paymentMethodName,
@Override
public Message toProtoMessage() {
- PB.MoneyGramAccountPayload.Builder builder =
- PB.MoneyGramAccountPayload.newBuilder()
+ protobuf.MoneyGramAccountPayload.Builder builder =
+ protobuf.MoneyGramAccountPayload.newBuilder()
.setHolderName(holderName)
.setCountryCode(countryCode)
.setState(state)
@@ -92,8 +90,8 @@ public Message toProtoMessage() {
.build();
}
- public static PaymentAccountPayload fromProto(PB.PaymentAccountPayload proto) {
- PB.MoneyGramAccountPayload moneyGramAccountPayload = proto.getMoneyGramAccountPayload();
+ public static PaymentAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
+ protobuf.MoneyGramAccountPayload moneyGramAccountPayload = proto.getMoneyGramAccountPayload();
return new MoneyGramAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
moneyGramAccountPayload.getCountryCode(),
diff --git a/core/src/main/java/bisq/core/payment/payload/NationalBankAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/NationalBankAccountPayload.java
index 381d0fa9be1..1ffc77eac66 100644
--- a/core/src/main/java/bisq/core/payment/payload/NationalBankAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/NationalBankAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -78,12 +76,12 @@ private NationalBankAccountPayload(String paymentMethodName,
@Override
public Message toProtoMessage() {
- PB.BankAccountPayload.Builder bankAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
+ protobuf.BankAccountPayload.Builder bankAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
.getCountryBasedPaymentAccountPayloadBuilder()
.getBankAccountPayloadBuilder()
- .setNationalBankAccountPayload(PB.NationalBankAccountPayload.newBuilder());
+ .setNationalBankAccountPayload(protobuf.NationalBankAccountPayload.newBuilder());
- PB.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
+ protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
.getCountryBasedPaymentAccountPayloadBuilder()
.setBankAccountPayload(bankAccountPayloadBuilder);
@@ -92,9 +90,9 @@ public Message toProtoMessage() {
.build();
}
- public static NationalBankAccountPayload fromProto(PB.PaymentAccountPayload proto) {
- PB.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
- PB.BankAccountPayload bankAccountPayloadPB = countryBasedPaymentAccountPayload.getBankAccountPayload();
+ public static NationalBankAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
+ protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
+ protobuf.BankAccountPayload bankAccountPayloadPB = countryBasedPaymentAccountPayload.getBankAccountPayload();
return new NationalBankAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
countryBasedPaymentAccountPayload.getCountryCode(),
diff --git a/core/src/main/java/bisq/core/payment/payload/OKPayAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/OKPayAccountPayload.java
index 4be25fb12a4..f5e2d6adab8 100644
--- a/core/src/main/java/bisq/core/payment/payload/OKPayAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/OKPayAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -71,12 +69,12 @@ private OKPayAccountPayload(String paymentMethod,
@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
- .setOKPayAccountPayload(PB.OKPayAccountPayload.newBuilder()
+ .setOKPayAccountPayload(protobuf.OKPayAccountPayload.newBuilder()
.setAccountNr(accountNr))
.build();
}
- public static OKPayAccountPayload fromProto(PB.PaymentAccountPayload proto) {
+ public static OKPayAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new OKPayAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getOKPayAccountPayload().getAccountNr(),
diff --git a/core/src/main/java/bisq/core/payment/payload/PaymentAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/PaymentAccountPayload.java
index 1fea94e836b..fb771f7aa17 100644
--- a/core/src/main/java/bisq/core/payment/payload/PaymentAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/PaymentAccountPayload.java
@@ -23,8 +23,6 @@
import bisq.common.util.JsonExclude;
import bisq.common.util.Utilities;
-import io.bisq.generated.protobuffer.PB;
-
import org.apache.commons.lang3.ArrayUtils;
import java.nio.charset.Charset;
@@ -104,8 +102,8 @@ protected PaymentAccountPayload(String paymentMethodId,
this.excludeFromJsonDataMap.put(SALT, Utilities.encodeToHex(CryptoUtils.getRandomBytes(32)));
}
- protected PB.PaymentAccountPayload.Builder getPaymentAccountPayloadBuilder() {
- final PB.PaymentAccountPayload.Builder builder = PB.PaymentAccountPayload.newBuilder()
+ protected protobuf.PaymentAccountPayload.Builder getPaymentAccountPayloadBuilder() {
+ final protobuf.PaymentAccountPayload.Builder builder = protobuf.PaymentAccountPayload.newBuilder()
.setPaymentMethodId(paymentMethodId)
.setMaxTradePeriod(maxTradePeriod)
.setId(id);
@@ -120,9 +118,9 @@ protected PB.PaymentAccountPayload.Builder getPaymentAccountPayloadBuilder() {
// API
///////////////////////////////////////////////////////////////////////////////////////////
- abstract public String getPaymentDetails();
+ public abstract String getPaymentDetails();
- abstract public String getPaymentDetailsForTradePopup();
+ public abstract String getPaymentDetailsForTradePopup();
public byte[] getSalt() {
checkNotNull(excludeFromJsonDataMap, "excludeFromJsonDataMap must not be null");
diff --git a/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java b/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java
index f125fcc29aa..983d0177e62 100644
--- a/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java
+++ b/core/src/main/java/bisq/core/payment/payload/PaymentMethod.java
@@ -17,13 +17,12 @@
package bisq.core.payment.payload;
+import bisq.core.locale.CurrencyUtil;
import bisq.core.locale.Res;
import bisq.core.payment.TradeLimits;
import bisq.common.proto.persistable.PersistablePayload;
-import io.bisq.generated.protobuffer.PB;
-
import org.bitcoinj.core.Coin;
import java.util.ArrayList;
@@ -53,8 +52,9 @@ public final class PaymentMethod implements PersistablePayload, Comparable {
private static final long DAY = TimeUnit.HOURS.toMillis(24);
// Default trade limits.
- // We initialize very early before reading persisted data. We will apply later the limit from the DAO param
- // but that can be only done after the dao is initialized. The default values will be used for deriving the
+ // We initialize very early before reading persisted data. We will apply later the limit from
+ // the DAO param (Param.MAX_TRADE_LIMIT) but that can be only done after the dao is initialized.
+ // The default values will be used for deriving the
// risk factor so the relation between the risk categories stays the same as with the default values.
// We must not change those values as it could lead to invalid offers if amount becomes lower then new trade limit.
// Increasing might be ok, but needs more thought as well...
@@ -72,6 +72,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable {
public static final String SEPA_INSTANT_ID = "SEPA_INSTANT";
public static final String FASTER_PAYMENTS_ID = "FASTER_PAYMENTS";
public static final String NATIONAL_BANK_ID = "NATIONAL_BANK";
+ public static final String JAPAN_BANK_ID = "JAPAN_BANK";
public static final String SAME_BANK_ID = "SAME_BANK";
public static final String SPECIFIC_BANKS_ID = "SPECIFIC_BANKS";
public static final String SWISH_ID = "SWISH";
@@ -108,6 +109,7 @@ public final class PaymentMethod implements PersistablePayload, Comparable {
public static PaymentMethod SEPA_INSTANT;
public static PaymentMethod FASTER_PAYMENTS;
public static PaymentMethod NATIONAL_BANK;
+ public static PaymentMethod JAPAN_BANK;
public static PaymentMethod SAME_BANK;
public static PaymentMethod SPECIFIC_BANKS;
public static PaymentMethod SWISH;
@@ -176,6 +178,9 @@ public final class PaymentMethod implements PersistablePayload, Comparable {
PERFECT_MONEY = new PaymentMethod(PERFECT_MONEY_ID, DAY, DEFAULT_TRADE_LIMIT_LOW_RISK),
ADVANCED_CASH = new PaymentMethod(ADVANCED_CASH_ID, DAY, DEFAULT_TRADE_LIMIT_VERY_LOW_RISK),
+ // Japan
+ JAPAN_BANK = new PaymentMethod(JAPAN_BANK_ID, DAY, DEFAULT_TRADE_LIMIT_LOW_RISK),
+
// China
ALI_PAY = new PaymentMethod(ALI_PAY_ID, DAY, DEFAULT_TRADE_LIMIT_LOW_RISK),
WECHAT_PAY = new PaymentMethod(WECHAT_PAY_ID, DAY, DEFAULT_TRADE_LIMIT_LOW_RISK),
@@ -255,15 +260,15 @@ private PaymentMethod(String id) {
///////////////////////////////////////////////////////////////////////////////////////////
@Override
- public PB.PaymentMethod toProtoMessage() {
- return PB.PaymentMethod.newBuilder()
+ public protobuf.PaymentMethod toProtoMessage() {
+ return protobuf.PaymentMethod.newBuilder()
.setId(id)
.setMaxTradePeriod(maxTradePeriod)
.setMaxTradeLimit(maxTradeLimit)
.build();
}
- public static PaymentMethod fromProto(PB.PaymentMethod proto) {
+ public static PaymentMethod fromProto(protobuf.PaymentMethod proto) {
return new PaymentMethod(proto.getId(),
proto.getMaxTradePeriod(),
Coin.valueOf(proto.getMaxTradeLimit()));
@@ -317,11 +322,18 @@ public boolean isAsset() {
return this.equals(BLOCK_CHAINS_INSTANT) || this.equals(BLOCK_CHAINS);
}
- public static boolean hasChargebackRisk(PaymentMethod paymentMethod) {
+ public static boolean hasChargebackRisk(PaymentMethod paymentMethod, String currencyCode) {
if (paymentMethod == null)
return false;
String id = paymentMethod.getId();
+ return hasChargebackRisk(id, currencyCode);
+ }
+
+ public static boolean hasChargebackRisk(String id, String currencyCode) {
+ if (CurrencyUtil.getMatureMarketCurrencies().stream()
+ .noneMatch(c -> c.getCode().equals(currencyCode)))
+ return false;
return id.equals(PaymentMethod.SEPA_ID) ||
id.equals(PaymentMethod.SEPA_INSTANT_ID) ||
id.equals(PaymentMethod.INTERAC_E_TRANSFER_ID) ||
diff --git a/core/src/main/java/bisq/core/payment/payload/PerfectMoneyAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/PerfectMoneyAccountPayload.java
index 2a5c80d1d58..e734e820cae 100644
--- a/core/src/main/java/bisq/core/payment/payload/PerfectMoneyAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/PerfectMoneyAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -71,12 +69,12 @@ private PerfectMoneyAccountPayload(String paymentMethod,
@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
- .setPerfectMoneyAccountPayload(PB.PerfectMoneyAccountPayload.newBuilder()
+ .setPerfectMoneyAccountPayload(protobuf.PerfectMoneyAccountPayload.newBuilder()
.setAccountNr(accountNr))
.build();
}
- public static PerfectMoneyAccountPayload fromProto(PB.PaymentAccountPayload proto) {
+ public static PerfectMoneyAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new PerfectMoneyAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getPerfectMoneyAccountPayload().getAccountNr(),
diff --git a/core/src/main/java/bisq/core/payment/payload/PopmoneyAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/PopmoneyAccountPayload.java
index a27c3ac6a87..6d7a490178b 100644
--- a/core/src/main/java/bisq/core/payment/payload/PopmoneyAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/PopmoneyAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -72,13 +70,13 @@ private PopmoneyAccountPayload(String paymentMethod,
@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
- .setPopmoneyAccountPayload(PB.PopmoneyAccountPayload.newBuilder()
+ .setPopmoneyAccountPayload(protobuf.PopmoneyAccountPayload.newBuilder()
.setAccountId(accountId)
.setHolderName(holderName))
.build();
}
- public static PopmoneyAccountPayload fromProto(PB.PaymentAccountPayload proto) {
+ public static PopmoneyAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new PopmoneyAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getPopmoneyAccountPayload().getAccountId(),
diff --git a/core/src/main/java/bisq/core/payment/payload/PromptPayAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/PromptPayAccountPayload.java
index 568272c7aee..1d365d66f85 100644
--- a/core/src/main/java/bisq/core/payment/payload/PromptPayAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/PromptPayAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -70,12 +68,12 @@ private PromptPayAccountPayload(String paymentMethod, String id,
@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
- .setPromptPayAccountPayload(PB.PromptPayAccountPayload.newBuilder()
+ .setPromptPayAccountPayload(protobuf.PromptPayAccountPayload.newBuilder()
.setPromptPayId(promptPayId))
.build();
}
- public static PromptPayAccountPayload fromProto(PB.PaymentAccountPayload proto) {
+ public static PromptPayAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new PromptPayAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getPromptPayAccountPayload().getPromptPayId(),
diff --git a/core/src/main/java/bisq/core/payment/payload/RevolutAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/RevolutAccountPayload.java
index fa2be433b64..fef979aebbb 100644
--- a/core/src/main/java/bisq/core/payment/payload/RevolutAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/RevolutAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -69,12 +67,12 @@ private RevolutAccountPayload(String paymentMethod,
@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
- .setRevolutAccountPayload(PB.RevolutAccountPayload.newBuilder()
+ .setRevolutAccountPayload(protobuf.RevolutAccountPayload.newBuilder()
.setAccountId(accountId))
.build();
}
- public static RevolutAccountPayload fromProto(PB.PaymentAccountPayload proto) {
+ public static RevolutAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new RevolutAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getRevolutAccountPayload().getAccountId(),
diff --git a/core/src/main/java/bisq/core/payment/payload/SameBankAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/SameBankAccountPayload.java
index c481bbef581..313117f9872 100644
--- a/core/src/main/java/bisq/core/payment/payload/SameBankAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/SameBankAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -79,12 +77,12 @@ private SameBankAccountPayload(String paymentMethodName,
@Override
public Message toProtoMessage() {
- PB.BankAccountPayload.Builder bankAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
+ protobuf.BankAccountPayload.Builder bankAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
.getCountryBasedPaymentAccountPayloadBuilder()
.getBankAccountPayloadBuilder()
- .setSameBankAccontPayload(PB.SameBankAccountPayload.newBuilder());
+ .setSameBankAccontPayload(protobuf.SameBankAccountPayload.newBuilder());
- PB.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
+ protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
.getCountryBasedPaymentAccountPayloadBuilder()
.setBankAccountPayload(bankAccountPayloadBuilder);
@@ -93,9 +91,9 @@ public Message toProtoMessage() {
.build();
}
- public static SameBankAccountPayload fromProto(PB.PaymentAccountPayload proto) {
- PB.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
- PB.BankAccountPayload bankAccountPayload = countryBasedPaymentAccountPayload.getBankAccountPayload();
+ public static SameBankAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
+ protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
+ protobuf.BankAccountPayload bankAccountPayload = countryBasedPaymentAccountPayload.getBankAccountPayload();
return new SameBankAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
countryBasedPaymentAccountPayload.getCountryCode(),
diff --git a/core/src/main/java/bisq/core/payment/payload/SepaAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/SepaAccountPayload.java
index a8fe37f1aa2..75aee237351 100644
--- a/core/src/main/java/bisq/core/payment/payload/SepaAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/SepaAccountPayload.java
@@ -21,8 +21,6 @@
import bisq.core.locale.CountryUtil;
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -100,14 +98,14 @@ private SepaAccountPayload(String paymentMethodName,
@Override
public Message toProtoMessage() {
- PB.SepaAccountPayload.Builder builder =
- PB.SepaAccountPayload.newBuilder()
+ protobuf.SepaAccountPayload.Builder builder =
+ protobuf.SepaAccountPayload.newBuilder()
.setHolderName(holderName)
.setIban(iban)
.setBic(bic)
.setEmail(email)
.addAllAcceptedCountryCodes(acceptedCountryCodes);
- final PB.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayload = getPaymentAccountPayloadBuilder()
+ final protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayload = getPaymentAccountPayloadBuilder()
.getCountryBasedPaymentAccountPayloadBuilder()
.setSepaAccountPayload(builder);
return getPaymentAccountPayloadBuilder()
@@ -115,9 +113,9 @@ public Message toProtoMessage() {
.build();
}
- public static PaymentAccountPayload fromProto(PB.PaymentAccountPayload proto) {
- PB.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
- PB.SepaAccountPayload sepaAccountPayloadPB = countryBasedPaymentAccountPayload.getSepaAccountPayload();
+ public static PaymentAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
+ protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
+ protobuf.SepaAccountPayload sepaAccountPayloadPB = countryBasedPaymentAccountPayload.getSepaAccountPayload();
return new SepaAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
countryBasedPaymentAccountPayload.getCountryCode(),
diff --git a/core/src/main/java/bisq/core/payment/payload/SepaInstantAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/SepaInstantAccountPayload.java
index 10e2e23951c..f57a96cb914 100644
--- a/core/src/main/java/bisq/core/payment/payload/SepaInstantAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/SepaInstantAccountPayload.java
@@ -21,8 +21,6 @@
import bisq.core.locale.CountryUtil;
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -97,13 +95,13 @@ private SepaInstantAccountPayload(String paymentMethodName,
@Override
public Message toProtoMessage() {
- PB.SepaInstantAccountPayload.Builder builder =
- PB.SepaInstantAccountPayload.newBuilder()
+ protobuf.SepaInstantAccountPayload.Builder builder =
+ protobuf.SepaInstantAccountPayload.newBuilder()
.setHolderName(holderName)
.setIban(iban)
.setBic(bic)
.addAllAcceptedCountryCodes(acceptedCountryCodes);
- final PB.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayload = getPaymentAccountPayloadBuilder()
+ final protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayload = getPaymentAccountPayloadBuilder()
.getCountryBasedPaymentAccountPayloadBuilder()
.setSepaInstantAccountPayload(builder);
return getPaymentAccountPayloadBuilder()
@@ -111,9 +109,9 @@ public Message toProtoMessage() {
.build();
}
- public static PaymentAccountPayload fromProto(PB.PaymentAccountPayload proto) {
- PB.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
- PB.SepaInstantAccountPayload sepaInstantAccountPayloadPB = countryBasedPaymentAccountPayload.getSepaInstantAccountPayload();
+ public static PaymentAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
+ protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
+ protobuf.SepaInstantAccountPayload sepaInstantAccountPayloadPB = countryBasedPaymentAccountPayload.getSepaInstantAccountPayload();
return new SepaInstantAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
countryBasedPaymentAccountPayload.getCountryCode(),
diff --git a/core/src/main/java/bisq/core/payment/payload/SpecificBanksAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/SpecificBanksAccountPayload.java
index 8d8be40da91..6d136651a97 100644
--- a/core/src/main/java/bisq/core/payment/payload/SpecificBanksAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/SpecificBanksAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -88,15 +86,15 @@ private SpecificBanksAccountPayload(String paymentMethodName,
@Override
public Message toProtoMessage() {
- final PB.SpecificBanksAccountPayload.Builder builder = PB.SpecificBanksAccountPayload.newBuilder()
+ final protobuf.SpecificBanksAccountPayload.Builder builder = protobuf.SpecificBanksAccountPayload.newBuilder()
.addAllAcceptedBanks(acceptedBanks);
- PB.BankAccountPayload.Builder bankAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
+ protobuf.BankAccountPayload.Builder bankAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
.getCountryBasedPaymentAccountPayloadBuilder()
.getBankAccountPayloadBuilder()
.setSpecificBanksAccountPayload(builder);
- PB.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
+ protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayloadBuilder = getPaymentAccountPayloadBuilder()
.getCountryBasedPaymentAccountPayloadBuilder()
.setBankAccountPayload(bankAccountPayloadBuilder);
@@ -105,10 +103,10 @@ public Message toProtoMessage() {
.build();
}
- public static SpecificBanksAccountPayload fromProto(PB.PaymentAccountPayload proto) {
- PB.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
- PB.BankAccountPayload bankAccountPayload = countryBasedPaymentAccountPayload.getBankAccountPayload();
- PB.SpecificBanksAccountPayload specificBanksAccountPayload = bankAccountPayload.getSpecificBanksAccountPayload();
+ public static SpecificBanksAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
+ protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
+ protobuf.BankAccountPayload bankAccountPayload = countryBasedPaymentAccountPayload.getBankAccountPayload();
+ protobuf.SpecificBanksAccountPayload specificBanksAccountPayload = bankAccountPayload.getSpecificBanksAccountPayload();
return new SpecificBanksAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
countryBasedPaymentAccountPayload.getCountryCode(),
diff --git a/core/src/main/java/bisq/core/payment/payload/SwishAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/SwishAccountPayload.java
index ddc0e70b02a..142d61f0377 100644
--- a/core/src/main/java/bisq/core/payment/payload/SwishAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/SwishAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -72,13 +70,13 @@ private SwishAccountPayload(String paymentMethod, String id,
@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
- .setSwishAccountPayload(PB.SwishAccountPayload.newBuilder()
+ .setSwishAccountPayload(protobuf.SwishAccountPayload.newBuilder()
.setMobileNr(mobileNr)
.setHolderName(holderName))
.build();
}
- public static SwishAccountPayload fromProto(PB.PaymentAccountPayload proto) {
+ public static SwishAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new SwishAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getSwishAccountPayload().getMobileNr(),
diff --git a/core/src/main/java/bisq/core/payment/payload/USPostalMoneyOrderAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/USPostalMoneyOrderAccountPayload.java
index 94068c990af..83b9ec31350 100644
--- a/core/src/main/java/bisq/core/payment/payload/USPostalMoneyOrderAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/USPostalMoneyOrderAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -74,13 +72,13 @@ private USPostalMoneyOrderAccountPayload(String paymentMethod, String id,
@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
- .setUSPostalMoneyOrderAccountPayload(PB.USPostalMoneyOrderAccountPayload.newBuilder()
+ .setUSPostalMoneyOrderAccountPayload(protobuf.USPostalMoneyOrderAccountPayload.newBuilder()
.setPostalAddress(postalAddress)
.setHolderName(holderName))
.build();
}
- public static USPostalMoneyOrderAccountPayload fromProto(PB.PaymentAccountPayload proto) {
+ public static USPostalMoneyOrderAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new USPostalMoneyOrderAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getUSPostalMoneyOrderAccountPayload().getPostalAddress(),
diff --git a/core/src/main/java/bisq/core/payment/payload/UpholdAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/UpholdAccountPayload.java
index 44700ae32ed..a48280200f9 100644
--- a/core/src/main/java/bisq/core/payment/payload/UpholdAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/UpholdAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -69,12 +67,12 @@ private UpholdAccountPayload(String paymentMethod,
@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
- .setUpholdAccountPayload(PB.UpholdAccountPayload.newBuilder()
+ .setUpholdAccountPayload(protobuf.UpholdAccountPayload.newBuilder()
.setAccountId(accountId))
.build();
}
- public static UpholdAccountPayload fromProto(PB.PaymentAccountPayload proto) {
+ public static UpholdAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new UpholdAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getUpholdAccountPayload().getAccountId(),
diff --git a/core/src/main/java/bisq/core/payment/payload/VenmoAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/VenmoAccountPayload.java
index 713851c1adb..fc168fc6353 100644
--- a/core/src/main/java/bisq/core/payment/payload/VenmoAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/VenmoAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -75,13 +73,13 @@ private VenmoAccountPayload(String paymentMethod,
@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
- .setVenmoAccountPayload(PB.VenmoAccountPayload.newBuilder()
+ .setVenmoAccountPayload(protobuf.VenmoAccountPayload.newBuilder()
.setVenmoUserName(venmoUserName)
.setHolderName(holderName))
.build();
}
- public static VenmoAccountPayload fromProto(PB.PaymentAccountPayload proto) {
+ public static VenmoAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new VenmoAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getVenmoAccountPayload().getVenmoUserName(),
diff --git a/core/src/main/java/bisq/core/payment/payload/WeChatPayAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/WeChatPayAccountPayload.java
index 9300fafd2d0..9e040b599d3 100644
--- a/core/src/main/java/bisq/core/payment/payload/WeChatPayAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/WeChatPayAccountPayload.java
@@ -19,8 +19,6 @@
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -68,12 +66,12 @@ private WeChatPayAccountPayload(String paymentMethod,
@Override
public Message toProtoMessage() {
return getPaymentAccountPayloadBuilder()
- .setWeChatPayAccountPayload(PB.WeChatPayAccountPayload.newBuilder()
+ .setWeChatPayAccountPayload(protobuf.WeChatPayAccountPayload.newBuilder()
.setAccountNr(accountNr))
.build();
}
- public static WeChatPayAccountPayload fromProto(PB.PaymentAccountPayload proto) {
+ public static WeChatPayAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
return new WeChatPayAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
proto.getWeChatPayAccountPayload().getAccountNr(),
diff --git a/core/src/main/java/bisq/core/payment/payload/WesternUnionAccountPayload.java b/core/src/main/java/bisq/core/payment/payload/WesternUnionAccountPayload.java
index 7ffc131959c..db0722a2227 100644
--- a/core/src/main/java/bisq/core/payment/payload/WesternUnionAccountPayload.java
+++ b/core/src/main/java/bisq/core/payment/payload/WesternUnionAccountPayload.java
@@ -21,8 +21,6 @@
import bisq.core.locale.CountryUtil;
import bisq.core.locale.Res;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.protobuf.Message;
import org.springframework.util.CollectionUtils;
@@ -82,14 +80,14 @@ private WesternUnionAccountPayload(String paymentMethodName,
@Override
public Message toProtoMessage() {
- PB.WesternUnionAccountPayload.Builder builder =
- PB.WesternUnionAccountPayload.newBuilder()
+ protobuf.WesternUnionAccountPayload.Builder builder =
+ protobuf.WesternUnionAccountPayload.newBuilder()
.setHolderName(holderName)
.setCity(city)
.setState(state)
.setEmail(email);
- final PB.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayload = getPaymentAccountPayloadBuilder()
+ final protobuf.CountryBasedPaymentAccountPayload.Builder countryBasedPaymentAccountPayload = getPaymentAccountPayloadBuilder()
.getCountryBasedPaymentAccountPayloadBuilder()
.setWesternUnionAccountPayload(builder);
return getPaymentAccountPayloadBuilder()
@@ -97,9 +95,9 @@ public Message toProtoMessage() {
.build();
}
- public static PaymentAccountPayload fromProto(PB.PaymentAccountPayload proto) {
- PB.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
- PB.WesternUnionAccountPayload westernUnionAccountPayload = countryBasedPaymentAccountPayload.getWesternUnionAccountPayload();
+ public static PaymentAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
+ protobuf.CountryBasedPaymentAccountPayload countryBasedPaymentAccountPayload = proto.getCountryBasedPaymentAccountPayload();
+ protobuf.WesternUnionAccountPayload westernUnionAccountPayload = countryBasedPaymentAccountPayload.getWesternUnionAccountPayload();
return new WesternUnionAccountPayload(proto.getPaymentMethodId(),
proto.getId(),
countryBasedPaymentAccountPayload.getCountryCode(),
diff --git a/core/src/main/java/bisq/core/presentation/CorePresentationModule.java b/core/src/main/java/bisq/core/presentation/CorePresentationModule.java
index 6d84520d3ec..2d0b804886c 100644
--- a/core/src/main/java/bisq/core/presentation/CorePresentationModule.java
+++ b/core/src/main/java/bisq/core/presentation/CorePresentationModule.java
@@ -32,7 +32,7 @@ public CorePresentationModule(Environment environment) {
protected void configure() {
bind(BalancePresentation.class).in(Singleton.class);
bind(TradePresentation.class).in(Singleton.class);
- bind(DisputePresentation.class).in(Singleton.class);
+ bind(SupportTicketsPresentation.class).in(Singleton.class);
}
}
diff --git a/core/src/main/java/bisq/core/presentation/DisputePresentation.java b/core/src/main/java/bisq/core/presentation/DisputePresentation.java
deleted file mode 100644
index ab79175b993..00000000000
--- a/core/src/main/java/bisq/core/presentation/DisputePresentation.java
+++ /dev/null
@@ -1,49 +0,0 @@
-/*
- * 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 .
- */
-
-package bisq.core.presentation;
-
-import bisq.core.arbitration.DisputeManager;
-
-import javax.inject.Inject;
-
-import javafx.beans.property.BooleanProperty;
-import javafx.beans.property.SimpleBooleanProperty;
-import javafx.beans.property.SimpleStringProperty;
-import javafx.beans.property.StringProperty;
-
-import lombok.Getter;
-
-public class DisputePresentation {
- @Getter
- private final StringProperty numOpenDisputes = new SimpleStringProperty();
- @Getter
- private final BooleanProperty showOpenDisputesNotification = new SimpleBooleanProperty();
-
- @Inject
- public DisputePresentation(DisputeManager disputeManager) {
- disputeManager.getNumOpenDisputes().addListener((observable, oldValue, newValue) -> {
- int openDisputes = (int) newValue;
- if (openDisputes > 0)
- numOpenDisputes.set(String.valueOf(openDisputes));
- if (openDisputes > 9)
- numOpenDisputes.set("★");
-
- showOpenDisputesNotification.set(openDisputes > 0);
- });
- }
-}
diff --git a/core/src/main/java/bisq/core/presentation/SupportTicketsPresentation.java b/core/src/main/java/bisq/core/presentation/SupportTicketsPresentation.java
new file mode 100644
index 00000000000..be98548140a
--- /dev/null
+++ b/core/src/main/java/bisq/core/presentation/SupportTicketsPresentation.java
@@ -0,0 +1,78 @@
+/*
+ * 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 .
+ */
+
+package bisq.core.presentation;
+
+import bisq.core.support.dispute.arbitration.ArbitrationManager;
+import bisq.core.support.dispute.mediation.MediationManager;
+
+import javax.inject.Inject;
+
+import javafx.beans.property.BooleanProperty;
+import javafx.beans.property.SimpleBooleanProperty;
+import javafx.beans.property.SimpleStringProperty;
+import javafx.beans.property.StringProperty;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+import lombok.Getter;
+
+public class SupportTicketsPresentation {
+ @Getter
+ private final StringProperty numOpenArbitrationTickets = new SimpleStringProperty();
+ @Getter
+ private final BooleanProperty showOpenArbitrationTicketsNotification = new SimpleBooleanProperty();
+
+ @Getter
+ private final StringProperty numOpenMediationTickets = new SimpleStringProperty();
+ @Getter
+ private final BooleanProperty showOpenMediationTicketsNotification = new SimpleBooleanProperty();
+
+ @Getter
+ private final StringProperty numOpenSupportTickets = new SimpleStringProperty();
+ @Getter
+ private final BooleanProperty showOpenSupportTicketsNotification = new SimpleBooleanProperty();
+ @org.jetbrains.annotations.NotNull
+ private final ArbitrationManager arbitrationManager;
+ @org.jetbrains.annotations.NotNull
+ private final MediationManager mediationManager;
+
+ @Inject
+ public SupportTicketsPresentation(ArbitrationManager arbitrationManager, MediationManager mediationManager) {
+ this.arbitrationManager = arbitrationManager;
+ this.mediationManager = mediationManager;
+
+ arbitrationManager.getNumOpenDisputes().addListener((observable, oldValue, newValue) -> onChange());
+ mediationManager.getNumOpenDisputes().addListener((observable, oldValue, newValue) -> onChange());
+ }
+
+ private void onChange() {
+ AtomicInteger openArbitrationDisputes = new AtomicInteger(arbitrationManager.getNumOpenDisputes().get());
+ int arbitrationTickets = openArbitrationDisputes.get();
+ numOpenArbitrationTickets.set(String.valueOf(arbitrationTickets));
+ showOpenArbitrationTicketsNotification.set(arbitrationTickets > 0);
+
+ AtomicInteger openMediationDisputes = new AtomicInteger(mediationManager.getNumOpenDisputes().get());
+ int mediationTickets = openMediationDisputes.get();
+ numOpenMediationTickets.set(String.valueOf(mediationTickets));
+ showOpenMediationTicketsNotification.set(mediationTickets > 0);
+
+ int supportTickets = arbitrationTickets + mediationTickets;
+ numOpenSupportTickets.set(String.valueOf(supportTickets));
+ showOpenSupportTicketsNotification.set(supportTickets > 0);
+ }
+}
diff --git a/core/src/main/java/bisq/core/proto/CoreProtoResolver.java b/core/src/main/java/bisq/core/proto/CoreProtoResolver.java
index ebc101175e1..4799786b7db 100644
--- a/core/src/main/java/bisq/core/proto/CoreProtoResolver.java
+++ b/core/src/main/java/bisq/core/proto/CoreProtoResolver.java
@@ -17,9 +17,10 @@
package bisq.core.proto;
+import bisq.core.account.sign.SignedWitness;
+import bisq.core.account.witness.AccountAgeWitness;
import bisq.core.dao.governance.blindvote.storage.BlindVotePayload;
import bisq.core.dao.governance.proposal.storage.appendonly.ProposalPayload;
-import bisq.core.payment.AccountAgeWitness;
import bisq.core.payment.payload.AdvancedCashAccountPayload;
import bisq.core.payment.payload.AliPayAccountPayload;
import bisq.core.payment.payload.CashAppAccountPayload;
@@ -32,6 +33,7 @@
import bisq.core.payment.payload.HalCashAccountPayload;
import bisq.core.payment.payload.InstantCryptoCurrencyPayload;
import bisq.core.payment.payload.InteracETransferAccountPayload;
+import bisq.core.payment.payload.JapanBankAccountPayload;;
import bisq.core.payment.payload.MoneyBeamAccountPayload;
import bisq.core.payment.payload.MoneyGramAccountPayload;
import bisq.core.payment.payload.NationalBankAccountPayload;
@@ -57,16 +59,14 @@
import bisq.common.proto.ProtobufferRuntimeException;
import bisq.common.proto.persistable.PersistableEnvelope;
-import io.bisq.generated.protobuffer.PB;
-
import lombok.extern.slf4j.Slf4j;
@Slf4j
public class CoreProtoResolver implements ProtoResolver {
@Override
- public PaymentAccountPayload fromProto(PB.PaymentAccountPayload proto) {
+ public PaymentAccountPayload fromProto(protobuf.PaymentAccountPayload proto) {
if (proto != null) {
- final PB.PaymentAccountPayload.MessageCase messageCase = proto.getMessageCase();
+ final protobuf.PaymentAccountPayload.MessageCase messageCase = proto.getMessageCase();
switch (messageCase) {
case ALI_PAY_ACCOUNT_PAYLOAD:
return AliPayAccountPayload.fromProto(proto);
@@ -77,10 +77,10 @@ public PaymentAccountPayload fromProto(PB.PaymentAccountPayload proto) {
case CLEAR_XCHANGE_ACCOUNT_PAYLOAD:
return ClearXchangeAccountPayload.fromProto(proto);
case COUNTRY_BASED_PAYMENT_ACCOUNT_PAYLOAD:
- final PB.CountryBasedPaymentAccountPayload.MessageCase messageCaseCountry = proto.getCountryBasedPaymentAccountPayload().getMessageCase();
+ final protobuf.CountryBasedPaymentAccountPayload.MessageCase messageCaseCountry = proto.getCountryBasedPaymentAccountPayload().getMessageCase();
switch (messageCaseCountry) {
case BANK_ACCOUNT_PAYLOAD:
- final PB.BankAccountPayload.MessageCase messageCaseBank = proto.getCountryBasedPaymentAccountPayload().getBankAccountPayload().getMessageCase();
+ final protobuf.BankAccountPayload.MessageCase messageCaseBank = proto.getCountryBasedPaymentAccountPayload().getBankAccountPayload().getMessageCase();
switch (messageCaseBank) {
case NATIONAL_BANK_ACCOUNT_PAYLOAD:
return NationalBankAccountPayload.fromProto(proto);
@@ -114,6 +114,8 @@ public PaymentAccountPayload fromProto(PB.PaymentAccountPayload proto) {
return FasterPaymentsAccountPayload.fromProto(proto);
case INTERAC_E_TRANSFER_ACCOUNT_PAYLOAD:
return InteracETransferAccountPayload.fromProto(proto);
+ case JAPAN_BANK_ACCOUNT_PAYLOAD:
+ return JapanBankAccountPayload.fromProto(proto);
case UPHOLD_ACCOUNT_PAYLOAD:
return UpholdAccountPayload.fromProto(proto);
case MONEY_BEAM_ACCOUNT_PAYLOAD:
@@ -157,7 +159,7 @@ public PaymentAccountPayload fromProto(PB.PaymentAccountPayload proto) {
}
@Override
- public PersistableEnvelope fromProto(PB.PersistableNetworkPayload proto) {
+ public PersistableEnvelope fromProto(protobuf.PersistableNetworkPayload proto) {
if (proto != null) {
switch (proto.getMessageCase()) {
case ACCOUNT_AGE_WITNESS:
@@ -168,6 +170,8 @@ public PersistableEnvelope fromProto(PB.PersistableNetworkPayload proto) {
return ProposalPayload.fromProto(proto.getProposalPayload());
case BLIND_VOTE_PAYLOAD:
return BlindVotePayload.fromProto(proto.getBlindVotePayload());
+ case SIGNED_WITNESS:
+ return SignedWitness.fromProto(proto.getSignedWitness());
default:
throw new ProtobufferRuntimeException("Unknown proto message case (PB.PersistableNetworkPayload). messageCase=" + proto.getMessageCase());
}
diff --git a/core/src/main/java/bisq/core/proto/ProtoDevUtil.java b/core/src/main/java/bisq/core/proto/ProtoDevUtil.java
index c62b65e0ea5..6b70441a866 100644
--- a/core/src/main/java/bisq/core/proto/ProtoDevUtil.java
+++ b/core/src/main/java/bisq/core/proto/ProtoDevUtil.java
@@ -17,8 +17,8 @@
package bisq.core.proto;
-import bisq.core.arbitration.DisputeResult;
import bisq.core.btc.model.AddressEntry;
+import bisq.core.support.dispute.DisputeResult;
import bisq.core.offer.AvailabilityResult;
import bisq.core.offer.Offer;
import bisq.core.offer.OfferPayload;
diff --git a/core/src/main/java/bisq/core/proto/network/CoreNetworkProtoResolver.java b/core/src/main/java/bisq/core/proto/network/CoreNetworkProtoResolver.java
index 4c9509a947f..9d84408420b 100644
--- a/core/src/main/java/bisq/core/proto/network/CoreNetworkProtoResolver.java
+++ b/core/src/main/java/bisq/core/proto/network/CoreNetworkProtoResolver.java
@@ -19,13 +19,6 @@
import bisq.core.alert.Alert;
import bisq.core.alert.PrivateNotificationMessage;
-import bisq.core.arbitration.Arbitrator;
-import bisq.core.arbitration.Mediator;
-import bisq.core.arbitration.messages.DisputeCommunicationMessage;
-import bisq.core.arbitration.messages.DisputeResultMessage;
-import bisq.core.arbitration.messages.OpenNewDisputeMessage;
-import bisq.core.arbitration.messages.PeerOpenedDisputeMessage;
-import bisq.core.arbitration.messages.PeerPublishedDisputePayoutTxMessage;
import bisq.core.dao.governance.blindvote.network.messages.RepublishGovernanceDataRequest;
import bisq.core.dao.governance.proposal.storage.temp.TempProposalPayload;
import bisq.core.dao.monitoring.network.messages.GetBlindVoteStateHashesRequest;
@@ -45,16 +38,25 @@
import bisq.core.offer.messages.OfferAvailabilityRequest;
import bisq.core.offer.messages.OfferAvailabilityResponse;
import bisq.core.proto.CoreProtoResolver;
+import bisq.core.support.dispute.arbitration.arbitrator.Arbitrator;
+import bisq.core.support.dispute.arbitration.messages.PeerPublishedDisputePayoutTxMessage;
+import bisq.core.support.dispute.mediation.mediator.Mediator;
+import bisq.core.support.dispute.messages.DisputeResultMessage;
+import bisq.core.support.dispute.messages.OpenNewDisputeMessage;
+import bisq.core.support.dispute.messages.PeerOpenedDisputeMessage;
+import bisq.core.support.messages.ChatMessage;
import bisq.core.trade.messages.CounterCurrencyTransferStartedMessage;
import bisq.core.trade.messages.DepositTxPublishedMessage;
+import bisq.core.trade.messages.MediatedPayoutTxPublishedMessage;
+import bisq.core.trade.messages.MediatedPayoutTxSignatureMessage;
import bisq.core.trade.messages.PayDepositRequest;
import bisq.core.trade.messages.PayoutTxPublishedMessage;
import bisq.core.trade.messages.PublishDepositTxRequest;
import bisq.core.trade.statistics.TradeStatistics;
import bisq.network.p2p.AckMessage;
-import bisq.network.p2p.CloseConnectionMessage;
import bisq.network.p2p.BundleOfEnvelopes;
+import bisq.network.p2p.CloseConnectionMessage;
import bisq.network.p2p.PrefixedSealedAndSignedMessage;
import bisq.network.p2p.peers.getdata.messages.GetDataResponse;
import bisq.network.p2p.peers.getdata.messages.GetUpdatedDataRequest;
@@ -78,14 +80,14 @@
import bisq.common.proto.network.NetworkPayload;
import bisq.common.proto.network.NetworkProtoResolver;
-import io.bisq.generated.protobuffer.PB;
-
import javax.inject.Inject;
+import javax.inject.Singleton;
import lombok.extern.slf4j.Slf4j;
// TODO Use ProtobufferException instead of ProtobufferRuntimeException
@Slf4j
+@Singleton
public class CoreNetworkProtoResolver extends CoreProtoResolver implements NetworkProtoResolver {
@Inject
@@ -93,7 +95,7 @@ public CoreNetworkProtoResolver() {
}
@Override
- public NetworkEnvelope fromProto(PB.NetworkEnvelope proto) throws ProtobufferException {
+ public NetworkEnvelope fromProto(protobuf.NetworkEnvelope proto) throws ProtobufferException {
if (proto != null) {
final int messageVersion = proto.getMessageVersion();
switch (proto.getMessageCase()) {
@@ -142,13 +144,17 @@ public NetworkEnvelope fromProto(PB.NetworkEnvelope proto) throws ProtobufferExc
return CounterCurrencyTransferStartedMessage.fromProto(proto.getCounterCurrencyTransferStartedMessage(), messageVersion);
case PAYOUT_TX_PUBLISHED_MESSAGE:
return PayoutTxPublishedMessage.fromProto(proto.getPayoutTxPublishedMessage(), messageVersion);
+ case MEDIATED_PAYOUT_TX_SIGNATURE_MESSAGE:
+ return MediatedPayoutTxSignatureMessage.fromProto(proto.getMediatedPayoutTxSignatureMessage(), messageVersion);
+ case MEDIATED_PAYOUT_TX_PUBLISHED_MESSAGE:
+ return MediatedPayoutTxPublishedMessage.fromProto(proto.getMediatedPayoutTxPublishedMessage(), messageVersion);
case OPEN_NEW_DISPUTE_MESSAGE:
return OpenNewDisputeMessage.fromProto(proto.getOpenNewDisputeMessage(), this, messageVersion);
case PEER_OPENED_DISPUTE_MESSAGE:
return PeerOpenedDisputeMessage.fromProto(proto.getPeerOpenedDisputeMessage(), this, messageVersion);
- case DISPUTE_COMMUNICATION_MESSAGE:
- return DisputeCommunicationMessage.fromProto(proto.getDisputeCommunicationMessage(), messageVersion);
+ case CHAT_MESSAGE:
+ return ChatMessage.fromProto(proto.getChatMessage(), messageVersion);
case DISPUTE_RESULT_MESSAGE:
return DisputeResultMessage.fromProto(proto.getDisputeResultMessage(), messageVersion);
case PEER_PUBLISHED_DISPUTE_PAYOUT_TX_MESSAGE:
@@ -204,7 +210,7 @@ public NetworkEnvelope fromProto(PB.NetworkEnvelope proto) throws ProtobufferExc
}
}
- public NetworkPayload fromProto(PB.StorageEntryWrapper proto) {
+ public NetworkPayload fromProto(protobuf.StorageEntryWrapper proto) {
if (proto != null) {
switch (proto.getMessageCase()) {
case PROTECTED_MAILBOX_STORAGE_ENTRY:
@@ -221,7 +227,7 @@ public NetworkPayload fromProto(PB.StorageEntryWrapper proto) {
}
}
- public NetworkPayload fromProto(PB.StoragePayload proto) {
+ public NetworkPayload fromProto(protobuf.StoragePayload proto) {
if (proto != null) {
switch (proto.getMessageCase()) {
case ALERT:
diff --git a/core/src/main/java/bisq/core/proto/persistable/CorePersistenceProtoResolver.java b/core/src/main/java/bisq/core/proto/persistable/CorePersistenceProtoResolver.java
index 0878077c5ce..796572b0c3f 100644
--- a/core/src/main/java/bisq/core/proto/persistable/CorePersistenceProtoResolver.java
+++ b/core/src/main/java/bisq/core/proto/persistable/CorePersistenceProtoResolver.java
@@ -17,7 +17,8 @@
package bisq.core.proto.persistable;
-import bisq.core.arbitration.DisputeList;
+import bisq.core.account.sign.SignedWitnessStore;
+import bisq.core.account.witness.AccountAgeWitnessStore;
import bisq.core.btc.model.AddressEntryList;
import bisq.core.btc.wallet.BtcWalletService;
import bisq.core.dao.governance.blindvote.MyBlindVoteList;
@@ -32,9 +33,10 @@
import bisq.core.dao.state.model.governance.BallotList;
import bisq.core.dao.state.model.governance.MeritList;
import bisq.core.dao.state.unconfirmed.UnconfirmedBsqChangeOutputList;
-import bisq.core.payment.AccountAgeWitnessStore;
import bisq.core.payment.PaymentAccountList;
import bisq.core.proto.CoreProtoResolver;
+import bisq.core.support.dispute.arbitration.ArbitrationDisputeList;
+import bisq.core.support.dispute.mediation.MediationDisputeList;
import bisq.core.trade.TradableList;
import bisq.core.trade.statistics.TradeStatistics2Store;
import bisq.core.user.PreferencesPayload;
@@ -49,14 +51,14 @@
import bisq.common.proto.persistable.NavigationPath;
import bisq.common.proto.persistable.PersistableEnvelope;
import bisq.common.proto.persistable.PersistenceProtoResolver;
+import bisq.common.storage.CorruptedDatabaseFilesHandler;
import bisq.common.storage.Storage;
-import io.bisq.generated.protobuffer.PB;
-
import com.google.inject.Provider;
import javax.inject.Inject;
import javax.inject.Named;
+import javax.inject.Singleton;
import java.io.File;
@@ -64,23 +66,27 @@
// TODO Use ProtobufferException instead of ProtobufferRuntimeException
@Slf4j
+@Singleton
public class CorePersistenceProtoResolver extends CoreProtoResolver implements PersistenceProtoResolver {
private final Provider btcWalletService;
private final NetworkProtoResolver networkProtoResolver;
private final File storageDir;
+ private final CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler;
@Inject
public CorePersistenceProtoResolver(Provider btcWalletService,
NetworkProtoResolver networkProtoResolver,
- @Named(Storage.STORAGE_DIR) File storageDir) {
+ @Named(Storage.STORAGE_DIR) File storageDir,
+ CorruptedDatabaseFilesHandler corruptedDatabaseFilesHandler) {
this.btcWalletService = btcWalletService;
this.networkProtoResolver = networkProtoResolver;
this.storageDir = storageDir;
+ this.corruptedDatabaseFilesHandler = corruptedDatabaseFilesHandler;
}
@Override
- public PersistableEnvelope fromProto(PB.PersistableEnvelope proto) {
+ public PersistableEnvelope fromProto(protobuf.PersistableEnvelope proto) {
if (proto != null) {
switch (proto.getMessageCase()) {
case SEQUENCE_NUMBER_MAP:
@@ -92,14 +98,18 @@ public PersistableEnvelope fromProto(PB.PersistableEnvelope proto) {
case TRADABLE_LIST:
return TradableList.fromProto(proto.getTradableList(),
this,
- new Storage<>(storageDir, this),
+ new Storage<>(storageDir, this, corruptedDatabaseFilesHandler),
btcWalletService.get());
case TRADE_STATISTICS_LIST:
throw new ProtobufferRuntimeException("TRADE_STATISTICS_LIST is not used anymore");
- case DISPUTE_LIST:
- return DisputeList.fromProto(proto.getDisputeList(),
+ case ARBITRATION_DISPUTE_LIST:
+ return ArbitrationDisputeList.fromProto(proto.getArbitrationDisputeList(),
+ this,
+ new Storage<>(storageDir, this, corruptedDatabaseFilesHandler));
+ case MEDIATION_DISPUTE_LIST:
+ return MediationDisputeList.fromProto(proto.getMediationDisputeList(),
this,
- new Storage<>(storageDir, this));
+ new Storage<>(storageDir, this, corruptedDatabaseFilesHandler));
case PREFERENCES_PAYLOAD:
return PreferencesPayload.fromProto(proto.getPreferencesPayload(), this);
case USER_PAYLOAD:
@@ -138,6 +148,8 @@ public PersistableEnvelope fromProto(PB.PersistableEnvelope proto) {
return MyProofOfBurnList.fromProto(proto.getMyProofOfBurnList());
case UNCONFIRMED_BSQ_CHANGE_OUTPUT_LIST:
return UnconfirmedBsqChangeOutputList.fromProto(proto.getUnconfirmedBsqChangeOutputList());
+ case SIGNED_WITNESS_STORE:
+ return SignedWitnessStore.fromProto(proto.getSignedWitnessStore());
default:
throw new ProtobufferRuntimeException("Unknown proto message case(PB.PersistableEnvelope). " +
diff --git a/core/src/main/java/bisq/core/provider/ProvidersRepository.java b/core/src/main/java/bisq/core/provider/ProvidersRepository.java
index 3f97db1e682..27f7b9bc053 100644
--- a/core/src/main/java/bisq/core/provider/ProvidersRepository.java
+++ b/core/src/main/java/bisq/core/provider/ProvidersRepository.java
@@ -44,7 +44,6 @@ public class ProvidersRepository {
"http://xc3nh4juf2hshy7e.onion/", // @emzy
"http://ceaanhbvluug4we6.onion/", // @mrosseel
"http://44mgyoe2b6oqiytt.onion/", // @devinbileck
- "http://5bmpx76qllutpcyp.onion/", // @cbeams
"http://62nvujg5iou3vu3i.onion/" // @alexej996
);
diff --git a/core/src/main/java/bisq/core/provider/price/PriceFeedService.java b/core/src/main/java/bisq/core/provider/price/PriceFeedService.java
index 09e8ed93559..08b84c0b83d 100644
--- a/core/src/main/java/bisq/core/provider/price/PriceFeedService.java
+++ b/core/src/main/java/bisq/core/provider/price/PriceFeedService.java
@@ -139,10 +139,10 @@ public String getProviderNodeAddress() {
private void request(boolean repeatRequests) {
if (requestTs == 0)
- log.info("request from provider {}",
+ log.debug("request from provider {}",
providersRepository.getBaseUrl());
else
- log.info("request from provider {} {} sec. after last request",
+ log.debug("request from provider {} {} sec. after last request",
providersRepository.getBaseUrl(),
(System.currentTimeMillis() - requestTs) / 1000d);
@@ -158,12 +158,12 @@ private void request(boolean repeatRequests) {
if (success) {
final MarketPrice marketPrice = cache.get(currencyCode);
if (marketPrice != null)
- log.info("Received new {} from provider {} after {} sec.",
+ log.debug("Received new {} from provider {} after {} sec.",
marketPrice,
baseUrlOfRespondingProvider,
(System.currentTimeMillis() - requestTs) / 1000d);
else
- log.info("Received new data from provider {} after {} sec. " +
+ log.debug("Received new data from provider {} after {} sec. " +
"Requested market price for currency {} was not provided. " +
"That is expected if currency is not listed at provider.",
baseUrlOfRespondingProvider,
@@ -182,7 +182,7 @@ private void request(boolean repeatRequests) {
baseUrlOfCurrentRequest, baseUrlOfFaultyRequest);
retryWithNewProvider();
} else {
- log.info("We received an error from an earlier request. We have started a new request already so we ignore that error. " +
+ log.debug("We received an error from an earlier request. We have started a new request already so we ignore that error. " +
"baseUrlOfCurrentRequest={}, baseUrlOfFaultyRequest={}",
baseUrlOfCurrentRequest, baseUrlOfFaultyRequest);
}
@@ -360,10 +360,10 @@ private boolean applyPriceToConsumer() {
}
} else {
if (baseUrlOfRespondingProvider == null)
- log.info("Market price for currency " + currencyCode + " was not delivered by provider " +
+ log.debug("Market price for currency " + currencyCode + " was not delivered by provider " +
baseUrl + ". That is expected at startup.");
else
- log.info("Market price for currency " + currencyCode + " is not provided by the provider " +
+ log.debug("Market price for currency " + currencyCode + " is not provided by the provider " +
baseUrl + ". That is expected for currencies not listed at providers.");
result = true;
}
@@ -372,7 +372,7 @@ private boolean applyPriceToConsumer() {
". priceProvider=" + baseUrl + ". Exception=" + t;
}
} else {
- log.info("We don't have a price for currency " + currencyCode + ". priceProvider=" + baseUrl +
+ log.debug("We don't have a price for currency " + currencyCode + ". priceProvider=" + baseUrl +
". That is expected for currencies not listed at providers.");
result = true;
}
diff --git a/core/src/main/java/bisq/core/provider/price/PriceRequest.java b/core/src/main/java/bisq/core/provider/price/PriceRequest.java
index 04718345d9f..e1d3cc91f7d 100644
--- a/core/src/main/java/bisq/core/provider/price/PriceRequest.java
+++ b/core/src/main/java/bisq/core/provider/price/PriceRequest.java
@@ -49,7 +49,7 @@ public SettableFuture, Map>> reque
Futures.addCallback(future, new FutureCallback, Map>>() {
public void onSuccess(Tuple2