Skip to content
This repository has been archived by the owner on Jun 17, 2020. It is now read-only.

Commit

Permalink
Redesign asset listing and validation infrastructure
Browse files Browse the repository at this point in the history
This change builds on initial work in prior commits to fundamentally
redesign the way we manage assets in Bisq.

Previously, assets were "listed" by adding them in several places,
mainly AltCoinAddressValidator and CurrencyUtil. This led to large and
growing classes that do everything and that are prone to merge conflicts
any time there is more than one open pull request to list an asset.

Now we have a new, top-level 'bisq.asset' package (we may want to
extract this to its own repository for several reasons). Within, we have
a first class concept of an 'Asset' (think "crypto asset", as in the most
general term possible for all different kinds of crypto currencies,
tokens, colored coins, etc.). Assets implementations are listed in the
META-INF/services/bisq.asset.Asset service-provider file.

Two subtypes of Asset exist: Coin and Token. 'Coin' is what we have
always meant when saying "altcoin" so far: i.e. a coin that has its own
blockchain. A 'Token' is an asset that does not have its own blockchain,
but rides on top of another through a smart contract, e.g. ERC-20
tokens. And indeed, there is an abstract Erc20Token subtype that captures
this common suitation and provides various conveniences.

In this commit, several assets have been extracted, including Bitcoin,
Bitcoin Cash, Ether, Instacash and Ellaism. Each represents an at least
somewhat different kind of asset, and therefore provided a good basis
for ensuring that the changes in this commit were sufficiently
generalized to accommodate the other asset extractions that will follow
in subsequent commits:

 - Bitcoin is a base currency for Bisq
 - Bitcoin Cash is a typcial Bitcoin-based altcoin
 - Instacash is another Bitcoin-based altcoin
 - Ether is a non Bitcoin-based altcoin
 - Ellaism is an ERC-20 token

A number of changes remain to be made in the new types introduced
here, including Javadoc, and this will be added prior to merging the
series of commits that will make up the overall pull request.

Also note that the tests in AltCoinAddressValidatorTest have been left
intact for now, as a means of double-checking that everything works as
expected from the application level.

It should also be noted that AltCoinAddressValidator is essentially
becoming a translation layer (an "anti-corruption layer" in DDD terms)
where the new 'bisq.asset' world meets the old AltCoinAddressValidator /
CurrencyUtil world that bisq-desktop already knows. It is intentional that
this refactoring has been isolated in this way, leaving the old
"contract" for AltCoinAddressValidator and CurrencyUtil intact. We can
see about refactoring bisq-desktop to deal more directly with the new
AssetRegistry interface in the future, but it is not necessary, and
indeed not desirable to do all of that now in this PR. The idea is to
redesign the underlying infrastructure now, enough to make it more
manageable to deal with going forward.
  • Loading branch information
cbeams committed Mar 27, 2018
1 parent 695053d commit cab46e2
Show file tree
Hide file tree
Showing 36 changed files with 746 additions and 379 deletions.
2 changes: 2 additions & 0 deletions .idea/codeStyles/Project.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

32 changes: 32 additions & 0 deletions src/main/java/bisq/asset/AbstractAsset.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package bisq.asset;

import static org.apache.commons.lang3.Validate.notBlank;
import static org.apache.commons.lang3.Validate.notNull;

