Skip to content

Commit

Permalink
Merge pull request #2217 from ManfredKarrer/list-grin
Browse files Browse the repository at this point in the history
Add Grin
  • Loading branch information
ripcurlx committed Jan 8, 2019
2 parents df1a05c + 05f6c87 commit 88a7292
Show file tree
Hide file tree
Showing 4 changed files with 211 additions and 0 deletions.
106 changes: 106 additions & 0 deletions assets/src/main/java/bisq/asset/GrinAddressValidator.java
@@ -0,0 +1,106 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/

package bisq.asset;

/**
* The supported "address" (better wallet URL) format is IP:port or the grinbox format.
*
* Here is the information from a conversation with the Grinbox developer regarding the Grinbox address format.
*
A Grinbox address is of the format: grinbox://<key>@domain.com:port where everything besides <key> is optional.
If no domain is specified, the default relay grinbox.io will be used.
The <key> 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://<key>@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 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}$";

public GrinAddressValidator() {
}

@Override
public AddressValidationResult validate(String address) {
if (address == null || address.length() == 0)
return AddressValidationResult.invalidAddress("Address may not be empty");

if (address.matches("^" + IPV4 + ":" + PORT))
return AddressValidationResult.validAddress();


// We might have a 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");

if (domain != null && !domain.matches("^" + DOMAIN))
return AddressValidationResult.invalidAddress("Invalid domain");

if (port != null && !port.matches("^" + PORT))
return AddressValidationResult.invalidAddress("Invalid port");

return AddressValidationResult.validAddress();

}
}
28 changes: 28 additions & 0 deletions assets/src/main/java/bisq/asset/coins/Grin.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 <http://www.gnu.org/licenses/>.
*/

package bisq.asset.coins;

import bisq.asset.Coin;
import bisq.asset.GrinAddressValidator;

public class Grin extends Coin {

public Grin() {
super("Grin", "GRIN", new GrinAddressValidator());
}
}
Expand Up @@ -25,6 +25,7 @@ bisq.asset.coins.Dragonglass
bisq.asset.coins.Ether
bisq.asset.coins.EtherClassic
bisq.asset.coins.GambleCoin
bisq.asset.coins.Grin
bisq.asset.coins.FourtyTwo
bisq.asset.coins.Gridcoin
bisq.asset.coins.Horizen
Expand Down
76 changes: 76 additions & 0 deletions assets/src/test/java/bisq/asset/coins/GrinTest.java
@@ -0,0 +1,76 @@
/*
* 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 <http://www.gnu.org/licenses/>.
*/

package bisq.asset.coins;

import bisq.asset.AbstractAssetTest;

import org.junit.Test;

public class GrinTest extends AbstractAssetTest {

public GrinTest() {
super(new Grin());
}

@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");
assertValidAddress("gVw9TWimGFXRjoDXWhWxeNQbu84ZpLkvnenkKvA5aJeDo31eM5tC@somerelay.com");
assertValidAddress("gVw9TWimGFXRjoDXWhWxeNQbu84ZpLkvnenkKvA5aJeDo31eM5tC@somerelay.com:1220");
assertValidAddress("grinbox://gVwjSsYW5vvHpK4AunJ5piKhhQTV6V3Jb818Uqs6PdC3SsB36AsA@somerelay.com");
assertValidAddress("grinbox://gVwjSsYW5vvHpK4AunJ5piKhhQTV6V3Jb818Uqs6PdC3SsB36AsA@somerelay.com:1220");
}

@Test
public void testInvalidAddresses() {
assertInvalidAddress("google.com");
assertInvalidAddress("100.100.100.100");
assertInvalidAddress(".100.100.100.100:1222");
assertInvalidAddress("100..100.100.100:1222.");
assertInvalidAddress("100.100.100.100.:1222");
assertInvalidAddress("999.999.999.999:1222");
assertInvalidAddress("256.256.256.256:1222");
assertInvalidAddress("256.100.100.100.100:1222");
assertInvalidAddress("123.123.123:1222");
assertInvalidAddress("http://123.123.123:1222");
assertInvalidAddress("1000.2.3.4:1222");
assertInvalidAddress("999.2.3.4:1222");
// too large port
assertInvalidAddress("173.194.34.134:65536");

assertInvalidAddress("gVvk7rLBg3r3qoWYL3VsREnBbooT7nynxx5HtDvUWCJUaNCnddvY1111");
assertInvalidAddress("grinbox:/gVtWzX5NTLCBkyNV19QVdnLXue13heAVRD36sfkGD6xpqy7k7e4a");
assertInvalidAddress("gVw9TWimGFXRjoDXWhWxeNQbu84ZpLkvnenkKvA5aJeDo31eM5tC@somerelay.com.");
assertInvalidAddress("gVw9TWimGFXRjoDXWhWxeNQbu84ZpLkvnenkKvA5aJeDo31eM5tC@somerelay.com:1220a");
assertInvalidAddress("grinbox://gVwjSsYW5vvHpK4AunJ5piKhhQTV6V3Jb818Uqs6PdC3SsB36AsAsomerelay.com");
assertInvalidAddress("grinbox://gVwjSsYW5vvHpK4AunJ5piKhhQTV6V3Jb818Uqs6PdC3SsB36AsA@somerelay.com1220");

}
}

0 comments on commit 88a7292

Please sign in to comment.