From 5bf7bba0c661ffecadc71962c2b13a12ec56f40a Mon Sep 17 00:00:00 2001
From: jmacxx <47253594+jmacxx@users.noreply.github.com>
Date: Wed, 10 Nov 2021 14:23:04 -0600
Subject: [PATCH] Changes required for GRIN re-listing
---
.../java/bisq/asset/GrinAddressValidator.java | 102 ------------------
.../src/main/java/bisq/asset/coins/Grin.java | 29 ++++-
.../test/java/bisq/asset/coins/GrinTest.java | 26 +++--
.../resources/i18n/displayStrings.properties | 10 +-
4 files changed, 50 insertions(+), 117 deletions(-)
delete mode 100644 assets/src/main/java/bisq/asset/GrinAddressValidator.java
diff --git a/assets/src/main/java/bisq/asset/GrinAddressValidator.java b/assets/src/main/java/bisq/asset/GrinAddressValidator.java
deleted file mode 100644
index f397bca0bae..00000000000
--- a/assets/src/main/java/bisq/asset/GrinAddressValidator.java
+++ /dev/null
@@ -1,102 +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;
-
-/**
- * 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.
- *
- A Grinbox address is of the format: grinbox://@domain.com:port where everything besides is optional.
- If no domain is specified, the default relay grinbox.io will be used.
-
- The is a base58check encoded value (like in Bitcoin). For Grin mainnet, the first 2 bytes will be [1, 11] and
- the following 33 bytes should be a valid secp256k1 compressed public key.
-
- Some examples of valid addresses are:
-
- gVvRNiuopubvxPrs1BzJdQjVdFAxmkLzMqiVJzUZ7ubznhdtNTGB
- gVvUcSafSTD3YTSqgNf9ojEYWkz3zMZNfsjdpdb9en5mxc6gmja6
- gVvk7rLBg3r3qoWYL3VsREnBbooT7nynxx5HtDvUWCJUaNCnddvY
- grinbox://gVtWzX5NTLCBkyNV19QVdnLXue13heAVRD36sfkGD6xpqy7k7e4a
- gVw9TWimGFXRjoDXWhWxeNQbu84ZpLkvnenkKvA5aJeDo31eM5tC@somerelay.com
- grinbox://gVwjSsYW5vvHpK4AunJ5piKhhQTV6V3Jb818Uqs6PdC3SsB36AsA@somerelay.com:1220
-
- Some examples of invalid addresses are:
-
- gVuBJDKcWkhueMfBLAbFwV4ax55YXPeinWXdRME1Zi3eiC6sFNye (invalid checksum)
- geWGCMQjxZMHG3EtTaRbR7rH9rE4DsmLfpm1iiZEa7HFKjjkgpf2 (wrong version bytes)
- gVvddC2jYAfxTxnikcbTEQKLjhJZpqpBg39tXkwAKnD2Pys2mWiK (invalid public key)
-
- We only add the basic validation without checksum, version byte and pubkey validation as that would require much more
- effort. Any Grin developer is welcome to add that though!
-
- */
-public class GrinAddressValidator implements AddressValidator {
- // A Grin Wallet URL (address is not the correct term) can be in the form IP:port or a grinbox format.
- // The grinbox has the format grinbox://@domain.com:port where everything beside the key is optional.
-
-
- // Regex for IP validation borrowed from https://stackoverflow.com/questions/53497/regular-expression-that-matches-valid-ipv6-addresses
- 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}$";
-
- public GrinAddressValidator() {
- }
-
- @Override
- public AddressValidationResult validate(String address) {
- if (address == null || address.length() == 0)
- return AddressValidationResult.invalidAddress("Address may not be empty (only Grinbox format is supported)");
-
- // We only support grinbox address
- String key;
- String domain = null;
- String port = null;
- address = address.replace("grinbox://", "");
- if (address.contains("@")) {
- String[] keyAndDomain = address.split("@");
- key = keyAndDomain[0];
- if (keyAndDomain.length > 1) {
- domain = keyAndDomain[1];
- if (domain.contains(":")) {
- String[] domainAndPort = domain.split(":");
- domain = domainAndPort[0];
- if (domainAndPort.length > 1)
- port = domainAndPort[1];
- }
- }
- } else {
- key = address;
- }
-
- if (!key.matches("^" + KEY))
- return AddressValidationResult.invalidAddress("Invalid key (only Grinbox format is supported)");
-
- if (domain != null && !domain.matches("^" + DOMAIN))
- return AddressValidationResult.invalidAddress("Invalid domain (only Grinbox format is supported)");
-
- if (port != null && !port.matches("^" + PORT))
- return AddressValidationResult.invalidAddress("Invalid port (only Grinbox format is supported)");
-
- return AddressValidationResult.validAddress();
-
- }
-}
diff --git a/assets/src/main/java/bisq/asset/coins/Grin.java b/assets/src/main/java/bisq/asset/coins/Grin.java
index 7812aacc294..b73c863284b 100644
--- a/assets/src/main/java/bisq/asset/coins/Grin.java
+++ b/assets/src/main/java/bisq/asset/coins/Grin.java
@@ -17,14 +17,39 @@
package bisq.asset.coins;
+import bisq.asset.AddressValidationResult;
+import bisq.asset.AddressValidator;
import bisq.asset.AltCoinAccountDisclaimer;
import bisq.asset.Coin;
-import bisq.asset.GrinAddressValidator;
+
+import org.bitcoinj.core.AddressFormatException;
+import org.bitcoinj.core.Bech32;
@AltCoinAccountDisclaimer("account.altcoin.popup.grin.msg")
public class Grin extends Coin {
+ static String coinName = "Grin";
+
public Grin() {
- super("Grin", "GRIN", new GrinAddressValidator());
+ super(coinName, coinName.toUpperCase(), new GrinAddressValidator());
+ }
+
+ public static class GrinAddressValidator implements AddressValidator {
+
+ @Override
+ public AddressValidationResult validate(String address) {
+ try {
+ Bech32.Bech32Data bechData = Bech32.decode(address);
+ if (!bechData.hrp.equals(coinName.toLowerCase())) {
+ return AddressValidationResult.invalidAddress(String.format("invalid address prefix %x", bechData.hrp));
+ }
+ if (bechData.data.length != 52) {
+ return AddressValidationResult.invalidAddress(String.format("invalid address length %x", bechData.data.length));
+ }
+ return AddressValidationResult.validAddress();
+ } catch (AddressFormatException e) {
+ return AddressValidationResult.invalidStructure();
+ }
+ }
}
}
diff --git a/assets/src/test/java/bisq/asset/coins/GrinTest.java b/assets/src/test/java/bisq/asset/coins/GrinTest.java
index 83b602607a8..bea8d71cae8 100644
--- a/assets/src/test/java/bisq/asset/coins/GrinTest.java
+++ b/assets/src/test/java/bisq/asset/coins/GrinTest.java
@@ -29,17 +29,29 @@ public GrinTest() {
@Test
public void testValidAddresses() {
- // grinbox
- assertValidAddress("gVvk7rLBg3r3qoWYL3VsREnBbooT7nynxx5HtDvUWCJUaNCnddvY");
- assertValidAddress("grinbox://gVtWzX5NTLCBkyNV19QVdnLXue13heAVRD36sfkGD6xpqy7k7e4a");
- assertValidAddress("gVw9TWimGFXRjoDXWhWxeNQbu84ZpLkvnenkKvA5aJeDo31eM5tC@somerelay.com");
- assertValidAddress("gVw9TWimGFXRjoDXWhWxeNQbu84ZpLkvnenkKvA5aJeDo31eM5tC@somerelay.com:1220");
- assertValidAddress("grinbox://gVwjSsYW5vvHpK4AunJ5piKhhQTV6V3Jb818Uqs6PdC3SsB36AsA@somerelay.com");
- assertValidAddress("grinbox://gVwjSsYW5vvHpK4AunJ5piKhhQTV6V3Jb818Uqs6PdC3SsB36AsA@somerelay.com:1220");
+ // valid slatepack addresses
+ assertValidAddress("grin1ephxt0u33rz9zpl7exer2awfr9s9ae28qsx7908q2zq03uv3sj7suqdule");
+ assertValidAddress("grin1wwg5k80qje0lw32ldttgl52lew0ucmv64zux27pzanl0a2ku85ps5gxafa");
+ assertValidAddress("grin1mdxxaz8g5zc4fhqcvcu79c0sp3md9j2f6tt5cxde78scjatkh3zqzrgl9r");
+ assertValidAddress("grin17whxsfzj3su0rtpd3hkcjt3hlatvc89dpc9syvrmq2shhnhc9f6sehqe3x");
+ assertValidAddress("grin1cq636ment795xn68knzu0ewp73f3zdlgv6dsqv8x7vf2v0j4ek5sk6nmk3");
+ assertValidAddress("grin1wm78wjsf2ws507hea4zqrcywxltjwhtgfrwzhdrr9l80l7tpz5fsj58lk0");
+ assertValidAddress("grin1jezf3lkcexvj3ydjwanan6khs42fr4036guh0c4vkc04fyxarl6svjzuuh");
}
@Test
public void testInvalidAddresses() {
+ // invalid slatepack address (bech32 format invalid)
+ assertInvalidAddress("grin1p4fuklglxqsgg602hu4c4jl4aunu5tynyf4lkg96ezh3jefzpy6swshp5x"); // from 0015-slatepack.md#slatepackaddress
+
+ // grinbox
+ assertInvalidAddress("gVvk7rLBg3r3qoWYL3VsREnBbooT7nynxx5HtDvUWCJUaNCnddvY");
+ assertInvalidAddress("grinbox://gVtWzX5NTLCBkyNV19QVdnLXue13heAVRD36sfkGD6xpqy7k7e4a");
+ assertInvalidAddress("gVw9TWimGFXRjoDXWhWxeNQbu84ZpLkvnenkKvA5aJeDo31eM5tC@somerelay.com");
+ assertInvalidAddress("gVw9TWimGFXRjoDXWhWxeNQbu84ZpLkvnenkKvA5aJeDo31eM5tC@somerelay.com:1220");
+ assertInvalidAddress("grinbox://gVwjSsYW5vvHpK4AunJ5piKhhQTV6V3Jb818Uqs6PdC3SsB36AsA@somerelay.com");
+ assertInvalidAddress("grinbox://gVwjSsYW5vvHpK4AunJ5piKhhQTV6V3Jb818Uqs6PdC3SsB36AsA@somerelay.com:1220");
+
// valid IP:port addresses but not supported in Bisq
assertInvalidAddress("0.0.0.0:8080");
assertInvalidAddress("173.194.34.134:8080");
diff --git a/core/src/main/resources/i18n/displayStrings.properties b/core/src/main/resources/i18n/displayStrings.properties
index c0102446e7b..c3eead303db 100644
--- a/core/src/main/resources/i18n/displayStrings.properties
+++ b/core/src/main/resources/i18n/displayStrings.properties
@@ -1729,15 +1729,13 @@ account.altcoin.popup.XZC.msg=When using Zcoin you can only use the transparent
the untraceable addresses, because the mediator or arbitrator would not be able to verify the transaction with untraceable addresses at a block explorer.
# suppress inspection "UnusedProperty"
account.altcoin.popup.grin.msg=GRIN requires an interactive process between the sender and receiver to create the \
- transaction. Be sure to follow the instructions from the GRIN project web page to reliably send and receive GRIN \
- (the receiver needs to be online or at least be online during a certain time frame). \n\n\
- Bisq supports only the Grinbox (Wallet713) wallet URL format. \n\n\
+ transaction. Be sure to follow the instructions from the GRIN project web page [HYPERLINK:https://grin.mw] to reliably send and receive GRIN. \
+ More information on transacting GRIN can be found here [HYPERLINK:https://docs.grin.mw/about-grin/transactions/].\n\n\
The GRIN sender is required to provide proof that they have sent GRIN successfully. If the wallet cannot provide that proof, a \
potential dispute will be resolved in favor of the GRIN receiver. Please be sure that you use the \
- latest Grinbox software which supports the transaction proof and that you understand the process of transferring and \
+ latest GRIN software which supports the transaction proof and that you understand the process of transferring and \
receiving GRIN as well as how to create the proof. \n\n\
- See https://github.com/vault713/wallet713/blob/master/docs/usage.md#transaction-proofs-grinbox-only for more \
- information about the Grinbox proof tool.
+ See [HYPERLINK:https://bisq.wiki/Trading_GRIN] for more information about trading GRIN on Bisq.
# suppress inspection "UnusedProperty"
account.altcoin.popup.beam.msg=BEAM requires an interactive process between the sender and receiver to create the \
transaction. \n\n\