diff --git a/.github/ISSUE_TEMPLATE/new_asset.md b/.github/ISSUE_TEMPLATE/new_asset.md new file mode 100644 index 00000000000..7f69fae8338 --- /dev/null +++ b/.github/ISSUE_TEMPLATE/new_asset.md @@ -0,0 +1,18 @@ +Please fill in the following data to request for a new asset to be listed on Bisq. For more details, be sure to read [the full documentation](https://docs.bisq.network/exchange/howto/list-asset.html) on adding a new asset. + +### 1. Asset name + + +### 2. Ticker +_Your asset's ticker must not conflict with any national currency tickers (per [ISO 4217](https://en.wikipedia.org/wiki/ISO_4217)) or any of the [top 100 cryptocurrency tickers](https://coinmarketcap.com/coins/)._ + + +### 3. Block explorer URL +_Your asset's block explorer must be active and publicly available so that transactions can be verified with a receiver's address...if this isn't possible, [see workarounds here](file:///home/steve/wb/bisq/bisq-docs/build/asciidoc/html5/exchange/howto/list-asset.html#arbitrators-must-be-able-to-look-up-transactions-in-the-asset-block-explorer)._ + +### 4. Additional technical requirements (yes/no) +_Your asset should not have any additional requirements (for example, needing input fields for anything other than an address)._ + + +### 5. Initial coin offering (yes/no) +_Bisq will not list your token if it has taken part in an initial coin offering (ICO)_ diff --git a/.gitignore b/.gitignore index 544eb84dfcd..0a68aa585c3 100644 --- a/.gitignore +++ b/.gitignore @@ -31,3 +31,4 @@ deploy */releases/* /monitor/TorHiddenServiceStartupTimeTests/* /monitor/monitor-tor/* +.java-version diff --git a/CODEOWNERS b/CODEOWNERS index 75e13175617..b6079f97ce1 100644 --- a/CODEOWNERS +++ b/CODEOWNERS @@ -1,8 +1,8 @@ # This doc specifies who gets requested to review GitHub pull requests. # See https://help.github.com/articles/about-codeowners/. -* @ManfredKarrer +* @ripcurlx /assets/ @blabno -/desktop/ @ripcurlx @ManfredKarrer +/desktop/ @ripcurlx @sqrrm *gradle* @cbeams /pricenode/ @cbeams diff --git a/assets/src/main/java/bisq/asset/CryptoNoteAddressValidator.java b/assets/src/main/java/bisq/asset/CryptoNoteAddressValidator.java new file mode 100644 index 00000000000..6409e5a4f8e --- /dev/null +++ b/assets/src/main/java/bisq/asset/CryptoNoteAddressValidator.java @@ -0,0 +1,265 @@ +/* + * 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; + +import java.nio.ByteBuffer; +import java.nio.ByteOrder; + +import java.math.BigInteger; + +import java.util.Map; + +/** + * {@link AddressValidator} for Base58-encoded Cryptonote addresses. + * + * @author Xiphon + */ +public class CryptoNoteAddressValidator implements AddressValidator { + + private final long[] validPrefixes; + private final boolean validateChecksum; + + public CryptoNoteAddressValidator(boolean validateChecksum, long... validPrefixes) { + this.validPrefixes = validPrefixes; + this.validateChecksum = validateChecksum; + } + + public CryptoNoteAddressValidator(long... validPrefixes) { + this(true, validPrefixes); + } + + @Override + public AddressValidationResult validate(String address) { + try { + long prefix = MoneroBase58.decodeAddress(address, this.validateChecksum); + for (long validPrefix : this.validPrefixes) { + if (prefix == validPrefix) { + return AddressValidationResult.validAddress(); + } + } + return AddressValidationResult.invalidAddress(String.format("invalid address prefix %x", prefix)); + } catch (Exception e) { + return AddressValidationResult.invalidStructure(); + } + } +} + +class Keccak { + + private static final int BLOCK_SIZE = 136; + private static final int LONGS_PER_BLOCK = BLOCK_SIZE / 8; + private static final int KECCAK_ROUNDS = 24; + private static final long[] KECCAKF_RNDC = { + 0x0000000000000001L, 0x0000000000008082L, 0x800000000000808aL, + 0x8000000080008000L, 0x000000000000808bL, 0x0000000080000001L, + 0x8000000080008081L, 0x8000000000008009L, 0x000000000000008aL, + 0x0000000000000088L, 0x0000000080008009L, 0x000000008000000aL, + 0x000000008000808bL, 0x800000000000008bL, 0x8000000000008089L, + 0x8000000000008003L, 0x8000000000008002L, 0x8000000000000080L, + 0x000000000000800aL, 0x800000008000000aL, 0x8000000080008081L, + 0x8000000000008080L, 0x0000000080000001L, 0x8000000080008008L + }; + private static final int[] KECCAKF_ROTC = { + 1, 3, 6, 10, 15, 21, 28, 36, 45, 55, 2, 14, + 27, 41, 56, 8, 25, 43, 62, 18, 39, 61, 20, 44 + }; + private static final int[] KECCAKF_PILN = { + 10, 7, 11, 17, 18, 3, 5, 16, 8, 21, 24, 4, + 15, 23, 19, 13, 12, 2, 20, 14, 22, 9, 6, 1 + }; + + private static long rotateLeft(long value, int shift) { + return (value << shift) | (value >>> (64 - shift)); + } + + private static void keccakf(long[] st, int rounds) { + long[] bc = new long[5]; + + for (int round = 0; round < rounds; ++round) { + for (int i = 0; i < 5; ++i) { + bc[i] = st[i] ^ st[i + 5] ^ st[i + 10] ^ st[i + 15] ^ st[i + 20]; + } + + for (int i = 0; i < 5; i++) { + long t = bc[(i + 4) % 5] ^ rotateLeft(bc[(i + 1) % 5], 1); + for (int j = 0; j < 25; j += 5) { + st[j + i] ^= t; + } + } + + long t = st[1]; + for (int i = 0; i < 24; ++i) { + int j = KECCAKF_PILN[i]; + bc[0] = st[j]; + st[j] = rotateLeft(t, KECCAKF_ROTC[i]); + t = bc[0]; + } + + for (int j = 0; j < 25; j += 5) { + for (int i = 0; i < 5; i++) { + bc[i] = st[j + i]; + } + for (int i = 0; i < 5; i++) { + st[j + i] ^= (~bc[(i + 1) % 5]) & bc[(i + 2) % 5]; + } + } + + st[0] ^= KECCAKF_RNDC[round]; + } + } + + public static ByteBuffer keccak1600(ByteBuffer input) { + input.order(ByteOrder.LITTLE_ENDIAN); + + int fullBlocks = input.remaining() / BLOCK_SIZE; + long[] st = new long[25]; + for (int block = 0; block < fullBlocks; ++block) { + for (int index = 0; index < LONGS_PER_BLOCK; ++index) { + st[index] ^= input.getLong(); + } + keccakf(st, KECCAK_ROUNDS); + } + + ByteBuffer lastBlock = ByteBuffer.allocate(144).order(ByteOrder.LITTLE_ENDIAN); + lastBlock.put(input); + lastBlock.put((byte)1); + int paddingOffset = BLOCK_SIZE - 1; + lastBlock.put(paddingOffset, (byte)(lastBlock.get(paddingOffset) | 0x80)); + lastBlock.rewind(); + + for (int index = 0; index < LONGS_PER_BLOCK; ++index) { + st[index] ^= lastBlock.getLong(); + } + + keccakf(st, KECCAK_ROUNDS); + + ByteBuffer result = ByteBuffer.allocate(32); + result.slice().order(ByteOrder.LITTLE_ENDIAN).asLongBuffer().put(st, 0, 4); + return result; + } +} + +class MoneroBase58 { + + private static final String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + private static final BigInteger ALPHABET_SIZE = BigInteger.valueOf(ALPHABET.length()); + private static final int FULL_DECODED_BLOCK_SIZE = 8; + private static final int FULL_ENCODED_BLOCK_SIZE = 11; + private static final BigInteger UINT64_MAX = new BigInteger("18446744073709551615"); + private static final Map DECODED_CHUNK_LENGTH = Map.of( 2, 1, + 3, 2, + 5, 3, + 6, 4, + 7, 5, + 9, 6, + 10, 7, + 11, 8); + + private static void decodeChunk(String input, + int inputOffset, + int inputLength, + byte[] decoded, + int decodedOffset, + int decodedLength) throws Exception { + + BigInteger result = BigInteger.ZERO; + + BigInteger order = BigInteger.ONE; + for (int index = inputOffset + inputLength; index != inputOffset; order = order.multiply(ALPHABET_SIZE)) { + char character = input.charAt(--index); + int digit = ALPHABET.indexOf(character); + if (digit == -1) { + throw new Exception("invalid character " + character); + } + result = result.add(order.multiply(BigInteger.valueOf(digit))); + if (result.compareTo(UINT64_MAX) > 0) { + throw new Exception("64-bit unsigned integer overflow " + result.toString()); + } + } + + BigInteger maxCapacity = BigInteger.ONE.shiftLeft(8 * decodedLength); + if (result.compareTo(maxCapacity) >= 0) { + throw new Exception("capacity overflow " + result.toString()); + } + + for (int index = decodedOffset + decodedLength; index != decodedOffset; result = result.shiftRight(8)) { + decoded[--index] = result.byteValue(); + } + } + + private static byte[] decode(String input) throws Exception { + if (input.length() == 0) { + return new byte[0]; + } + + int chunks = input.length() / FULL_ENCODED_BLOCK_SIZE; + int lastEncodedSize = input.length() % FULL_ENCODED_BLOCK_SIZE; + int lastChunkSize = lastEncodedSize > 0 ? DECODED_CHUNK_LENGTH.get(lastEncodedSize) : 0; + + byte[] result = new byte[chunks * FULL_DECODED_BLOCK_SIZE + lastChunkSize]; + int inputOffset = 0; + int resultOffset = 0; + for (int chunk = 0; chunk < chunks; ++chunk, + inputOffset += FULL_ENCODED_BLOCK_SIZE, + resultOffset += FULL_DECODED_BLOCK_SIZE) { + decodeChunk(input, inputOffset, FULL_ENCODED_BLOCK_SIZE, result, resultOffset, FULL_DECODED_BLOCK_SIZE); + } + if (lastChunkSize > 0) { + decodeChunk(input, inputOffset, lastEncodedSize, result, resultOffset, lastChunkSize); + } + + return result; + } + + private static long readVarInt(ByteBuffer buffer) { + long result = 0; + for (int shift = 0; ; shift += 7) { + byte current = buffer.get(); + result += (current & 0x7fL) << shift; + if ((current & 0x80L) == 0) { + break; + } + } + return result; + } + + public static long decodeAddress(String address, boolean validateChecksum) throws Exception { + byte[] decoded = decode(address); + + int checksumSize = 4; + if (decoded.length < checksumSize) { + throw new Exception("invalid length"); + } + + ByteBuffer decodedAddress = ByteBuffer.wrap(decoded, 0, decoded.length - checksumSize); + + long prefix = readVarInt(decodedAddress.slice()); + if (!validateChecksum) { + return prefix; + } + + ByteBuffer fastHash = Keccak.keccak1600(decodedAddress.slice()); + int checksum = fastHash.getInt(); + int expected = ByteBuffer.wrap(decoded, decoded.length - checksumSize, checksumSize).getInt(); + if (checksum != expected) { + throw new Exception(String.format("invalid checksum %08X, expected %08X", checksum, expected)); + } + + return prefix; + } +} diff --git a/assets/src/main/java/bisq/asset/CryptonoteAddressValidator.java b/assets/src/main/java/bisq/asset/CryptonoteAddressValidator.java deleted file mode 100644 index 47a6883154e..00000000000 --- a/assets/src/main/java/bisq/asset/CryptonoteAddressValidator.java +++ /dev/null @@ -1,86 +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; - -/** - * {@link AddressValidator} for Base58-encoded Cryptonote addresses. - * - * @author Chris Beams - * @since 0.7.0 - */ -public class CryptonoteAddressValidator implements AddressValidator { - - private final String prefix; - private final String subAddressPrefix; - private final String validCharactersRegex = "^[1-9A-HJ-NP-Za-km-z]+$"; - - public CryptonoteAddressValidator(String prefix, String subAddressPrefix) { - this.prefix = prefix; - this.subAddressPrefix = subAddressPrefix; - } - - @Override - public AddressValidationResult validate(String address) { - if (!address.matches(validCharactersRegex)) { - // Invalid characters - return AddressValidationResult.invalidStructure(); - } - if (address.startsWith(prefix)) { - if (prefix.length() == 1 && address.length() == 94 + prefix.length()) { - // XMR-type Standard address - return AddressValidationResult.validAddress(); - } - else if (prefix.length() == 2 && address.length() == 95 + prefix.length()) { - //Aeon & Blur-type addresses - return AddressValidationResult.validAddress(); - } - else if (prefix.length() == 4 && address.length() == 94 + prefix.length()) { - // FourtyTwo-type address - return AddressValidationResult.validAddress(); - } - else { - //Non-supported prefix - return AddressValidationResult.invalidStructure(); - } - } - if (address.startsWith(subAddressPrefix)) { - if (subAddressPrefix.length() == 1 && address.length() == 94 + subAddressPrefix.length()) { - // XMR-type subaddress - return AddressValidationResult.validAddress(); - } - else if (subAddressPrefix.length() == 2 && address.length() == 95 + subAddressPrefix.length()) { - // Aeon, Mask & Blur-type subaddress - return AddressValidationResult.validAddress(); - } - if (subAddressPrefix.length() == 5 && address.length() == 96 + subAddressPrefix.length()) { - // FourtyTwo-type subaddress - return AddressValidationResult.validAddress(); - } - else { - // Non-supported subAddress - return AddressValidationResult.invalidStructure(); - } - } - else { - //Integrated? Invalid? Doesn't matter - return AddressValidationResult.invalidStructure(); - } - } -} - - diff --git a/assets/src/main/java/bisq/asset/GrinAddressValidator.java b/assets/src/main/java/bisq/asset/GrinAddressValidator.java index 71c8ec36f95..f397bca0bae 100644 --- a/assets/src/main/java/bisq/asset/GrinAddressValidator.java +++ b/assets/src/main/java/bisq/asset/GrinAddressValidator.java @@ -18,7 +18,8 @@ package bisq.asset; /** - * The supported "address" (better wallet URL) format is IP:port or the grinbox format. + * We only support the grinbox format as it is currently the only tool which offers a validation options of sender. + * Beside that is the IP:port format very insecure with MITM attacks. * * Here is the information from a conversation with the Grinbox developer regarding the Grinbox address format. * @@ -53,7 +54,6 @@ public class GrinAddressValidator implements AddressValidator { // Regex for IP validation borrowed from https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses - private static final String IPV4 = "((25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])\\.){3,3}(25[0-5]|(2[0-4]|1{0,1}[0-9]){0,1}[0-9])"; private static final String PORT = "((6553[0-5])|(655[0-2][0-9])|(65[0-4][0-9]{2})|(6[0-4][0-9]{3})|([1-5][0-9]{4})|([0-5]{0,5})|([0-9]{1,4}))$"; private static final String DOMAIN = "[a-zA-Z0-9][a-zA-Z0-9-]{1,61}[a-zA-Z0-9]\\.[a-zA-Z]{2,}$"; private static final String KEY = "[a-km-zA-HJ-NP-Z1-9]{52}$"; @@ -64,13 +64,9 @@ public GrinAddressValidator() { @Override public AddressValidationResult validate(String address) { if (address == null || address.length() == 0) - return AddressValidationResult.invalidAddress("Address may not be empty"); + return AddressValidationResult.invalidAddress("Address may not be empty (only Grinbox format is supported)"); - if (address.matches("^" + IPV4 + ":" + PORT)) - return AddressValidationResult.validAddress(); - - - // We might have a grinbox address + // We only support grinbox address String key; String domain = null; String port = null; @@ -92,13 +88,13 @@ public AddressValidationResult validate(String address) { } if (!key.matches("^" + KEY)) - return AddressValidationResult.invalidAddress("Invalid key"); + return AddressValidationResult.invalidAddress("Invalid key (only Grinbox format is supported)"); if (domain != null && !domain.matches("^" + DOMAIN)) - return AddressValidationResult.invalidAddress("Invalid domain"); + return AddressValidationResult.invalidAddress("Invalid domain (only Grinbox format is supported)"); if (port != null && !port.matches("^" + PORT)) - return AddressValidationResult.invalidAddress("Invalid port"); + return AddressValidationResult.invalidAddress("Invalid port (only Grinbox format is supported)"); return AddressValidationResult.validAddress(); diff --git a/assets/src/main/java/bisq/asset/coins/Adeptio.java b/assets/src/main/java/bisq/asset/coins/Adeptio.java new file mode 100644 index 00000000000..ecfd4b34113 --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/Adeptio.java @@ -0,0 +1,56 @@ +/* + * 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.Base58BitcoinAddressValidator; +import bisq.asset.Coin; +import bisq.asset.NetworkParametersAdapter; + +public class Adeptio extends Coin { + + public Adeptio() { + super("Adeptio", "ADE", new AdeptioAddressValidator()); + } + + + public static class AdeptioAddressValidator extends Base58BitcoinAddressValidator { + + public AdeptioAddressValidator() { + super(new AdeptioParams()); + } + + @Override + public AddressValidationResult validate(String address) { + if (!address.matches("^[A][a-km-zA-HJ-NP-Z1-9]{24,33}$")) + return AddressValidationResult.invalidStructure(); + + return super.validate(address); + } + } + + + public static class AdeptioParams extends NetworkParametersAdapter { + + public AdeptioParams() { + addressHeader = 23; + p2shHeader = 16; + acceptableAddressCodes = new int[]{addressHeader, p2shHeader}; + } + } +} diff --git a/assets/src/main/java/bisq/asset/coins/Aeon.java b/assets/src/main/java/bisq/asset/coins/Aeon.java index a1ded133e6d..1af6aa838d2 100644 --- a/assets/src/main/java/bisq/asset/coins/Aeon.java +++ b/assets/src/main/java/bisq/asset/coins/Aeon.java @@ -18,11 +18,11 @@ package bisq.asset.coins; import bisq.asset.Coin; -import bisq.asset.CryptonoteAddressValidator; +import bisq.asset.CryptoNoteAddressValidator; public class Aeon extends Coin { public Aeon() { - super("Aeon", "AEON", new CryptonoteAddressValidator("Wm", "Xn")); + super("Aeon", "AEON", new CryptoNoteAddressValidator(0xB2, 0x06B8)); } } diff --git a/assets/src/main/java/bisq/asset/coins/Amitycoin.java b/assets/src/main/java/bisq/asset/coins/Amitycoin.java new file mode 100644 index 00000000000..8265df5d981 --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/Amitycoin.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 Amitycoin extends Coin { + + public Amitycoin() { + super("Amitycoin", "AMIT", new RegexAddressValidator("^amit[1-9A-Za-z^OIl]{94}")); + } +} diff --git a/desktop/src/main/java/bisq/desktop/util/validation/VenmoValidator.java b/assets/src/main/java/bisq/asset/coins/Arqma.java similarity index 67% rename from desktop/src/main/java/bisq/desktop/util/validation/VenmoValidator.java rename to assets/src/main/java/bisq/asset/coins/Arqma.java index 6906ffc0256..472db1c0b65 100644 --- a/desktop/src/main/java/bisq/desktop/util/validation/VenmoValidator.java +++ b/assets/src/main/java/bisq/asset/coins/Arqma.java @@ -15,17 +15,16 @@ * along with Bisq. If not, see . */ -package bisq.desktop.util.validation; +package bisq.asset.coins; -import bisq.core.util.validation.InputValidator; +import bisq.asset.AltCoinAccountDisclaimer; +import bisq.asset.Coin; +import bisq.asset.CryptoNoteAddressValidator; -// Removed due too high chargeback risk -@Deprecated -public final class VenmoValidator extends InputValidator { +@AltCoinAccountDisclaimer("account.altcoin.popup.arq.msg") +public class Arqma extends Coin { - @Override - public ValidationResult validate(String input) { - // TODO - return super.validate(input); + public Arqma() { + super("Arqma", "ARQ", new CryptoNoteAddressValidator(0x2cca, 0x6847)); } } diff --git a/assets/src/test/java/bisq/asset/coins/GridcoinTest.java b/assets/src/main/java/bisq/asset/coins/Askcoin.java similarity index 77% rename from assets/src/test/java/bisq/asset/coins/GridcoinTest.java rename to assets/src/main/java/bisq/asset/coins/Askcoin.java index 62b1241db51..39d4ddf4c41 100644 --- a/assets/src/test/java/bisq/asset/coins/GridcoinTest.java +++ b/assets/src/main/java/bisq/asset/coins/Askcoin.java @@ -17,11 +17,12 @@ package bisq.asset.coins; -import bisq.asset.AbstractAssetWithDefaultValidatorTest; +import bisq.asset.Coin; +import bisq.asset.RegexAddressValidator; -public class GridcoinTest extends AbstractAssetWithDefaultValidatorTest { +public class Askcoin extends Coin { - public GridcoinTest() { - super(new Gridcoin()); + public Askcoin() { + super("Askcoin", "ASK", new RegexAddressValidator("^[1-9][0-9]{0,11}")); } } diff --git a/assets/src/main/java/bisq/asset/coins/Beam.java b/assets/src/main/java/bisq/asset/coins/Beam.java index ae233aad841..99fa273e02a 100644 --- a/assets/src/main/java/bisq/asset/coins/Beam.java +++ b/assets/src/main/java/bisq/asset/coins/Beam.java @@ -17,6 +17,7 @@ package bisq.asset.coins; +import bisq.asset.AltCoinAccountDisclaimer; import bisq.asset.Coin; import bisq.asset.RegexAddressValidator; @@ -30,6 +31,7 @@ * but it's a more complex test, requiring cryptographic code. * */ +@AltCoinAccountDisclaimer("account.altcoin.popup.beam.msg") public class Beam extends Coin { public Beam() { super("Beam", "BEAM", new RegexAddressValidator("^([0-9a-f]{1,80})$")); diff --git a/assets/src/main/java/bisq/asset/coins/BitDaric.java b/assets/src/main/java/bisq/asset/coins/BitDaric.java new file mode 100644 index 00000000000..7871fbbbe82 --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/BitDaric.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.asset.coins; + +import bisq.asset.Coin; +import bisq.asset.RegexAddressValidator; + +public class BitDaric extends Coin { + + public BitDaric() { + super("BitDaric", "DARX", new RegexAddressValidator("^[R][a-km-zA-HJ-NP-Z1-9]{25,34}$")); + } +} + diff --git a/assets/src/main/java/bisq/asset/coins/Bitzec.java b/assets/src/main/java/bisq/asset/coins/Bitzec.java new file mode 100644 index 00000000000..df1207315d5 --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/Bitzec.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.asset.coins; + +import bisq.asset.Coin; +import bisq.asset.RegexAddressValidator; + +public class Bitzec extends Coin { + + public Bitzec() { + super("Bitzec", "BZC", new RegexAddressValidator("^t.*", "validation.altcoin.zAddressesNotSupported")); + } + +} diff --git a/assets/src/main/java/bisq/asset/coins/Blur.java b/assets/src/main/java/bisq/asset/coins/Blur.java index 90eea565751..99fb0422af2 100644 --- a/assets/src/main/java/bisq/asset/coins/Blur.java +++ b/assets/src/main/java/bisq/asset/coins/Blur.java @@ -19,12 +19,12 @@ import bisq.asset.AltCoinAccountDisclaimer; import bisq.asset.Coin; -import bisq.asset.CryptonoteAddressValidator; +import bisq.asset.CryptoNoteAddressValidator; @AltCoinAccountDisclaimer("account.altcoin.popup.blur.msg") public class Blur extends Coin { public Blur() { - super("Blur", "BLUR", new CryptonoteAddressValidator("bL", "Ry")); + super("Blur", "BLUR", new CryptoNoteAddressValidator(0x1e4d, 0x2195)); } } diff --git a/assets/src/main/java/bisq/asset/coins/BurntBlackCoin.java b/assets/src/main/java/bisq/asset/coins/BurntBlackCoin.java new file mode 100644 index 00000000000..c825d9fd824 --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/BurntBlackCoin.java @@ -0,0 +1,33 @@ +/* + * 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.RegexAddressValidator; + +@AltCoinAccountDisclaimer("account.altcoin.popup.blk-burnt.msg") +public class BurntBlackCoin extends Coin { + public static final short PAYLOAD_LIMIT = 15000; + + public BurntBlackCoin() { + super("Burnt BlackCoin", + "BLK-BURNT", + new RegexAddressValidator(String.format("(?:[0-9a-z]{2}?){1,%d}+", 2 * PAYLOAD_LIMIT))); + } +} diff --git a/assets/src/main/java/bisq/asset/coins/CRowdCLassic.java b/assets/src/main/java/bisq/asset/coins/CRowdCLassic.java new file mode 100644 index 00000000000..db156cabefb --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/CRowdCLassic.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.asset.coins; + +import bisq.asset.Coin; +import bisq.asset.RegexAddressValidator; + +public class CRowdCLassic extends Coin { + + public CRowdCLassic() { + super("CRowdCLassic", "CRCL", new RegexAddressValidator("^[C][a-zA-Z0-9]{33}$")); + } +} + \ No newline at end of file diff --git a/desktop/src/main/java/bisq/desktop/util/validation/CashAppValidator.java b/assets/src/main/java/bisq/asset/coins/Cash2.java similarity index 67% rename from desktop/src/main/java/bisq/desktop/util/validation/CashAppValidator.java rename to assets/src/main/java/bisq/asset/coins/Cash2.java index 4a861938495..3c7ad2718f7 100644 --- a/desktop/src/main/java/bisq/desktop/util/validation/CashAppValidator.java +++ b/assets/src/main/java/bisq/asset/coins/Cash2.java @@ -15,18 +15,16 @@ * along with Bisq. If not, see . */ -package bisq.desktop.util.validation; +package bisq.asset.coins; +import bisq.asset.AltCoinAccountDisclaimer; +import bisq.asset.Coin; +import bisq.asset.CryptoNoteAddressValidator; -import bisq.core.util.validation.InputValidator; +@AltCoinAccountDisclaimer("account.altcoin.popup.cash2.msg") +public class Cash2 extends Coin { -// Removed due too high chargeback risk -@Deprecated -public final class CashAppValidator extends InputValidator { - - @Override - public ValidationResult validate(String input) { - // TODO - return super.validate(input); + public Cash2() { + super("Cash2", "CASH2", new CryptoNoteAddressValidator(false, 0x6)); } } diff --git a/assets/src/main/java/bisq/asset/coins/CloakCoin.java b/assets/src/main/java/bisq/asset/coins/CloakCoin.java new file mode 100644 index 00000000000..19b5d7727ed --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/CloakCoin.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 CloakCoin extends Coin { + + public CloakCoin() { + super("CloakCoin", "CLOAK", new RegexAddressValidator("^[B|C][a-km-zA-HJ-NP-Z1-9]{33}|^smY[a-km-zA-HJ-NP-Z1-9]{99}$")); + } +} diff --git a/assets/src/main/java/bisq/asset/coins/Credits.java b/assets/src/main/java/bisq/asset/coins/Credits.java new file mode 100644 index 00000000000..1a64f4a391e --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/Credits.java @@ -0,0 +1,56 @@ +/* + * 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.Base58BitcoinAddressValidator; +import bisq.asset.Coin; +import bisq.asset.NetworkParametersAdapter; + +public class Credits extends Coin { + + public Credits() { + super("Credits", "CRDS", new CreditsAddressValidator()); + } + + + public static class CreditsAddressValidator extends Base58BitcoinAddressValidator { + + public CreditsAddressValidator() { + super(new CreditsParams()); + } + + @Override + public AddressValidationResult validate(String address) { + if (!address.matches("^[C][a-km-zA-HJ-NP-Z1-9]{25,34}$")) + return AddressValidationResult.invalidStructure(); + + return super.validate(address); + } + } + + + public static class CreditsParams extends NetworkParametersAdapter { + + public CreditsParams() { + addressHeader = 28; + p2shHeader = 5; + acceptableAddressCodes = new int[]{addressHeader, p2shHeader}; + } + } +} \ No newline at end of file diff --git a/assets/src/main/java/bisq/asset/coins/DSTRA.java b/assets/src/main/java/bisq/asset/coins/DSTRA.java new file mode 100644 index 00000000000..e7ec0e2ca3d --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/DSTRA.java @@ -0,0 +1,56 @@ +/* + * 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.Base58BitcoinAddressValidator; +import bisq.asset.Coin; +import bisq.asset.NetworkParametersAdapter; + +public class DSTRA extends Coin { + + public DSTRA() { + super("DSTRA", "DST", new DSTRAAddressValidator()); + } + + + public static class DSTRAAddressValidator extends Base58BitcoinAddressValidator { + + public DSTRAAddressValidator() { + super(new DSTRAParams()); + } + + @Override + public AddressValidationResult validate(String address) { + if (!address.matches("^[D][a-km-zA-HJ-NP-Z1-9]{33}$")) + return AddressValidationResult.invalidStructure(); + + return super.validate(address); + } + } + + + public static class DSTRAParams extends NetworkParametersAdapter { + + public DSTRAParams() { + addressHeader = 30; + p2shHeader = 33; + acceptableAddressCodes = new int[]{addressHeader, p2shHeader}; + } + } +} diff --git a/assets/src/main/java/bisq/asset/coins/Dash.java b/assets/src/main/java/bisq/asset/coins/Dash.java index 28ca118afc3..754c8528b58 100644 --- a/assets/src/main/java/bisq/asset/coins/Dash.java +++ b/assets/src/main/java/bisq/asset/coins/Dash.java @@ -19,11 +19,18 @@ import bisq.asset.Base58BitcoinAddressValidator; import bisq.asset.Coin; - -import org.libdohj.params.DashMainNetParams; +import bisq.asset.NetworkParametersAdapter; public class Dash extends Coin { public Dash() { - super("Dash", "DASH", new Base58BitcoinAddressValidator(DashMainNetParams.get()), Network.MAINNET); + super("Dash", "DASH", new Base58BitcoinAddressValidator(new DashMainNetParams()), Network.MAINNET); + } + + public static class DashMainNetParams extends NetworkParametersAdapter { + public DashMainNetParams() { + this.addressHeader = 76; + this.p2shHeader = 16; + this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader}; + } } } diff --git a/assets/src/main/java/bisq/asset/coins/DeepOnion.java b/assets/src/main/java/bisq/asset/coins/DeepOnion.java index ed5ba25e88b..716d1b96dae 100644 --- a/assets/src/main/java/bisq/asset/coins/DeepOnion.java +++ b/assets/src/main/java/bisq/asset/coins/DeepOnion.java @@ -22,8 +22,6 @@ import bisq.asset.Coin; import bisq.asset.NetworkParametersAdapter; -import org.libdohj.params.DashMainNetParams; - public class DeepOnion extends Coin { public DeepOnion() { super("DeepOnion", "ONION", new DeepOnionAddressValidator()); diff --git a/assets/src/main/java/bisq/asset/coins/Dogecoin.java b/assets/src/main/java/bisq/asset/coins/Dogecoin.java index 159803e1e0a..40a500ea529 100644 --- a/assets/src/main/java/bisq/asset/coins/Dogecoin.java +++ b/assets/src/main/java/bisq/asset/coins/Dogecoin.java @@ -19,12 +19,19 @@ import bisq.asset.Base58BitcoinAddressValidator; import bisq.asset.Coin; - -import org.libdohj.params.DogecoinMainNetParams; +import bisq.asset.NetworkParametersAdapter; public class Dogecoin extends Coin { public Dogecoin() { - super("Dogecoin", "DOGE", new Base58BitcoinAddressValidator(DogecoinMainNetParams.get())); + super("Dogecoin", "DOGE", new Base58BitcoinAddressValidator(new DogecoinMainNetParams()), Network.MAINNET); + } + + public static class DogecoinMainNetParams extends NetworkParametersAdapter { + public DogecoinMainNetParams() { + this.addressHeader = 30; + this.p2shHeader = 22; + this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader}; + } } } diff --git a/assets/src/main/java/bisq/asset/coins/Doichain.java b/assets/src/main/java/bisq/asset/coins/Doichain.java new file mode 100644 index 00000000000..9bf904cc713 --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/Doichain.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 Doichain extends Coin { + + public Doichain() { + super("Doichain", "DOI", new Base58BitcoinAddressValidator(new DoichainParams())); + } + + public static class DoichainParams extends NetworkParametersAdapter { + public DoichainParams() { + addressHeader = 52; + p2shHeader = 13; + acceptableAddressCodes = new int[]{addressHeader, p2shHeader}; + } + } +} diff --git a/assets/src/main/java/bisq/asset/coins/FourtyTwo.java b/assets/src/main/java/bisq/asset/coins/FourtyTwo.java index fb21882df4e..4e3c16d6a0a 100644 --- a/assets/src/main/java/bisq/asset/coins/FourtyTwo.java +++ b/assets/src/main/java/bisq/asset/coins/FourtyTwo.java @@ -18,11 +18,11 @@ package bisq.asset.coins; import bisq.asset.Coin; -import bisq.asset.CryptonoteAddressValidator; +import bisq.asset.CryptoNoteAddressValidator; public class FourtyTwo extends Coin { public FourtyTwo() { - super("FourtyTwo", "FRTY", new CryptonoteAddressValidator("foUr", "SNake")); + super("FourtyTwo", "FRTY", new CryptoNoteAddressValidator(0x1cbd67, 0x13271817)); } } diff --git a/assets/src/main/java/bisq/asset/coins/Galilel.java b/assets/src/main/java/bisq/asset/coins/Galilel.java new file mode 100644 index 00000000000..138e965330d --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/Galilel.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 Galilel extends Coin { + public Galilel() { + super("Galilel", "GALI", new Base58BitcoinAddressValidator(new GalilelMainNetParams())); + } + + public static class GalilelMainNetParams extends NetworkParametersAdapter { + public GalilelMainNetParams() { + this.addressHeader = 68; + this.p2shHeader = 16; + this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader}; + } + } +} diff --git a/assets/src/main/java/bisq/asset/coins/Grin.java b/assets/src/main/java/bisq/asset/coins/Grin.java index b934077801a..7812aacc294 100644 --- a/assets/src/main/java/bisq/asset/coins/Grin.java +++ b/assets/src/main/java/bisq/asset/coins/Grin.java @@ -17,9 +17,11 @@ package bisq.asset.coins; +import bisq.asset.AltCoinAccountDisclaimer; import bisq.asset.Coin; import bisq.asset.GrinAddressValidator; +@AltCoinAccountDisclaimer("account.altcoin.popup.grin.msg") public class Grin extends Coin { public Grin() { diff --git a/assets/src/main/java/bisq/asset/coins/Hatch.java b/assets/src/main/java/bisq/asset/coins/Hatch.java new file mode 100644 index 00000000000..bbff61765bf --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/Hatch.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 Hatch extends Coin { + public Hatch() { + super("Hatch", "HATCH", new Base58BitcoinAddressValidator(new HatchMainNetParams()), Network.MAINNET); + } + + public static class HatchMainNetParams extends NetworkParametersAdapter { + public HatchMainNetParams() { + this.addressHeader = 76; + this.p2shHeader = 16; + this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader}; + } + } +} diff --git a/assets/src/main/java/bisq/asset/coins/ZeroOneCoin.java b/assets/src/main/java/bisq/asset/coins/Helium.java similarity index 72% rename from assets/src/main/java/bisq/asset/coins/ZeroOneCoin.java rename to assets/src/main/java/bisq/asset/coins/Helium.java index 0fc6b3849cd..cec17a9f7ba 100644 --- a/assets/src/main/java/bisq/asset/coins/ZeroOneCoin.java +++ b/assets/src/main/java/bisq/asset/coins/Helium.java @@ -17,22 +17,22 @@ package bisq.asset.coins; +import bisq.asset.AddressValidationResult; import bisq.asset.Base58BitcoinAddressValidator; import bisq.asset.Coin; import bisq.asset.NetworkParametersAdapter; -public class ZeroOneCoin extends Coin { +public class Helium extends Coin { - public ZeroOneCoin() { - super("01coin", "ZOC", new Base58BitcoinAddressValidator(new ZeroOneCoinAddressParams())); + public Helium() { + super("Helium", "HLM", new Base58BitcoinAddressValidator(new HeliumParams())); } + public static class HeliumParams extends NetworkParametersAdapter { - public static class ZeroOneCoinAddressParams extends NetworkParametersAdapter { - - public ZeroOneCoinAddressParams() { - addressHeader = 80; - p2shHeader = 10; + public HeliumParams() { + addressHeader = 63; + p2shHeader = 5; acceptableAddressCodes = new int[]{addressHeader, p2shHeader}; } } diff --git a/assets/src/main/java/bisq/asset/coins/Litecoin.java b/assets/src/main/java/bisq/asset/coins/Litecoin.java index 6c2463205d7..57b61a3cb50 100644 --- a/assets/src/main/java/bisq/asset/coins/Litecoin.java +++ b/assets/src/main/java/bisq/asset/coins/Litecoin.java @@ -19,11 +19,18 @@ import bisq.asset.Base58BitcoinAddressValidator; import bisq.asset.Coin; - -import org.libdohj.params.LitecoinMainNetParams; +import bisq.asset.NetworkParametersAdapter; public class Litecoin extends Coin { public Litecoin() { - super("Litecoin", "LTC", new Base58BitcoinAddressValidator(LitecoinMainNetParams.get()), Network.MAINNET); + super("Litecoin", "LTC", new Base58BitcoinAddressValidator(new LitecoinMainNetParams()), Network.MAINNET); + } + + public static class LitecoinMainNetParams extends NetworkParametersAdapter { + public LitecoinMainNetParams() { + this.addressHeader = 48; + this.p2shHeader = 5; + this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader}; + } } } diff --git a/assets/src/main/java/bisq/asset/coins/LitecoinPlus.java b/assets/src/main/java/bisq/asset/coins/LitecoinPlus.java new file mode 100644 index 00000000000..aaf8d669b96 --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/LitecoinPlus.java @@ -0,0 +1,38 @@ +/* + * 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 LitecoinPlus extends Coin { + + public LitecoinPlus() { + super("LitecoinPlus", "LCP", new Base58BitcoinAddressValidator(new LitecoinPlusMainNetParams())); + } + + public static class LitecoinPlusMainNetParams extends NetworkParametersAdapter { + public LitecoinPlusMainNetParams() { + this.addressHeader = 75; + this.p2shHeader = 8; + this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader}; + } + } +} + diff --git a/assets/src/main/java/bisq/asset/coins/LitecoinZ.java b/assets/src/main/java/bisq/asset/coins/LitecoinZ.java new file mode 100644 index 00000000000..2d6bc0a28ed --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/LitecoinZ.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.asset.coins; + +import bisq.asset.Coin; +import bisq.asset.RegexAddressValidator; + +public class LitecoinZ extends Coin { + + public LitecoinZ() { + super("LitecoinZ", "LTZ", new RegexAddressValidator("^L.*", "validation.altcoin.ltz.zAddressesNotSupported")); + } + +} diff --git a/assets/src/main/java/bisq/asset/coins/Lytix.java b/assets/src/main/java/bisq/asset/coins/Lytix.java new file mode 100644 index 00000000000..d9a0de079b0 --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/Lytix.java @@ -0,0 +1,39 @@ +/* + * 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.Base58BitcoinAddressValidator; +import bisq.asset.Coin; +import bisq.asset.NetworkParametersAdapter; + +public class Lytix extends Coin { + + public Lytix() { + super("Lytix", "LYTX", new Base58BitcoinAddressValidator(new LytixParams())); + } + + public static class LytixParams extends NetworkParametersAdapter { + + public LytixParams() { + addressHeader = 19; + p2shHeader = 11; + acceptableAddressCodes = new int[]{addressHeader, p2shHeader}; + } + } +} diff --git a/assets/src/main/java/bisq/asset/coins/Mask.java b/assets/src/main/java/bisq/asset/coins/Mask.java index 99217222152..1ab50ba4b31 100644 --- a/assets/src/main/java/bisq/asset/coins/Mask.java +++ b/assets/src/main/java/bisq/asset/coins/Mask.java @@ -18,10 +18,10 @@ package bisq.asset.coins; import bisq.asset.Coin; -import bisq.asset.CryptonoteAddressValidator; +import bisq.asset.CryptoNoteAddressValidator; public class Mask extends Coin { public Mask() { - super("Mask", "MASK", new CryptonoteAddressValidator("M", "bT")); + super("Mask", "MASK", new CryptoNoteAddressValidator(123, 206)); } } diff --git a/assets/src/main/java/bisq/asset/coins/MirQuiX.java b/assets/src/main/java/bisq/asset/coins/MirQuiX.java new file mode 100644 index 00000000000..142daa46ca5 --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/MirQuiX.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 MirQuiX extends Coin { + + public MirQuiX() { + super("MirQuiX", "MQX", new RegexAddressValidator("^[M][a-km-zA-HJ-NP-Z1-9]{33}$")); + } +} diff --git a/assets/src/main/java/bisq/asset/coins/Monero.java b/assets/src/main/java/bisq/asset/coins/Monero.java index 898ff326ad3..68c2c774f68 100644 --- a/assets/src/main/java/bisq/asset/coins/Monero.java +++ b/assets/src/main/java/bisq/asset/coins/Monero.java @@ -19,12 +19,12 @@ import bisq.asset.AltCoinAccountDisclaimer; import bisq.asset.Coin; -import bisq.asset.CryptonoteAddressValidator; +import bisq.asset.CryptoNoteAddressValidator; @AltCoinAccountDisclaimer("account.altcoin.popup.xmr.msg") public class Monero extends Coin { public Monero() { - super("Monero", "XMR", new CryptonoteAddressValidator("4", "8")); + super("Monero", "XMR", new CryptoNoteAddressValidator(18, 42)); } } diff --git a/pricenode/src/main/java/bisq/price/mining/providers/FixedFeeRateProvider.java b/assets/src/main/java/bisq/asset/coins/Navcoin.java similarity index 55% rename from pricenode/src/main/java/bisq/price/mining/providers/FixedFeeRateProvider.java rename to assets/src/main/java/bisq/asset/coins/Navcoin.java index 23661001798..31c07866573 100644 --- a/pricenode/src/main/java/bisq/price/mining/providers/FixedFeeRateProvider.java +++ b/assets/src/main/java/bisq/asset/coins/Navcoin.java @@ -15,26 +15,22 @@ * along with Bisq. If not, see . */ -package bisq.price.mining.providers; +package bisq.asset.coins; -import bisq.price.mining.FeeRate; -import bisq.price.mining.FeeRateProvider; +import bisq.asset.Base58BitcoinAddressValidator; +import bisq.asset.Coin; +import bisq.asset.NetworkParametersAdapter; -import java.time.Duration; -import java.time.Instant; - -abstract class FixedFeeRateProvider extends FeeRateProvider { - - private final String currency; - private final long price; - - public FixedFeeRateProvider(String currency, long price) { - super(Duration.ofDays(1)); - this.currency = currency; - this.price = price; +public class Navcoin extends Coin { + public Navcoin() { + super("Navcoin", "NAV", new Base58BitcoinAddressValidator(new NavcoinParams())); } - protected final FeeRate doGet() { - return new FeeRate(currency, price, Instant.now().getEpochSecond()); + public static class NavcoinParams extends NetworkParametersAdapter { + public NavcoinParams() { + this.addressHeader = 53; + this.p2shHeader = 85; + this.acceptableAddressCodes = new int[]{this.addressHeader, this.p2shHeader}; + } } } diff --git a/assets/src/main/java/bisq/asset/coins/ParsiCoin.java b/assets/src/main/java/bisq/asset/coins/ParsiCoin.java new file mode 100644 index 00000000000..cceee9f2002 --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/ParsiCoin.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.pars.msg") +public class ParsiCoin extends Coin { + + public ParsiCoin() { + super("ParsiCoin", "PARS", new CryptoNoteAddressValidator(false, 0x90004)); + } +} \ No newline at end of file diff --git a/assets/src/main/java/bisq/asset/coins/Plenteum.java b/assets/src/main/java/bisq/asset/coins/Plenteum.java new file mode 100644 index 00000000000..4e99108383d --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/Plenteum.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 Plenteum extends Coin { + + public Plenteum() { + super("Plenteum", "PLE", new RegexAddressValidator("^PLe[1-9A-Za-z^OIl]{95}")); + } +} diff --git a/assets/src/main/java/bisq/asset/coins/Qwertycoin.java b/assets/src/main/java/bisq/asset/coins/Qwertycoin.java new file mode 100644 index 00000000000..58d0849f294 --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/Qwertycoin.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.qwertycoin.msg") +public class Qwertycoin extends Coin { + + public Qwertycoin() { + super("Qwertycoin", "QWC", new CryptoNoteAddressValidator(false, 0x14820c)); + } +} diff --git a/pricenode/src/main/java/bisq/price/mining/providers/DogecoinFeeRateProvider.java b/assets/src/main/java/bisq/asset/coins/TEO.java similarity index 74% rename from pricenode/src/main/java/bisq/price/mining/providers/DogecoinFeeRateProvider.java rename to assets/src/main/java/bisq/asset/coins/TEO.java index 5edcf3c091d..e36581e2da3 100644 --- a/pricenode/src/main/java/bisq/price/mining/providers/DogecoinFeeRateProvider.java +++ b/assets/src/main/java/bisq/asset/coins/TEO.java @@ -15,14 +15,14 @@ * along with Bisq. If not, see . */ -package bisq.price.mining.providers; +package bisq.asset.coins; -import org.springframework.stereotype.Component; +import bisq.asset.Coin; +import bisq.asset.RegexAddressValidator; -@Component -class DogecoinFeeRateProvider extends FixedFeeRateProvider { +public class TEO extends Coin { - public DogecoinFeeRateProvider() { - super("DOGE", 5_000_000); + public TEO() { + super("Trust Ether reOrigin", "TEO", new RegexAddressValidator("^0x[0-9a-fA-F]{40}$")); } } diff --git a/assets/src/main/java/bisq/asset/coins/Veil.java b/assets/src/main/java/bisq/asset/coins/Veil.java new file mode 100644 index 00000000000..792cba487ab --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/Veil.java @@ -0,0 +1,57 @@ +/* + * 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.*; +import org.bitcoinj.core.Address; +import org.bitcoinj.core.AddressFormatException; + +public class Veil extends Coin { + + public Veil() { + super("Veil", "VEIL", new VeilAddressValidator()); + } + + public static class VeilAddressValidator extends Base58BitcoinAddressValidator { + + public VeilAddressValidator() { + super(new VeilParams()); + } + + @Override + public AddressValidationResult validate(String address) { + if (address.startsWith("V")) { + return super.validate(address); + }else if (address.startsWith("bv")){ + // TODO: Add bech32 support + return AddressValidationResult.invalidAddress("Bech32 addresses not supported on bisq"); + } + return AddressValidationResult.invalidStructure(); + } + } + + public static class VeilParams extends NetworkParametersAdapter { + + public VeilParams() { + addressHeader = 70; + p2shHeader = 5; + acceptableAddressCodes = new int[]{addressHeader, p2shHeader}; + } + } +} + diff --git a/assets/src/main/java/bisq/asset/coins/Gridcoin.java b/assets/src/main/java/bisq/asset/coins/XDR.java similarity index 81% rename from assets/src/main/java/bisq/asset/coins/Gridcoin.java rename to assets/src/main/java/bisq/asset/coins/XDR.java index 717573613c3..ea236b29e21 100644 --- a/assets/src/main/java/bisq/asset/coins/Gridcoin.java +++ b/assets/src/main/java/bisq/asset/coins/XDR.java @@ -18,11 +18,11 @@ package bisq.asset.coins; import bisq.asset.Coin; -import bisq.asset.DefaultAddressValidator; -public class Gridcoin extends Coin { +public class XDR extends Coin { - public Gridcoin() { - super("Gridcoin", "GRC", new DefaultAddressValidator()); + public XDR() { + super("XDR", "XDR0", new Mile.MileAddressValidator()); } + } diff --git a/assets/src/main/java/bisq/asset/coins/ZeroClassic.java b/assets/src/main/java/bisq/asset/coins/ZeroClassic.java new file mode 100644 index 00000000000..a593b9bc704 --- /dev/null +++ b/assets/src/main/java/bisq/asset/coins/ZeroClassic.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.asset.coins; + +import bisq.asset.Coin; +import bisq.asset.RegexAddressValidator; + +public class ZeroClassic extends Coin { + + public ZeroClassic() { + super("ZeroClassic", "ZERC", new RegexAddressValidator("^t.*", "validation.altcoin.zAddressesNotSupported")); + } + +} diff --git a/pricenode/src/main/java/bisq/price/mining/providers/DashFeeRateProvider.java b/assets/src/main/java/bisq/asset/tokens/AugmintEuro.java similarity index 76% rename from pricenode/src/main/java/bisq/price/mining/providers/DashFeeRateProvider.java rename to assets/src/main/java/bisq/asset/tokens/AugmintEuro.java index abedc627e23..32ac1d581e2 100644 --- a/pricenode/src/main/java/bisq/price/mining/providers/DashFeeRateProvider.java +++ b/assets/src/main/java/bisq/asset/tokens/AugmintEuro.java @@ -15,14 +15,13 @@ * along with Bisq. If not, see . */ -package bisq.price.mining.providers; +package bisq.asset.tokens; -import org.springframework.stereotype.Component; +import bisq.asset.Erc20Token; -@Component -class DashFeeRateProvider extends FixedFeeRateProvider { +public class AugmintEuro extends Erc20Token { - public DashFeeRateProvider() { - super("DASH", 50); + public AugmintEuro() { + super("Augmint Euro", "AEUR"); } } diff --git a/pricenode/src/main/java/bisq/price/mining/providers/LitecoinFeeRateProvider.java b/assets/src/main/java/bisq/asset/tokens/DaiStablecoin.java similarity index 75% rename from pricenode/src/main/java/bisq/price/mining/providers/LitecoinFeeRateProvider.java rename to assets/src/main/java/bisq/asset/tokens/DaiStablecoin.java index b6681d9a812..f0f673c527d 100644 --- a/pricenode/src/main/java/bisq/price/mining/providers/LitecoinFeeRateProvider.java +++ b/assets/src/main/java/bisq/asset/tokens/DaiStablecoin.java @@ -15,14 +15,13 @@ * along with Bisq. If not, see . */ -package bisq.price.mining.providers; +package bisq.asset.tokens; -import org.springframework.stereotype.Component; +import bisq.asset.Erc20Token; -@Component -class LitecoinFeeRateProvider extends FixedFeeRateProvider { +public class DaiStablecoin extends Erc20Token { - public LitecoinFeeRateProvider() { - super("LTC", 500); + public DaiStablecoin() { + super("Dai Stablecoin", "DAI"); } } diff --git a/assets/src/main/java/bisq/asset/tokens/TrueUSD.java b/assets/src/main/java/bisq/asset/tokens/TrueUSD.java new file mode 100644 index 00000000000..0ca465fe8a2 --- /dev/null +++ b/assets/src/main/java/bisq/asset/tokens/TrueUSD.java @@ -0,0 +1,27 @@ +/* + * 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.tokens; + +import bisq.asset.Erc20Token; + +public class TrueUSD extends Erc20Token { + + public TrueUSD() { + super("TrueUSD", "TUSD"); + } +} diff --git a/assets/src/main/java/bisq/asset/tokens/USDCoin.java b/assets/src/main/java/bisq/asset/tokens/USDCoin.java new file mode 100644 index 00000000000..91d5a926e31 --- /dev/null +++ b/assets/src/main/java/bisq/asset/tokens/USDCoin.java @@ -0,0 +1,27 @@ +/* + * 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.tokens; + +import bisq.asset.Erc20Token; + +public class USDCoin extends Erc20Token { + + public USDCoin() { + super("USD Coin", "USDC"); + } +} diff --git a/assets/src/main/java/bisq/asset/tokens/VectorspaceAI.java b/assets/src/main/java/bisq/asset/tokens/VectorspaceAI.java new file mode 100644 index 00000000000..c080f848c6e --- /dev/null +++ b/assets/src/main/java/bisq/asset/tokens/VectorspaceAI.java @@ -0,0 +1,27 @@ +/* + * 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.tokens; + +import bisq.asset.Erc20Token; + +public class VectorspaceAI extends Erc20Token { + + public VectorspaceAI() { + super("VectorspaceAI", "VXV"); + } +} 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 aacd6ed9118..2a6cf1a7d54 100644 --- a/assets/src/main/resources/META-INF/services/bisq.asset.Asset +++ b/assets/src/main/resources/META-INF/services/bisq.asset.Asset @@ -3,55 +3,78 @@ # See bisq.asset.Asset and bisq.asset.AssetRegistry for further details. # See https://bisq.network/list-asset for complete instructions. bisq.asset.coins.Actinium +bisq.asset.coins.Adeptio bisq.asset.coins.Aeon +bisq.asset.coins.Amitycoin +bisq.asset.coins.Arqma +bisq.asset.coins.Askcoin bisq.asset.coins.Australiacash bisq.asset.coins.Beam bisq.asset.coins.Bitcoin$Mainnet bisq.asset.coins.Bitcoin$Regtest bisq.asset.coins.BitcoinRhodium bisq.asset.coins.Bitcoin$Testnet +bisq.asset.coins.BitDaric bisq.asset.coins.Bitmark +bisq.asset.coins.Bitzec bisq.asset.coins.Blur 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 bisq.asset.coins.Counterparty +bisq.asset.coins.Credits bisq.asset.coins.Croat +bisq.asset.coins.CRowdCLassic 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.Dragonglass +bisq.asset.coins.DSTRA bisq.asset.coins.Ether bisq.asset.coins.EtherClassic bisq.asset.coins.FourtyTwo bisq.asset.coins.Fujicoin +bisq.asset.coins.Galilel bisq.asset.coins.GambleCoin -bisq.asset.coins.Gridcoin bisq.asset.coins.Grin +bisq.asset.coins.Hatch +bisq.asset.coins.Helium bisq.asset.coins.Horizen bisq.asset.coins.IdaPay bisq.asset.coins.Iridium bisq.asset.coins.Kekcoin bisq.asset.coins.Litecoin +bisq.asset.coins.LitecoinPlus +bisq.asset.coins.LitecoinZ +bisq.asset.coins.Lytix bisq.asset.coins.Mask bisq.asset.coins.Mile +bisq.asset.coins.MirQuiX bisq.asset.coins.MobitGlobal bisq.asset.coins.Monero bisq.asset.coins.MonetaryUnit bisq.asset.coins.MoX bisq.asset.coins.Namecoin +bisq.asset.coins.Navcoin bisq.asset.coins.Neos bisq.asset.coins.Noir +bisq.asset.coins.ParsiCoin bisq.asset.coins.Persona bisq.asset.coins.Pinkcoin bisq.asset.coins.PIVX +bisq.asset.coins.Plenteum bisq.asset.coins.PZDC bisq.asset.coins.Qbase bisq.asset.coins.QMCoin +bisq.asset.coins.Qwertycoin bisq.asset.coins.Radium bisq.asset.coins.Remix bisq.asset.coins.Ryo @@ -61,14 +84,22 @@ bisq.asset.coins.SpaceCash bisq.asset.coins.Spectrecoin bisq.asset.coins.Starwels bisq.asset.coins.SUB1X +bisq.asset.coins.TEO bisq.asset.coins.TurtleCoin bisq.asset.coins.UnitedCommunityCoin bisq.asset.coins.Unobtanium +bisq.asset.coins.Veil bisq.asset.coins.Webchain bisq.asset.coins.WrkzCoin +bisq.asset.coins.XDR bisq.asset.coins.Zcash bisq.asset.coins.Zcoin bisq.asset.coins.ZelCash bisq.asset.coins.Zero -bisq.asset.coins.ZeroOneCoin +bisq.asset.coins.ZeroClassic +bisq.asset.tokens.AugmintEuro +bisq.asset.tokens.DaiStablecoin bisq.asset.tokens.EtherStone +bisq.asset.tokens.TrueUSD +bisq.asset.tokens.USDCoin +bisq.asset.tokens.VectorspaceAI diff --git a/assets/src/test/java/bisq/asset/coins/AdeptioTest.java b/assets/src/test/java/bisq/asset/coins/AdeptioTest.java new file mode 100644 index 00000000000..4efa16b6ee3 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/AdeptioTest.java @@ -0,0 +1,47 @@ +/* + * 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 AdeptioTest extends AbstractAssetTest { + + public AdeptioTest() { + super(new Adeptio()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("AP7rSyQMZRek9HGy9QB1bpung69xViesN7"); + assertValidAddress("AWVXtnMo4pS2vBSNrBPLVvMgYvJGD6gSXk"); + assertValidAddress("AHq8sM8DEeFoZXeDkaimfCLtnMuuSWXFE7"); + assertValidAddress("ANG52tPNJuVknLQiLUdzVFoZ3vyo8UzkDL"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("aP7rSyQMZRek9HGy9QB1bpung69xViesN7"); + assertInvalidAddress("DAeiBSH4nudXgoxS4kY6uhTPobc7AlrWDA"); + assertInvalidAddress("BGhVYBXk511m8TPvQA6YokzxdpdhRE3sG6"); + assertInvalidAddress("AZt2Kuy9cWFbTc888HNphppkuCTNyqu5PY"); + assertInvalidAddress("AbosH98t3TRKzyNb8pPQV9boupVcBAX6of"); + assertInvalidAddress("DTPAqTryNRCE2FgsxzohTtJXfCBIDnG6Rc"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/AmitycoinTest.java b/assets/src/test/java/bisq/asset/coins/AmitycoinTest.java new file mode 100644 index 00000000000..ae9135b981a --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/AmitycoinTest.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 AmitycoinTest extends AbstractAssetTest { + + public AmitycoinTest() { + super(new Amitycoin()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("amitMgDfvfUZ2CP1g1SEJQSN4n7qK4d45hqXSDtiFMwE5uo7DnSihknJzcEG9WtFc26fnhDHK6ydjBDKe6wjCoGt4RiP18a5Zb"); + assertValidAddress("amitUnFFwApLG9btiPWRgTjRCQUj9kZjQJ8kH3ZraSsCU4yzX4AzgaoP8jkgXhp5c5jQT3idFJChAPYzA2EydJ5A4bShqrEixa"); + assertValidAddress("amitAcVJTUZKJtYYsosMXJBQeEbt3ZV9qSvoQ1EqkvA45MRUaYWECYNKyRZ82BvLM9MPD2Gpud3DbGzGsStKnZ9x5yKVPVGJUa"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("amitAcVJTUZKJtYYsosMXJBQeEbt3ZV9qSvoQ1EqkvA45MRUaYWECYNKyRZ82BvLM9MPD2Gpud3DbGzGsStKnZ9"); + assertInvalidAddress("amitAcVJTUZKJtYYsosMXJBQeEbt3ZV9qSvoQ1EqkvA45MRUaYWECYNKyRZ82BvLM9MPD2Gpud3DbGzGsStKnZ9x5yKVPVGJUaljashfeafh"); + assertInvalidAddress(""); + assertInvalidAddress("amitAcVJTUZKJtYYsosMXJBQeEbt3ZV9qSvoQ1EqkvA45MRUaYWECY#RoPOWRwpsx1F"); + assertInvalidAddress("amitAcVJTUZKJtYYsosMXJByRZ82BvLM9MPD2Gpud3DbGzGsStKnZ9x5yKVPVGJUaJbc2q4C4fWN$C4fWNLoDLDvADvpjNYdt3sdRB434UidKXimQQn"); + assertInvalidAddress("dsfkjasd56yaSDdguaw"); + assertInvalidAddress("KEKlulzlksadfwe"); + assertInvalidAddress("HOleeSheetdsdjqwqwpoo3"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/ArqmaTest.java b/assets/src/test/java/bisq/asset/coins/ArqmaTest.java new file mode 100644 index 00000000000..3c5a5a9842b --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/ArqmaTest.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 ArqmaTest extends AbstractAssetTest { + + public ArqmaTest() { + super(new Arqma()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("ar3ZLUTSac5DhxhyLJB11gcXWLYPKJchg7c8hoaKmqchC9TtHEdXzxGgt2vzCLUYwtSvkJQTXNCjzCR7KZiFUySV138PEopVC"); + assertValidAddress("aRS3V2hXuVAGAb5XWcDvN7McsSyqrEZ3XWyfMdEDCqioWNmVUuoKyNxDo7rwPCg55Ugb6KHXLN7hLZEGcnZzbm8M7uJ9YdVpeN"); + assertValidAddress("ar3mXR6SQeC3P9Dmq2LGsAeq5eDvjiNnYaywtqdNzixe6xLr38DiNVaaRKMkAQkR3NV3TuVAwAwEGH3QDgXJF3th1RwxABa9a"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress(""); + assertInvalidAddress("ar3ZLUTSac5DhxhyLJB11gcXWLYPKJchg7c8hoaKmqchC9TtHEdXzxGgt2vzCLUYwtSvkJQTXNCjzCR7KZiFUySV138PEopV"); + assertInvalidAddress("aRS3V2hXuVAGAb5XWcDvN7McsSyqrEZ3XWyfMdEDCqioWNmVUuoKyNxDo7rwPCg55Ugb6KHXLN7hLZEGcnZzbm8M7uJ9YdVpeNZz"); + assertInvalidAddress("aRV3V2hXuVAGAb5XWcDvN7McsSyqrEZ3XWyfMdEDCqioWNmVUuoKyNxDo7rwPCg55Ugb6KHXLN7hLZEGcnZzbm8M7uJ9YdVpeN"); + assertInvalidAddress("ar3mXR6SQeC3P9Dmq2LGsAeq5eDvjiNnYaywtqdNzi#exLr38DiNVaaRKMkAQkR3NV3TuVAwAwEGH3QDgXJF3th1RwxABa9a"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/AskcoinTest.java b/assets/src/test/java/bisq/asset/coins/AskcoinTest.java new file mode 100644 index 00000000000..f1f5b587cc3 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/AskcoinTest.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 AskcoinTest extends AbstractAssetTest { + + public AskcoinTest() { + super(new Askcoin()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("1"); + assertValidAddress("123"); + assertValidAddress("876982302333"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("0"); + assertInvalidAddress("038292"); + assertInvalidAddress(""); + assertInvalidAddress("000232320382"); + assertInvalidAddress("1298934567890"); + assertInvalidAddress("123abc5ab"); + assertInvalidAddress("null"); + assertInvalidAddress("xidjfwi23ii0"); + } +} \ No newline at end of file diff --git a/assets/src/test/java/bisq/asset/coins/BitDaricTest.java b/assets/src/test/java/bisq/asset/coins/BitDaricTest.java new file mode 100644 index 00000000000..a21f1d8afcd --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/BitDaricTest.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.AbstractAssetTest; +import org.junit.Test; +public class BitDaricTest extends AbstractAssetTest { + public BitDaricTest() { + super(new BitDaric()); + } + @Test + public void testValidAddresses() { + assertValidAddress("RKWuQUtmV3em1MyB7QKdshgDEAwKQXuifa"); + assertValidAddress("RG9YuDw7fa21a8h4E3Z2z2tgHrFNN27NnG"); + } + @Test + public void testInvalidAddresses() { + assertInvalidAddress("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem"); + assertInvalidAddress("38NwrYsD1HxQW5zfLT0QcUUXGMPvQgzTSn"); + assertInvalidAddress("8tP9rh3SH6n9cSLmV22vnSNNw56LKGpLrB"); + assertInvalidAddress("8Zbvjr"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/BitzecTest.java b/assets/src/test/java/bisq/asset/coins/BitzecTest.java new file mode 100644 index 00000000000..dcc3ac36c75 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/BitzecTest.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 BitzecTest extends AbstractAssetTest { + + public BitzecTest() { + super(new Bitzec()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("t1K6LGT7z2uNTLxag6eK6XwGNpdkHbncBaK"); + assertValidAddress("t1ZjdqCGEkqL9nZ8fk9R6KA7bqNvXaVLUpF"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem"); + assertInvalidAddress("38NwrYsD1HxQW5zfLT0QcUUXGMPvQgzTSn"); + assertInvalidAddress("8tP9rh3SH6n9cSLmV22vnSNNw56LKGpLrB"); + assertInvalidAddress("8Zbvjr"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/BurntBlackCoinTest.java b/assets/src/test/java/bisq/asset/coins/BurntBlackCoinTest.java new file mode 100644 index 00000000000..941ea5f5851 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/BurntBlackCoinTest.java @@ -0,0 +1,46 @@ +/* + * 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 java.util.Collections; +import org.junit.Test; + +public class BurntBlackCoinTest extends AbstractAssetTest { + + public BurntBlackCoinTest() { + super(new BurntBlackCoin()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("4b"); + assertValidAddress("536865206d616b657320796f75206275726e207769746820612077617665206f66206865722068616e64"); + String longAddress = String.join("", Collections.nCopies(2 * BurntBlackCoin.PAYLOAD_LIMIT, "af")); + assertValidAddress(longAddress); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("AF"); + assertInvalidAddress("afa"); + assertInvalidAddress("B4Wa1C8zFgkSY4daLg8jWnxuKpw7UmWFoo"); + String tooLongAddress = String.join("", Collections.nCopies(2 * BurntBlackCoin.PAYLOAD_LIMIT + 1, "af")); + assertInvalidAddress(tooLongAddress); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/CRowdCLassicTest.java b/assets/src/test/java/bisq/asset/coins/CRowdCLassicTest.java new file mode 100644 index 00000000000..ca834002ff6 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/CRowdCLassicTest.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 CRowdCLassicTest extends AbstractAssetTest { + + public CRowdCLassicTest() { + super(new CRowdCLassic()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("CfvddKQHdd975N5XQgmpVGTuK9mumvDBQo"); + assertValidAddress("CU7pAhQjw2mjgQEAkxpsvAmeLU4Gs7ogQb"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("0xmnuL9poRmnuLd55bzKe7t48xtYv2bRES"); + assertInvalidAddress("cvaAgcLKrno2AC7kYhHVDC"); + assertInvalidAddress("19p49poRmnuLdnu55bzKe7t48xtYv2bRES"); + assertInvalidAddress("csabbfjqwr12fbdf2gvffbdb12vdssdcaa"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/Cash2Test.java b/assets/src/test/java/bisq/asset/coins/Cash2Test.java new file mode 100644 index 00000000000..2cbfd40373a --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/Cash2Test.java @@ -0,0 +1,108 @@ +/* + * 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 Cash2Test extends AbstractAssetTest { + + public Cash2Test() { + super(new Cash2()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("21mCcygjJivUzYW4TMTeHbEfv3Fq9NnMGEeChYcVNa3cUcRrVvy3K6mD6oMZ99fv6DQq53hbWB8Td36oVbipR7Yk6bovyL7"); + assertValidAddress("22nnHUyz7DScf3QLL27NsuAxFiuVnfDWUaDF38a35aa3CEPp2zDgcEGLfBkCdu2ohzKt7mVNfNa2NDNZHSoFWa5j3kY9os6"); + assertValidAddress("232Vo5FGYWRHhKmJ3Vz8CRCTy25RJyLJQ8wQo8mUDtZJiGLqQqPgzPJSivKR1ux9GNizSSRh6ACMR74i4qREuQrRK6KF3XH"); + assertValidAddress("247r4orbN2jcXtnSSEBxxdJgRNxexjHZRUiE3aPU7ZL4AoRF6eVh9eY3GQTi2rNuw4PSbZzttoaJPWfJnbUnJ4ZSL8tYppR"); + assertValidAddress("25vJ3RnYBveVqavx1eZshSYc5Rn9YaFWcJ2q2WouT17DMouujdDiAT3MnE7C49hdmF84zbv1TG8mTNcchuTx6L2sBXkjFgw"); + assertValidAddress("26UfQDRNs5X7FFoTrfZXFv5Phze2aotTkGPB5iwDpaM3iXQrhX87e5eUGRbiSzVbb53yuA1jpHG5xiieVkYkrhnSBCJCWHU"); + assertValidAddress("27yDdygjMcLHPRh6iiEQDqZcb6dXYWDpiRhUYZbo3ztGTtEKG72FH7mUtRevHn4rdCX51MHLJMc2afycbSrouoXoGJkA8KE"); + assertValidAddress("28t4qvTKmt34kscL3raEx9EBFjBF9t4JadFpL7vq4GsTj4PSt1mEXW36ENBZgJfW3FRJoBGP47yhj7S9CRSCXEPdVrTBG4m"); + assertValidAddress("295wF4wHgFMGsP67t3te2e2ihruA1V5Bu9KBtrVrMRky9Wwt1mZhwFANpUTCiwuxHAV7cnWhx4y9bMN4esfZXAFJ59YrG9U"); + assertValidAddress("2AZqafQ7tXmgui7ReiGdqsCqKnWVPC4uJ4RDag7pspk5jCA5dQ7ysoNeMGTQss8D4jQhp2ySvvD7XZ8JeNNgHTgULErC5BA"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress(""); + assertInvalidAddress("09s5NiYva6XS9bhhVc6jKYgXsH9wuHhZhWsqyAoPoWPUEiwEo9AZCDNbksvknyvZk73zwhHWSiXdgcDGLyhk5teEM7yxTgk"); + assertInvalidAddress("15a2NPZy7Xe2WZt3nKMZBsBpgNdevnKfy6PLk99eCjYw5fWQ5nu4uM6LerRBvVKTJpdGp2acZ25X3QDPHc7ocTxz1WfN2Za"); + assertInvalidAddress("34B8imA1UH29uR6PHiGpcz9MYdnL3rku27gGeLosn5XuSedFC7jPBmzaB9DoxmDA5VUZa5hPv6PSe3tJH2MJhBktMEJXaZ8"); + assertInvalidAddress("45Ghz2JRTTrLh8Z4bm6QhzZxVbq7LPiKbgjjhHPNDvVXZAJLop91zRu9A7wJMjyrU89uF7QpZB5kHhniuGZ88MJv7jRZXNi"); + assertInvalidAddress("58FFmFEGcS52mTWmhAskaKSSiX1BnHo8YcDjuhPdYBpWT9Q6ZCDz54k6cs3jPF2nk6desb1T6vRfHLfthiNf561qPct2SY1"); + assertInvalidAddress("67rMF5ve4nt2wTHYJ1pZ6j3o2YP5KDBnE7GDxnr6bpem9WcqeHzw9yKWXvtxYdpDXCBbLiX9nm97r4aEtnXq8YNb9WPn15f"); + assertInvalidAddress("798Qr9sWTprQ2sH2y5PGpfV3RAnFxUsJYY2a2VA9GjZ3MiyScD8VEh8ifWk4toYRCcbLZmRJw2dSsJBJAJ1Ava8WBzW7J12"); + assertInvalidAddress("85CQSLDNNKR4HGHwhtsxhm8jheYEvk6ngf44AhqCRWDV2XsaTHr6ittDuyfCjinAP1SzBqnVJfqNhYGDJLzxq4Y7FBVofXV"); + assertInvalidAddress("9AeKW87bkao59oadmTXGf8Jv7sMYByPrKahRbnmZEmGzRgoxGRbWqmmXuPDW6jPJSUAdpZRZn6E5B9935LtWD5gHAPpZQAh"); + assertInvalidAddress("AATHHjFhvpWXksjxJri6yaRkjTAGML2wQ7B2srLFSFXCfQy4C4UdLx5gMLBaxtfvjLe54ZfdSyRDyH94gH9Z17WpSeoBnG6"); + assertInvalidAddress("B1NiHMasw7bQsTyGLYGWh3RyUtvfJtzPyKj7NoGxMr9nJwZ4Un7vzM69EV2xpduUYEf3YMFPF58QvBmttLrUoJYDJzdVWXY"); + assertInvalidAddress("C4ak4b51DGLhGm9sPCXzHe88r9J6bWbJo5LzG4jBVjfBKhqmiQseAUcPkeSwNeNZWtVxSHuTNAk8tRZCbpZcY1rZGvGrEqZ"); + assertInvalidAddress("D8NnxEjgt5LcKLHEydcB7eUhQ1RUMSaHwN6f4w7rYcNH35ti897AAbtAk5Yon72oUee5t45ByaM651ytVVYhDtAFGfuhPBL"); + assertInvalidAddress("E3LDMVt5dzdW9NfnUT7cmUBWjeTuKiYD6Uuq6LB1ETVaJLFwrEZekxLAtLhbcSwPQg2kPeTYG4gZJMK5qmSqTUoDKUvaR7N"); + assertInvalidAddress("F3Jj7vhhZSrWRJirVT3tVSQroPzFdFxB2ChN5276kXEP93We6KJ532ZMQAj136yrrG4exJYtcYVfNZQNGNnV2rkh2bwetrP"); + assertInvalidAddress("G4Lo9KzkK9LUpKL1n6StdrYG2oBKuTqaUEyHekA9jxy7T3VZj4og91CKtfBbuiPVgzYYhL7vpDsk4fDFpyrQ8k18LovPrw7"); + assertInvalidAddress("H1Sv8KX7bnxEXmo6fh4x2y9pfiftbxnsx1QM6bhBjWgwaEqNBeyPdqi1mQKB6JSZqU1u4oEQcsUFY8yyTeP9Jh3s2jZ6qVc"); + assertInvalidAddress("I5wP79cd9oz4Pw2Gdj5Youi5J2Jft1QRwBdtRdx7bFe782Gxacw9hCpQ3jbyqs5U18EWiuzpJaAgiGrwD3aC17He7vWRxQM"); + assertInvalidAddress("J7icdECeckdDAofi9aBLwMZDvLnABZiT6XHFTu115E2pe3GqqBkFPL9dtbRUMrL5ZicQ6JMs2VamZNYyCWNt9jkEJvE4Fir"); + assertInvalidAddress("K7vZECGxgqcgtLTcbyVH9d4z68Z3SYgJFD3jiyrimiiR87qqVQUXdoTciVr6JQCMSY3qNxk1SDqVFAmv7dFbhWA6AJBtQq1"); + assertInvalidAddress("L5zCC9MAJVqXEogZ8YZFAHFN3Pp9J47vi3bXKV3tvP69FoSNzpsCgBHATYpJY7Aho958RyvbwxMDYFNqK5UiFe6WKy8xxQC"); + assertInvalidAddress("M6kpYUXiyT7TBraQqtbxuZRtAzb9Px8vz7FWtBtM2UwqP68jYGoKENeDs8u6SGK7msXevM97AaB3ZYM9pk55uXSf9dbu8BD"); + assertInvalidAddress("N8FMot8AeSzBNeNGzAwXb8eN3rNmb8neUWWL7epoVE6mSJdQ87p1byWcs6NTLQkJUkgUx7t51WhfKSQcJFrZq9EBPcWsQmP"); + assertInvalidAddress("O4c4hCkAWf7RbVXsiZu4v9S9BQ5KdWZWreykUpHdMAFxYerg4xsg4KPCoR5bq9z9ahMKb3sHuHW627zCdcBRPLe8Ft2qvDp"); + assertInvalidAddress("P6PhpdMqmcgAwV8iRjcoboFprEHgrPgYEYLzjaeU5HvRJAXu1yzWM1Q3D9zxvju6bwEv54Sccdp2S33HPx1s86uGSsZ9K8Q"); + assertInvalidAddress("Q8DP7okc13sjL7Hens8obs3mgpKyXzteccUHpuRhDyRsfxyFx8KNeBdGUNHYxWcc4pVk4gdUQq9hiZhw5K8m4pxC5rtRXo1"); + assertInvalidAddress("R9xFn1dKj6Rdsp6ZwCkpfDC2n98HHLa6M7DmV47qkYhm9vbeer1bbPoJopG4DYhspgNmTpbwe2nco3o7AsaMrT4D6MQaVxg"); + assertInvalidAddress("S89QzLjkGJiFaYdb83wrQEEtMNBizmaiz3kHYUmwZURm5mbDcGLEnBpGrqSuJVxQjHE4cpiqFF1A6Gk2ZB2uwDUb1nms8Dg"); + assertInvalidAddress("T7iiGq9NExdRwgUV6WcT58DPWA8SL8VyDdBEqY6vG8mwHedpWzU1e1Z7k5wc8DL7nyWfCYFsZKn2KcP5DXwYcvwRB9Xy4zG"); + assertInvalidAddress("U2Ec4PmgrMuVahrYGAkS5jhisb1w8b63ra33t5eoY2e5V9syeyhqU8xUqSLe22WrxMYk4gve6isGb7EpU7RLrRGzANDVUtz"); + assertInvalidAddress("V4U3d86FzU3bKvgjNNs4fuGDNRYQFoLx3XAKKtq4SiwbPLwmTpo9P2jMbwvby4YZmPCkTu6RgAdv1XispG1qtnT64Vbkn6W"); + assertInvalidAddress("W1JeT4tzGAw4b9EiLsH1pC3dWLzTSGGaaVAGux1z8PuqCH8ziEmEMDZeEhcnxgjz8n27bS7oUvb1UcUYbYTHt5jaKwicC1x"); + assertInvalidAddress("X5EAA2wJRhC3QomYEgu6NMg7AW77LfjcxhhK7YHT94XnRwGsEWmNW71Ct3UiNLbs3ab1xiWVfu4ymF3enZ19hgfM93Xp2dz"); + assertInvalidAddress("Y3YWhEp25gw1gpVtdWxdyd9Fgj5quPGuy6hC9h8knpC58YPtB4TxpZEfhb9cRgXezxCXnq1GTmQ49TCQ3CsJ8gFW3q4WN95"); + assertInvalidAddress("Z6q1WzvdPpZhiCEqzugGSPM5b39S6cdn64DtF6FcvtFg4d9hNaxXevvbkEYM8GwEH4ihW98pd6SVkR8meDu21oDbPgncEz9"); + assertInvalidAddress("a6GQ2ZBomH5WojBELhHSmQXmgNDecv65ebzhhMMkmxZVhiJxRixh29ZJ7oQK4Yg8FF4qjYMv1ykA4JA7n6KoWy18DJPaUVs"); + assertInvalidAddress("b4jmgQskiHLW8PtdX3X662eMLN2hnAnTzJsu4PLbggomVuhVFuGaUWEDntQSzpcKXgReLZAeYGEaYWPpFsTgmwEpLhEfN4m"); + assertInvalidAddress("c9Nc2eUQXBnR2PpcRrKqbA2A4DSEeLDt7LhYy4aKmvCr6JCRGtXZxrePTJpbMC83MyR8W2KCCfVwfhygpLa437DBC2NQpYH"); + assertInvalidAddress("dA5bw23DkMoXpYXbX8aPncW8ZgHKyPLngJkJS7tGPegjZycvquRKktFFf46n3VFxfrLT2UnrCkBE4LrqbWnDfRUW6Nfut6g"); + assertInvalidAddress("e49CqpKzaDG8yV6rNRuQ2VVrZi8FCTVJ4b2C5AsVkqNtGFGKCBAjTeDFhWkGJvLfFTNDUkxsgQ9bP41Uhx5G3gdCB4k6oVJ"); + assertInvalidAddress("f6x8ajQFtUReSoNYvCc7RjXpzZRngNaUU6xTAc6YvFsw8uTzwL4WDuM71cuBAW5oNAQrBjmPQmBZV8DYav6bAEVQQR7mLh2"); + assertInvalidAddress("g1Pdnp4qJ4qYPu11EEBeUhTU7Bb3b7k1Rg8hAxAqJf2XDncBqrePPrNGsgqaLeRdpBFfsZRCHTabpHvQWMzUsiLNJGFvGnR"); + assertInvalidAddress("h3DzqGR97GwWe7G3YC7D4mgCA7b68zMQmAq4r559JtcAjbG1GeXvjedTnHys9aS9vL9iG8djvVeZMdVi4S8Kc6oX2Zovt8r"); + assertInvalidAddress("iALCRLmNc8WSzbyjri4dgw9iaL6a2Uf3QYsUwsXseJfb7FCQnUgGja2ATbYpLREQTxc5VLvExQpwqFsmvhdvpx5VEVAgmyJ"); + assertInvalidAddress("j3bKBtupDeZcauKPMvzBLWHnHFn5q6ZVxDCZdvmvXJ7sgT5cQKQ8iJgARzJQ1SpzSKLwb6Kx8EVebbv4d9Y4o8AcKSQgWyx"); + assertInvalidAddress("k1u7EQDv25yGG67XtWkCSDYsbSpHFwTKESVpAxM8XSPqFrYDWPQV8KWReVmPR4piLtByikCpTgvWW5tXaxrfSuRXKo8DwWh"); + assertInvalidAddress("l6kW6xriMLxTTJBHdErywLZHQp6HchZwmZLXM4GyTfV3GFsZ7rF9JzrLx7ykNe75bqjii4b3kVX7SU98AEZmfyExNQFnZTm"); + assertInvalidAddress("m5hY6yRHGDKbjYbZiveah4DntcKbGAaqnLR5QWnF8hFP7NDouKXcFPKfWX7q8jaXdKKTJsi3Aec36Lbz4rapaxB7PKtM4mw"); + assertInvalidAddress("n9kXzy9NJhS5txFKQzh88XFFx7vi8XoLGc1UMXp7uFdK5NoaABPvemWRGm4zb6VNqgh786Q9ch1muayCQnszr8YzRYrxwWE"); + assertInvalidAddress("o7bZkG5wPryY1Ld3TPhcjECcDFeP63neFD5cA1iXC8ZPJtBsAwXFFsdbyR9eV7oKp8bB26TKWyjU86ibaJVg9RtoR5Hr18N"); + assertInvalidAddress("p37iEL6AWJaZm357fSqgQPQLzFigpuzTT9wTmUaGM7VfEzf9qmcZjP76y8bnN51bjqBKsMYPF7XLxA87vMhGAiAe5jdBhtX"); + assertInvalidAddress("q6TkiMru8ELSdXeX1DWquJ9WH7yxjFC3QdGovpUZYG7v2nCDhCxyDdz8CcqpRaqzf55xg8suNHbVAgNaUVCeCv1yETsaFJq"); + assertInvalidAddress("r9HCvadnFDSjDUAqhzorvaZmPeRqKgGG5GUnr3ph2zQteQ3TgGEvq6oiK2H967UUoUJKCH9yXmfuX3oDiyHNm2xaP7ZcPqa"); + assertInvalidAddress("s7XmwW4Q2hdN4VqEcES8KnXGTaE7Dq2w4gsjzDfBAQKWZ3S45DGBSpwb32o7Y1STZvQDtxPKVXtgbScjWizvpbC8SNYcabo"); + assertInvalidAddress("t5ZmMnkKCU8h44srsPYr5JVkvDhHBZG44QQYE2gEbUhTN4orqDgiKnMTyQYPj3XC1M5bST42rNUfR9LuWpGvkJmoCZaFvYJ"); + assertInvalidAddress("uARGu2zWWtu9k9pb1TK6zmS1ASnNVX1Kj9H3nRq6MGGhLcNshUHML4gid6grswb3aaVq47t5qqre41isaExKFDGRD9LCUHG"); + assertInvalidAddress("v1tYtfLchdzUrJow8RqMbGcH1ZAtWzSUmJHaQnrG1EypRkktGDo3tqXdk5yby64rgJjBgmMjJJ6NkRWsukHi9RTQ3XQBbqB"); + assertInvalidAddress("w4Q6hafxurmZWPSHpmp8R2GSxYiAw5DJQ3fcS9irCF3zKRnYarXLxfQPd5t24rEyYRCDAUSV1DL7CTY5guRE6dk4FgXrw5H"); + assertInvalidAddress("x7o5bwgPr1JMLMZQX8RoDT6JYfD7GwFanQa3QcMsUNbaj3siUp5i5okZxF237s5MhjWmWxWyVDxNvTq1c9MXSnQJHpNKq4d"); + assertInvalidAddress("yAENYbDcrf49FUHHDdSbtCF4EEG6LxxjvE7CsusYoi6bQUoUCfqH9yqjbuTP8i8e5vPYzWqLj1VpdMSZ4DQdhhUB8MtdvcL"); + assertInvalidAddress("z2kefw5QxZ9CmzdPCnFD766oaJ1yU1NXr5WwD2xZTpTFAGL8HRjzUzmXkdo2fqiiZyiTVAYMfxMtfJvo5QLEkHUnJEPmps4"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/CloakCoinTest.java b/assets/src/test/java/bisq/asset/coins/CloakCoinTest.java new file mode 100644 index 00000000000..4f6b3f7cf34 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/CloakCoinTest.java @@ -0,0 +1,49 @@ +/* + * 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 CloakCoinTest extends AbstractAssetTest { + + public CloakCoinTest() { + super(new CloakCoin()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("C3MwbThsvquwA4Yg6recThXpAhR2hvRKws"); + assertValidAddress("B6MwbThsvquwA4Yg6recThXpAhR2hvKRsz"); + assertValidAddress("BCA31xPpijxiCuTQeYMpMTQsTH1m2jTg5t"); + assertValidAddress("smYmLVV33zExmaFyVp3AUjU3fJMK5E93kwzDfMnPLnEBQ7BoHZkSQhCP92hZz7Hm24yavCceNeQm8RHekqdvrhFe8gX7EdXNwnhQgQ"); + + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("1sA31xPpijxiCuTQeYMpMTQsTH1m2jTgtS"); + assertInvalidAddress("BsA31xPpijxiCuTQeYMpMTQsTH1m2jTgtSd"); + assertInvalidAddress("bech3ThsvquwA4Yg6recThXpAhR2hvRKws"); + assertInvalidAddress("smYmLYcVVzExmaFyVp3AUjU3fJMK5E93kwzDfMnPLnEBQ7BoHZkSQhCP92hZz7Hm24yavCceNeQm8RHekqdv"); + assertInvalidAddress("C3MwbThsvquwA4Yg6recThXpAhR2hvRKw"); + assertInvalidAddress(" B6MwbThsvquwA4Yg6recThXpAhR2hvKRsz"); + assertInvalidAddress("B6MwbThsvquwA4Yg6recThXpAhR2hvKRsz "); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/CreditsTest.java b/assets/src/test/java/bisq/asset/coins/CreditsTest.java new file mode 100644 index 00000000000..7a699999787 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/CreditsTest.java @@ -0,0 +1,46 @@ +/* + * 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 CreditsTest extends AbstractAssetTest { + + public CreditsTest() { + super(new Credits()); + } + + + @Test + public void testValidAddresses() { + assertValidAddress("CfXBhPhSxx1wqxGQCryfgn6iU1M1XFUuCo"); + assertValidAddress("CMde7YERCFWkCL2W5i8uyJmnpCVj8Chhww"); + assertValidAddress("CcbqU3MLZuGAED2CuhUkquyJxKaSJqv6Vb"); + assertValidAddress("CKaig5pznaUgiLqe6WkoCNGagNMhNLtqhK"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("1fXBhPhSxx1wqxGQCryfgn6iU1M1XFUuCo32"); + assertInvalidAddress("CMde7YERCFWkCL2W5i8uyJmnpCVj8Chh"); + assertInvalidAddress("CcbqU3MLZuGAED2CuhUkquyJxKaSJqv6V6#"); + assertInvalidAddress("bKaig5pznaUgiLqe6WkoCNGagNMhNLtqhKkggg"); + } +} \ No newline at end of file diff --git a/assets/src/test/java/bisq/asset/coins/ZeroOneCoinTest.java b/assets/src/test/java/bisq/asset/coins/DSTRATest.java similarity index 58% rename from assets/src/test/java/bisq/asset/coins/ZeroOneCoinTest.java rename to assets/src/test/java/bisq/asset/coins/DSTRATest.java index 0dfdac67d1e..d371044cfa4 100644 --- a/assets/src/test/java/bisq/asset/coins/ZeroOneCoinTest.java +++ b/assets/src/test/java/bisq/asset/coins/DSTRATest.java @@ -21,26 +21,24 @@ import org.junit.Test; -public class ZeroOneCoinTest extends AbstractAssetTest { +public class DSTRATest extends AbstractAssetTest { - public ZeroOneCoinTest() { - super(new ZeroOneCoin()); + public DSTRATest() { + super(new DSTRA()); } @Test public void testValidAddresses() { - assertValidAddress("ZN17ww22Kg1cqM2VykoDwZW4fCTCvxGQMb"); - assertValidAddress("ZZJG1oqJ9VWHAy5AuE7bAugqoYvcGtPJcH"); - assertValidAddress("ZaUSzTWurWuaBw4zr8E4oEN25DzJK9vwbR"); - assertValidAddress("5AchYc7iQS7ynce7hNZ6Ya8djsbm5N9JBS"); + assertValidAddress("DGiwGS8n3tJZuKxUdWF6MyTYvv6xgDcyd7"); + assertValidAddress("DQcAKx5bFoeRwAEHE4EHQykyq8u2M1pwFa"); } @Test public void testInvalidAddresses() { - assertInvalidAddress("ZaUSzTWurWuaBw4zr8E4oEN25DzJK9vqqe"); - assertInvalidAddress("ZN17ww22Kg1cqM2VykoDwZW4fCTCvxGQM"); - assertInvalidAddress("ZaUSzTWurWuaBw4zr8E4oEN25DzJK9vwbb"); - assertInvalidAddress("Zb17ww22Kg1cqM2VykoDwZW4fCTCvxGQMb"); + assertInvalidAddress("DGiwGS8n3tJZuKxUdWF6MyTYvv6xgDcyd77"); + assertInvalidAddress("DGiwGS8n3tJZuKxUdWF6MyTYvv6xgDcyd"); + assertInvalidAddress("dGiwGS8n3tJZuKxUdWF6MyTYvv6xgDcyd7"); + assertInvalidAddress("FGiwGS8n3tJZuKxUdWF6MyTYvv6xgDcyd7"); + assertInvalidAddress("fGiwGS8n3tJZuKxUdWF6MyTYvv6xgDcyd7"); } - -} \ No newline at end of file +} diff --git a/assets/src/test/java/bisq/asset/coins/DoichainTest.java b/assets/src/test/java/bisq/asset/coins/DoichainTest.java new file mode 100644 index 00000000000..5465a3415c7 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/DoichainTest.java @@ -0,0 +1,42 @@ +/* + * 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 DoichainTest extends AbstractAssetTest { + + public DoichainTest() { + super(new Doichain()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("NGHV9LstnZfrkGx5QJmYhEepbzc66W7LN5"); + assertValidAddress("N4jeY9YhU49qHN5wUv7HBxeVZrFg32XFy7"); + assertValidAddress("6a6xk7Ff6XbgrNWhSwn7nM394KZJNt7JuV"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("NGHV9LstnZfrkGx5QJmYhEepbzc66W7LN5x"); + assertInvalidAddress("16iWWt1uoG8Dct56Cq6eKHFxvGSDha46Lo"); + assertInvalidAddress("38BFQkc9CdyJUxQK8PhebnDcA1tRRwLDW4"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/GalilelTest.java b/assets/src/test/java/bisq/asset/coins/GalilelTest.java new file mode 100644 index 00000000000..70726fcf7cb --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/GalilelTest.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 GalilelTest extends AbstractAssetTest { + + public GalilelTest() { + super(new Galilel()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("UVwXGh5B1NZbYdgWThqf2cLdkEupVXEVNi"); + assertValidAddress("UbNJbC1hZgBH5tQ4HyrrQMEPswKxwwfziw"); + assertValidAddress("UgqDDV8aekEXFP7BWLmTNpSQfk7uVk1jCF"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("1UgqDDV8aekEXFP7BWLmTNpSQfk7uVk1jCF"); + assertInvalidAddress("UgqDDV8aekEXFP7BWLmTNpSQfk7uVk1jCFd"); + assertInvalidAddress("UgqDDV8aekEXFP7BWLmTNpSQfk7uVk1jCF#"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/GrinTest.java b/assets/src/test/java/bisq/asset/coins/GrinTest.java index 22851f78bb6..83b602607a8 100644 --- a/assets/src/test/java/bisq/asset/coins/GrinTest.java +++ b/assets/src/test/java/bisq/asset/coins/GrinTest.java @@ -29,16 +29,6 @@ public GrinTest() { @Test public void testValidAddresses() { - assertValidAddress("0.0.0.0:8080"); - assertValidAddress("173.194.34.134:8080"); - assertValidAddress("127.0.0.1:8080"); - assertValidAddress("192.168.0.1:8080"); - assertValidAddress("18.101.25.153:8080"); - assertValidAddress("173.194.34.134:1"); - assertValidAddress("173.194.34.134:11"); - assertValidAddress("173.194.34.134:1111"); - assertValidAddress("173.194.34.134:65535"); - // grinbox assertValidAddress("gVvk7rLBg3r3qoWYL3VsREnBbooT7nynxx5HtDvUWCJUaNCnddvY"); assertValidAddress("grinbox://gVtWzX5NTLCBkyNV19QVdnLXue13heAVRD36sfkGD6xpqy7k7e4a"); @@ -50,6 +40,18 @@ public void testValidAddresses() { @Test public void testInvalidAddresses() { + // valid IP:port addresses but not supported in Bisq + assertInvalidAddress("0.0.0.0:8080"); + assertInvalidAddress("173.194.34.134:8080"); + assertInvalidAddress("127.0.0.1:8080"); + assertInvalidAddress("192.168.0.1:8080"); + assertInvalidAddress("18.101.25.153:8080"); + assertInvalidAddress("173.194.34.134:1"); + assertInvalidAddress("173.194.34.134:11"); + assertInvalidAddress("173.194.34.134:1111"); + assertInvalidAddress("173.194.34.134:65535"); + + // invalid IP:port addresses assertInvalidAddress("google.com"); assertInvalidAddress("100.100.100.100"); assertInvalidAddress(".100.100.100.100:1222"); @@ -71,6 +73,5 @@ public void testInvalidAddresses() { assertInvalidAddress("gVw9TWimGFXRjoDXWhWxeNQbu84ZpLkvnenkKvA5aJeDo31eM5tC@somerelay.com:1220a"); assertInvalidAddress("grinbox://gVwjSsYW5vvHpK4AunJ5piKhhQTV6V3Jb818Uqs6PdC3SsB36AsAsomerelay.com"); assertInvalidAddress("grinbox://gVwjSsYW5vvHpK4AunJ5piKhhQTV6V3Jb818Uqs6PdC3SsB36AsA@somerelay.com1220"); - } } diff --git a/assets/src/test/java/bisq/asset/coins/HatchTest.java b/assets/src/test/java/bisq/asset/coins/HatchTest.java new file mode 100644 index 00000000000..634bae0e02e --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/HatchTest.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 HatchTest extends AbstractAssetTest { + + public HatchTest() { + super(new Hatch()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("XgUfhrcfKWTVprA1GGhTggAA3VVQy1xqNp"); + assertValidAddress("Xo88XjP8RD2w3k7Fd16UT62y3oNcjbv4bz"); + assertValidAddress("XrA7ZGDLQkiLwUsfKT6y6tLrYjsvRLrZQG"); + + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("1XrA7ZGDLQkiLwUsfKT6y6tLrYjsvRLrZQG"); + assertInvalidAddress("XrA7ZGDLQkiLwUsfKT6y6tLrYjsvRLrZQGd"); + assertInvalidAddress("XrA7ZGDLQkiLwUsfKT6y6tLrYjsvRLrZQG#"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/HeliumTest.java b/assets/src/test/java/bisq/asset/coins/HeliumTest.java new file mode 100644 index 00000000000..0fa127d382d --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/HeliumTest.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 HeliumTest extends AbstractAssetTest { + + public HeliumTest() { + super(new Helium()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("SPSXRJSwzGKxSiYXePf1vnkk4v9WKVLhZp"); + assertValidAddress("SbzXDLmMfWDJZ1wEikUVAMbAzM2UnaSt4g"); + assertValidAddress("Sd14293Zhxxur2Pim7NkjxPGVaJTjGR5qY"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("1PSXRJSwzGKxSiYXePf1vnkk4v9WKVLhZp"); + assertInvalidAddress("SPSXRJSwzGKxSiYXePf1vnkk4v9WKVLhZpp"); + assertInvalidAddress("SPSSPSSPSGKxSiYXePf1vnkk4v9WKVLhZp"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/LitecoinPlusTest.java b/assets/src/test/java/bisq/asset/coins/LitecoinPlusTest.java new file mode 100644 index 00000000000..c3a8b169d4d --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/LitecoinPlusTest.java @@ -0,0 +1,42 @@ +/* + * 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 LitecoinPlusTest extends AbstractAssetTest { + + public LitecoinPlusTest() { + super(new LitecoinPlus()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("XGnikpGiuDTaxq9vPfDF9m9VfTpv4SnNN5"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("1LgfapHEPhZbRF9pMd5WPT35hFXcZS1USrW"); + assertInvalidAddress("LgfapHEPhZbdRF9pMd5WPT35hFXcZS1USrW"); + assertInvalidAddress("LgfapHEPhZbRF9pMd5WPT35hFXcZS1USrW#"); + } +} + diff --git a/assets/src/test/java/bisq/asset/coins/LitecoinZTest.java b/assets/src/test/java/bisq/asset/coins/LitecoinZTest.java new file mode 100644 index 00000000000..e8f2e63ed0b --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/LitecoinZTest.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 LitecoinZTest extends AbstractAssetTest { + + public LitecoinZTest() { + super(new LitecoinZ()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("L17opZaVcRK4h9MV4KhkCmzUBa56BxSRb8A"); + assertValidAddress("L1EjNbAPVtg8jE9EyvbsA7epibZ9j8bdYmV"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem"); + assertInvalidAddress("38NwrYsD1HxQW5zfLT0QcUUXGMPvQgzTSn"); + assertInvalidAddress("8tP9rh3SH6n9cSLmV22vnSNNw56LKGpLrB"); + assertInvalidAddress("8Zbvjr"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/LytixTest.java b/assets/src/test/java/bisq/asset/coins/LytixTest.java new file mode 100644 index 00000000000..12747938021 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/LytixTest.java @@ -0,0 +1,47 @@ +/* + * 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 LytixTest extends AbstractAssetTest { + + public LytixTest() { + super(new Lytix()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("8hTBZgtuexiUVMxCPcrPgMem7jurB2YJds"); + assertValidAddress("8hqgpDE5uSuyRrDMXo1w3y59SCxfv8sSsf"); + assertValidAddress("8wtCT2JHu4wd4JqCwxnWFQXhmggnwdjpSn"); + assertValidAddress("8pYVReruVqYdp6LRhsy63nuVgsg9Rx7FJT"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("6pYVReruVqYdp6LRhsy63nuVgsg9Rx7FJT"); + assertInvalidAddress("8mgfRRiHVxf4JZH3pvffuY6NrKhffh13Q"); + assertInvalidAddress("8j75cPWABNXdZ62u6ZfF4tDQ1tVdvJx2oh7"); + assertInvalidAddress("FryiHzNPFatNV15hTurq9iFWeHTrQhUhG6"); + assertInvalidAddress("8ryiHzNPFatNV15hTurq9iFWefffQhUhG6"); + assertInvalidAddress("8ryigz2PFatNV15hTurq9iFWeHTrQhUhG1"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/MirQuiXTest.java b/assets/src/test/java/bisq/asset/coins/MirQuiXTest.java new file mode 100644 index 00000000000..cf86ad6ee56 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/MirQuiXTest.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 MirQuiXTest extends AbstractAssetTest { + + public MirQuiXTest() { + super(new MirQuiX()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("MCfFP5bFtN9riJiRRnH2QRkqCDqgNVC3FX"); + assertValidAddress("MEoLjNvFbNv63NtBW6eyYHUAGgLsJrpJbG"); + assertValidAddress("M84gmHb7mg4PMNBpVt3BeeAWVuKBmH6vtd"); + assertValidAddress("MNurUTgTSgg5ckmCcbjPrkgp7fekouLYgh"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("MCfFP5bFtN9riJiRRnH2QRkqCDqgNVC3FX2"); + assertInvalidAddress("MmEoLjNvFbNv63NtBW6eyYHUAGgLsJrpJbG"); + assertInvalidAddress("M84gmHb7mg4PMNBpVt3BeeAWVuKBmH63vtd"); + assertInvalidAddress("MNurUTgTSgg5ckmCcbjPrkgp7fekouLYfgh"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/NavcoinTest.java b/assets/src/test/java/bisq/asset/coins/NavcoinTest.java new file mode 100644 index 00000000000..55a1182d8c3 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/NavcoinTest.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 NavcoinTest extends AbstractAssetTest { + + public NavcoinTest() { + super(new Navcoin()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("NNR93HzmuhYKZ4Tnc9TGoD2DK6TVzXG9P7"); + assertValidAddress("NSm5NyCe5BFRuV3gFY5VcfhxWx7GTu9U9F"); + assertValidAddress("NaSdzJ64o8DQo5DMPexVrL4PYFCBZqcmsW"); + + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("NNR93HzmuhYKZ4Tnc9TGoD2DK6TVzXG9P"); + assertInvalidAddress("NNR93HzmuhYKZ4TnO9TGoD2DK6TVzXG9P8"); + assertInvalidAddress("NNR93HzmuhYKZ4Tnc9TGoD2DK6TVzXG9P71"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/ParsiCoinTest.java b/assets/src/test/java/bisq/asset/coins/ParsiCoinTest.java new file mode 100644 index 00000000000..3840990d15f --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/ParsiCoinTest.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 ParsiCoinTest extends AbstractAssetTest { + + public ParsiCoinTest() { + super(new ParsiCoin()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("PARSGnjdcRG4gY9g4rMTFAEHZLGU7uK8YMiFY3Do1uzoMz4LMA6PqmdPp7ZxDu25b56RyhCevkWjbAMng532iFFj8L5RaPyT4s"); + assertValidAddress("PARSftfY5pwJaUFtaxThVgKY9Sepd4mG44WpyncbtAxTddwTvJ84GCgGfoxYjzG53kLhRm21ENWp3fx5bneArq1D815ZoWNVqA"); + assertValidAddress("PARSju1hCQ5GmXSRbca8weGYDn2pqCypgLyTrENqL4XU3mdEx1mZ2vR7osrVA2hHNGRJRA5pRENF2Q8Pee8BscHoABVrcfkWnx"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress(""); + assertInvalidAddress("1GfqxEuuFmwwHTFkch3Aq3frEBbdpYfWPP"); + assertInvalidAddress("PARsaUEu1c9HWPQx6WpCcjZNmpS3vMhN4Jws12KrccLhH9vzUw4racG3g7St2FKDYngjcnkNF3N2sKQJ5jv1NYqD2buCpmVKE"); + assertInvalidAddress("PArSeoCiQL2Rjyo9GR39boeLCTM6ou3zGiv8AuFFblGHfNasy5iKfvG6JgnksNby26J6i5sEorRcmG8gF2AxC8bYiHyDGEfD6hp8T9KfwjQxVa"); + assertInvalidAddress("PaRSaUEu1c9HWPQx6WpCcjZNmpS3vMhN4Jws12rccLhH9vzUw4racG3g7St2#FKDYngjcnkNF3N2sKQJ5jv1NYqD2buCpmVKE"); + assertInvalidAddress("pARSeoCiQL2Rjyo9GR39boeLCTM6ou3zGiv8AuFFby5iKfvG6JNby26J6i5s$&*orRcmG8gF2AxC8bYiHyDGEfD6hp8T9KfwjQxVa"); + assertInvalidAddress("hyrjMmPhaznQkJD6C9dcmbBH9y6r9vYAg2aTG9CHSzL1R89xrFi7wj1azmkXyLPiWDBeTCsKGMmr6JzygbP2ZGSN2JqWs1WcK"); + assertInvalidAddress("parsGnjdcRG4gY9g4rMTFAEHZLGU7uK8YMiFY3Do1uzoMz4LMA6PqmdPp7ZxDu25b56RyhCevkWjbAMng532iFFj8L5RaPyT"); + } +} \ No newline at end of file diff --git a/assets/src/test/java/bisq/asset/coins/PlenteumTest.java b/assets/src/test/java/bisq/asset/coins/PlenteumTest.java new file mode 100644 index 00000000000..ce36a0f819c --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/PlenteumTest.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 PlenteumTest extends AbstractAssetTest { + + public PlenteumTest() { + super(new Plenteum()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("PLeah9bvqxEDUWbRFqgNcYDeoL772WH9mcCQu9p29MC23NeCUkbVdUEfwDAtF8SgV81kf2hwCdpxqAJmC9k3nJsA7W4UThrufj"); + assertValidAddress("PLeavHTKHz9UcTCSCmd8eihuLxbsK9a7wSpfcYXPYY87JMpvYwwTH6Df32fRLc1r4rQMKoDLpTvywXx4FUVTggCR4jh9PEhvXb"); + assertValidAddress("PLeazd7iQEoFWJttR6353BMvs1cJfMqDmEUk2Z2XSoDdZigY5CbNLvrFUr7duvnEFdSKRdCQYTDkrcySYD1zaFtT9YMubRjHL2"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("PLev23ymatPTWgN1jncG33hMdJxZBLrBcCWQBGGGC14CFMUCq1nvxiV8d5cW92mmavzw542bpyjYXd8"); + assertInvalidAddress("PLeuxauCnCH7XZrSZSZw7XEEbkgrnZcaE1MK8wLtTYkF3g1J7nciYiaZDsTNYm2oDLTAM2JPq4rrlhVN5cXWpTPYh8P5wKbXNdoh"); + assertInvalidAddress(""); + assertInvalidAddress("PLev3xxpAFfXKwF5ond4sWDX3ATpZngT88KpPCCJKcuRjGktgp5HHTK2yV7NTo8687u5jwMigLmHaoFKho0OhVmF8WP9pVZhBL9kC#RoPOWRwpsx1F"); + assertInvalidAddress("PLeuwafXHTPzj1d2wc7c9X69r3qG1277ecnLnUaZ61M1YV5d3GYAs1Jbc2q4C4fWN$C4fWNLoDLDvADvpjNYdt3sdRB434UidKXimQQn"); + assertInvalidAddress("1jRo3rcp9fjdfjdSGpx"); + assertInvalidAddress("GDARp92UtmTWDjZatG8sduRockSteadyWasHere3atrHSXr9vJzjHq2TfPrjateDz9Wc8ZJKuDayqJ$%"); + assertInvalidAddress("F3xQ8Gv6xnvDhUrM57z71bfFvu9HeofXtXpZRLnrCN2s2cKvkQowrWjJTGz4676ymKvU4NzYT5Aadgsdhsdfhg4gfJwL2yhhkJ7"); + } +} \ No newline at end of file diff --git a/assets/src/test/java/bisq/asset/coins/QwertycoinTest.java b/assets/src/test/java/bisq/asset/coins/QwertycoinTest.java new file mode 100644 index 00000000000..ed39da44b71 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/QwertycoinTest.java @@ -0,0 +1,56 @@ +/* + * 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 QwertycoinTest extends AbstractAssetTest { + + public QwertycoinTest() { + super(new Qwertycoin()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("QWC1NStUeRB9hZiYH8sG5RAWEt7YycyB44YZnpZQBpgq4CLwmLw4vAk9tU3h7Td21NL9aMbLHxseDGKdEv3gRexo2QCodNEZWa"); + assertValidAddress("QWC1anUNJRo2HePBmenLFkGu8rnug4odGLCjHaCqAwMxboiZZS3Gv9ACLfn2zvcsGVcCc51eqZXB8Dot9X5qAt3F53F8BxjDrG"); + assertValidAddress("QWC1hgpbsxsPrpxH9H3wL771p4KdgS7vA369PQTiznHiCC3NjZxKJSmBtJPVCJBBUKE346FcPTsQ18W6fgiDzj762BHNgo2sir"); + assertValidAddress("QWC1YAvWpYBVs8XT2eSt2JV5iAJSdm8CwbQhDruuBeTzRNKSdtdK8Mn3WjaXQrFvjMMWWTf24x89p31mWppJN2Br9uiA5zdYQu"); + assertValidAddress("QWC1YzR91Zmcj7fpf1HRZhSfz6cgXbxqAVTjQTtrUV6Bfv1ysEzb78qgVojE7FuQWSRnVqSb3LyxP9nH2q4vWyo82Fonutfkzr"); + assertValidAddress("QWC1KYAwX6sRXK94HabKLCFNMjfC12KFC74cRjTgFtsD79VUBydTtMd3G2z4xLg2e1LKaXsTt3zkYibH3pBrAMjd5z5ConjRXn"); + assertValidAddress("QWC1ZgSyFwS3tUbmCRPGDBi224ynMZXgXCHxvQ5pEmtuZSCrmid4z1de1DWRjhZKRZXe4E5LYhtP6e7FmpN8R2MM2SHGFvg12z"); + assertValidAddress("QWC1W7223e83cBdseddQp461j49bhr7y4VHh8FTPs7qWArhpqBzNvrYR5QXyFtc3eRaoASo3QVhuT6ogAa6AHhgt4bVMUNpZGh"); + assertValidAddress("QWC1NgBcSwvXghUkEqGttNPSSmPEgEdknXELNLyTG444Fx3cKkV2oJ9iCwzySbps7y9BqqkWAKbkvdkA8FTspfdm29ScDzASK1"); + assertValidAddress("QWC1FVgbYqkafwnpW8KU2gKXLTKoraMXuEJ2c1yG6PNdesh6BA3Wq8d1mgRYqfsbCn53g5VLHuxyLT8CXnGRLxN64wHssuSa9D"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress(""); + assertInvalidAddress("QW009s5NiYva6XS9bhhVc6jKYgXsH9wuHhZhWsqyAoPoWPUEiwEo9AZCDNbksvknyvZk73zwhHWSiXdgcDGLyhk5teEM7yxTgk"); + assertInvalidAddress("WC115a2NPZy7Xe2WZt3nKMZBsBpgNdevnKfy6PLk99eCjYw5fWQ5nu4uM6LerRBvVKTJpdGp2acZ25X3QDPHc7ocTxz1WfN2Za"); + assertInvalidAddress("34BQWC8imA1UH29uR6PHiGpcz9MYdnL3rku27gGeLosn5XuSedFC7jPBmzaB9DoxmDA5VUZa5hPv6PSe3tJH2MJhBktMEJXaZ8"); + assertInvalidAddress("KWC45Ghz2JRTTrLh8Z4bm6QhzZxVbq7LPiKbgjjhHPNDvVXZAJLop91zRu9A7wJMjyrU89uF7QpZB5kHhniuGZ88MJv7jRZXNi"); + assertInvalidAddress("ABc58FFmFEGcS52mTWmhAskQaKSSiX1BnHo8YcDjuhPdYBpWT9Q6ZCDz54k6cs3jPF2nk6desb1T6vRfHLfthiNf561qPct2SY"); + assertInvalidAddress("2K267rMF5ve4nt2wTHYJ1pZ6j3o2YP5KDBnE7GDxnr6bpem9WcqeHzw9yKWXvtxYdpDXCBbLiX9nm97r4aEtnXq8YNb9WPn15f"); + assertInvalidAddress("798Qr9sWTprQ2sH2y5PGpfV3RAnFxUsJYY2a2VQWCA9GjZ3MiyScD8VEh8ifWk4toYRCcbLZmRJw2dSsJBJAJ1Ava8WBzW7J12"); + assertInvalidAddress("A2o85CQSLDNNKR4HGHwhtsxhm8jheYEvk6ngf44AhqCRWDV2XsaTHr6ittDuyfCjinAP1SzBqnVJfqNhYGDJLzxq4Y7FBVofXV"); + assertInvalidAddress("QW9AeKW87bkao59oadmTXGf8Jv7sMYByPrKahRbnmZEmGzRgoxGRbWqmmXuPDW6jPJSUAdpZRZn6E5B9935LtWD5gHAPpZQA"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/TEOTest.java b/assets/src/test/java/bisq/asset/coins/TEOTest.java new file mode 100644 index 00000000000..66f67b605ff --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/TEOTest.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 TEOTest extends AbstractAssetTest { + + public TEOTest() { + super(new TEO()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("0x8d1ba0497c3e3db17143604ab7f5e93a3cbac68b"); + assertValidAddress("0x23c9c5ae8c854e9634a610af82924a5366a360a3"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress(""); + assertInvalidAddress("8d1ba0497c3e3db17143604ab7f5e93a3cbac68b"); + assertInvalidAddress("0x8d1ba0497c3e3db17143604ab7f5e93a3cbac68"); + assertInvalidAddress("0x8d1ba0497c3e3db17143604ab7f5e93a3cbac68k"); + assertInvalidAddress("098d1ba0497c3e3db17143604ab7f5e93a3cbac68b"); + assertInvalidAddress("098d1ba0497c3e3db17143604ab7f5e93a3cbac68b"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/VeilTest.java b/assets/src/test/java/bisq/asset/coins/VeilTest.java new file mode 100644 index 00000000000..68e9ca856a3 --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/VeilTest.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 VeilTest extends AbstractAssetTest { + + public VeilTest() { + super(new Veil()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("VS2oF2pouKoLPJCjY8D7E1dStmUtitACu7"); + assertValidAddress("VV8VtpWTsYFBnhnvgQVnTvqoTx7XRRevte"); + assertValidAddress("VRZF4Am891FS224uuNirsrEugqMyg3VxjJ"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhemqq"); + assertInvalidAddress("3EktnHQD7RiAE6uzMj2ZifT9YgRrkSgzQX"); + assertInvalidAddress("DRbnCYbuMXdKU4y8dya9EnocL47gFjErWeg"); + assertInvalidAddress("DTPAqTryNRCE2FgsxzohTtJXfCBODnG6Rc"); + assertInvalidAddress("DTPAqTryNRCE2FgsxzohTtJXfCB0DnG6Rc"); + assertInvalidAddress("DTPAqTryNRCE2FgsxzohTtJXfCBIDnG6Rc"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/XDRTest.java b/assets/src/test/java/bisq/asset/coins/XDRTest.java new file mode 100644 index 00000000000..dcf61c808fc --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/XDRTest.java @@ -0,0 +1,63 @@ +/* + * 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 XDRTest extends AbstractAssetTest { + + public XDRTest() { + super(new XDR()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("2WeY8JpRJgrvWQxbSPuyhsBMjtZMMN7cADEomPHh2bCkdZ7xQW"); + assertValidAddress("NTvSfK1Gr5Jg97UvJo2wvi7BTZo8KqJzgSL2FCGucF6nUH7yq"); + assertValidAddress("ztNdPsuyfDWt1ufCbDqaCDQH3FXvucXNZqVrdzsWvzDHPrkSh"); + assertValidAddress("jkvx3z98rJmuVKqMSktDpKTSBrsqJEtTBW1CBSWJEtchDGkDX"); + assertValidAddress("is2YXBxk91d4Lw4Pet7RoP8KAxCKFHUC6iQyaNgmac5ies6ko"); + assertValidAddress("2NNEr5YLniGxWajoeXiiAZPR68hJXncnhEmC4GWAaV5kwaLRcP"); + assertValidAddress("wGmjgRu8hgjgRsRV8k6h2puis1K9UQCTKWZEPa4yS8mrmJUpU"); + assertValidAddress("i8rc9oMunRtVbSxA4VBESxbYzHnfhP39aM5M1srtxVZ8oBiKD"); + assertValidAddress("vP4w8khXHFQ7cJ2BJNyPbJiV5kFfBHPVivHxKf5nyd8cEgB9U"); + assertValidAddress("QQQZZa46QJ3499RL8CatuqaUx4haKQGUuZ4ZE5SeL13Awkf6m"); + assertValidAddress("qqqfpHD3VbbyZXTHgCW2VX8jvoERcxanzQkCqVyHB8fRBszMn"); + assertValidAddress("BiSQkPqCCET4UovJASnnU1Hk5bnqBxBVi5bjA5wLZpN9HCA6A"); + assertValidAddress("bisqFm6Zbf6ULcpJqQ2ibn2adkL2E9iivQFTAP15Q18daQxnS"); + assertValidAddress("miLEgbhGv4ARoPG2kAhTCy8UGqBcFbsY6rr5tXq63nH8RyqcE"); + + + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("1WeY8JpRJgrvWQxbSPuyhsBMjtZMMN7cADEomPHh2bCkdZ7xQW"); + assertInvalidAddress("2WeY8JpRJgrvWQxbSPuyhsBMjtZMMN3cADEomPHh2bCkdZ7xQW"); + assertInvalidAddress("2WeY8JpRJgrvWQxbSPuyhsBMjtZMMN7cADEomPHh2bCkdZ7xQ1"); + assertInvalidAddress("2WeY8JpRJgrvWQxbSPuyhsBMjtZMMN7cADEomPHh2bCkdZ7xQ"); + assertInvalidAddress("WeY8JpRJgrvWQxbSPuyhsBMjtZMMN7cADEomPHh2bCkdZ7xQW"); + assertInvalidAddress("2WeY8JpRJgrvWQx"); + assertInvalidAddress("2WeY8JpRJgrvWQxbSPuyhsBMjtZMMN7cADEomPHh2bCkdZ7xQW1"); + assertInvalidAddress("milEgbhGv4ARoPG2kAhTCy8UGqBcFbsY6rr5tXq63nH8RyqcE"); + assertInvalidAddress("miLegbhGv4ARoPG2kAhTCy8UGqBcFbsY6rr5tXq63nH8RyqcE"); + assertInvalidAddress("1111111"); + } +} diff --git a/assets/src/test/java/bisq/asset/coins/ZeroClassicTest.java b/assets/src/test/java/bisq/asset/coins/ZeroClassicTest.java new file mode 100644 index 00000000000..d175790f77d --- /dev/null +++ b/assets/src/test/java/bisq/asset/coins/ZeroClassicTest.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 ZeroClassicTest extends AbstractAssetTest { + + public ZeroClassicTest() { + super(new ZeroClassic()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("t1PLfc14vCYaRz6Nv1zxpKXhn5W5h9vUdUE"); + assertValidAddress("t1MjXvaqL5X2CquP8hLmvyxCiJqCBzuMofS"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("17VZNX1SN5NtKa8UQFxwQbFeFc3iqRYhem"); + assertInvalidAddress("38NwrYsD1HxQW5zfLT0QcUUXGMPvQgzTSn"); + assertInvalidAddress("8tP9rh3SH6n9cSLmV22vnSNNw56LKGpLrB"); + assertInvalidAddress("8Zbvjr"); + } +} diff --git a/assets/src/test/java/bisq/asset/tokens/AugmintEuroTest.java b/assets/src/test/java/bisq/asset/tokens/AugmintEuroTest.java new file mode 100644 index 00000000000..0a7013da8b7 --- /dev/null +++ b/assets/src/test/java/bisq/asset/tokens/AugmintEuroTest.java @@ -0,0 +1,42 @@ +/* + * 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.tokens; + +import bisq.asset.AbstractAssetTest; + +import org.junit.Test; + +public class AugmintEuroTest extends AbstractAssetTest { + + public AugmintEuroTest() { + super(new AugmintEuro()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("0x0d81d9e21bd7c5bb095535624dcb0759e64b3899"); + assertValidAddress("0d81d9e21bd7c5bb095535624dcb0759e64b3899"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("0x65767ec6d4d3d18a200842352485cdc37cbf3a216"); + assertInvalidAddress("0x65767ec6d4d3d18a200842352485cdc37cbf3a2g"); + assertInvalidAddress("65767ec6d4d3d18a200842352485cdc37cbf3a2g"); + } +} diff --git a/assets/src/test/java/bisq/asset/tokens/DaiStablecoinTest.java b/assets/src/test/java/bisq/asset/tokens/DaiStablecoinTest.java new file mode 100644 index 00000000000..d567cce57da --- /dev/null +++ b/assets/src/test/java/bisq/asset/tokens/DaiStablecoinTest.java @@ -0,0 +1,42 @@ +/* + * 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.tokens; + +import bisq.asset.AbstractAssetTest; + +import org.junit.Test; + +public class DaiStablecoinTest extends AbstractAssetTest { + + public DaiStablecoinTest() { + super(new DaiStablecoin()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("0x2a65Aca4D5fC5B5C859090a6c34d164135398226"); + assertValidAddress("2a65Aca4D5fC5B5C859090a6c34d164135398226"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("0x2a65Aca4D5fC5B5C859090a6c34d1641353982266"); + assertInvalidAddress("0x2a65Aca4D5fC5B5C859090a6c34d16413539822g"); + assertInvalidAddress("2a65Aca4D5fC5B5C859090a6c34d16413539822g"); + } +} diff --git a/assets/src/test/java/bisq/asset/tokens/TrueUSDTest.java b/assets/src/test/java/bisq/asset/tokens/TrueUSDTest.java new file mode 100644 index 00000000000..e86612cdda8 --- /dev/null +++ b/assets/src/test/java/bisq/asset/tokens/TrueUSDTest.java @@ -0,0 +1,42 @@ +/* + * 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.tokens; + +import bisq.asset.AbstractAssetTest; + +import org.junit.Test; + +public class TrueUSDTest extends AbstractAssetTest { + + public TrueUSDTest() { + super(new TrueUSD()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("0xa23579c2f7b462e5fb2e92f8cf02971fe4de4f82"); + assertValidAddress("0xdb59b63738e27e6d689c9d72c92c7a12f22161bb"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("0x2a65Aca4D5fC5B5C859090a6c34d1641353982266"); + assertInvalidAddress("0x2a65Aca4D5fC5B5C859090a6c34d16413539822g"); + assertInvalidAddress("2a65Aca4D5fC5B5C859090a6c34d16413539822g"); + } +} diff --git a/assets/src/test/java/bisq/asset/tokens/USDCoinTest.java b/assets/src/test/java/bisq/asset/tokens/USDCoinTest.java new file mode 100644 index 00000000000..dd76c40e908 --- /dev/null +++ b/assets/src/test/java/bisq/asset/tokens/USDCoinTest.java @@ -0,0 +1,42 @@ +/* + * 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.tokens; + +import bisq.asset.AbstractAssetTest; + +import org.junit.Test; + +public class USDCoinTest extends AbstractAssetTest { + + public USDCoinTest() { + super(new USDCoin()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("0xb86bb5fc804768db34f1a37da8b719e19af9dffd"); + assertValidAddress("0xea82afd93ebfc4f6564f3e5bd823cdef710f75dd"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("0x2a65Aca4D5fC5B5C859090a6c34d1641353982266"); + assertInvalidAddress("0x2a65Aca4D5fC5B5C859090a6c34d16413539822g"); + assertInvalidAddress("2a65Aca4D5fC5B5C859090a6c34d16413539822g"); + } +} diff --git a/assets/src/test/java/bisq/asset/tokens/VectorspaceAITest.java b/assets/src/test/java/bisq/asset/tokens/VectorspaceAITest.java new file mode 100644 index 00000000000..4e4e5e4cc42 --- /dev/null +++ b/assets/src/test/java/bisq/asset/tokens/VectorspaceAITest.java @@ -0,0 +1,42 @@ +/* + * 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.tokens; + +import bisq.asset.AbstractAssetTest; + +import org.junit.Test; + +public class VectorspaceAITest extends AbstractAssetTest { + + public VectorspaceAITest () { + super(new VectorspaceAI()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("0xdd88dbdde30b684798881d4f3d9a3752d6c1dd71"); + assertValidAddress("dd88dbdde30b684798881d4f3d9a3752d6c1dd71"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("0x2ecf455d8a2e6baf8d1039204c4f97efeddf27a82"); + assertInvalidAddress("0xh8wheG1jdka0c8b8263758chanbmshj2937zgab"); + assertInvalidAddress("h8wheG1jdka0c8b8263758chanbmshj2937zgab"); + } +} diff --git a/build.gradle b/build.gradle index 92e2892da56..92316e488df 100644 --- a/build.gradle +++ b/build.gradle @@ -33,8 +33,7 @@ configure(subprojects) { jmockitVersion = '1.42' joptVersion = '5.0.3' langVersion = '3.4' - libdohjVersion = '7be803fa' - bitcoinjVersion = 'cd30ad5b' + bitcoinjVersion = 'a88d36d' logbackVersion = '1.1.10' lombokVersion = '1.18.2' mockitoVersion = '2.21.0' @@ -66,7 +65,8 @@ configure([project(':desktop'), project(':monitor'), project(':relay'), project(':seednode'), - project(':statsnode')]) { + project(':statsnode'), + project(':pricenode')]) { apply plugin: 'application' @@ -132,13 +132,14 @@ configure([project(':desktop'), configure(project(':assets')) { dependencies { - compile("network.bisq.libdohj:libdohj-core:$libdohjVersion") { - exclude(module: 'protobuf-java') - exclude(module: 'bitcoinj-core') - } compile("com.github.bisq-network.bitcoinj:bitcoinj-core:$bitcoinjVersion") { + exclude(module: 'jsr305') + exclude(module: 'slf4j-api') + exclude(module: 'guava') exclude(module: 'protobuf-java') } + compile 'com.google.guava:guava:20.0' + 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" @@ -174,11 +175,6 @@ configure(project(':common')) { compile('com.google.inject:guice:4.1.0') { exclude(module: 'guava') } - compile("network.bisq.libdohj:libdohj-core:$libdohjVersion") { - exclude(module: 'slf4j-api') - exclude(module: 'protobuf-java') - exclude(module: 'bitcoinj-core') - } compile("com.github.bisq-network.bitcoinj:bitcoinj-core:$bitcoinjVersion") { exclude(module: 'jsr305') exclude(module: 'slf4j-api') @@ -199,10 +195,10 @@ configure(project(':common')) { configure(project(':p2p')) { dependencies { compile project(':common') - compile('com.github.JesusMcCloud.netlayer:tor.native:0.6.3') { + compile('com.github.JesusMcCloud.netlayer:tor.native:0.6.5') { exclude(module: 'slf4j-api') } - compile('com.github.JesusMcCloud.netlayer:tor.external:0.6.3') { + compile('com.github.JesusMcCloud.netlayer:tor.external:0.6.5') { exclude(module: 'slf4j-api') } compile('org.apache.httpcomponents:httpclient:4.5.3') { @@ -276,7 +272,7 @@ configure(project(':desktop')) { apply plugin: 'witness' apply from: '../gradle/witness/gradle-witness.gradle' - version = '0.9.3-SNAPSHOT' + version = '1.1.2-SNAPSHOT' mainClassName = 'bisq.desktop.app.BisqAppMain' @@ -339,6 +335,7 @@ configure(project(':monitor')) { } dependencies { + compile project(':core') compile "org.slf4j:slf4j-api:$slf4jVersion" compile "ch.qos.logback:logback-core:$logbackVersion" compile "ch.qos.logback:logback-classic:$logbackVersion" @@ -347,10 +344,6 @@ configure(project(':monitor')) { compileOnly "org.projectlombok:lombok:$lombokVersion" annotationProcessor "org.projectlombok:lombok:$lombokVersion" - compile('com.github.JesusMcCloud.netlayer:tor.native:0.6.2') { - exclude(module: 'slf4j-api') - } - testCompile 'org.junit.jupiter:junit-jupiter-api:5.3.2' testCompile 'org.junit.jupiter:junit-jupiter-params:5.3.2' testCompileOnly "org.projectlombok:lombok:$lombokVersion" diff --git a/common/src/main/java/bisq/common/Clock.java b/common/src/main/java/bisq/common/Clock.java index 43f990011e9..3383b8eba51 100644 --- a/common/src/main/java/bisq/common/Clock.java +++ b/common/src/main/java/bisq/common/Clock.java @@ -21,22 +21,24 @@ import java.util.List; import java.util.concurrent.TimeUnit; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; +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. +@Slf4j public class Clock { - private static final Logger log = LoggerFactory.getLogger(Clock.class); - - public static final int IDLE_TOLERANCE = 20000; + public static final int IDLE_TOLERANCE_MS = 20000; public interface Listener { void onSecondTick(); void onMinuteTick(); - void onMissedSecondTick(long missed); + default void onMissedSecondTick(long missedMs) { + } + + default void onAwakeFromStandby(long missedMs) { + } } private Timer timer; @@ -51,18 +53,24 @@ public void start() { if (timer == null) { lastSecondTick = System.currentTimeMillis(); timer = UserThread.runPeriodically(() -> { - listeners.stream().forEach(Listener::onSecondTick); + listeners.forEach(Listener::onSecondTick); counter++; if (counter >= 60) { counter = 0; - listeners.stream().forEach(Listener::onMinuteTick); + listeners.forEach(Listener::onMinuteTick); } long currentTimeMillis = System.currentTimeMillis(); long diff = currentTimeMillis - lastSecondTick; - if (diff > 1000) - listeners.stream().forEach(listener -> listener.onMissedSecondTick(diff - 1000)); - + if (diff > 1000) { + long missedMs = diff - 1000; + listeners.forEach(listener -> listener.onMissedSecondTick(missedMs)); + + if (missedMs > Clock.IDLE_TOLERANCE_MS) { + log.info("We have been in standby mode for {} sec", missedMs / 1000); + listeners.forEach(listener -> listener.onAwakeFromStandby(missedMs)); + } + } lastSecondTick = currentTimeMillis; }, 1, TimeUnit.SECONDS); } diff --git a/common/src/main/java/bisq/common/Envelope.java b/common/src/main/java/bisq/common/Envelope.java index 40fc91b8966..c713e8a26c6 100644 --- a/common/src/main/java/bisq/common/Envelope.java +++ b/common/src/main/java/bisq/common/Envelope.java @@ -18,7 +18,7 @@ package bisq.common; /** - * Interface for the outside envelope object sent over the network or persisted to disc. + * Interface for the outside envelope object sent over the network or persisted to disk. */ public interface Envelope extends Proto { } diff --git a/common/src/main/java/bisq/common/UserThread.java b/common/src/main/java/bisq/common/UserThread.java index c46b576d22d..d7b994eeda5 100644 --- a/common/src/main/java/bisq/common/UserThread.java +++ b/common/src/main/java/bisq/common/UserThread.java @@ -37,7 +37,7 @@ * For JavaFX it is usually the Platform::RunLater executor, for a headless application it is any single threaded * executor. * Additionally sets a timer class so JavaFX and headless applications can set different timers (UITimer for JavaFX - * otherwise we use teh default FrameRateTimer). + * otherwise we use the default FrameRateTimer). *

* Provides also methods for delayed and periodic executions. */ diff --git a/common/src/main/java/bisq/common/app/Capabilities.java b/common/src/main/java/bisq/common/app/Capabilities.java index 015a98c74f8..841b9d1c494 100644 --- a/common/src/main/java/bisq/common/app/Capabilities.java +++ b/common/src/main/java/bisq/common/app/Capabilities.java @@ -17,55 +17,106 @@ package bisq.common.app; -import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.stream.Collectors; -import lombok.Getter; -import lombok.Setter; +import lombok.EqualsAndHashCode; +/** + * hold a set of capabilities and offers appropriate comparison methods. + * + * @author Florian Reimair + */ +@EqualsAndHashCode public class Capabilities { - // 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. - // 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, - BSQ_BLOCK + + /** + * The global set of capabilities, i.e. the capabilities if the local app. + */ + public static final Capabilities app = new Capabilities(); + + protected final Set capabilities = new HashSet<>(); + + public Capabilities(Capability... capabilities) { + this(Arrays.asList(capabilities)); + } + + public Capabilities(Capabilities capabilities) { + this(capabilities.capabilities); + } + + public Capabilities(Collection capabilities) { + this.capabilities.addAll(capabilities); + } + + public void set(Capability... capabilities) { + set(Arrays.asList(capabilities)); + } + + public void set(Capabilities capabilities) { + set(capabilities.capabilities); + } + + public void set(Collection capabilities) { + this.capabilities.clear(); + this.capabilities.addAll(capabilities); } - // Application need to set supported capabilities at startup - @Getter - @Setter - private static List supportedCapabilities = new ArrayList<>(); + public void addAll(Capability... capabilities) { + this.capabilities.addAll(Arrays.asList(capabilities)); + } + + public void addAll(Capabilities capabilities) { + if(capabilities != null) + this.capabilities.addAll(capabilities.capabilities); + } + + public boolean containsAll(final Set requiredItems) { + return capabilities.containsAll(requiredItems); + } + + public boolean containsAll(final Capabilities capabilities) { + return containsAll(capabilities.capabilities); + } + + public boolean isEmpty() { + return capabilities.isEmpty(); + } + + + /** + * helper for protobuffer stuff + * + * @param capabilities + * @return int list of Capability ordinals + */ + public static List toIntList(Capabilities capabilities) { + return capabilities.capabilities.stream().map(capability -> capability.ordinal()).sorted().collect(Collectors.toList()); + } + + /** + * helper for protobuffer stuff + * + * @param capabilities a list of Capability ordinals + * @return a {@link Capabilities} object + */ + public static Capabilities fromIntList(List capabilities) { + return new Capabilities(capabilities.stream() + .filter(integer -> integer < Capability.values().length) + .map(integer -> Capability.values()[integer]) + .collect(Collectors.toSet())); + } - public static void addCapability(int capability) { - supportedCapabilities.add(capability); + @Override + public String toString() { + return Arrays.toString(Capabilities.toIntList(this).toArray()); } - public static boolean isCapabilitySupported(final List requiredItems, final List supportedItems) { - if (requiredItems != null && !requiredItems.isEmpty()) { - if (supportedItems != null && !supportedItems.isEmpty()) { - List matches = new ArrayList<>(); - for (int requiredItem : requiredItems) { - matches.addAll(supportedItems.stream() - .filter(supportedItem -> requiredItem == supportedItem) - .collect(Collectors.toList())); - } - return matches.size() == requiredItems.size(); - } else { - return false; - } - } else { - return true; - } + 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 new file mode 100644 index 00000000000..83e4d0f1136 --- /dev/null +++ b/common/src/main/java/bisq/common/app/Capability.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.common.app; + +// 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. +// 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, + BSQ_BLOCK, + DAO_STATE +} diff --git a/common/src/main/java/bisq/common/app/DevEnv.java b/common/src/main/java/bisq/common/app/DevEnv.java index d1ed2579dc7..14429b7a3bb 100644 --- a/common/src/main/java/bisq/common/app/DevEnv.java +++ b/common/src/main/java/bisq/common/app/DevEnv.java @@ -52,10 +52,7 @@ public static void setDevMode(boolean devMode) { DevEnv.devMode = devMode; } - private static final boolean DAO_PHASE2_ACTIVATED = false; - private static final boolean DAO_TRADING_ACTIVATED = false; - - private static boolean daoActivated = false; + private static boolean daoActivated = true; public static boolean isDaoActivated() { return daoActivated; @@ -71,11 +68,7 @@ public static void logErrorAndThrowIfDevMode(String msg) { throw new RuntimeException(msg); } - public static boolean isDaoPhase2Activated() { - return DAO_PHASE2_ACTIVATED || daoActivated; - } - public static boolean isDaoTradingActivated() { - return DAO_TRADING_ACTIVATED || daoActivated; + return true; } } diff --git a/common/src/main/java/bisq/common/app/HasCapabilities.java b/common/src/main/java/bisq/common/app/HasCapabilities.java new file mode 100644 index 00000000000..9652f8825cc --- /dev/null +++ b/common/src/main/java/bisq/common/app/HasCapabilities.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.common.app; + +/** + * Holds a set of {@link Capabilities}. + * + * @author Florian Reimair + */ +public interface HasCapabilities { + + Capabilities getCapabilities(); +} diff --git a/common/src/main/java/bisq/common/app/Log.java b/common/src/main/java/bisq/common/app/Log.java index 45eae96b494..bb2268a70d6 100644 --- a/common/src/main/java/bisq/common/app/Log.java +++ b/common/src/main/java/bisq/common/app/Log.java @@ -91,26 +91,4 @@ public static void setup(String fileName) { public static void setCustomLogLevel(String pattern, Level logLevel) { ((Logger) LoggerFactory.getLogger(pattern)).setLevel(logLevel); } - - public static void traceCall() { - if (LoggerFactory.getLogger(Log.class).isTraceEnabled()) { - StackTraceElement stackTraceElement = new Throwable().getStackTrace()[1]; - String methodName = stackTraceElement.getMethodName(); - if (methodName.equals("")) - methodName = "Constructor "; - String className = stackTraceElement.getClassName(); - LoggerFactory.getLogger(className).trace("Called: {}", methodName); - } - } - - public static void traceCall(String message) { - if (LoggerFactory.getLogger(Log.class).isTraceEnabled()) { - StackTraceElement stackTraceElement = new Throwable().getStackTrace()[1]; - String methodName = stackTraceElement.getMethodName(); - if (methodName.equals("")) - methodName = "Constructor "; - String className = stackTraceElement.getClassName(); - LoggerFactory.getLogger(className).trace("Called: {} [{}]", methodName, message); - } - } } diff --git a/common/src/main/java/bisq/common/app/Version.java b/common/src/main/java/bisq/common/app/Version.java index 02a3bbab3cc..f0ba73988d3 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 = "0.9.3"; + public static final String VERSION = "1.1.2"; public static int getMajorVersion(String version) { return getSubVersion(version, 0); @@ -82,6 +82,7 @@ private static int getSubVersion(String version, int index) { // The version no. of the current protocol. The offer holds that version. // A taker will check the version of the offers to see if his version is compatible. + // Offers created with the old version will become invalid and have to be canceled. // VERSION = 0.5.0 -> TRADE_PROTOCOL_VERSION = 1 public static final int TRADE_PROTOCOL_VERSION = 1; private static int p2pMessageVersion; diff --git a/common/src/main/java/bisq/common/crypto/PGP.java b/common/src/main/java/bisq/common/crypto/PGP.java index 46b87b6f204..efccbc222bd 100644 --- a/common/src/main/java/bisq/common/crypto/PGP.java +++ b/common/src/main/java/bisq/common/crypto/PGP.java @@ -17,6 +17,8 @@ package bisq.common.crypto; +import com.google.common.base.Charsets; + import org.bouncycastle.bcpg.BCPGKey; import org.bouncycastle.bcpg.RSAPublicBCPGKey; import org.bouncycastle.openpgp.PGPException; @@ -54,7 +56,7 @@ public class PGP { @Nullable public static PGPPublicKey getPubKeyFromPem(@Nullable String pem) { if (pem != null) { - InputStream inputStream = new ByteArrayInputStream(pem.getBytes()); + InputStream inputStream = new ByteArrayInputStream(pem.getBytes(Charsets.UTF_8)); try { inputStream = PGPUtil.getDecoderStream(inputStream); try { diff --git a/common/src/main/java/bisq/common/proto/ProtoUtil.java b/common/src/main/java/bisq/common/proto/ProtoUtil.java index de2c566eb33..2cb80250bd9 100644 --- a/common/src/main/java/bisq/common/proto/ProtoUtil.java +++ b/common/src/main/java/bisq/common/proto/ProtoUtil.java @@ -69,9 +69,10 @@ public static > E enumFromProto(Class enumType, String name E result = Enums.getIfPresent(enumType, name).orNull(); if (result == null) { log.error("Invalid value for enum " + enumType.getSimpleName() + ": " + name); - // TODO returning null here can cause problems in caller. Maybe we should throw an exception? Or maybe - // better to ensure that enums have always a default value with represents an undefined state and we fall - // back to that. + result = Enums.getIfPresent(enumType, "UNDEFINED").orNull(); + log.error("We try to lookup for an enum entry with name 'UNDEFINED' and use that if available, " + + "otherwise the enum is null. enum={}", result); + return result; } return result; } diff --git a/common/src/main/java/bisq/common/proto/persistable/PersistableEnvelope.java b/common/src/main/java/bisq/common/proto/persistable/PersistableEnvelope.java index 32357d3fea2..dfab4f0b4dd 100644 --- a/common/src/main/java/bisq/common/proto/persistable/PersistableEnvelope.java +++ b/common/src/main/java/bisq/common/proto/persistable/PersistableEnvelope.java @@ -20,7 +20,7 @@ import bisq.common.Envelope; /** - * Interface for the outside envelope object persisted to disc. + * Interface for the outside envelope object persisted to disk. */ public interface PersistableEnvelope extends Envelope { } diff --git a/common/src/main/java/bisq/common/storage/FileManager.java b/common/src/main/java/bisq/common/storage/FileManager.java index 7291fb9cae5..a0f907cc9cf 100644 --- a/common/src/main/java/bisq/common/storage/FileManager.java +++ b/common/src/main/java/bisq/common/storage/FileManager.java @@ -133,7 +133,6 @@ public synchronized T read(File file) { } public synchronized void removeFile(String fileName) { - log.debug("removeFile" + fileName); File file = new File(dir, fileName); boolean result = file.delete(); if (!result) @@ -163,16 +162,21 @@ void shutDown() { } } - public synchronized void removeAndBackupFile(String fileName) throws IOException { - File corruptedBackupDir = new File(Paths.get(dir.getAbsolutePath(), "backup_of_corrupted_data").toString()); + public static void removeAndBackupFile(File dbDir, File storageFile, String fileName, String backupFolderName) + throws IOException { + File corruptedBackupDir = new File(Paths.get(dbDir.getAbsolutePath(), backupFolderName).toString()); if (!corruptedBackupDir.exists()) if (!corruptedBackupDir.mkdir()) log.warn("make dir failed"); - File corruptedFile = new File(Paths.get(dir.getAbsolutePath(), "backup_of_corrupted_data", fileName).toString()); + File corruptedFile = new File(Paths.get(dbDir.getAbsolutePath(), backupFolderName, fileName).toString()); FileUtil.renameFile(storageFile, corruptedFile); } + public synchronized void removeAndBackupFile(String fileName) throws IOException { + removeAndBackupFile(dir, storageFile, fileName, "backup_of_corrupted_data"); + } + public synchronized void backupFile(String fileName, int numMaxBackupFiles) { FileUtil.rollingBackup(dir, fileName, numMaxBackupFiles); } diff --git a/common/src/main/java/bisq/common/storage/JsonFileManager.java b/common/src/main/java/bisq/common/storage/JsonFileManager.java index d3070eea258..05532148fd9 100644 --- a/common/src/main/java/bisq/common/storage/JsonFileManager.java +++ b/common/src/main/java/bisq/common/storage/JsonFileManager.java @@ -79,6 +79,13 @@ public void writeToDisc(String json, String fileName) { printWriter = new PrintWriter(tempFile); printWriter.println(json); + // This close call and comment is borrowed from FileManager. Not 100% sure it that is really needed but + // seems that had fixed in the past and we got reported issues on Windows so that fix might be still + // required. + // Close resources before replacing file with temp file because otherwise it causes problems on windows + // when rename temp file + printWriter.close(); + FileUtil.renameFile(tempFile, jsonFile); } catch (Throwable t) { log.error("storageFile " + jsonFile.toString()); diff --git a/common/src/main/java/bisq/common/storage/Storage.java b/common/src/main/java/bisq/common/storage/Storage.java index 199f26615ba..21e5a89fb76 100644 --- a/common/src/main/java/bisq/common/storage/Storage.java +++ b/common/src/main/java/bisq/common/storage/Storage.java @@ -114,7 +114,6 @@ public void setNumMaxBackupFiles(int numMaxBackupFiles) { // Save delayed and on a background thread public void queueUpForSave(T persistable) { if (persistable != null) { - log.trace("save " + fileName); checkNotNull(storageFile, "storageFile = null. Call setupFileStorage before using read/write."); fileManager.saveLater(persistable); @@ -125,7 +124,6 @@ public void queueUpForSave(T persistable) { public void queueUpForSave(T persistable, long delayInMilli) { if (persistable != null) { - log.trace("save " + fileName); checkNotNull(storageFile, "storageFile = null. Call setupFileStorage before using read/write."); fileManager.saveLater(persistable, delayInMilli); diff --git a/common/src/main/java/bisq/common/taskrunner/TaskRunner.java b/common/src/main/java/bisq/common/taskrunner/TaskRunner.java index ce0eaab15ac..f6f6d12d2bb 100644 --- a/common/src/main/java/bisq/common/taskrunner/TaskRunner.java +++ b/common/src/main/java/bisq/common/taskrunner/TaskRunner.java @@ -82,7 +82,6 @@ public void cancel() { } void handleComplete() { - log.trace("Task completed: " + currentTask.getSimpleName()); sharedModel.persist(); next(); } diff --git a/common/src/main/java/bisq/common/util/ExtraDataMapValidator.java b/common/src/main/java/bisq/common/util/ExtraDataMapValidator.java new file mode 100644 index 00000000000..df158557165 --- /dev/null +++ b/common/src/main/java/bisq/common/util/ExtraDataMapValidator.java @@ -0,0 +1,83 @@ +/* + * 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.common.util; + +import java.util.HashMap; +import java.util.Map; + +import lombok.extern.slf4j.Slf4j; + +import javax.annotation.Nullable; + +import static com.google.common.base.Preconditions.checkArgument; + +/** + * Validator for extraDataMap fields used in network payloads. + * Ensures that we don't get the network attacked by huge data inserted there. + */ +@Slf4j +public class ExtraDataMapValidator { + // ExtraDataMap is only used for exceptional cases to not break backward compatibility. + // We don't expect many entries there. + public final static int MAX_SIZE = 10; + public final static int MAX_KEY_LENGTH = 100; + public final static int MAX_VALUE_LENGTH = 100000; // 100 kb + + public static Map getValidatedExtraDataMap(@Nullable Map extraDataMap) { + return getValidatedExtraDataMap(extraDataMap, MAX_SIZE, MAX_KEY_LENGTH, MAX_VALUE_LENGTH); + } + + public static Map getValidatedExtraDataMap(@Nullable Map extraDataMap, int maxSize, + int maxKeyLength, int maxValueLength) { + if (extraDataMap == null) + return null; + + try { + checkArgument(extraDataMap.entrySet().size() <= maxSize, + "Size of map must not exceed " + maxSize); + extraDataMap.forEach((key, value) -> { + checkArgument(key.length() <= maxKeyLength, + "Length of key must not exceed " + maxKeyLength); + checkArgument(value.length() <= maxValueLength, + "Length of value must not exceed " + maxValueLength); + }); + return extraDataMap; + } catch (Throwable t) { + return new HashMap<>(); + } + } + + public static void validate(@Nullable Map extraDataMap) { + validate(extraDataMap, MAX_SIZE, MAX_KEY_LENGTH, MAX_VALUE_LENGTH); + } + + public static void validate(@Nullable Map extraDataMap, int maxSize, int maxKeyLength, + int maxValueLength) { + if (extraDataMap == null) + return; + + checkArgument(extraDataMap.entrySet().size() <= maxSize, + "Size of map must not exceed " + maxSize); + extraDataMap.forEach((key, value) -> { + checkArgument(key.length() <= maxKeyLength, + "Length of key must not exceed " + maxKeyLength); + checkArgument(value.length() <= maxValueLength, + "Length of value must not exceed " + maxValueLength); + }); + } +} diff --git a/common/src/main/java/bisq/common/util/PermutationUtil.java b/common/src/main/java/bisq/common/util/PermutationUtil.java new file mode 100644 index 00000000000..0a84e478179 --- /dev/null +++ b/common/src/main/java/bisq/common/util/PermutationUtil.java @@ -0,0 +1,109 @@ +/* + * 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.common.util; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashSet; +import java.util.List; + +import lombok.extern.slf4j.Slf4j; + +@Slf4j +public class PermutationUtil { + + /** + * @param list Original list + * @param indicesToRemove List of indices to remove + * @param Type of List items + * @return Partial list where items at indices of indicesToRemove have been removed + */ + public static List getPartialList(List list, List indicesToRemove) { + List altered = new ArrayList<>(list); + + // Eliminate duplicates + indicesToRemove = new ArrayList<>(new HashSet<>(indicesToRemove)); + + // Sort + Collections.sort(indicesToRemove); + + // Reverse list. + // We need to remove from highest index downwards to not change order of remaining indices + Collections.reverse(indicesToRemove); + + indicesToRemove.forEach(index -> { + if (altered.size() > index && index >= 0) + altered.remove((int) index); + }); + return altered; + } + + //TODO optimize algorithm so that it starts from all objects and goes down instead starting with from the bottom. + // That should help that we are not hitting the iteration limit so easily. + /** + * Returns a list of all possible permutations of a give sorted list ignoring duplicates. + * E.g. List [A,B,C] results in this list of permutations: [[A], [B], [A,B], [C], [A,C], [B,C], [A,B,C]] + * Number of variations and iterations grows with 2^n - 1 where n is the number of items in the list. + * With 20 items we reach about 1 million iterations and it takes about 0.5 sec. + * To avoid performance issues we added the maxIterations parameter to stop once the number of iterations has + * reached the maxIterations and return in such a case the list of permutations we have been able to create. + * Depending on the type of object which is stored in the list the memory usage should be considered as well for + * choosing the right maxIterations value. + * + * @param list List from which we create permutations + * @param maxIterations Max. number of iterations including inner iterations + * @param Type of list items + * @return List of possible permutations of the original list + */ + public static List> findAllPermutations(List list, int maxIterations) { + List> result = new ArrayList<>(); + int counter = 0; + long ts = System.currentTimeMillis(); + for (T item : list) { + counter++; + if (counter > maxIterations) { + log.warn("We reached maxIterations of our allowed iterations and return current state of the result. " + + "counter={}", counter); + return result; + } + + List> subLists = new ArrayList<>(); + for (int n = 0; n < result.size(); n++) { + counter++; + if (counter > maxIterations) { + log.warn("We reached maxIterations of our allowed iterations and return current state of the result. " + + "counter={}", counter); + return result; + } + List subList = new ArrayList<>(result.get(n)); + subList.add(item); + subLists.add(subList); + } + + // add single item + result.add(new ArrayList<>(Collections.singletonList(item))); + + // add subLists + result.addAll(subLists); + } + + log.info("findAllPermutations took {} ms for {} items and {} iterations. Heap size used: {} MB", + (System.currentTimeMillis() - ts), list.size(), counter, Profiler.getUsedMemoryInMB()); + return result; + } +} diff --git a/common/src/main/java/bisq/common/util/Utilities.java b/common/src/main/java/bisq/common/util/Utilities.java index 4c8f5e81903..11c72ac8a84 100644 --- a/common/src/main/java/bisq/common/util/Utilities.java +++ b/common/src/main/java/bisq/common/util/Utilities.java @@ -155,6 +155,21 @@ public static ScheduledThreadPoolExecutor getScheduledThreadPoolExecutor(String return executor; } + /** + * @return true if defaults read -g AppleInterfaceStyle has an exit status of 0 (i.e. _not_ returning "key not found"). + */ + public static boolean isMacMenuBarDarkMode() { + try { + // check for exit status only. Once there are more modes than "dark" and "default", we might need to analyze string contents.. + Process process = Runtime.getRuntime().exec(new String[]{"defaults", "read", "-g", "AppleInterfaceStyle"}); + process.waitFor(100, TimeUnit.MILLISECONDS); + return process.exitValue() == 0; + } catch (IOException | InterruptedException | IllegalThreadStateException ex) { + // IllegalThreadStateException thrown by proc.exitValue(), if process didn't terminate + return false; + } + } + public static boolean isUnix() { return isOSX() || isLinux() || getOSName().contains("freebsd"); } @@ -171,6 +186,14 @@ public static boolean isLinux() { return getOSName().contains("linux"); } + public static boolean isDebianLinux() { + return isLinux() && new File("/etc/debian_version").isFile(); + } + + public static boolean isRedHatLinux() { + return isLinux() && new File("/etc/redhat-release").isFile(); + } + private static String getOSName() { return System.getProperty("os.name").toLowerCase(Locale.US); } @@ -489,15 +512,29 @@ public static void checkCryptoPolicySetup() throws NoSuchAlgorithmException, Lim throw new LimitedKeyStrengthException(); } + public static String toTruncatedString(Object message) { + return toTruncatedString(message, 200, true); + } + public static String toTruncatedString(Object message, int maxLength) { - if (message != null) { - return StringUtils.abbreviate(message.toString(), maxLength).replace("\n", ""); - } - return "null"; + return toTruncatedString(message, maxLength, true); } - public static String toTruncatedString(Object message) { - return toTruncatedString(message, 200); + public static String toTruncatedString(Object message, boolean removeLinebreaks) { + return toTruncatedString(message, 200, removeLinebreaks); + } + + public static String toTruncatedString(Object message, int maxLength, boolean removeLinebreaks) { + if (message == null) + return "null"; + + + String result = StringUtils.abbreviate(message.toString(), maxLength); + if (removeLinebreaks) + return result.replace("\n", ""); + + return result; + } public static String getRandomPrefix(int minLength, int maxLength) { diff --git a/common/src/main/proto/pb.proto b/common/src/main/proto/pb.proto index 6653b665363..aba03e79d81 100644 --- a/common/src/main/proto/pb.proto +++ b/common/src/main/proto/pb.proto @@ -57,6 +57,15 @@ message NetworkEnvelope { AddPersistableNetworkPayloadMessage add_persistable_network_payload_message = 31; AckMessage ack_message = 32; RepublishGovernanceDataRequest republish_governance_data_request = 33; + NewDaoStateHashMessage new_dao_state_hash_message = 34; + GetDaoStateHashesRequest get_dao_state_hashes_request = 35; + GetDaoStateHashesResponse get_dao_state_hashes_response = 36; + NewProposalStateHashMessage new_proposal_state_hash_message = 37; + GetProposalStateHashesRequest get_proposal_state_hashes_request = 38; + GetProposalStateHashesResponse get_proposal_state_hashes_response = 39; + NewBlindVoteStateHashMessage new_blind_vote_state_hash_message = 40; + GetBlindVoteStateHashesRequest get_blind_vote_state_hashes_request = 41; + GetBlindVoteStateHashesResponse get_blind_vote_state_hashes_response = 42; } } @@ -308,6 +317,8 @@ message PrivateNotificationMessage { message GetBlocksRequest { int32 from_block_height = 1; int32 nonce = 2; + NodeAddress sender_node_address = 3; + repeated int32 supported_capabilities = 4; } message GetBlocksResponse { @@ -324,6 +335,48 @@ message NewBlockBroadcastMessage { message RepublishGovernanceDataRequest { } +message NewDaoStateHashMessage { + DaoStateHash state_hash = 1; +} + +message NewProposalStateHashMessage { + ProposalStateHash state_hash = 1; +} + +message NewBlindVoteStateHashMessage { + BlindVoteStateHash state_hash = 1; +} + +message GetDaoStateHashesRequest { + int32 height = 1; + int32 nonce = 2; +} + +message GetProposalStateHashesRequest { + int32 height = 1; + int32 nonce = 2; +} + +message GetBlindVoteStateHashesRequest { + int32 height = 1; + int32 nonce = 2; +} + +message GetDaoStateHashesResponse { + repeated DaoStateHash state_hashes = 1; + int32 request_nonce = 2; +} + +message GetProposalStateHashesResponse { + repeated ProposalStateHash state_hashes = 1; + int32 request_nonce = 2; +} + +message GetBlindVoteStateHashesResponse { + repeated BlindVoteStateHash state_hashes = 1; + int32 request_nonce = 2; +} + /////////////////////////////////////////////////////////////////////////////////////////// // Payload /////////////////////////////////////////////////////////////////////////////////////////// @@ -476,6 +529,9 @@ message Filter { repeated string price_relay_nodes = 11; bool prevent_public_btc_network = 12; repeated string btc_nodes = 13; + bool disable_dao = 14; + string disable_dao_below_version = 15; + string disable_trade_below_version = 16; } // not used anymore from v0.6 on. But leave it for receiving TradeStatistics objects from older @@ -709,14 +765,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; + OKPayAccountPayload o_k_pay_account_payload = 11; // Deprecated, not used anymore 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; + CashAppAccountPayload cash_app_account_payload = 17; // Deprecated, not used anymore MoneyBeamAccountPayload money_beam_account_payload = 18; - VenmoAccountPayload venmo_account_payload = 19; + VenmoAccountPayload venmo_account_payload = 19; // Deprecated, not used anymore PopmoneyAccountPayload popmoney_account_payload = 20; RevolutAccountPayload revolut_account_payload = 21; WeChatPayAccountPayload we_chat_pay_account_payload = 22; @@ -724,6 +780,7 @@ message PaymentAccountPayload { HalCashAccountPayload hal_cash_account_payload = 24; PromptPayAccountPayload prompt_pay_account_payload = 25; AdvancedCashAccountPayload advanced_cash_account_payload = 26; + InstantCryptoCurrencyAccountPayload instant_crypto_currency_account_payload = 27; } map exclude_from_json_data = 15; } @@ -835,6 +892,10 @@ message CryptoCurrencyAccountPayload { string address = 1; } +message InstantCryptoCurrencyAccountPayload { + string address = 1; +} + message FasterPaymentsAccountPayload { string sort_code = 1; string account_nr = 2; @@ -848,6 +909,7 @@ message InteracETransferAccountPayload { string answer = 4; } +// Deprecated, not used anymore message OKPayAccountPayload { string account_nr = 1; } @@ -856,6 +918,7 @@ message UpholdAccountPayload { string account_id = 1; } +// Deprecated, not used anymore message CashAppAccountPayload { string cash_tag = 1; } @@ -864,6 +927,7 @@ message MoneyBeamAccountPayload { string account_id = 1; } +// Deprecated, not used anymore message VenmoAccountPayload { string venmo_user_name = 1; string holder_name = 2; @@ -906,7 +970,6 @@ message AdvancedCashAccountPayload { string account_nr = 1; } - /////////////////////////////////////////////////////////////////////////////////////////// // PersistableEnvelope /////////////////////////////////////////////////////////////////////////////////////////// @@ -950,6 +1013,7 @@ message PersistableEnvelope { DaoStateStore dao_state_store = 24; MyReputationList my_reputation_list = 25; MyProofOfBurnList my_proof_of_burn_list = 26; + UnconfirmedBsqChangeOutputList unconfirmed_bsq_change_output_list = 27; } } @@ -1268,7 +1332,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; + int64 buyer_security_deposit_as_long = 30; // Deprectated: Superseded by buyerSecurityDepositAsPercent bool use_animations = 31; PaymentAccount selectedPayment_account_for_createOffer = 32; bool pay_fee_in_Btc = 33; @@ -1288,6 +1352,10 @@ message PreferencesPayload { string rpc_user = 47; string rpc_pw = 48; string take_offer_selected_payment_account_id = 49; + double buyer_security_deposit_as_percent = 50; + int32 ignore_dust_threshold = 51; + double buyer_security_deposit_as_percent_for_crypto = 52; + int32 block_notify_port = 53; } /////////////////////////////////////////////////////////////////////////////////////////// @@ -1359,7 +1427,7 @@ message Tx { // Because of the way how PB implements inheritence we need to use the super class as type repeated BaseTxOutput tx_outputs = 1; TxType txType = 2; - int64 burnt_fee = 3; + int64 burnt_bsq = 3; } enum TxType { @@ -1379,6 +1447,7 @@ enum TxType { UNLOCK = 13; ASSET_LISTING_FEE = 14; PROOF_OF_BURN = 15; + IRREGULAR = 16; } message TxInput { @@ -1401,6 +1470,12 @@ message BaseTxOutput { } } +message UnconfirmedTxOutput { + int32 index = 1; + int64 value = 2; + string tx_id = 3; +} + message RawTxOutput { } @@ -1471,20 +1546,19 @@ message Cycle { repeated DaoPhase dao_phase = 2; } -message BsqState { +message DaoState { int32 chain_height = 1; // Because of the way how PB implements inheritence we need to use the super class as type repeated BaseBlock blocks = 2; repeated Cycle cycles = 3; // Because of the way how PB implements inheritence we need to use the super class as type map unspent_tx_output_map = 4; - map non_bsq_tx_output_map = 5; - map issuance_map = 6; - repeated string confiscated_lockup_tx_list = 7; - map spent_info_map = 8; - repeated ParamChange param_change_list = 9; - repeated EvaluatedProposal evaluated_proposal_list = 10; - repeated DecryptedBallotsWithMerits decrypted_ballots_with_merits_list = 11; + map issuance_map = 5; + repeated string confiscated_lockup_tx_list = 6; + map spent_info_map = 7; + repeated ParamChange param_change_list = 8; + repeated EvaluatedProposal evaluated_proposal_list = 9; + repeated DecryptedBallotsWithMerits decrypted_ballots_with_merits_list = 10; } message Issuance { @@ -1510,6 +1584,8 @@ message Proposal { GenericProposal generic_proposal = 11; RemoveAssetProposal remove_asset_proposal = 12; } + // We leave some index space here in case we add more subclasses + map extra_data = 20; } message CompensationProposal { @@ -1529,6 +1605,8 @@ message ChangeParamProposal { message RoleProposal { Role role = 1; + int64 required_bond_unit = 2; + int32 unlock_time = 3; } message ConfiscateBondProposal { @@ -1567,6 +1645,10 @@ message MyProofOfBurnList { repeated MyProofOfBurn my_proof_of_burn = 1; } +message UnconfirmedBsqChangeOutputList { + repeated UnconfirmedTxOutput unconfirmed_tx_output = 1; +} + message TempProposalPayload { Proposal proposal = 1; bytes owner_pub_key_encoded = 2; @@ -1636,6 +1718,8 @@ message BlindVote { string tx_id = 2; int64 stake = 3; bytes encrypted_merit_list = 4; + int64 date = 5; + map extra_data = 6; } message MyBlindVoteList { @@ -1648,8 +1732,7 @@ message BlindVoteStore { message BlindVotePayload { BlindVote blind_vote = 1; - int64 date = 2; - bytes hash = 3; + bytes hash = 2; } message Vote { @@ -1677,8 +1760,6 @@ message ProposalVoteResult { message EvaluatedProposal { bool is_accepted = 1; ProposalVoteResult proposal_vote_result = 2; - int64 required_quorum = 3; - int64 required_threshold = 4; } message DecryptedBallotsWithMerits { @@ -1691,7 +1772,28 @@ message DecryptedBallotsWithMerits { } message DaoStateStore { - BsqState bsq_state = 1; + DaoState dao_state = 1; + repeated DaoStateHash dao_state_hash = 2; +} + +message DaoStateHash { + int32 height = 1; + bytes hash = 2; + bytes prev_hash = 3; +} + +message ProposalStateHash { + int32 height = 1; + bytes hash = 2; + bytes prev_hash = 3; + int32 num_proposals = 4; +} + +message BlindVoteStateHash { + int32 height = 1; + bytes hash = 2; + bytes prev_hash = 3; + int32 num_blind_votes = 4; } /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/common/src/test/java/bisq/common/app/CapabilitiesTest.java b/common/src/test/java/bisq/common/app/CapabilitiesTest.java index 23e7ef83387..d0166e130c6 100644 --- a/common/src/test/java/bisq/common/app/CapabilitiesTest.java +++ b/common/src/test/java/bisq/common/app/CapabilitiesTest.java @@ -17,39 +17,47 @@ package bisq.common.app; -import java.util.Arrays; +import java.util.HashSet; import org.junit.Test; +import static bisq.common.app.Capability.*; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertTrue; public class CapabilitiesTest { @Test - public void testVersionNumber() { - // if required are null or empty its true - assertTrue(Capabilities.isCapabilitySupported(null, null)); - assertTrue(Capabilities.isCapabilitySupported(null, Arrays.asList())); - assertTrue(Capabilities.isCapabilitySupported(null, Arrays.asList(0))); - assertTrue(Capabilities.isCapabilitySupported(Arrays.asList(), null)); - assertTrue(Capabilities.isCapabilitySupported(Arrays.asList(), Arrays.asList())); - assertTrue(Capabilities.isCapabilitySupported(Arrays.asList(), Arrays.asList(0))); - - // required are not null and not empty but supported is null or empty its false - assertFalse(Capabilities.isCapabilitySupported(Arrays.asList(0), null)); - assertFalse(Capabilities.isCapabilitySupported(Arrays.asList(0), Arrays.asList())); + public void testNoCapabilitiesAvailable() { + Capabilities DUT = new Capabilities(); + + assertTrue(DUT.containsAll(new HashSet<>())); + assertFalse(DUT.containsAll(new Capabilities(SEED_NODE))); + } + + @Test + public void testO() { + Capabilities DUT = new Capabilities(TRADE_STATISTICS); + + assertTrue(DUT.containsAll(new HashSet<>())); + } + + @Test + public void testSingleMatch() { + Capabilities DUT = new Capabilities(TRADE_STATISTICS); // single match - assertTrue(Capabilities.isCapabilitySupported(Arrays.asList(0), Arrays.asList(0))); - assertFalse(Capabilities.isCapabilitySupported(Arrays.asList(1), Arrays.asList(0))); - assertFalse(Capabilities.isCapabilitySupported(Arrays.asList(0), Arrays.asList(1))); - - // multi match - assertTrue(Capabilities.isCapabilitySupported(Arrays.asList(0), Arrays.asList(0, 1))); - assertFalse(Capabilities.isCapabilitySupported(Arrays.asList(0), Arrays.asList(1, 2))); - assertTrue(Capabilities.isCapabilitySupported(Arrays.asList(0, 1), Arrays.asList(0, 1))); - assertTrue(Capabilities.isCapabilitySupported(Arrays.asList(0, 1), Arrays.asList(1, 0))); - assertFalse(Capabilities.isCapabilitySupported(Arrays.asList(0, 1), Arrays.asList(0))); + assertTrue(DUT.containsAll(new Capabilities(TRADE_STATISTICS))); + assertFalse(DUT.containsAll(new Capabilities(SEED_NODE))); + } + + @Test + public void testMultiMatch() { + Capabilities DUT = new Capabilities(TRADE_STATISTICS, TRADE_STATISTICS_2); + + assertTrue(DUT.containsAll(new Capabilities(TRADE_STATISTICS))); + assertFalse(DUT.containsAll(new Capabilities(SEED_NODE))); + assertTrue(DUT.containsAll(new Capabilities(TRADE_STATISTICS, TRADE_STATISTICS_2))); + assertFalse(DUT.containsAll(new Capabilities(SEED_NODE, TRADE_STATISTICS_2))); } } diff --git a/common/src/test/java/bisq/common/util/PermutationTest.java b/common/src/test/java/bisq/common/util/PermutationTest.java new file mode 100644 index 00000000000..149cf9c971a --- /dev/null +++ b/common/src/test/java/bisq/common/util/PermutationTest.java @@ -0,0 +1,432 @@ +/* + * 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.common.util; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.junit.Test; + +import static org.junit.Assert.assertTrue; + +public class PermutationTest { + + + @Test + public void testGetPartialList() { + String blindVote0 = "blindVote0"; + String blindVote1 = "blindVote1"; + String blindVote2 = "blindVote2"; + String blindVote3 = "blindVote3"; + String blindVote4 = "blindVote4"; + String blindVote5 = "blindVote5"; + + List list = new ArrayList<>(Arrays.asList(blindVote0, blindVote1, blindVote2, blindVote3, blindVote4, blindVote5)); + List indicesToRemove = Arrays.asList(0, 3); + List expected = new ArrayList<>(Arrays.asList(blindVote1, blindVote2, blindVote4, blindVote5)); + List result = PermutationUtil.getPartialList(list, indicesToRemove); + assertTrue(expected.toString().equals(result.toString())); + + // remove nothing + indicesToRemove = new ArrayList<>(); + expected = new ArrayList<>(list); + result = PermutationUtil.getPartialList(list, indicesToRemove); + assertTrue(expected.toString().equals(result.toString())); + + // remove first + indicesToRemove = Collections.singletonList(0); + expected = new ArrayList<>(list); + expected.remove(0); + result = PermutationUtil.getPartialList(list, indicesToRemove); + assertTrue(expected.toString().equals(result.toString())); + + // remove last + indicesToRemove = Collections.singletonList(5); + expected = new ArrayList<>(list); + expected.remove(5); + result = PermutationUtil.getPartialList(list, indicesToRemove); + assertTrue(expected.toString().equals(result.toString())); + + // remove all + indicesToRemove = Arrays.asList(0, 1, 2, 3, 4, 5); + expected = new ArrayList<>(); + result = PermutationUtil.getPartialList(list, indicesToRemove); + assertTrue(expected.toString().equals(result.toString())); + + // wrong sorting of indices + indicesToRemove = Arrays.asList(4, 0, 1); + expected = expected = new ArrayList<>(Arrays.asList(blindVote2, blindVote3, blindVote5)); + result = PermutationUtil.getPartialList(list, indicesToRemove); + assertTrue(expected.toString().equals(result.toString())); + + // wrong sorting of indices + indicesToRemove = Arrays.asList(0, 0); + expected = new ArrayList<>(Arrays.asList(blindVote1, blindVote2, blindVote3, blindVote4, blindVote5)); + result = PermutationUtil.getPartialList(list, indicesToRemove); + assertTrue(expected.toString().equals(result.toString())); + + // don't remove as invalid index + indicesToRemove = Collections.singletonList(9); + expected = new ArrayList<>(list); + result = PermutationUtil.getPartialList(list, indicesToRemove); + assertTrue(expected.toString().equals(result.toString())); + + // don't remove as invalid index + indicesToRemove = Collections.singletonList(-2); + expected = new ArrayList<>(list); + result = PermutationUtil.getPartialList(list, indicesToRemove); + assertTrue(expected.toString().equals(result.toString())); + } + + @Test + public void testFindAllPermutations() { + String blindVote0 = "blindVote0"; + String blindVote1 = "blindVote1"; + String blindVote2 = "blindVote2"; + String blindVote3 = "blindVote3"; + String blindVote4 = "blindVote4"; + + // Up to about 1M iterations performance is acceptable (0.5 sec) + // findAllPermutations took 580 ms for 20 items and 1048575 iterations + // findAllPermutations took 10 ms for 15 items and 32767 iterations + // findAllPermutations took 0 ms for 10 items and 1023 iterations + int limit = 1048575; + List list; + List> expected; + List> result; + List subList; + + + /* list = new ArrayList<>(); + for (int i = 0; i < 20; i++) { + list.add("blindVote"+i); + } + PermutationUtil.findAllPermutations(list, limit);*/ + + + list = new ArrayList<>(); + expected = new ArrayList<>(); + result = PermutationUtil.findAllPermutations(list, limit); + assertTrue(expected.toString().equals(result.toString())); + + list = new ArrayList<>(Arrays.asList(blindVote0)); + expected = new ArrayList<>(); + expected.add(list); + result = PermutationUtil.findAllPermutations(list, limit); + assertTrue(expected.toString().equals(result.toString())); + + // 2 items -> 3 variations + list = new ArrayList<>(Arrays.asList(blindVote0, blindVote1)); + expected = new ArrayList<>(); + expected.add(Arrays.asList(list.get(0))); + + expected.add(Arrays.asList(list.get(1))); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + expected.add(subList); + + result = PermutationUtil.findAllPermutations(list, limit); + assertTrue(expected.toString().equals(result.toString())); + + // 3 items -> 7 variations + list = new ArrayList<>(Arrays.asList(blindVote0, blindVote1, blindVote2)); + expected = new ArrayList<>(); + expected.add(Arrays.asList(list.get(0))); + + expected.add(Arrays.asList(list.get(1))); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + expected.add(subList); + + expected.add(Arrays.asList(list.get(2))); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(2)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(1)); + subList.add(list.get(2)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + subList.add(list.get(2)); + expected.add(subList); + + result = PermutationUtil.findAllPermutations(list, limit); + assertTrue(expected.toString().equals(result.toString())); + + // 4 items -> 15 variations + list = new ArrayList<>(Arrays.asList(blindVote0, blindVote1, blindVote2, blindVote3)); + expected = new ArrayList<>(); + expected.add(Arrays.asList(list.get(0))); + + expected.add(Arrays.asList(list.get(1))); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + expected.add(subList); + + expected.add(Arrays.asList(list.get(2))); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(2)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(1)); + subList.add(list.get(2)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + subList.add(list.get(2)); + expected.add(subList); + + expected.add(Arrays.asList(list.get(3))); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(3)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(1)); + subList.add(list.get(3)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + subList.add(list.get(3)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(2)); + subList.add(list.get(3)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(2)); + subList.add(list.get(3)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(1)); + subList.add(list.get(2)); + subList.add(list.get(3)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + subList.add(list.get(2)); + subList.add(list.get(3)); + expected.add(subList); + + result = PermutationUtil.findAllPermutations(list, limit); + assertTrue(expected.toString().equals(result.toString())); + + + // 5 items -> 31 variations + list = new ArrayList<>(Arrays.asList(blindVote0, blindVote1, blindVote2, blindVote3, blindVote4)); + expected = new ArrayList<>(); + expected.add(Arrays.asList(list.get(0))); + + expected.add(Arrays.asList(list.get(1))); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + expected.add(subList); + + expected.add(Arrays.asList(list.get(2))); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(2)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(1)); + subList.add(list.get(2)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + subList.add(list.get(2)); + expected.add(subList); + + expected.add(Arrays.asList(list.get(3))); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(3)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(1)); + subList.add(list.get(3)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + subList.add(list.get(3)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(2)); + subList.add(list.get(3)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(2)); + subList.add(list.get(3)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(1)); + subList.add(list.get(2)); + subList.add(list.get(3)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + subList.add(list.get(2)); + subList.add(list.get(3)); + expected.add(subList); + + expected.add(Arrays.asList(list.get(4))); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(1)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(2)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(2)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(1)); + subList.add(list.get(2)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + subList.add(list.get(2)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(3)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(3)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(1)); + subList.add(list.get(3)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + subList.add(list.get(3)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(2)); + subList.add(list.get(3)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(2)); + subList.add(list.get(3)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(1)); + subList.add(list.get(2)); + subList.add(list.get(3)); + subList.add(list.get(4)); + expected.add(subList); + + subList = new ArrayList<>(); + subList.add(list.get(0)); + subList.add(list.get(1)); + subList.add(list.get(2)); + subList.add(list.get(3)); + subList.add(list.get(4)); + expected.add(subList); + + result = PermutationUtil.findAllPermutations(list, limit); + assertTrue(expected.toString().equals(result.toString())); + + + } + + +} diff --git a/core/src/main/java/bisq/core/CoreModule.java b/core/src/main/java/bisq/core/CoreModule.java index db41abc2211..e22d44406ab 100644 --- a/core/src/main/java/bisq/core/CoreModule.java +++ b/core/src/main/java/bisq/core/CoreModule.java @@ -23,13 +23,13 @@ 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.network.p2p.seed.SeedNodeAddressLookup; import bisq.core.notifications.MobileMessageEncryption; import bisq.core.notifications.MobileModel; import bisq.core.notifications.MobileNotificationService; @@ -40,6 +40,7 @@ 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; @@ -80,11 +81,14 @@ 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); @@ -94,7 +98,6 @@ protected void configure() { bind(CorruptedDatabaseFilesHandler.class).in(Singleton.class); bind(AvoidStandbyModeService.class).in(Singleton.class); - bind(SeedNodeAddressLookup.class).in(Singleton.class); bind(SeedNodeRepository.class).to(DefaultSeedNodeRepository.class).in(Singleton.class); File storageDir = new File(environment.getRequiredProperty(Storage.STORAGE_DIR)); diff --git a/core/src/main/java/bisq/core/alert/Alert.java b/core/src/main/java/bisq/core/alert/Alert.java index cb2569f3901..4081b231f26 100644 --- a/core/src/main/java/bisq/core/alert/Alert.java +++ b/core/src/main/java/bisq/core/alert/Alert.java @@ -22,6 +22,7 @@ import bisq.common.app.Version; import bisq.common.crypto.Sig; +import bisq.common.util.ExtraDataMapValidator; import io.bisq.generated.protobuffer.PB; @@ -91,7 +92,7 @@ public Alert(String message, this.version = version; this.ownerPubKeyBytes = ownerPubKeyBytes; this.signatureAsBase64 = signatureAsBase64; - this.extraDataMap = extraDataMap; + this.extraDataMap = ExtraDataMapValidator.getValidatedExtraDataMap(extraDataMap); ownerPubKey = Sig.getPublicKeyFromBytes(ownerPubKeyBytes); } diff --git a/core/src/main/java/bisq/core/alert/AlertManager.java b/core/src/main/java/bisq/core/alert/AlertManager.java index 1473fc4ae2d..05a3872a7ff 100644 --- a/core/src/main/java/bisq/core/alert/AlertManager.java +++ b/core/src/main/java/bisq/core/alert/AlertManager.java @@ -34,6 +34,8 @@ import com.google.inject.Inject; import com.google.inject.name.Named; +import com.google.common.base.Charsets; + import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.SimpleObjectProperty; @@ -121,7 +123,7 @@ public boolean addAlertMessageIfKeyIsValid(Alert alert, String privKeyString) { user.setDevelopersAlert(alert); boolean result = p2PService.addProtectedStorageEntry(alert, true); if (result) { - log.trace("Add alertMessage to network was successful. AlertMessage = " + alert); + log.trace("Add alertMessage to network was successful. AlertMessage={}", alert); } } @@ -132,7 +134,7 @@ public boolean removeAlertMessageIfKeyIsValid(String privKeyString) { Alert alert = user.getDevelopersAlert(); if (isKeyValid(privKeyString) && alert != null) { if (p2PService.removeData(alert, true)) - log.trace("Remove alertMessage from network was successful. AlertMessage = " + alert); + log.trace("Remove alertMessage from network was successful. AlertMessage={}", alert); user.setDevelopersAlert(null); return true; @@ -151,13 +153,13 @@ private boolean isKeyValid(String privKeyString) { } private void signAndAddSignatureToAlertMessage(Alert alert) { - String alertMessageAsHex = Utils.HEX.encode(alert.getMessage().getBytes()); + String alertMessageAsHex = Utils.HEX.encode(alert.getMessage().getBytes(Charsets.UTF_8)); String signatureAsBase64 = alertSigningKey.signMessage(alertMessageAsHex); alert.setSigAndPubKey(signatureAsBase64, keyRing.getSignatureKeyPair().getPublic()); } private boolean verifySignature(Alert alert) { - String alertMessageAsHex = Utils.HEX.encode(alert.getMessage().getBytes()); + String alertMessageAsHex = Utils.HEX.encode(alert.getMessage().getBytes(Charsets.UTF_8)); try { ECKey.fromPublicOnly(HEX.decode(pubKeyAsHex)).verifyMessage(alertMessageAsHex, alert.getSignatureAsBase64()); return true; diff --git a/core/src/main/java/bisq/core/alert/PrivateNotificationManager.java b/core/src/main/java/bisq/core/alert/PrivateNotificationManager.java index a10a275f56d..529f4b7ed55 100644 --- a/core/src/main/java/bisq/core/alert/PrivateNotificationManager.java +++ b/core/src/main/java/bisq/core/alert/PrivateNotificationManager.java @@ -35,6 +35,8 @@ import com.google.inject.Inject; import com.google.inject.name.Named; +import com.google.common.base.Charsets; + import javafx.beans.property.ObjectProperty; import javafx.beans.property.ReadOnlyObjectProperty; import javafx.beans.property.SimpleObjectProperty; @@ -145,13 +147,13 @@ private boolean isKeyValid(String privKeyString) { } private void signAndAddSignatureToPrivateNotificationMessage(PrivateNotificationPayload privateNotification) { - String privateNotificationMessageAsHex = Utils.HEX.encode(privateNotification.getMessage().getBytes()); + String privateNotificationMessageAsHex = Utils.HEX.encode(privateNotification.getMessage().getBytes(Charsets.UTF_8)); String signatureAsBase64 = privateNotificationSigningKey.signMessage(privateNotificationMessageAsHex); privateNotification.setSigAndPubKey(signatureAsBase64, keyRing.getSignatureKeyPair().getPublic()); } private boolean verifySignature(PrivateNotificationPayload privateNotification) { - String privateNotificationMessageAsHex = Utils.HEX.encode(privateNotification.getMessage().getBytes()); + String privateNotificationMessageAsHex = Utils.HEX.encode(privateNotification.getMessage().getBytes(Charsets.UTF_8)); try { ECKey.fromPublicOnly(HEX.decode(pubKeyAsHex)).verifyMessage(privateNotificationMessageAsHex, privateNotification.getSignatureAsBase64()); return true; diff --git a/core/src/main/java/bisq/core/app/BisqEnvironment.java b/core/src/main/java/bisq/core/app/BisqEnvironment.java index d40e3bcc232..4c7afa5d49d 100644 --- a/core/src/main/java/bisq/core/app/BisqEnvironment.java +++ b/core/src/main/java/bisq/core/app/BisqEnvironment.java @@ -25,9 +25,9 @@ import bisq.core.filter.FilterManager; import bisq.network.NetworkOptionKeys; +import bisq.network.p2p.network.ConnectionConfig; import bisq.common.CommonOptionKeys; -import bisq.common.app.DevEnv; import bisq.common.app.Version; import bisq.common.crypto.KeyStorage; import bisq.common.storage.Storage; @@ -58,6 +58,7 @@ import java.io.FileOutputStream; import java.io.IOException; +import java.util.ArrayList; import java.util.Arrays; import java.util.List; import java.util.Properties; @@ -109,15 +110,6 @@ public static BaseCurrencyNetwork getDefaultBaseCurrencyNetwork() { protected static BaseCurrencyNetwork baseCurrencyNetwork = getDefaultBaseCurrencyNetwork(); - public static boolean isDAOActivatedAndBaseCurrencySupportingBsq() { - //noinspection ConstantConditions,PointlessBooleanExpression - return DevEnv.isDaoActivated() && isBaseCurrencySupportingBsq(); - } - - public static boolean isBaseCurrencySupportingBsq() { - return getBaseCurrencyNetwork().getCurrencyCode().equals("BTC"); - } - public static NetworkParameters getParameters() { return getBaseCurrencyNetwork().getParameters(); } @@ -174,10 +166,9 @@ private static String appDataDir(String userDataDir, String appName) { // Util to set isDaoActivated to true if either set as program argument or we run testnet or regtest. // Can be removed once DAO is live. public static boolean isDaoActivated(Environment environment) { - Boolean daoActivatedFromOptions = environment.getProperty(DaoOptionKeys.DAO_ACTIVATED, Boolean.class, false); + Boolean daoActivatedFromOptions = environment.getProperty(DaoOptionKeys.DAO_ACTIVATED, Boolean.class, true); BaseCurrencyNetwork baseCurrencyNetwork = BisqEnvironment.getBaseCurrencyNetwork(); - boolean isRegTestOrTestNet = (baseCurrencyNetwork.isTestnet() || baseCurrencyNetwork.isRegtest()); - return daoActivatedFromOptions || isRegTestOrTestNet; + return daoActivatedFromOptions || !baseCurrencyNetwork.isMainnet(); } @@ -202,9 +193,10 @@ public static boolean isDaoActivated(Environment environment) { protected final String btcNodes, seedNodes, ignoreDevMsg, useDevPrivilegeKeys, useDevMode, useTorForBtc, rpcUser, rpcPassword, rpcPort, rpcBlockNotificationPort, dumpBlockchainData, fullDaoNode, - myAddress, banList, dumpStatistics, maxMemory, socks5ProxyBtcAddress, + banList, dumpStatistics, maxMemory, socks5ProxyBtcAddress, torRcFile, torRcOptions, externalTorControlPort, externalTorPassword, externalTorCookieFile, - socks5ProxyHttpAddress, useAllProvidedNodes, numConnectionForBtc, genesisTxId, genesisBlockHeight, referralId, daoActivated; + socks5ProxyHttpAddress, useAllProvidedNodes, numConnectionForBtc, genesisTxId, genesisBlockHeight, genesisTotalSupply, + referralId, daoActivated, msgThrottlePerSec, msgThrottlePer10Sec, sendMsgThrottleTrigger, sendMsgThrottleSleep; protected final boolean externalTorUseSafeCookieAuthentication, torStreamIsolation; @@ -267,9 +259,6 @@ public BisqEnvironment(PropertySource commandLineProperties) { (String) commandLineProperties.getProperty(NetworkOptionKeys.SEED_NODES_KEY) : ""; - myAddress = commandLineProperties.containsProperty(NetworkOptionKeys.MY_ADDRESS) ? - (String) commandLineProperties.getProperty(NetworkOptionKeys.MY_ADDRESS) : - ""; banList = commandLineProperties.containsProperty(NetworkOptionKeys.BAN_LIST) ? (String) commandLineProperties.getProperty(NetworkOptionKeys.BAN_LIST) : ""; @@ -294,12 +283,20 @@ public BisqEnvironment(PropertySource commandLineProperties) { externalTorCookieFile = commandLineProperties.containsProperty(NetworkOptionKeys.EXTERNAL_TOR_COOKIE_FILE) ? (String) commandLineProperties.getProperty(NetworkOptionKeys.EXTERNAL_TOR_COOKIE_FILE) : ""; - externalTorUseSafeCookieAuthentication = commandLineProperties.containsProperty(NetworkOptionKeys.EXTERNAL_TOR_USE_SAFECOOKIE) ? - true : - false; - torStreamIsolation = commandLineProperties.containsProperty(NetworkOptionKeys.TOR_STREAM_ISOLATION) ? - true : - false; + externalTorUseSafeCookieAuthentication = commandLineProperties.containsProperty(NetworkOptionKeys.EXTERNAL_TOR_USE_SAFECOOKIE); + torStreamIsolation = commandLineProperties.containsProperty(NetworkOptionKeys.TOR_STREAM_ISOLATION); + msgThrottlePerSec = commandLineProperties.containsProperty(NetworkOptionKeys.MSG_THROTTLE_PER_SEC) ? + (String) commandLineProperties.getProperty(NetworkOptionKeys.MSG_THROTTLE_PER_SEC) : + String.valueOf(ConnectionConfig.MSG_THROTTLE_PER_SEC); + msgThrottlePer10Sec = commandLineProperties.containsProperty(NetworkOptionKeys.MSG_THROTTLE_PER_10_SEC) ? + (String) commandLineProperties.getProperty(NetworkOptionKeys.MSG_THROTTLE_PER_10_SEC) : + String.valueOf(ConnectionConfig.MSG_THROTTLE_PER_10_SEC); + sendMsgThrottleTrigger = commandLineProperties.containsProperty(NetworkOptionKeys.SEND_MSG_THROTTLE_TRIGGER) ? + (String) commandLineProperties.getProperty(NetworkOptionKeys.SEND_MSG_THROTTLE_TRIGGER) : + String.valueOf(ConnectionConfig.SEND_MSG_THROTTLE_TRIGGER); + sendMsgThrottleSleep = commandLineProperties.containsProperty(NetworkOptionKeys.SEND_MSG_THROTTLE_SLEEP) ? + (String) commandLineProperties.getProperty(NetworkOptionKeys.SEND_MSG_THROTTLE_SLEEP) : + String.valueOf(ConnectionConfig.SEND_MSG_THROTTLE_SLEEP); //RpcOptionKeys rpcUser = commandLineProperties.containsProperty(DaoOptionKeys.RPC_USER) ? @@ -326,9 +323,12 @@ public BisqEnvironment(PropertySource commandLineProperties) { genesisBlockHeight = commandLineProperties.containsProperty(DaoOptionKeys.GENESIS_BLOCK_HEIGHT) ? (String) commandLineProperties.getProperty(DaoOptionKeys.GENESIS_BLOCK_HEIGHT) : "-1"; + genesisTotalSupply = commandLineProperties.containsProperty(DaoOptionKeys.GENESIS_TOTAL_SUPPLY) ? + (String) commandLineProperties.getProperty(DaoOptionKeys.GENESIS_TOTAL_SUPPLY) : + "-1"; daoActivated = commandLineProperties.containsProperty(DaoOptionKeys.DAO_ACTIVATED) ? (String) commandLineProperties.getProperty(DaoOptionKeys.DAO_ACTIVATED) : - ""; + "true"; btcNodes = commandLineProperties.containsProperty(BtcOptionKeys.BTC_NODES) ? (String) commandLineProperties.getProperty(BtcOptionKeys.BTC_NODES) : @@ -356,7 +356,7 @@ public BisqEnvironment(PropertySource commandLineProperties) { bannedPriceRelayNodes = !bannedPriceRelayNodesAsString.isEmpty() ? Arrays.asList(StringUtils.deleteWhitespace(bannedPriceRelayNodesAsString).split(",")) : null; final String bannedSeedNodesAsString = getProperty(FilterManager.BANNED_SEED_NODES, ""); - bannedSeedNodes = !bannedSeedNodesAsString.isEmpty() ? Arrays.asList(StringUtils.deleteWhitespace(bannedSeedNodesAsString).split(",")) : null; + bannedSeedNodes = !bannedSeedNodesAsString.isEmpty() ? Arrays.asList(StringUtils.deleteWhitespace(bannedSeedNodesAsString).split(",")) : new ArrayList<>(); final String bannedBtcNodesAsString = getProperty(FilterManager.BANNED_BTC_NODES, ""); bannedBtcNodes = !bannedBtcNodesAsString.isEmpty() ? Arrays.asList(StringUtils.deleteWhitespace(bannedBtcNodesAsString).split(",")) : null; @@ -462,7 +462,6 @@ private PropertySource defaultProperties() { setProperty(CommonOptionKeys.USE_DEV_MODE, useDevMode); setProperty(NetworkOptionKeys.SEED_NODES_KEY, seedNodes); - setProperty(NetworkOptionKeys.MY_ADDRESS, myAddress); setProperty(NetworkOptionKeys.BAN_LIST, banList); setProperty(NetworkOptionKeys.TOR_DIR, Paths.get(btcNetworkDir, "tor").toString()); setProperty(NetworkOptionKeys.NETWORK_ID, String.valueOf(baseCurrencyNetwork.ordinal())); @@ -478,6 +477,11 @@ private PropertySource defaultProperties() { if (torStreamIsolation) setProperty(NetworkOptionKeys.TOR_STREAM_ISOLATION, "true"); + setProperty(NetworkOptionKeys.MSG_THROTTLE_PER_SEC, msgThrottlePerSec); + setProperty(NetworkOptionKeys.MSG_THROTTLE_PER_10_SEC, msgThrottlePer10Sec); + setProperty(NetworkOptionKeys.SEND_MSG_THROTTLE_TRIGGER, sendMsgThrottleTrigger); + setProperty(NetworkOptionKeys.SEND_MSG_THROTTLE_SLEEP, sendMsgThrottleSleep); + setProperty(AppOptionKeys.APP_DATA_DIR_KEY, appDataDir); setProperty(AppOptionKeys.DESKTOP_WITH_HTTP_API, desktopWithHttpApi); setProperty(AppOptionKeys.DESKTOP_WITH_GRPC_API, desktopWithGrpcApi); @@ -498,6 +502,7 @@ private PropertySource defaultProperties() { setProperty(DaoOptionKeys.FULL_DAO_NODE, fullDaoNode); setProperty(DaoOptionKeys.GENESIS_TX_ID, genesisTxId); setProperty(DaoOptionKeys.GENESIS_BLOCK_HEIGHT, genesisBlockHeight); + setProperty(DaoOptionKeys.GENESIS_TOTAL_SUPPLY, genesisTotalSupply); setProperty(DaoOptionKeys.DAO_ACTIVATED, daoActivated); setProperty(BtcOptionKeys.BTC_NODES, btcNodes); diff --git a/core/src/main/java/bisq/core/app/BisqExecutable.java b/core/src/main/java/bisq/core/app/BisqExecutable.java index 9050763edaa..b2a8ee122e7 100644 --- a/core/src/main/java/bisq/core/app/BisqExecutable.java +++ b/core/src/main/java/bisq/core/app/BisqExecutable.java @@ -33,6 +33,7 @@ import bisq.network.NetworkOptionKeys; import bisq.network.p2p.P2PService; +import bisq.network.p2p.network.ConnectionConfig; import bisq.common.CommonOptionKeys; import bisq.common.UserThread; @@ -68,9 +69,7 @@ import static bisq.core.app.BisqEnvironment.DEFAULT_APP_NAME; import static bisq.core.app.BisqEnvironment.DEFAULT_USER_DATA_DIR; -import static bisq.core.btc.BaseCurrencyNetwork.BTC_MAINNET; -import static bisq.core.btc.BaseCurrencyNetwork.BTC_REGTEST; -import static bisq.core.btc.BaseCurrencyNetwork.BTC_TESTNET; +import static bisq.core.btc.BaseCurrencyNetwork.*; import static com.google.common.base.Preconditions.checkNotNull; import static java.lang.String.format; @@ -256,7 +255,7 @@ protected void setupPersistedDataHosts(Injector injector) { // 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()); + log.error("Error at PersistedDataHost.apply: {}", t.toString()); throw t; }, 2); } @@ -339,11 +338,6 @@ protected void customizeOptionParsing(OptionParser parser) { .withRequiredArg() .describedAs("host:port[,...]"); - parser.accepts(NetworkOptionKeys.MY_ADDRESS, - "My own onion address (used for bootstrap nodes to exclude itself)") - .withRequiredArg() - .describedAs("host:port"); - parser.accepts(NetworkOptionKeys.BAN_LIST, "Nodes to exclude from network connections.") .withRequiredArg() @@ -415,6 +409,27 @@ protected void customizeOptionParsing(OptionParser parser) { parser.accepts(NetworkOptionKeys.TOR_STREAM_ISOLATION, "Use stream isolation for Tor [experimental!]."); + parser.accepts(NetworkOptionKeys.MSG_THROTTLE_PER_SEC, + format("Message throttle per sec for connection class (default: %s)", + String.valueOf(ConnectionConfig.MSG_THROTTLE_PER_SEC))) + .withRequiredArg() + .ofType(int.class); + parser.accepts(NetworkOptionKeys.MSG_THROTTLE_PER_10_SEC, + format("Message throttle per 10 sec for connection class (default: %s)", + String.valueOf(ConnectionConfig.MSG_THROTTLE_PER_10_SEC))) + .withRequiredArg() + .ofType(int.class); + parser.accepts(NetworkOptionKeys.SEND_MSG_THROTTLE_TRIGGER, + format("Time in ms when we trigger a sleep if 2 messages are sent (default: %s)", + String.valueOf(ConnectionConfig.SEND_MSG_THROTTLE_TRIGGER))) + .withRequiredArg() + .ofType(int.class); + parser.accepts(NetworkOptionKeys.SEND_MSG_THROTTLE_SLEEP, + format("Pause in ms to sleep if we get too many messages to send (default: %s)", + String.valueOf(ConnectionConfig.SEND_MSG_THROTTLE_SLEEP))) + .withRequiredArg() + .ofType(int.class); + //AppOptionKeys parser.accepts(AppOptionKeys.USER_DATA_DIR_KEY, format("User data directory (default: %s)", BisqEnvironment.DEFAULT_USER_DATA_DIR)) @@ -479,7 +494,7 @@ protected void customizeOptionParsing(OptionParser parser) { format("Base currency network (default: %s)", BisqEnvironment.getDefaultBaseCurrencyNetwork().name())) .withRequiredArg() .ofType(String.class) - .describedAs(format("%s|%s|%s", BTC_MAINNET, BTC_TESTNET, BTC_REGTEST)); + .describedAs(format("%s|%s|%s|%s", BTC_MAINNET, BTC_TESTNET, BTC_REGTEST, BTC_DAO_TESTNET, BTC_DAO_BETANET, BTC_DAO_REGTEST)); parser.accepts(BtcOptionKeys.REG_TEST_HOST, format("Bitcoin regtest host when using BTC_REGTEST network (default: %s)", RegTestHost.DEFAULT_HOST)) @@ -550,8 +565,12 @@ protected void customizeOptionParsing(OptionParser parser) { format("Genesis transaction block height when not using the hard coded one (default: %s)", "-1")) .withRequiredArg(); + parser.accepts(DaoOptionKeys.GENESIS_TOTAL_SUPPLY, + format("Genesis total supply when not using the hard coded one (default: %s)", "-1")) + .withRequiredArg(); + parser.accepts(DaoOptionKeys.DAO_ACTIVATED, - format("Developer flag. If true it enables dao phase 2 features. (default: %s)", "false")) + format("Developer flag. If true it enables dao phase 2 features. (default: %s)", "true")) .withRequiredArg() .ofType(boolean.class); } diff --git a/core/src/main/java/bisq/core/app/BisqHeadlessApp.java b/core/src/main/java/bisq/core/app/BisqHeadlessApp.java index 3bb23f40f2b..f7ece906fb7 100644 --- a/core/src/main/java/bisq/core/app/BisqHeadlessApp.java +++ b/core/src/main/java/bisq/core/app/BisqHeadlessApp.java @@ -78,26 +78,26 @@ protected void setupHandlers() { log.info("onDisplayTacHandler: We accept the tacs automatically in headless mode"); acceptedHandler.run(); }); - bisqSetup.setCryptoSetupFailedHandler(msg -> log.info("onCryptoSetupFailedHandler: msg={}", msg)); + bisqSetup.setCryptoSetupFailedHandler(msg -> log.error("onCryptoSetupFailedHandler: msg={}", msg)); bisqSetup.setDisplayTorNetworkSettingsHandler(show -> log.info("onDisplayTorNetworkSettingsHandler: show={}", show)); - bisqSetup.setSpvFileCorruptedHandler(msg -> log.info("onSpvFileCorruptedHandler: msg={}", msg)); - bisqSetup.setChainFileLockedExceptionHandler(msg -> log.info("onChainFileLockedExceptionHandler: msg={}", msg)); + bisqSetup.setSpvFileCorruptedHandler(msg -> log.error("onSpvFileCorruptedHandler: msg={}", msg)); + bisqSetup.setChainFileLockedExceptionHandler(msg -> log.error("onChainFileLockedExceptionHandler: msg={}", msg)); bisqSetup.setLockedUpFundsHandler(msg -> log.info("onLockedUpFundsHandler: msg={}", msg)); bisqSetup.setShowFirstPopupIfResyncSPVRequestedHandler(() -> log.info("onShowFirstPopupIfResyncSPVRequestedHandler")); bisqSetup.setRequestWalletPasswordHandler(aesKeyHandler -> log.info("onRequestWalletPasswordHandler")); bisqSetup.setDisplayUpdateHandler((alert, key) -> log.info("onDisplayUpdateHandler")); bisqSetup.setDisplayAlertHandler(alert -> log.info("onDisplayAlertHandler. alert={}", alert)); bisqSetup.setDisplayPrivateNotificationHandler(privateNotification -> log.info("onDisplayPrivateNotificationHandler. privateNotification={}", privateNotification)); - bisqSetup.setDaoErrorMessageHandler(errorMessage -> log.info("onDaoErrorMessageHandler. errorMessage={}", errorMessage)); - bisqSetup.setDaoWarnMessageHandler(warnMessage -> log.info("onDaoWarnMessageHandler. warnMessage={}", warnMessage)); + bisqSetup.setDaoErrorMessageHandler(errorMessage -> log.error("onDaoErrorMessageHandler. errorMessage={}", errorMessage)); + bisqSetup.setDaoWarnMessageHandler(warnMessage -> log.warn("onDaoWarnMessageHandler. warnMessage={}", warnMessage)); bisqSetup.setDisplaySecurityRecommendationHandler(key -> log.info("onDisplaySecurityRecommendationHandler")); bisqSetup.setDisplayLocalhostHandler(key -> log.info("onDisplayLocalhostHandler")); - bisqSetup.setWrongOSArchitectureHandler(msg -> log.info("onWrongOSArchitectureHandler. msg={}", msg)); - bisqSetup.setVoteResultExceptionHandler(voteResultException -> log.info("voteResultException={}", voteResultException)); + bisqSetup.setWrongOSArchitectureHandler(msg -> log.error("onWrongOSArchitectureHandler. msg={}", msg)); + bisqSetup.setVoteResultExceptionHandler(voteResultException -> log.warn("voteResultException={}", voteResultException)); //TODO move to bisqSetup - corruptedDatabaseFilesHandler.getCorruptedDatabaseFiles().ifPresent(files -> log.info("getCorruptedDatabaseFiles. files={}", files)); - tradeManager.setTakeOfferRequestErrorMessageHandler(errorMessage -> log.info("onTakeOfferRequestErrorMessageHandler")); + corruptedDatabaseFilesHandler.getCorruptedDatabaseFiles().ifPresent(files -> log.warn("getCorruptedDatabaseFiles. files={}", files)); + tradeManager.setTakeOfferRequestErrorMessageHandler(errorMessage -> log.error("onTakeOfferRequestErrorMessageHandler")); } public void stop() { diff --git a/core/src/main/java/bisq/core/app/BisqSetup.java b/core/src/main/java/bisq/core/app/BisqSetup.java index cb8e6aa997e..26cc912e6c7 100644 --- a/core/src/main/java/bisq/core/app/BisqSetup.java +++ b/core/src/main/java/bisq/core/app/BisqSetup.java @@ -43,7 +43,7 @@ import bisq.core.offer.OpenOfferManager; import bisq.core.payment.AccountAgeWitnessService; import bisq.core.payment.PaymentAccount; -import bisq.core.payment.payload.PaymentMethod; +import bisq.core.payment.TradeLimits; import bisq.core.provider.fee.FeeService; import bisq.core.provider.price.PriceFeedService; import bisq.core.trade.TradeManager; @@ -150,6 +150,8 @@ public interface BisqSetupCompleteListener { private final VoteResultService voteResultService; private final AssetTradeActivityCheck tradeActivityCheck; private final AssetService assetService; + private final TorSetup torSetup; + private final TradeLimits tradeLimits; private final BSFormatter formatter; @Setter @Nullable @@ -226,6 +228,8 @@ public BisqSetup(P2PNetworkSetup p2PNetworkSetup, VoteResultService voteResultService, AssetTradeActivityCheck tradeActivityCheck, AssetService assetService, + TorSetup torSetup, + TradeLimits tradeLimits, BSFormatter formatter) { @@ -264,6 +268,8 @@ public BisqSetup(P2PNetworkSetup p2PNetworkSetup, this.voteResultService = voteResultService; this.tradeActivityCheck = tradeActivityCheck; this.assetService = assetService; + this.torSetup = torSetup; + this.tradeLimits = tradeLimits; this.formatter = formatter; } @@ -286,6 +292,7 @@ private void step2() { } private void step3() { + torSetup.cleanupTorFiles(); readMapsFromResources(); checkCryptoSetup(); checkForCorrectOSArchitecture(); @@ -351,6 +358,10 @@ public StringProperty getBtcSplashSyncIconId() { return walletAppSetup.getBtcSplashSyncIconId(); } + public BooleanProperty getUseTorForBTC() { + return walletAppSetup.getUseTorForBTC(); + } + // P2P public StringProperty getP2PNetworkInfo() { return p2PNetworkSetup.getP2PNetworkInfo(); @@ -406,30 +417,35 @@ private void maybeShowTac() { } private void checkIfLocalHostNodeIsRunning() { - Thread checkIfLocalHostNodeIsRunningThread = new Thread(() -> { - Thread.currentThread().setName("checkIfLocalHostNodeIsRunningThread"); - Socket socket = null; - try { - socket = new Socket(); - socket.connect(new InetSocketAddress(InetAddresses.forString("127.0.0.1"), - BisqEnvironment.getBaseCurrencyNetwork().getParameters().getPort()), 5000); - log.info("Localhost Bitcoin node detected."); - UserThread.execute(() -> { - bisqEnvironment.setBitcoinLocalhostNodeRunning(true); - step3(); - }); - } catch (Throwable e) { - UserThread.execute(BisqSetup.this::step3); - } finally { - if (socket != null) { - try { - socket.close(); - } catch (IOException ignore) { + // For DAO testnet we ignore local btc node + if (BisqEnvironment.getBaseCurrencyNetwork().isDaoRegTest() || BisqEnvironment.getBaseCurrencyNetwork().isDaoTestNet()) { + step3(); + } else { + Thread checkIfLocalHostNodeIsRunningThread = new Thread(() -> { + Thread.currentThread().setName("checkIfLocalHostNodeIsRunningThread"); + Socket socket = null; + try { + socket = new Socket(); + socket.connect(new InetSocketAddress(InetAddresses.forString("127.0.0.1"), + BisqEnvironment.getBaseCurrencyNetwork().getParameters().getPort()), 5000); + log.info("Localhost Bitcoin node detected."); + UserThread.execute(() -> { + bisqEnvironment.setBitcoinLocalhostNodeRunning(true); + step3(); + }); + } catch (Throwable e) { + UserThread.execute(BisqSetup.this::step3); + } finally { + if (socket != null) { + try { + socket.close(); + } catch (IOException ignore) { + } } } - } - }); - checkIfLocalHostNodeIsRunningThread.start(); + }); + checkIfLocalHostNodeIsRunningThread.start(); + } } private void readMapsFromResources() { @@ -448,7 +464,6 @@ private void checkCryptoSetup() { Thread checkCryptoThread = new Thread(() -> { try { Thread.currentThread().setName("checkCryptoThread"); - log.trace("Run crypto test"); // just use any simple dummy msg Ping payload = new Ping(1, 1); SealedAndSigned sealedAndSigned = EncryptionService.encryptHybridWithSignature(payload, @@ -480,6 +495,11 @@ private void startP2pNetworkAndWallet() { }; Timer startupTimeout = UserThread.runAfter(() -> { + if (p2PNetworkSetup.p2pNetworkFailed.get()) { + // Skip this timeout action if the p2p network setup failed + // since a p2p network error prompt will be shown containing the error message + return; + } log.warn("startupTimeout called"); if (walletsManager.areWalletsEncrypted()) walletInitialized.addListener(walletInitializedListener); @@ -579,7 +599,7 @@ private void initDomainServices() { clock.start(); - PaymentMethod.onAllServicesInitialized(); + tradeLimits.onAllServicesInitialized(); disputeManager.onAllServicesInitialized(); @@ -629,11 +649,28 @@ private void initDomainServices() { filterManager.onAllServicesInitialized(); filterManager.addListener(filter -> { if (filter != null && filterWarningHandler != null) { - if (filter.getSeedNodes() != null && !filter.getSeedNodes().isEmpty()) - filterWarningHandler.accept(Res.get("popup.warning.nodeBanned", Res.get("popup.warning.seed"))); + if (filter.getSeedNodes() != null && !filter.getSeedNodes().isEmpty()) { + log.warn(Res.get("popup.warning.nodeBanned", Res.get("popup.warning.seed"))); + // Lets keep that more silent. Might be used in case a node is unstable and we don't want to confuse users. + // filterWarningHandler.accept(Res.get("popup.warning.nodeBanned", Res.get("popup.warning.seed"))); + } + + if (filter.getPriceRelayNodes() != null && !filter.getPriceRelayNodes().isEmpty()) { + log.warn(Res.get("popup.warning.nodeBanned", Res.get("popup.warning.priceRelay"))); + // Lets keep that more silent. Might be used in case a node is unstable and we don't want to confuse users. + // filterWarningHandler.accept(Res.get("popup.warning.nodeBanned", Res.get("popup.warning.priceRelay"))); + } - if (filter.getPriceRelayNodes() != null && !filter.getPriceRelayNodes().isEmpty()) - filterWarningHandler.accept(Res.get("popup.warning.nodeBanned", Res.get("popup.warning.priceRelay"))); + if (filterManager.requireUpdateToNewVersionForTrading()) { + filterWarningHandler.accept(Res.get("popup.warning.mandatoryUpdate.trading")); + } + + if (filterManager.requireUpdateToNewVersionForDAO()) { + filterWarningHandler.accept(Res.get("popup.warning.mandatoryUpdate.dao")); + } + if (filter.isDisableDao()) { + filterWarningHandler.accept(Res.get("popup.warning.disable.dao")); + } } }); diff --git a/core/src/main/java/bisq/core/app/P2PNetworkSetup.java b/core/src/main/java/bisq/core/app/P2PNetworkSetup.java index 8d70bf8bdca..cbcda4bb3af 100644 --- a/core/src/main/java/bisq/core/app/P2PNetworkSetup.java +++ b/core/src/main/java/bisq/core/app/P2PNetworkSetup.java @@ -65,6 +65,8 @@ public class P2PNetworkSetup { final StringProperty p2pNetworkWarnMsg = new SimpleStringProperty(); @Getter final BooleanProperty updatedDataReceived = new SimpleBooleanProperty(); + @Getter + final BooleanProperty p2pNetworkFailed = new SimpleBooleanProperty(); @Inject public P2PNetworkSetup(PriceFeedService priceFeedService, @@ -85,6 +87,7 @@ BooleanProperty init(Runnable initWalletServiceHandler, @Nullable Consumer { String result; + String daoFullNode = preferences.isDaoFullNode() ? Res.get("mainView.footer.daoFullNode") + " / " : ""; int peers = (int) numPeers; if (warning != null && peers == 0) { result = warning; @@ -97,7 +100,7 @@ BooleanProperty init(Runnable initWalletServiceHandler, @Nullable Consumer { p2PNetworkInfo.set(newValue); @@ -194,11 +197,12 @@ public void onUpdatedDataReceived() { @Override public void onSetupFailed(Throwable throwable) { - log.warn("onSetupFailed"); + log.error("onSetupFailed"); p2pNetworkWarnMsg.set(Res.get("mainView.p2pNetworkWarnMsg.connectionToP2PFailed", throwable.getMessage())); splashP2PNetworkAnimationVisible.set(false); bootstrapWarning.set(Res.get("mainView.bootstrapWarning.bootstrappingToP2PFailed")); p2pNetworkLabelId.set("splash-error-state-msg"); + p2pNetworkFailed.set(true); } @Override diff --git a/core/src/main/java/bisq/core/app/SetupUtils.java b/core/src/main/java/bisq/core/app/SetupUtils.java index c7cf8cafa3c..f3bfcd9fccd 100644 --- a/core/src/main/java/bisq/core/app/SetupUtils.java +++ b/core/src/main/java/bisq/core/app/SetupUtils.java @@ -54,7 +54,6 @@ public static void checkCryptoSetup(KeyRing keyRing, EncryptionService encryptio public void run() { try { Thread.currentThread().setName("checkCryptoThread"); - log.trace("Run crypto test"); // just use any simple dummy msg Ping payload = new Ping(1, 1); SealedAndSigned sealedAndSigned = EncryptionService.encryptHybridWithSignature(payload, @@ -86,8 +85,7 @@ public static BooleanProperty readFromResources(P2PDataStorage p2PDataStorage) { Thread.currentThread().setName("readFromResourcesThread"); // Used to load different files per base currency (EntryMap_BTC_MAINNET, EntryMap_LTC,...) final BaseCurrencyNetwork baseCurrencyNetwork = BisqEnvironment.getBaseCurrencyNetwork(); - final String postFix = "_" + baseCurrencyNetwork.getCurrencyCode() + "_" - + baseCurrencyNetwork.getNetwork(); + final String postFix = "_" + baseCurrencyNetwork.name(); long ts = new Date().getTime(); p2PDataStorage.readFromResources(postFix); log.info("readFromResources took {} ms", (new Date().getTime() - ts)); diff --git a/core/src/main/java/bisq/core/app/TorSetup.java b/core/src/main/java/bisq/core/app/TorSetup.java new file mode 100644 index 00000000000..238e23e97a4 --- /dev/null +++ b/core/src/main/java/bisq/core/app/TorSetup.java @@ -0,0 +1,69 @@ +/* + * 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.app; + +import bisq.network.NetworkOptionKeys; + +import bisq.common.handlers.ErrorMessageHandler; +import bisq.common.storage.FileUtil; + +import com.google.inject.name.Named; + +import javax.inject.Inject; + +import java.nio.file.Paths; + +import java.io.File; +import java.io.IOException; + +import lombok.extern.slf4j.Slf4j; + +import javax.annotation.Nullable; + +@Slf4j +public class TorSetup { + private File torDir; + + @Inject + public TorSetup(@Named(NetworkOptionKeys.TOR_DIR) File torDir) { + this.torDir = torDir; + } + + public void cleanupTorFiles() { + cleanupTorFiles(null, null); + } + + // We get sometimes Tor startup problems which is related to some tor files in the tor directory. It happens + // more often if the application got killed (not graceful shutdown). + // Creating all tor files newly takes about 3-4 sec. longer and it does not benefit from cache files. + // TODO: We should fix those startup problems in the netlayer library, once fixed there we can remove that call at the + // Bisq startup again. + public void cleanupTorFiles(@Nullable Runnable resultHandler, @Nullable ErrorMessageHandler errorMessageHandler) { + File hiddenservice = new File(Paths.get(torDir.getAbsolutePath(), "hiddenservice").toString()); + try { + FileUtil.deleteDirectory(torDir, hiddenservice, true); + if (resultHandler != null) + resultHandler.run(); + } catch (IOException e) { + e.printStackTrace(); + log.error(e.toString()); + if (errorMessageHandler != null) + errorMessageHandler.handleErrorMessage(e.toString()); + } + } +} diff --git a/core/src/main/java/bisq/core/app/WalletAppSetup.java b/core/src/main/java/bisq/core/app/WalletAppSetup.java index 49237f90951..e89df28ab85 100644 --- a/core/src/main/java/bisq/core/app/WalletAppSetup.java +++ b/core/src/main/java/bisq/core/app/WalletAppSetup.java @@ -23,8 +23,6 @@ import bisq.core.user.Preferences; import bisq.core.util.BSFormatter; -import org.libdohj.Version; - import org.bitcoinj.core.VersionMessage; import org.bitcoinj.store.BlockStoreException; import org.bitcoinj.store.ChainFileLockedException; @@ -34,8 +32,10 @@ import org.fxmisc.easybind.EasyBind; import org.fxmisc.easybind.monadic.MonadicBinding; +import javafx.beans.property.BooleanProperty; import javafx.beans.property.DoubleProperty; import javafx.beans.property.ObjectProperty; +import javafx.beans.property.SimpleBooleanProperty; import javafx.beans.property.SimpleDoubleProperty; import javafx.beans.property.SimpleObjectProperty; import javafx.beans.property.SimpleStringProperty; @@ -70,6 +70,8 @@ public class WalletAppSetup { private final StringProperty btcInfo = new SimpleStringProperty(Res.get("mainView.footer.btcInfo.initializing")); @Getter private int numBtcPeers = 0; + @Getter + private final BooleanProperty useTorForBTC = new SimpleBooleanProperty(); @Inject public WalletAppSetup(WalletsManager walletsManager, @@ -82,6 +84,7 @@ public WalletAppSetup(WalletsManager walletsManager, this.bisqEnvironment = bisqEnvironment; this.preferences = preferences; this.formatter = formatter; + this.useTorForBTC.set(preferences.getUseTorForBitcoinJ()); } void init(@Nullable Consumer chainFileLockedExceptionHandler, @@ -90,8 +93,8 @@ void init(@Nullable Consumer chainFileLockedExceptionHandler, Runnable walletPasswordHandler, Runnable downloadCompleteHandler, Runnable walletInitializedHandler) { - log.info("Initialize WalletAppSetup with BitcoinJ version {} and LibDohJ version {} with hash of BitcoinJ commit {}", - VersionMessage.BITCOINJ_VERSION, Version.VERSION, Version.BITCOINJ_VERSION); + log.info("Initialize WalletAppSetup with BitcoinJ version {} and hash of BitcoinJ commit {}", + VersionMessage.BITCOINJ_VERSION, "cd30ad5b"); ObjectProperty walletServiceException = new SimpleObjectProperty<>(); btcInfoBinding = EasyBind.combine(walletsSetup.downloadPercentageProperty(), @@ -114,7 +117,7 @@ void init(@Nullable Consumer chainFileLockedExceptionHandler, } else if (percentage > 0.0) { result = Res.get("mainView.footer.btcInfo", peers, - Res.get("mainView.footer.btcInfo.synchronizedWith"), + Res.get("mainView.footer.btcInfo.synchronizingWith"), getBtcNetworkAsString() + ": " + formatter.formatToPercentWithSymbol(percentage)); } else { result = Res.get("mainView.footer.btcInfo", 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 89adeacab21..07c74d7e760 100644 --- a/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java +++ b/core/src/main/java/bisq/core/app/misc/AppSetupWithP2P.java @@ -18,6 +18,7 @@ package bisq.core.app.misc; 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; @@ -46,6 +47,7 @@ public class AppSetupWithP2P extends AppSetup { protected final P2PService p2PService; protected final AccountAgeWitnessService accountAgeWitnessService; protected final FilterManager filterManager; + private final TorSetup torSetup; protected BooleanProperty p2pNetWorkReady; protected final TradeStatisticsManager tradeStatisticsManager; protected ArrayList persistedDataHosts; @@ -56,23 +58,25 @@ public AppSetupWithP2P(EncryptionService encryptionService, P2PService p2PService, TradeStatisticsManager tradeStatisticsManager, AccountAgeWitnessService accountAgeWitnessService, - FilterManager filterManager) { + FilterManager filterManager, + TorSetup torSetup) { super(encryptionService, keyRing); this.p2PService = p2PService; this.tradeStatisticsManager = tradeStatisticsManager; this.accountAgeWitnessService = accountAgeWitnessService; this.filterManager = filterManager; + this.torSetup = torSetup; this.persistedDataHosts = new ArrayList<>(); } @Override public void initPersistedDataHosts() { + torSetup.cleanupTorFiles(); persistedDataHosts.add(p2PService); // we apply at startup the reading of persisted data but don't want to get it triggered in the constructor - persistedDataHosts.stream().forEach(e -> { + persistedDataHosts.forEach(e -> { try { - log.info("call readPersisted at " + e.getClass().getSimpleName()); e.readPersisted(); } catch (Throwable e1) { log.error("readPersisted error", e1); @@ -115,7 +119,7 @@ public void onDisconnect(CloseConnectionReason closeConnectionReason, Connection if (connection.getPeerType() == Connection.PeerType.SEED_NODE && closeConnectionReason == CloseConnectionReason.RULE_VIOLATION) { log.warn("RULE_VIOLATION onDisconnect closeConnectionReason=" + closeConnectionReason); - log.warn("RULE_VIOLATION onDisconnect connection=" + connection); + log.warn("RULE_VIOLATION onDisconnect connection={}", connection); } } 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 50628e336e2..4a2a89c2953 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,7 @@ package bisq.core.app.misc; +import bisq.core.app.TorSetup; import bisq.core.dao.DaoOptionKeys; import bisq.core.dao.DaoSetup; import bisq.core.dao.governance.ballot.BallotListService; @@ -57,13 +58,15 @@ public AppSetupWithP2PAndDAO(EncryptionService encryptionService, MyProposalListService myProposalListService, MyReputationListService myReputationListService, MyProofOfBurnListService myProofOfBurnListService, + TorSetup torSetup, @Named(DaoOptionKeys.DAO_ACTIVATED) boolean daoActivated) { super(encryptionService, keyRing, p2PService, tradeStatisticsManager, accountAgeWitnessService, - filterManager); + filterManager, + torSetup); this.daoSetup = daoSetup; 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 a48dd4384be..55e41da3827 100644 --- a/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java +++ b/core/src/main/java/bisq/core/app/misc/ExecutableForAppWithP2p.java @@ -47,7 +47,7 @@ @Slf4j public abstract class ExecutableForAppWithP2p extends BisqExecutable implements UncaughtExceptionHandler { private static final long MAX_MEMORY_MB_DEFAULT = 500; - private static final long CHECK_MEMORY_PERIOD_SEC = 10; + private static final long CHECK_MEMORY_PERIOD_SEC = 300; private volatile boolean stopped; private static long maxMemory = MAX_MEMORY_MB_DEFAULT; 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 64cfcb465e3..35413918c2d 100644 --- a/core/src/main/java/bisq/core/app/misc/ModuleForAppWithP2p.java +++ b/core/src/main/java/bisq/core/app/misc/ModuleForAppWithP2p.java @@ -20,12 +20,12 @@ import bisq.core.alert.AlertModule; 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; import bisq.core.network.p2p.seed.DefaultSeedNodeRepository; -import bisq.core.network.p2p.seed.SeedNodeAddressLookup; import bisq.core.offer.OfferModule; import bisq.core.proto.network.CoreNetworkProtoResolver; import bisq.core.proto.persistable.CorePersistenceProtoResolver; @@ -74,8 +74,8 @@ protected void configure() { bind(PersistenceProtoResolver.class).to(CorePersistenceProtoResolver.class).in(Singleton.class); bind(Preferences.class).in(Singleton.class); bind(BridgeAddressProvider.class).to(Preferences.class).in(Singleton.class); + bind(TorSetup.class).in(Singleton.class); - bind(SeedNodeAddressLookup.class).in(Singleton.class); bind(SeedNodeRepository.class).to(DefaultSeedNodeRepository.class).in(Singleton.class); File storageDir = new File(environment.getRequiredProperty(Storage.STORAGE_DIR)); diff --git a/core/src/main/java/bisq/core/arbitration/Arbitrator.java b/core/src/main/java/bisq/core/arbitration/Arbitrator.java index a9b6d738c45..ffc6a8f4670 100644 --- a/core/src/main/java/bisq/core/arbitration/Arbitrator.java +++ b/core/src/main/java/bisq/core/arbitration/Arbitrator.java @@ -23,6 +23,7 @@ import bisq.common.crypto.PubKeyRing; import bisq.common.proto.ProtoUtil; +import bisq.common.util.ExtraDataMapValidator; import bisq.common.util.Utilities; import io.bisq.generated.protobuffer.PB; @@ -91,7 +92,7 @@ public Arbitrator(NodeAddress nodeAddress, this.registrationSignature = registrationSignature; this.emailAddress = emailAddress; this.info = info; - this.extraDataMap = extraDataMap; + this.extraDataMap = ExtraDataMapValidator.getValidatedExtraDataMap(extraDataMap); } /////////////////////////////////////////////////////////////////////////////////////////// diff --git a/core/src/main/java/bisq/core/arbitration/ArbitratorService.java b/core/src/main/java/bisq/core/arbitration/ArbitratorService.java index e29511d60cf..8e781cc5c10 100644 --- a/core/src/main/java/bisq/core/arbitration/ArbitratorService.java +++ b/core/src/main/java/bisq/core/arbitration/ArbitratorService.java @@ -107,7 +107,7 @@ public Map getArbitrators() { .filter(data -> data.getProtectedStoragePayload() instanceof Arbitrator) .map(data -> (Arbitrator) data.getProtectedStoragePayload()) .filter(a -> bannedArbitrators == null || - !bannedArbitrators.contains(a.getNodeAddress().getHostName())) + !bannedArbitrators.contains(a.getNodeAddress().getFullAddress())) .collect(Collectors.toSet()); Map map = new HashMap<>(); diff --git a/core/src/main/java/bisq/core/arbitration/DisputeManager.java b/core/src/main/java/bisq/core/arbitration/DisputeManager.java index 637357787c1..ed1a665bd5d 100644 --- a/core/src/main/java/bisq/core/arbitration/DisputeManager.java +++ b/core/src/main/java/bisq/core/arbitration/DisputeManager.java @@ -49,6 +49,7 @@ 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; @@ -119,6 +120,7 @@ public class DisputeManager implements PersistedDataHost { private final Map disputeIsClosedSubscriptionsMap = new HashMap<>(); @Getter private final IntegerProperty numOpenDisputes = new SimpleIntegerProperty(); + private boolean servicesInitialized; /////////////////////////////////////////////////////////////////////////////////////////// @@ -176,6 +178,7 @@ public void readPersisted() { } public void onAllServicesInitialized() { + servicesInitialized = true; p2PService.addP2PServiceListener(new BootstrapListener() { @Override public void onUpdatedDataReceived() { @@ -259,9 +262,13 @@ private void tryApplyMessages() { } 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(); + walletsSetup.hasSufficientPeersForBroadcast() && + servicesInitialized; } private void applyMessages() { @@ -337,8 +344,8 @@ public void sendOpenNewDisputeMessage(Dispute dispute, boolean reOpen, ResultHan final Optional storedDisputeOptional = findDispute(dispute.getTradeId(), dispute.getTraderId()); if (!storedDisputeOptional.isPresent() || reOpen) { String sysMsg = dispute.isSupportTicket() ? - Res.get("support.youOpenedTicket") - : Res.get("support.youOpenedDispute", disputeInfo); + Res.get("support.youOpenedTicket", disputeInfo, Version.VERSION) + : Res.get("support.youOpenedDispute", disputeInfo, Version.VERSION); DisputeCommunicationMessage disputeCommunicationMessage = new DisputeCommunicationMessage( dispute.getTradeId(), @@ -450,7 +457,7 @@ private String sendPeerOpenedDisputeMessage(Dispute disputeFromOpener, Contract final Optional storedDisputeOptional = findDispute(dispute.getTradeId(), dispute.getTraderId()); if (!storedDisputeOptional.isPresent()) { String sysMsg = dispute.isSupportTicket() ? - Res.get("support.peerOpenedTicket") + Res.get("support.peerOpenedTicket", disputeInfo) : Res.get("support.peerOpenedDispute", disputeInfo); DisputeCommunicationMessage disputeCommunicationMessage = new DisputeCommunicationMessage( dispute.getTradeId(), @@ -877,10 +884,9 @@ private void onDisputeResultMessage(DisputeResultMessage disputeResultMessage) { } return; } - + Dispute dispute = disputeOptional.get(); try { cleanupRetryMap(uid); - Dispute dispute = disputeOptional.get(); arbitratorsPubKeyRing = dispute.getArbitratorPubKeyRing(); DisputeCommunicationMessage disputeCommunicationMessage = disputeResult.getDisputeCommunicationMessage(); if (!dispute.getDisputeCommunicationMessages().contains(disputeCommunicationMessage)) @@ -996,10 +1002,25 @@ public void onFailure(TxBroadcastException exception) { success = true; } - } catch (AddressFormatException | WalletException | TransactionVerificationException e) { - e.printStackTrace(); + } catch (TransactionVerificationException e) { errorMessage = "Error at traderSignAndFinalizeDisputedPayoutTx " + e.toString(); - log.error(errorMessage); + 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 { diff --git a/core/src/main/java/bisq/core/arbitration/Mediator.java b/core/src/main/java/bisq/core/arbitration/Mediator.java index b5d4e3ca643..0673b5465c0 100644 --- a/core/src/main/java/bisq/core/arbitration/Mediator.java +++ b/core/src/main/java/bisq/core/arbitration/Mediator.java @@ -23,6 +23,7 @@ import bisq.common.crypto.PubKeyRing; import bisq.common.proto.ProtoUtil; +import bisq.common.util.ExtraDataMapValidator; import io.bisq.generated.protobuffer.PB; @@ -84,7 +85,7 @@ public Mediator(NodeAddress nodeAddress, this.registrationSignature = registrationSignature; this.emailAddress = emailAddress; this.info = info; - this.extraDataMap = extraDataMap; + this.extraDataMap = ExtraDataMapValidator.getValidatedExtraDataMap(extraDataMap); } diff --git a/core/src/main/java/bisq/core/btc/BaseCurrencyNetwork.java b/core/src/main/java/bisq/core/btc/BaseCurrencyNetwork.java index 51c27f66e09..c4468563299 100644 --- a/core/src/main/java/bisq/core/btc/BaseCurrencyNetwork.java +++ b/core/src/main/java/bisq/core/btc/BaseCurrencyNetwork.java @@ -17,13 +17,6 @@ package bisq.core.btc; -import org.libdohj.params.DashMainNetParams; -import org.libdohj.params.DashRegTestParams; -import org.libdohj.params.DashTestNet3Params; -import org.libdohj.params.LitecoinMainNetParams; -import org.libdohj.params.LitecoinRegTestParams; -import org.libdohj.params.LitecoinTestNet3Params; - import org.bitcoinj.core.NetworkParameters; import org.bitcoinj.params.MainNetParams; import org.bitcoinj.params.RegTestParams; @@ -35,14 +28,9 @@ public enum BaseCurrencyNetwork { BTC_MAINNET(MainNetParams.get(), "BTC", "MAINNET", "Bitcoin"), BTC_TESTNET(TestNet3Params.get(), "BTC", "TESTNET", "Bitcoin"), BTC_REGTEST(RegTestParams.get(), "BTC", "REGTEST", "Bitcoin"), - - LTC_MAINNET(LitecoinMainNetParams.get(), "LTC", "MAINNET", "Litecoin"), - LTC_TESTNET(LitecoinTestNet3Params.get(), "LTC", "TESTNET", "Litecoin"), - LTC_REGTEST(LitecoinRegTestParams.get(), "LTC", "REGTEST", "Litecoin"), - - DASH_MAINNET(DashMainNetParams.get(), "DASH", "MAINNET", "Dash"), - DASH_TESTNET(DashTestNet3Params.get(), "DASH", "TESTNET", "Dash"), - DASH_REGTEST(DashRegTestParams.get(), "DASH", "REGTEST", "Dash"); + BTC_DAO_TESTNET(RegTestParams.get(), "BTC", "REGTEST", "Bitcoin"), // server side regtest until v0.9.5 + BTC_DAO_BETANET(MainNetParams.get(), "BTC", "MAINNET", "Bitcoin"), // mainnet test genesis + BTC_DAO_REGTEST(RegTestParams.get(), "BTC", "REGTEST", "Bitcoin"); // server side regtest after v0.9.5, had breaking code changes so we started over again @Getter private final NetworkParameters parameters; @@ -61,27 +49,27 @@ public enum BaseCurrencyNetwork { } public boolean isMainnet() { - return "MAINNET".equals(network); + return "BTC_MAINNET".equals(name()); } public boolean isTestnet() { - return "TESTNET".equals(network); + return "BTC_TESTNET".equals(name()); } - public boolean isRegtest() { - return "REGTEST".equals(network); + public boolean isDaoTestNet() { + return "BTC_DAO_TESTNET".equals(name()); } - public boolean isBitcoin() { - return "BTC".equals(currencyCode); + public boolean isDaoRegTest() { + return "BTC_DAO_REGTEST".equals(name()); } - public boolean isLitecoin() { - return "LTC".equals(currencyCode); + public boolean isDaoBetaNet() { + return "BTC_DAO_BETANET".equals(name()); } - public boolean isDash() { - return "DASH".equals(currencyCode); + public boolean isRegtest() { + return "BTC_REGTEST".equals(name()); } public long getDefaultMinFeePerByte() { diff --git a/core/src/main/java/bisq/core/btc/BitcoinModule.java b/core/src/main/java/bisq/core/btc/BitcoinModule.java index a5de4e8efab..67a8265cc42 100644 --- a/core/src/main/java/bisq/core/btc/BitcoinModule.java +++ b/core/src/main/java/bisq/core/btc/BitcoinModule.java @@ -18,6 +18,7 @@ package bisq.core.btc; import bisq.core.app.AppOptionKeys; +import bisq.core.app.BisqEnvironment; import bisq.core.btc.model.AddressEntryList; import bisq.core.btc.nodes.BtcNodes; import bisq.core.btc.setup.RegTestHost; @@ -53,13 +54,25 @@ public BitcoinModule(Environment environment) { @Override protected void configure() { - String regTestHost = environment.getProperty(BtcOptionKeys.REG_TEST_HOST, String.class, RegTestHost.DEFAULT_HOST); + // If we we have selected BTC_DAO_REGTEST or BTC_DAO_TESTNET we use our master regtest node, + // otherwise the specified host or default (localhost) + String regTestHost = environment.getProperty(BtcOptionKeys.REG_TEST_HOST, String.class, ""); + if (regTestHost.isEmpty()) { + regTestHost = BisqEnvironment.getBaseCurrencyNetwork().isDaoTestNet() ? + "104.248.31.39" : + BisqEnvironment.getBaseCurrencyNetwork().isDaoRegTest() ? + "134.209.242.206" : + RegTestHost.DEFAULT_HOST; + } + + RegTestHost.HOST = regTestHost; if (Arrays.asList("localhost", "127.0.0.1").contains(regTestHost)) { bind(RegTestHost.class).toInstance(RegTestHost.LOCALHOST); + } else if ("none".equals(regTestHost)) { + bind(RegTestHost.class).toInstance(RegTestHost.NONE); } else { bind(RegTestHost.class).toInstance(RegTestHost.REMOTE_HOST); } - RegTestHost.HOST = regTestHost; bindConstant().annotatedWith(named(UserAgent.NAME_KEY)).to(environment.getRequiredProperty(UserAgent.NAME_KEY)); bindConstant().annotatedWith(named(UserAgent.VERSION_KEY)).to(environment.getRequiredProperty(UserAgent.VERSION_KEY)); diff --git a/core/src/main/java/bisq/core/btc/exceptions/BsqChangeBelowDustException.java b/core/src/main/java/bisq/core/btc/exceptions/BsqChangeBelowDustException.java new file mode 100644 index 00000000000..d0bf325151b --- /dev/null +++ b/core/src/main/java/bisq/core/btc/exceptions/BsqChangeBelowDustException.java @@ -0,0 +1,33 @@ +/* + * 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.btc.exceptions; + +import org.bitcoinj.core.Coin; + +import lombok.Getter; + +public class BsqChangeBelowDustException extends Exception { + @Getter + private final Coin outputValue; + + public BsqChangeBelowDustException(String message, Coin outputValue) { + super(message); + + this.outputValue = outputValue; + } +} diff --git a/core/src/main/java/bisq/core/btc/exceptions/TxBroadcastTimeoutException.java b/core/src/main/java/bisq/core/btc/exceptions/TxBroadcastTimeoutException.java index e54f35d5bea..a9aa4aa0dff 100644 --- a/core/src/main/java/bisq/core/btc/exceptions/TxBroadcastTimeoutException.java +++ b/core/src/main/java/bisq/core/btc/exceptions/TxBroadcastTimeoutException.java @@ -41,7 +41,7 @@ public class TxBroadcastTimeoutException extends TxBroadcastException { */ public TxBroadcastTimeoutException(Transaction localTx, int delay, Wallet wallet) { super("The transaction was not broadcasted in " + delay + - "seconds. txId=" + localTx.getHashAsString()); + " seconds. txId=" + localTx.getHashAsString()); this.localTx = localTx; this.delay = delay; this.wallet = wallet; diff --git a/core/src/main/java/bisq/core/btc/exceptions/TxMalleabilityException.java b/core/src/main/java/bisq/core/btc/exceptions/TxMalleabilityException.java deleted file mode 100644 index caa262b4a30..00000000000 --- a/core/src/main/java/bisq/core/btc/exceptions/TxMalleabilityException.java +++ /dev/null @@ -1,50 +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.btc.exceptions; - -import org.bitcoinj.core.Transaction; - -import lombok.Getter; - -import javax.annotation.Nullable; - - -public class TxMalleabilityException extends TxBroadcastException { - @Getter - @Nullable - private final Transaction localTx; - @Getter - @Nullable - private final Transaction networkTx; - - public TxMalleabilityException(Transaction localTx, Transaction networkTx) { - super("The transaction we received from the Bitcoin network has a different txId as the one we broadcasted.\n" + - "txId of local tx=" + localTx.getHashAsString() + - ", txId of received tx=" + localTx.getHashAsString()); - this.localTx = localTx; - this.networkTx = networkTx; - } - - @Override - public String toString() { - return "TxMalleabilityException{" + - "\n localTx=" + localTx + - ",\n networkTx=" + networkTx + - "\n} " + super.toString(); - } -} diff --git a/core/src/main/java/bisq/core/btc/listeners/BsqBalanceListener.java b/core/src/main/java/bisq/core/btc/listeners/BsqBalanceListener.java index 5a49bda668a..7923db370c5 100644 --- a/core/src/main/java/bisq/core/btc/listeners/BsqBalanceListener.java +++ b/core/src/main/java/bisq/core/btc/listeners/BsqBalanceListener.java @@ -20,9 +20,10 @@ import org.bitcoinj.core.Coin; public interface BsqBalanceListener { - void onUpdateBalances(Coin availableBalance, + void onUpdateBalances(Coin availableConfirmedBalance, Coin availableNonBsqBalance, Coin unverifiedBalance, + Coin unconfirmedChangeBalance, Coin lockedForVotingBalance, Coin lockedInBondsBalance, Coin unlockingBondsBalance); 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 08b0ad188b9..6cb1bffc12b 100644 --- a/core/src/main/java/bisq/core/btc/model/AddressEntryList.java +++ b/core/src/main/java/bisq/core/btc/model/AddressEntryList.java @@ -25,6 +25,7 @@ import com.google.protobuf.Message; +import org.bitcoinj.core.Transaction; import org.bitcoinj.crypto.DeterministicKey; import org.bitcoinj.wallet.Wallet; @@ -32,6 +33,7 @@ import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -110,16 +112,45 @@ public void onWalletReady(Wallet wallet) { list = new ArrayList<>(); add(new AddressEntry(wallet.freshReceiveKey(), AddressEntry.Context.ARBITRATOR)); - // In case we restore from seed words and have balance we need to add the relevant addresses to our list: + // In case we restore from seed words and have balance we need to add the relevant addresses to our list. + // IssuedReceiveAddresses does not contain all addressed where we expect balance so we need to listen to + // incoming txs at blockchain sync to add the rest. if (wallet.getBalance().isPositive()) { wallet.getIssuedReceiveAddresses().forEach(address -> { - log.info("Create AddressEntry for address={}", address); + log.info("Create AddressEntry for IssuedReceiveAddress. address={}", address.toString()); add(new AddressEntry((DeterministicKey) wallet.findKeyFromPubHash(address.getHash160()), AddressEntry.Context.AVAILABLE)); }); } - persist(); } + + // We add those listeners to get notified about potential new transactions and + // add an address entry list in case it does not exist yet. This is mainly needed for restore from seed words + // but can help as well in case the addressEntry list would miss an address where the wallet was received + // funds (e.g. if the user sends funds to an address which has not been provided in the main UI - like from the + // wallet details window). + wallet.addCoinsReceivedEventListener((w, tx, prevBalance, newBalance) -> { + updateList(tx); + }); + wallet.addCoinsSentEventListener((w, tx, prevBalance, newBalance) -> { + updateList(tx); + }); + } + + private void updateList(Transaction tx) { + tx.getOutputs().stream() + .filter(output -> output.isMine(wallet)) + .map(output -> output.getAddressFromP2PKHScript(wallet.getNetworkParameters())) + .filter(Objects::nonNull) + .filter(address -> !listContainsEntryWithAddress(address.toBase58())) + .map(address -> (DeterministicKey) wallet.findKeyFromPubHash(address.getHash160())) + .filter(Objects::nonNull) + .map(deterministicKey -> new AddressEntry(deterministicKey, AddressEntry.Context.AVAILABLE)) + .forEach(addressEntry -> list.add(addressEntry)); + } + + private boolean listContainsEntryWithAddress(String addressString) { + return list.stream().anyMatch(addressEntry -> Objects.equals(addressEntry.getAddressString(), addressString)); } private boolean add(AddressEntry addressEntry) { diff --git a/core/src/main/java/bisq/core/btc/nodes/BtcNodeConverter.java b/core/src/main/java/bisq/core/btc/nodes/BtcNodeConverter.java index 61bf64a4e50..2cb29b8f49e 100644 --- a/core/src/main/java/bisq/core/btc/nodes/BtcNodeConverter.java +++ b/core/src/main/java/bisq/core/btc/nodes/BtcNodeConverter.java @@ -23,7 +23,7 @@ import bisq.network.DnsLookupTor; import org.bitcoinj.core.PeerAddress; -import org.bitcoinj.net.OnionCat; +import org.bitcoinj.net.OnionCatConverter; import com.runjva.sourceforge.jsocks.protocol.Socks5Proxy; @@ -56,7 +56,7 @@ PeerAddress convertOnionHost(BtcNode node) { // no DNS lookup for onion addresses String onionAddress = Objects.requireNonNull(node.getOnionAddress()); try { - // OnionCat.onionHostToInetAddress converts onion to ipv6 representation + // OnionCatConverter.onionHostToInetAddress converts onion to ipv6 representation // inetAddress is not used but required for wallet persistence. Throws nullPointer if not set. InetAddress inetAddress = facade.onionHostToInetAddress(onionAddress); PeerAddress result = new PeerAddress(onionAddress, node.getPort()); @@ -127,7 +127,7 @@ private static PeerAddress create(String hostName, int port) { static class Facade { InetAddress onionHostToInetAddress(String onionAddress) throws UnknownHostException { - return OnionCat.onionHostToInetAddress(onionAddress); + return OnionCatConverter.onionHostToInetAddress(onionAddress); } InetAddress torLookup(Socks5Proxy proxy, String host) throws DnsLookupException { 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 4f4c243c382..b97030bf250 100644 --- a/core/src/main/java/bisq/core/btc/nodes/BtcNodes.java +++ b/core/src/main/java/bisq/core/btc/nodes/BtcNodes.java @@ -54,7 +54,7 @@ public List getProvidedBtcNodes() { // emzy new BtcNode("kirsche.emzy.de", "fz6nsij6jiyuwlsc.onion", "78.47.61.83", BtcNode.DEFAULT_PORT, "@emzy"), new BtcNode("node2.emzy.de", "c6ac4jdfyeiakex2.onion", "62.75.210.81", BtcNode.DEFAULT_PORT, "@emzy"), - new BtcNode("node1.emzy.de", "sjyzmwwu6diiit3r.onion", "163.172.171.119", BtcNode.DEFAULT_PORT, "@emzy"), + new BtcNode("node1.emzy.de", "sjyzmwwu6diiit3r.onion", "167.86.90.239", BtcNode.DEFAULT_PORT, "@emzy"), new BtcNode(null, "3xucqntxp5ddoaz5.onion", null, BtcNode.DEFAULT_PORT, "@emzy"), // cannot provide IP because no static IP // ripcurlx @@ -68,6 +68,12 @@ public List getProvidedBtcNodes() { new BtcNode("btc1.sqrrm.net", "3r44ddzjitznyahw.onion", "185.25.48.184", BtcNode.DEFAULT_PORT, "@sqrrm"), new BtcNode("btc2.sqrrm.net", "i3a5xtzfm4xwtybd.onion", "81.171.22.143", BtcNode.DEFAULT_PORT, "@sqrrm"), + // KanoczTomas + new BtcNode("btc.ispol.sk", "mbm6ffx6j5ygi2ck.onion", "193.58.196.212", BtcNode.DEFAULT_PORT, "@KanoczTomas"), + + // Devin Bileck + new BtcNode("btc1.dnsalias.net", "lva54pnbq2nsmjyr.onion", "165.227.34.198", BtcNode.DEFAULT_PORT, "@devinbileck"), + // sgeisler new BtcNode("bcwat.ch", "z33nukt7ngik3cpe.onion", "5.189.166.193", BtcNode.DEFAULT_PORT, "@sgeisler"), @@ -79,7 +85,7 @@ public List getProvidedBtcNodes() { } public boolean useProvidedBtcNodes() { - return BisqEnvironment.getBaseCurrencyNetwork().isBitcoin() && BisqEnvironment.getBaseCurrencyNetwork().isMainnet(); + return BisqEnvironment.getBaseCurrencyNetwork().isMainnet(); } public static List toBtcNodesList(Collection nodes) { diff --git a/core/src/main/java/bisq/core/btc/nodes/SeedPeersSocks5Dns.java b/core/src/main/java/bisq/core/btc/nodes/SeedPeersSocks5Dns.java index 6c1dabbf2b0..20f835de7b5 100644 --- a/core/src/main/java/bisq/core/btc/nodes/SeedPeersSocks5Dns.java +++ b/core/src/main/java/bisq/core/btc/nodes/SeedPeersSocks5Dns.java @@ -162,7 +162,7 @@ public static InetSocketAddress lookup(Socks5Proxy proxy, InetSocketAddress addr InetAddress addrResolved = proxySocket.getInetAddress(); proxySocket.close(); if (addrResolved != null) { - log.debug("Resolved " + addr.getHostString() + " to " + addrResolved.getHostAddress()); + //log.debug("Resolved " + addr.getHostString() + " to " + addrResolved.getHostAddress()); return new InetSocketAddress(addrResolved, addr.getPort()); } else { // note: .onion nodes fall in here when proxy is Tor. But they have no IP address. diff --git a/core/src/main/java/bisq/core/btc/setup/WalletConfig.java b/core/src/main/java/bisq/core/btc/setup/WalletConfig.java index 3e88fd63951..95a441b258c 100644 --- a/core/src/main/java/bisq/core/btc/setup/WalletConfig.java +++ b/core/src/main/java/bisq/core/btc/setup/WalletConfig.java @@ -80,7 +80,6 @@ import javax.annotation.Nullable; -import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkState; @@ -88,7 +87,9 @@ // Does the basic wiring @Slf4j public class WalletConfig extends AbstractIdleService { - private static final int TIMEOUT = 120 * 1000; // connectTimeoutMillis. 60 sec used in bitcoinj, but for Tor we allow more. + private static final int TOR_SOCKET_TIMEOUT = 120 * 1000; // 1 sec used in bitcoinj, but since bisq uses Tor we allow more. + private static final int TOR_VERSION_EXCHANGE_TIMEOUT = 125 * 1000; // 5 sec used in bitcoinj, but since bisq uses Tor we allow more. + /////////////////////////////////////////////////////////////////////////////////////////// // WalletFactory @@ -125,7 +126,7 @@ public interface BisqWalletFactory extends WalletProtobufSerializer.WalletFactor private DeterministicSeed seed; private volatile BlockChain vChain; - private volatile BlockStore vStore; + private volatile SPVBlockStore vStore; private volatile PeerGroup vPeerGroup; private boolean useAutoSave = true; private PeerAddress[] peerAddresses; @@ -172,8 +173,6 @@ public Wallet create(NetworkParameters params, KeyChainGroup keyChainGroup) { // We have already the chain here so we can use this to distinguish. List deterministicKeyChains = keyChainGroup.getDeterministicKeyChains(); if (!deterministicKeyChains.isEmpty() && deterministicKeyChains.get(0) instanceof BisqDeterministicKeyChain) { - checkArgument(BisqEnvironment.isBaseCurrencySupportingBsq(), "BisqEnvironment.isBaseCurrencySupportingBsq() is false but we get get " + - "called BisqWalletFactory.create with BisqDeterministicKeyChain"); return new BsqWallet(params, keyChainGroup); } else { return new Wallet(params, keyChainGroup); @@ -184,8 +183,6 @@ public Wallet create(NetworkParameters params, KeyChainGroup keyChainGroup) { public Wallet create(NetworkParameters params, KeyChainGroup keyChainGroup, boolean isBsqWallet) { // This is called at first startup when we create the wallet if (isBsqWallet) { - checkArgument(BisqEnvironment.isBaseCurrencySupportingBsq(), "BisqEnvironment.isBaseCurrencySupportingBsq() is false but we get get " + - "called BisqWalletFactory.create with isBsqWallet=true"); return new BsqWallet(params, keyChainGroup); } else { return new Wallet(params, keyChainGroup); @@ -214,9 +211,12 @@ public Wallet create(NetworkParameters params, KeyChainGroup keyChainGroup, bool } private PeerGroup createPeerGroup() { + PeerGroup peerGroup; // no proxy case. if (socks5Proxy == null) { - return new PeerGroup(params, vChain); + peerGroup = new PeerGroup(params, vChain); + // For dao testnet (server side regtest) we prevent to connect to a localhost node to avoid confusion + // if local btc node is not synced with our dao testnet master node. } else { // proxy case (tor). Proxy proxy = new Proxy(Proxy.Type.SOCKS, @@ -224,18 +224,23 @@ private PeerGroup createPeerGroup() { socks5Proxy.getPort())); ProxySocketFactory proxySocketFactory = new ProxySocketFactory(proxy); - // we dont use tor mode if we have a local node running + // We don't use tor mode if we have a local node running BlockingClientManager blockingClientManager = bisqEnvironment.isBitcoinLocalhostNodeRunning() ? new BlockingClientManager() : new BlockingClientManager(proxySocketFactory); - PeerGroup peerGroup = new PeerGroup(params, vChain, blockingClientManager); - - blockingClientManager.setConnectTimeoutMillis(TIMEOUT); - peerGroup.setConnectTimeoutMillis(TIMEOUT); + peerGroup = new PeerGroup(params, vChain, blockingClientManager); - return peerGroup; + blockingClientManager.setConnectTimeoutMillis(TOR_SOCKET_TIMEOUT); + peerGroup.setConnectTimeoutMillis(TOR_VERSION_EXCHANGE_TIMEOUT); } + + // For dao testnet (server side regtest) we prevent to connect to a localhost node to avoid confusion + // if local btc node is not synced with our dao testnet master node. + if (BisqEnvironment.getBaseCurrencyNetwork().isDaoRegTest() || BisqEnvironment.getBaseCurrencyNetwork().isDaoTestNet()) + peerGroup.setUseLocalhostPeerWhenPossible(false); + + return peerGroup; } /** @@ -322,13 +327,6 @@ private List provideWalletExtensions() { return ImmutableList.of(); } - /** - * Override this to use a {@link BlockStore} that isn't the default of {@link SPVBlockStore}. - */ - private BlockStore provideBlockStore(File file) throws BlockStoreException { - return new SPVBlockStore(params, file); - } - /** * This method is invoked on a background thread after all objects are initialised, but before the peer group * or block chain download is started. You can tweak the objects configuration here. @@ -394,14 +392,12 @@ protected void startUp() throws Exception { keyChainGroup = new BisqKeyChainGroup(params, new BisqDeterministicKeyChain(vBtcWallet.getKeyChainSeed()), false); // BSQ wallet - if (BisqEnvironment.isBaseCurrencySupportingBsq()) { - vBsqWalletFile = new File(directory, bsqWalletFileName); - vBsqWallet = createOrLoadWallet(vBsqWalletFile, shouldReplayWallet, keyChainGroup, true, seed); - vBsqWallet.setRiskAnalyzer(new BisqRiskAnalysis.Analyzer()); - } + vBsqWalletFile = new File(directory, bsqWalletFileName); + vBsqWallet = createOrLoadWallet(vBsqWalletFile, shouldReplayWallet, keyChainGroup, true, seed); + vBsqWallet.setRiskAnalyzer(new BisqRiskAnalysis.Analyzer()); // Initiate Bitcoin network objects (block store, blockchain and peer group) - vStore = provideBlockStore(chainFile); + vStore = new SPVBlockStore(params, chainFile); if (!chainFileExists || seed != null) { if (checkpoints != null) { // Initialize the chain file with a checkpoint to speed up first-run sync. @@ -411,11 +407,8 @@ protected void startUp() throws Exception { // we created both wallets at the same time time = seed.getCreationTimeSeconds(); if (chainFileExists) { - log.info("Deleting the chain file in preparation from restore."); - vStore.close(); - if (!chainFile.delete()) - throw new IOException("Failed to delete chain file in preparation for restore."); - vStore = new SPVBlockStore(params, chainFile); + log.info("Clearing the chain file in preparation from restore."); + vStore.clear(); } } else { time = vBtcWallet.getEarliestKeyCreationTime(); @@ -427,11 +420,8 @@ protected void startUp() throws Exception { else log.warn("Creating a new uncheckpointed block store due to a wallet with a creation time of zero: this will result in a very slow chain sync"); } else if (chainFileExists) { - log.info("Deleting the chain file in preparation from restore."); - vStore.close(); - if (!chainFile.delete()) - throw new IOException("Failed to delete chain file in preparation for restore."); - vStore = new SPVBlockStore(params, chainFile); + log.info("Clearing the chain file in preparation from restore."); + vStore.clear(); } } vChain = new BlockChain(params, vStore); @@ -446,8 +436,10 @@ protected void startUp() throws Exception { // before we're actually connected the broadcast waits for an appropriate number of connections. if (peerAddresses != null) { for (PeerAddress addr : peerAddresses) vPeerGroup.addAddress(addr); - log.info("We try to connect to {} btc nodes", numConnectionForBtc); - vPeerGroup.setMaxConnections(Math.min(numConnectionForBtc, peerAddresses.length)); + int maxConnections = Math.min(numConnectionForBtc, peerAddresses.length); + log.info("We try to connect to {} btc nodes", maxConnections); + vPeerGroup.setMaxConnections(maxConnections); + vPeerGroup.setAddPeersFromAddressMessage(false); peerAddresses = null; } else if (!params.equals(RegTestParams.get())) { vPeerGroup.addPeerDiscovery(discovery != null ? discovery : new DnsDiscovery(params)); diff --git a/core/src/main/java/bisq/core/btc/setup/WalletsSetup.java b/core/src/main/java/bisq/core/btc/setup/WalletsSetup.java index 936c617625a..14dd75236ac 100644 --- a/core/src/main/java/bisq/core/btc/setup/WalletsSetup.java +++ b/core/src/main/java/bisq/core/btc/setup/WalletsSetup.java @@ -33,7 +33,6 @@ import bisq.common.Timer; import bisq.common.UserThread; -import bisq.common.app.Log; import bisq.common.handlers.ExceptionHandler; import bisq.common.handlers.ResultHandler; import bisq.common.storage.FileUtil; @@ -170,8 +169,6 @@ public WalletsSetup(RegTestHost regTestHost, /////////////////////////////////////////////////////////////////////////////////////////// public void initialize(@Nullable DeterministicSeed seed, ResultHandler resultHandler, ExceptionHandler exceptionHandler) { - Log.traceCall(); - // Tell bitcoinj to execute event handlers on the JavaFX UI thread. This keeps things simple and means // we cannot forget to switch threads when adding event handlers. Unfortunately, the DownloadListener // we give to the app kit is currently an exception and runs on a library thread. It'll get fixed in @@ -236,7 +233,6 @@ protected void onSetupCompleted() { if (regTestHost == RegTestHost.LOCALHOST) { walletConfig.setPeerNodesForLocalHost(); } else if (regTestHost == RegTestHost.REMOTE_HOST) { - walletConfig.setMinBroadcastConnections(1); configPeerNodesForRegTestServer(); } else { configPeerNodes(socks5Proxy); @@ -315,7 +311,11 @@ private int evaluateMode(String socks5DiscoverModeString) { private void configPeerNodesForRegTestServer() { try { - walletConfig.setPeerNodes(new PeerAddress(InetAddress.getByName(RegTestHost.HOST), params.getPort())); + if (RegTestHost.HOST.endsWith(".onion")) { + walletConfig.setPeerNodes(new PeerAddress(RegTestHost.HOST, params.getPort())); + } else { + walletConfig.setPeerNodes(new PeerAddress(InetAddress.getByName(RegTestHost.HOST), params.getPort())); + } } catch (UnknownHostException e) { log.error(e.toString()); e.printStackTrace(); diff --git a/core/src/main/java/bisq/core/btc/wallet/BisqDefaultCoinSelector.java b/core/src/main/java/bisq/core/btc/wallet/BisqDefaultCoinSelector.java index 496c37ae43e..57923d0ab32 100644 --- a/core/src/main/java/bisq/core/btc/wallet/BisqDefaultCoinSelector.java +++ b/core/src/main/java/bisq/core/btc/wallet/BisqDefaultCoinSelector.java @@ -75,17 +75,19 @@ public CoinSelection select(Coin target, List candidates) { long total = 0; long targetValue = target.value; for (TransactionOutput output : sortedOutputs) { - if (total >= targetValue) { - long change = total - targetValue; - if (change == 0 || change >= Restrictions.getMinNonDustOutput().value) - break; - } - - if (output.getParentTransaction() != null && - isTxSpendable(output.getParentTransaction()) && - isTxOutputSpendable(output)) { - selected.add(output); - total += output.getValue().value; + if (!isDustAttackUtxo(output)) { + if (total >= targetValue) { + long change = total - targetValue; + if (change == 0 || change >= Restrictions.getMinNonDustOutput().value) + break; + } + + if (output.getParentTransaction() != null && + isTxSpendable(output.getParentTransaction()) && + isTxOutputSpendable(output)) { + selected.add(output); + total += output.getValue().value; + } } } // Total may be lower than target here, if the given candidates were insufficient to create to requested @@ -93,6 +95,8 @@ public CoinSelection select(Coin target, List candidates) { return new CoinSelection(Coin.valueOf(total), selected); } + protected abstract boolean isDustAttackUtxo(TransactionOutput output); + public Coin getChange(Coin target, CoinSelection coinSelection) throws InsufficientMoneyException { long value = target.value; long available = coinSelection.valueGathered.value; @@ -103,7 +107,8 @@ public Coin getChange(Coin target, CoinSelection coinSelection) throws Insuffici return Coin.valueOf(change); } - // We allow spending own pending txs and if permitForeignPendingTx is set as well foreign unconfirmed txs. + // We allow spending from own unconfirmed txs and if permitForeignPendingTx is set as well from foreign + // unconfirmed txs. protected boolean isTxSpendable(Transaction tx) { TransactionConfidence confidence = tx.getConfidence(); TransactionConfidence.ConfidenceType type = confidence.getConfidenceType(); diff --git a/core/src/main/java/bisq/core/btc/wallet/BisqRiskAnalysis.java b/core/src/main/java/bisq/core/btc/wallet/BisqRiskAnalysis.java index d148202165c..dfd81746c92 100644 --- a/core/src/main/java/bisq/core/btc/wallet/BisqRiskAnalysis.java +++ b/core/src/main/java/bisq/core/btc/wallet/BisqRiskAnalysis.java @@ -113,6 +113,13 @@ private Result analyzeIsFinal() { if (tx.getConfidence().getSource() == TransactionConfidence.Source.SELF) return Result.OK; + // Relative time-locked transactions are risky too. We can't check the locks because usually we don't know the + // spent outputs (to know when they were created). + if (tx.hasRelativeLockTime()) { + nonFinal = tx; + return Result.NON_FINAL; + } + if (wallet == null) return null; @@ -157,7 +164,7 @@ public enum RuleViolation { */ public static RuleViolation isStandard(Transaction tx) { // TODO: Finish this function off. - if (tx.getVersion() > 1 || tx.getVersion() < 1) { + if (tx.getVersion() > 2 || tx.getVersion() < 1) { log.warn("TX considered non-standard due to unknown version number {}", tx.getVersion()); return RuleViolation.VERSION; } diff --git a/core/src/main/java/bisq/core/btc/wallet/BsqCoinSelector.java b/core/src/main/java/bisq/core/btc/wallet/BsqCoinSelector.java index f81fd3b7ed7..72e3b1af347 100644 --- a/core/src/main/java/bisq/core/btc/wallet/BsqCoinSelector.java +++ b/core/src/main/java/bisq/core/btc/wallet/BsqCoinSelector.java @@ -19,7 +19,9 @@ import bisq.core.dao.state.DaoStateService; import bisq.core.dao.state.model.blockchain.TxOutputKey; +import bisq.core.dao.state.unconfirmed.UnconfirmedBsqChangeOutputListService; +import org.bitcoinj.core.Transaction; import org.bitcoinj.core.TransactionOutput; import javax.inject.Inject; @@ -32,18 +34,42 @@ */ @Slf4j public class BsqCoinSelector extends BisqDefaultCoinSelector { - private DaoStateService daoStateService; + private final DaoStateService daoStateService; + private final UnconfirmedBsqChangeOutputListService unconfirmedBsqChangeOutputListService; @Inject - public BsqCoinSelector(DaoStateService daoStateService) { - super(true); + public BsqCoinSelector(DaoStateService daoStateService, UnconfirmedBsqChangeOutputListService unconfirmedBsqChangeOutputListService) { + // permitForeignPendingTx is not relevant here as we do not support pending foreign utxos anyway. + super(false); this.daoStateService = daoStateService; + this.unconfirmedBsqChangeOutputListService = unconfirmedBsqChangeOutputListService; } @Override protected boolean isTxOutputSpendable(TransactionOutput output) { // output.getParentTransaction() cannot be null as it is checked in calling method - return output.getParentTransaction() != null && - daoStateService.isTxOutputSpendable(new TxOutputKey(output.getParentTransaction().getHashAsString(), output.getIndex())); + Transaction parentTransaction = output.getParentTransaction(); + if (parentTransaction == null) + return false; + + // If it is a normal confirmed BSQ output we use the default lookup at the daoState + if (daoStateService.isTxOutputSpendable(new TxOutputKey(parentTransaction.getHashAsString(), output.getIndex()))) + return true; + + // It might be that it is an unconfirmed change output which we allow to be used for spending without requiring a confirmation. + // We check if we have the output in the dao state, if so we have a confirmed but unspendable output (e.g. confiscated). + if (daoStateService.getTxOutput(new TxOutputKey(parentTransaction.getHashAsString(), output.getIndex())).isPresent()) + return false; + + // Only if its not existing yet in the dao state (unconfirmed) we use our unconfirmedBsqChangeOutputList to + // check if it is an own change output. + return unconfirmedBsqChangeOutputListService.hasTransactionOutput(output); + } + + // For BSQ we do not check for dust attack utxos as they are 5.46 BSQ and a considerable value. + // The default 546 sat dust limit is handled in the BitcoinJ side anyway. + @Override + protected boolean isDustAttackUtxo(TransactionOutput output) { + return false; } } 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 ef9902e065f..49018f8bca9 100644 --- a/core/src/main/java/bisq/core/btc/wallet/BsqWalletService.java +++ b/core/src/main/java/bisq/core/btc/wallet/BsqWalletService.java @@ -17,18 +17,21 @@ package bisq.core.btc.wallet; -import bisq.core.app.BisqEnvironment; +import bisq.core.btc.exceptions.BsqChangeBelowDustException; import bisq.core.btc.exceptions.InsufficientBsqException; import bisq.core.btc.exceptions.TransactionVerificationException; import bisq.core.btc.exceptions.WalletException; import bisq.core.btc.listeners.BsqBalanceListener; import bisq.core.btc.setup.WalletsSetup; +import bisq.core.dao.DaoKillSwitch; import bisq.core.dao.state.DaoStateListener; import bisq.core.dao.state.DaoStateService; import bisq.core.dao.state.model.blockchain.Block; import bisq.core.dao.state.model.blockchain.Tx; import bisq.core.dao.state.model.blockchain.TxOutput; import bisq.core.dao.state.model.blockchain.TxOutputKey; +import bisq.core.dao.state.model.blockchain.TxType; +import bisq.core.dao.state.unconfirmed.UnconfirmedBsqChangeOutputListService; import bisq.core.provider.fee.FeeService; import bisq.core.user.Preferences; @@ -47,6 +50,7 @@ import org.bitcoinj.core.TransactionOutput; import org.bitcoinj.script.Script; import org.bitcoinj.wallet.CoinSelection; +import org.bitcoinj.wallet.CoinSelector; import org.bitcoinj.wallet.SendRequest; import org.bitcoinj.wallet.Wallet; import org.bitcoinj.wallet.listeners.AbstractWalletEventListener; @@ -79,6 +83,7 @@ public class BsqWalletService extends WalletService implements DaoStateListener private final BsqCoinSelector bsqCoinSelector; private final NonBsqCoinSelector nonBsqCoinSelector; private final DaoStateService daoStateService; + private final UnconfirmedBsqChangeOutputListService unconfirmedBsqChangeOutputListService; private final ObservableList walletTransactions = FXCollections.observableArrayList(); private final CopyOnWriteArraySet bsqBalanceListeners = new CopyOnWriteArraySet<>(); @@ -86,10 +91,12 @@ public class BsqWalletService extends WalletService implements DaoStateListener @Getter private Coin availableNonBsqBalance = Coin.ZERO; @Getter - private Coin availableBalance = Coin.ZERO; + private Coin availableConfirmedBalance = Coin.ZERO; @Getter private Coin unverifiedBalance = Coin.ZERO; @Getter + private Coin unconfirmedChangeBalance = Coin.ZERO; + @Getter private Coin lockedForVotingBalance = Coin.ZERO; @Getter private Coin lockupBondsBalance = Coin.ZERO; @@ -106,6 +113,7 @@ public BsqWalletService(WalletsSetup walletsSetup, BsqCoinSelector bsqCoinSelector, NonBsqCoinSelector nonBsqCoinSelector, DaoStateService daoStateService, + UnconfirmedBsqChangeOutputListService unconfirmedBsqChangeOutputListService, Preferences preferences, FeeService feeService) { super(walletsSetup, @@ -115,65 +123,65 @@ public BsqWalletService(WalletsSetup walletsSetup, this.bsqCoinSelector = bsqCoinSelector; this.nonBsqCoinSelector = nonBsqCoinSelector; this.daoStateService = daoStateService; + this.unconfirmedBsqChangeOutputListService = unconfirmedBsqChangeOutputListService; + + walletsSetup.addSetupCompletedHandler(() -> { + wallet = walletsSetup.getBsqWallet(); + if (wallet != null) { + wallet.setCoinSelector(bsqCoinSelector); + wallet.addEventListener(walletEventListener); + + //noinspection deprecation + wallet.addEventListener(new AbstractWalletEventListener() { + @Override + public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) { + updateBsqWalletTransactions(); + } - if (BisqEnvironment.isBaseCurrencySupportingBsq()) { - walletsSetup.addSetupCompletedHandler(() -> { - wallet = walletsSetup.getBsqWallet(); - if (wallet != null) { - wallet.setCoinSelector(bsqCoinSelector); - wallet.addEventListener(walletEventListener); - - //noinspection deprecation - wallet.addEventListener(new AbstractWalletEventListener() { - @Override - public void onCoinsReceived(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) { - updateBsqWalletTransactions(); - } - - @Override - public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) { - updateBsqWalletTransactions(); - } + @Override + public void onCoinsSent(Wallet wallet, Transaction tx, Coin prevBalance, Coin newBalance) { + updateBsqWalletTransactions(); + } - @Override - public void onReorganize(Wallet wallet) { - log.warn("onReorganize "); - updateBsqWalletTransactions(); - } + @Override + public void onReorganize(Wallet wallet) { + log.warn("onReorganize "); + updateBsqWalletTransactions(); + unconfirmedBsqChangeOutputListService.onReorganize(); + } - @Override - public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) { - updateBsqWalletTransactions(); - } + @Override + public void onTransactionConfidenceChanged(Wallet wallet, Transaction tx) { + updateBsqWalletTransactions(); + unconfirmedBsqChangeOutputListService.onTransactionConfidenceChanged(tx); + } - @Override - public void onKeysAdded(List keys) { - updateBsqWalletTransactions(); - } + @Override + public void onKeysAdded(List keys) { + updateBsqWalletTransactions(); + } - @Override - public void onScriptsChanged(Wallet wallet, List