From 0fc1a38588bc57fe5bd393ae2531b31b634cdd96 Mon Sep 17 00:00:00 2001 From: Bernard Labno Date: Thu, 29 Mar 2018 09:53:29 +0200 Subject: [PATCH] Extract Koto --- src/main/java/bisq/asset/coins/Koto.java | 91 +++++++++++++++++++ .../java/bisq/core/locale/CurrencyUtil.java | 1 - .../validation/AltCoinAddressValidator.java | 3 - .../altcoins/KOTOAddressValidator.java | 80 ---------------- .../META-INF/services/bisq.asset.Asset | 1 + src/test/java/bisq/asset/coins/KotoTest.java | 45 +++++++++ 6 files changed, 137 insertions(+), 84 deletions(-) create mode 100644 src/main/java/bisq/asset/coins/Koto.java delete mode 100644 src/main/java/bisq/core/payment/validation/altcoins/KOTOAddressValidator.java create mode 100644 src/test/java/bisq/asset/coins/KotoTest.java diff --git a/src/main/java/bisq/asset/coins/Koto.java b/src/main/java/bisq/asset/coins/Koto.java new file mode 100644 index 00000000..7a8dd574 --- /dev/null +++ b/src/main/java/bisq/asset/coins/Koto.java @@ -0,0 +1,91 @@ +/* + * This file is part of Bisq. + * + * Bisq is free software: you can redistribute it and/or modify it + * under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation, either version 3 of the License, or (at + * your option) any later version. + * + * Bisq is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU Affero General Public + * License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with Bisq. If not, see . + */ + +package bisq.asset.coins; + +import bisq.asset.AddressValidationResult; +import bisq.asset.AddressValidator; +import bisq.asset.Coin; + +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import java.util.Arrays; + +public class Koto extends Coin { + + public Koto() { + super("Koto", "KOTO", new KotoAddressValidator()); + } + + + public static class KotoAddressValidator implements AddressValidator { + private final static String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; + + @Override + public AddressValidationResult validate(String address) { + if (address.startsWith("z")) + return AddressValidationResult.invalidAddress("KOTO_Addr_Invalid: z Address not supported!"); + if (address.length() != 35) + return AddressValidationResult.invalidAddress("KOTO_Addr_Invalid: Length must be 35!"); + if (!address.startsWith("k1") && !address.startsWith("jz")) + return AddressValidationResult.invalidAddress("KOTO_Addr_Invalid: must start with 'k1' or 'jz'!"); + byte[] decoded = decodeBase58(address, 58, 26); + if (decoded == null) + return AddressValidationResult.invalidAddress("KOTO_Addr_Invalid: Base58 decoder error!"); + + byte[] hash = getSha256(decoded, 0, 22, 2); + if (hash == null || !Arrays.equals(Arrays.copyOfRange(hash, 0, 4), Arrays.copyOfRange(decoded, 22, 26))) + return AddressValidationResult.invalidAddress("KOTO_Addr_Invalid: Checksum error!"); + + return AddressValidationResult.validAddress(); + + } + + private static byte[] decodeBase58(String input, int base, int len) { + byte[] output = new byte[len]; + for (int i = 0; i < input.length(); i++) { + char t = input.charAt(i); + + int p = ALPHABET.indexOf(t); + if (p == -1) + return null; + for (int j = len - 1; j >= 0; j--, p /= 256) { + p += base * (output[j] & 0xFF); + output[j] = (byte) (p % 256); + } + if (p != 0) + return null; + } + + return output; + } + + private static byte[] getSha256(byte[] data, int start, int len, int recursion) { + if (recursion == 0) + return data; + + try { + MessageDigest md = MessageDigest.getInstance("SHA-256"); + md.update(Arrays.copyOfRange(data, start, start + len)); + return getSha256(md.digest(), 0, 32, recursion - 1); + } catch (NoSuchAlgorithmException e) { + return null; + } + } + } +} diff --git a/src/main/java/bisq/core/locale/CurrencyUtil.java b/src/main/java/bisq/core/locale/CurrencyUtil.java index b4b35e82..90235a9f 100644 --- a/src/main/java/bisq/core/locale/CurrencyUtil.java +++ b/src/main/java/bisq/core/locale/CurrencyUtil.java @@ -138,7 +138,6 @@ private static List createAllSortedCryptoCurrenciesList() { result.add(new CryptoCurrency("XZC", "Zcoin")); // Added 0.7.0 - result.add(new CryptoCurrency("KOTO", "Koto")); result.add(new CryptoCurrency("UBQ", "Ubiq")); result.add(new CryptoCurrency("QWARK", "Qwark", true)); result.add(new CryptoCurrency("GEO", "GeoCoin", true)); diff --git a/src/main/java/bisq/core/payment/validation/AltCoinAddressValidator.java b/src/main/java/bisq/core/payment/validation/AltCoinAddressValidator.java index 52f0e831..1058f572 100644 --- a/src/main/java/bisq/core/payment/validation/AltCoinAddressValidator.java +++ b/src/main/java/bisq/core/payment/validation/AltCoinAddressValidator.java @@ -20,7 +20,6 @@ import bisq.core.app.BisqEnvironment; import bisq.core.btc.BaseCurrencyNetwork; import bisq.core.locale.Res; -import bisq.core.payment.validation.altcoins.KOTOAddressValidator; import bisq.core.payment.validation.params.PhoreParams; import bisq.core.util.validation.InputValidator; @@ -85,8 +84,6 @@ public ValidationResult validate(String input) { } switch (currencyCode) { - case "KOTO": - return KOTOAddressValidator.ValidateAddress(input); case "UBQ": if (!input.matches("^(0x)?[0-9a-fA-F]{40}$")) return regexTestFailed; diff --git a/src/main/java/bisq/core/payment/validation/altcoins/KOTOAddressValidator.java b/src/main/java/bisq/core/payment/validation/altcoins/KOTOAddressValidator.java deleted file mode 100644 index a5ac3b35..00000000 --- a/src/main/java/bisq/core/payment/validation/altcoins/KOTOAddressValidator.java +++ /dev/null @@ -1,80 +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.payment.validation.altcoins; - - -import bisq.core.util.validation.InputValidator.ValidationResult; - -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; - -import java.util.Arrays; - -public class KOTOAddressValidator { - private final static String ALPHABET = "123456789ABCDEFGHJKLMNPQRSTUVWXYZabcdefghijkmnopqrstuvwxyz"; - - public static ValidationResult ValidateAddress(String addr) { - if (addr.startsWith("z")) - return new ValidationResult(false, "KOTO_Addr_Invalid: z Address not supported!"); - if (addr.length() != 35) - return new ValidationResult(false, "KOTO_Addr_Invalid: Length must be 35!"); - if (!addr.startsWith("k1") && !addr.startsWith("jz")) - return new ValidationResult(false, "KOTO_Addr_Invalid: must start with 'k1' or 'jz'!"); - byte[] decoded = decodeBase58(addr, 58, 26); - if (decoded == null) - return new ValidationResult(false, "KOTO_Addr_Invalid: Base58 decoder error!"); - - byte[] hash = getSha256(decoded, 0, 22, 2); - if (hash == null || !Arrays.equals(Arrays.copyOfRange(hash, 0, 4), Arrays.copyOfRange(decoded, 22, 26))) - return new ValidationResult(false, "KOTO_Addr_Invalid: Checksum error!"); - - return new ValidationResult(true); - } - - private static byte[] decodeBase58(String input, int base, int len) { - byte[] output = new byte[len]; - for (int i = 0; i < input.length(); i++) { - char t = input.charAt(i); - - int p = ALPHABET.indexOf(t); - if (p == -1) - return null; - for (int j = len - 1; j >= 0; j--, p /= 256) { - p += base * (output[j] & 0xFF); - output[j] = (byte) (p % 256); - } - if (p != 0) - return null; - } - - return output; - } - - private static byte[] getSha256(byte[] data, int start, int len, int recursion) { - if (recursion == 0) - return data; - - try { - MessageDigest md = MessageDigest.getInstance("SHA-256"); - md.update(Arrays.copyOfRange(data, start, start + len)); - return getSha256(md.digest(), 0, 32, recursion - 1); - } catch (NoSuchAlgorithmException e) { - return null; - } - } -} diff --git a/src/main/resources/META-INF/services/bisq.asset.Asset b/src/main/resources/META-INF/services/bisq.asset.Asset index c704f917..23854ab5 100644 --- a/src/main/resources/META-INF/services/bisq.asset.Asset +++ b/src/main/resources/META-INF/services/bisq.asset.Asset @@ -28,6 +28,7 @@ bisq.asset.coins.Ether bisq.asset.coins.InfinityEconomics bisq.asset.coins.Instacash bisq.asset.coins.InternetOfPeople +bisq.asset.coins.Koto bisq.asset.coins.Litecoin$Mainnet bisq.asset.coins.Litecoin$Regtest bisq.asset.coins.Litecoin$Testnet diff --git a/src/test/java/bisq/asset/coins/KotoTest.java b/src/test/java/bisq/asset/coins/KotoTest.java new file mode 100644 index 00000000..af6efae4 --- /dev/null +++ b/src/test/java/bisq/asset/coins/KotoTest.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 KotoTest extends AbstractAssetTest { + + public KotoTest() { + super(new Koto()); + } + + @Test + public void testValidAddresses() { + assertValidAddress("k13dNgJJjf1SCU2Xv2jLnuUb5Q7zZx7P9vW"); + assertValidAddress("k1BGB7dreqk9yCVEjC5sqjStfRxMUHiVtTg"); + assertValidAddress("jzz6Cgk8wYy7MXZH5TCSxHbe6exCKmhXk8N"); + } + + @Test + public void testInvalidAddresses() { + assertInvalidAddress("K1JqGEiRi3pApex3rButyuFN8HVEji9dygo"); + assertInvalidAddress("k2De32yyMZ8xdDFBJXjVseiN99S9eJpvty5"); + assertInvalidAddress("jyzCuxaXN38djCzdkb8nQs7v1joHWtkC4v8"); + assertInvalidAddress("JzyNxmc9iDaGokmMrkmMCncfMQvw5vbHBKv"); + assertInvalidAddress("zkPRkLZKf4BuzBsC6r9Ls5suw1ZV9tCwiBTF5vcz2NZLUDsoXGp5rAFUjKnb7DdkFbLp7aSpejCcC4FTxsVvDxq9YKSprzf"); + } +}