public abstract class AbstractAsset implements Asset {

private final String name;
private final String tickerSymbol;
private final AddressValidator addressValidator;

public AbstractAsset(String name, String tickerSymbol, AddressValidator addressValidator) {
this.name = notBlank(name);
this.tickerSymbol = notBlank(tickerSymbol);
this.addressValidator = notNull(addressValidator);
}

@Override
public final String getName() {
return name;
}

@Override
public final String getTickerSymbol() {
return tickerSymbol;
}

@Override
public final AddressValidationResult validateAddress(String address) {
return addressValidator.validate(address);
}
}
65 changes: 65 additions & 0 deletions src/main/java/bisq/asset/AddressValidationResult.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
/*
* 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;

public class AddressValidationResult {

public static AddressValidationResult VALID = new AddressValidationResult(true);

private final boolean isValid;
private String message;
private String i18nKey;

private AddressValidationResult(boolean isValid) {
this.isValid = isValid;
}

private AddressValidationResult(boolean isValid, String message, String i18nKey) {
this(isValid);
this.message = message;
this.i18nKey = i18nKey;
}

public boolean isValid() {
return isValid;
}

public String getI18nKey() {
return i18nKey;
}

public String getMessage() {
return message;
}

public static AddressValidationResult validAddress() {
return VALID;
}

public static AddressValidationResult invalidStructure() {
return new AddressValidationResult(false, "", "validation.altcoin.wrongStructure");
}

public static AddressValidationResult invalidAddress(String cause) {
return new AddressValidationResult(false, cause, "validation.altcoin.invalidAddress");
}

public static AddressValidationResult invalidAddress(Throwable cause) {
return invalidAddress(cause.getMessage());
}
}
23 changes: 23 additions & 0 deletions src/main/java/bisq/asset/AddressValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
/*
* 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;

public interface AddressValidator {

AddressValidationResult validate(String address);
}
10 changes: 10 additions & 0 deletions src/main/java/bisq/asset/Asset.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
package bisq.asset;

public interface Asset {

String getName();

String getTickerSymbol();

AddressValidationResult validateAddress(String address);
}
38 changes: 38 additions & 0 deletions src/main/java/bisq/asset/AssetRegistry.java
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/

package bisq.asset;

import java.util.ArrayList;
import java.util.List;
import java.util.ServiceLoader;
import java.util.stream.Stream;

public class AssetRegistry {

private static final List<Asset> registeredAssets = new ArrayList<>();

static {
for (Asset asset : ServiceLoader.load(Asset.class)) {
registeredAssets.add(asset);
}
}

public Stream<Asset> stream() {
return registeredAssets.stream();
}
}
47 changes: 47 additions & 0 deletions src/main/java/bisq/asset/Base58BitcoinAddressValidator.java
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/

package bisq.asset;

import org.bitcoinj.core.Address;
import org.bitcoinj.core.AddressFormatException;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.params.MainNetParams;

public class Base58BitcoinAddressValidator implements AddressValidator {

private final NetworkParameters networkParameters;

public Base58BitcoinAddressValidator() {
this(MainNetParams.get());
}

public Base58BitcoinAddressValidator(NetworkParameters networkParameters) {
this.networkParameters = networkParameters;
}

@Override
public AddressValidationResult validate(String address) {
try {
Address.fromBase58(networkParameters, address);
} catch (AddressFormatException ex) {
return AddressValidationResult.invalidAddress(ex);
}

return AddressValidationResult.validAddress();
}
}
38 changes: 38 additions & 0 deletions src/main/java/bisq/asset/Coin.java
Original file line number Diff line number Diff line change
@@ -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 <http://www.gnu.org/licenses/>.
*/

package bisq.asset;

public abstract class Coin extends AbstractAsset {

public enum Network { MAINNET, TESTNET, REGTEST }

private final Network network;

public Coin(String name, String tickerSymbol, AddressValidator addressValidator) {
this(name, tickerSymbol, addressValidator, Network.MAINNET);
}

public Coin(String name, String tickerSymbol, AddressValidator addressValidator, Network network) {
super(name, tickerSymbol, addressValidator);
this.network = network;
}

public Network getNetwork() {
return network;
}
}
25 changes: 25 additions & 0 deletions src/main/java/bisq/asset/Erc20Token.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
/*
* 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;

public abstract class Erc20Token extends Token {

public Erc20Token(String name, String tickerSymbol) {
super(name, tickerSymbol, new EtherAddressValidator());
}
}
26 changes: 26 additions & 0 deletions src/main/java/bisq/asset/EtherAddressValidator.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
/*
* 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;

public class EtherAddressValidator extends RegexAddressValidator {

public EtherAddressValidator() {
// https://github.com/ethereum/web3.js/blob/master/lib/utils/utils.js#L403
super("^(0x)?[0-9a-fA-F]{40}$");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.core.payment.validation.params;
package bisq.asset;

import org.bitcoinj.core.BitcoinSerializer;
import org.bitcoinj.core.Block;
Expand All @@ -27,26 +27,8 @@
import org.bitcoinj.store.BlockStoreException;
import org.bitcoinj.utils.MonetaryFormat;

public class ICHParams extends NetworkParameters {
public abstract class NetworkParametersAdapter extends NetworkParameters {

private static ICHParams instance;

public static synchronized ICHParams get() {
if (instance == null) {
instance = new ICHParams();
}
return instance;
}

// We only use the properties needed for address validation
public ICHParams() {
super();
addressHeader = 23;
p2shHeader = 13;
acceptableAddressCodes = new int[]{addressHeader, p2shHeader};
}

// default dummy implementations, not used...
@Override
public String getPaymentProtocolId() {
return PAYMENT_PROTOCOL_ID_MAINNET;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,22 +15,21 @@
* along with Bisq. If not, see <http://www.gnu.org/licenses/>.
*/

package bisq.core.payment;
package bisq.asset;

import bisq.core.payment.validation.AssetProviderRegistry;
public class RegexAddressValidator implements AddressValidator {

import bisq.common.app.AppModule;
private final String regex;

import org.springframework.core.env.Environment;

public class PaymentModule extends AppModule {

public PaymentModule(Environment environment) {
super(environment);
public RegexAddressValidator(String regex) {
this.regex = regex;
}

@Override
protected final void configure() {
bind(AssetProviderRegistry.class).toInstance(AssetProviderRegistry.getInstance());
public AddressValidationResult validate(String address) {
if (!address.matches(regex))
return AddressValidationResult.invalidStructure();

return AddressValidationResult.validAddress();
}
}
Loading

0 comments on commit cab46e2

Please sign in to comment.