AddressParser: simpler address parsing by making it a @FunctionalInterface

We`re making `AddressParser` the `@FunctionalInterface` and a nested class
is used to define an `AddressParserProvider`
This commit is contained in:
Sean Gilligan 2023-07-18 13:46:45 -07:00 committed by Andreas Schildbach
parent 39c34186cc
commit dead2c74ab
14 changed files with 145 additions and 102 deletions

View file

@ -26,8 +26,7 @@ import java.util.Comparator;
/**
* Interface for addresses, e.g. native segwit addresses ({@link SegwitAddress}) or legacy addresses ({@link LegacyAddress}).
* <p>
* Use an implementation of {@link AddressParser#parseAddress(String, Network)} to conveniently construct any kind of address from its textual
* form.
* Use {@link AddressParser} to construct any kind of address from its textual form.
*/
public interface Address extends Comparable<Address> {
/**
@ -42,15 +41,12 @@ public interface Address extends Comparable<Address> {
* if the given string doesn't parse or the checksum is invalid
* @throws AddressFormatException.WrongNetwork
* if the given string is valid but not for the expected network (eg testnet vs mainnet)
* @deprecated Use {@link org.bitcoinj.wallet.Wallet#parseAddress(String)} or {@link AddressParser#parseAddress(String, Network)}
* @deprecated Use {@link org.bitcoinj.wallet.Wallet#parseAddress(String)} or {@link AddressParser#parseAddress(String)}
*/
@Deprecated
static Address fromString(@Nullable NetworkParameters params, String str)
throws AddressFormatException {
AddressParser addressParser = DefaultAddressParser.fromNetworks();
return (params != null)
? addressParser.parseAddress(str, params.network())
: addressParser.parseAddressAnyNetwork(str);
return AddressParser.getLegacy(params).parseAddress(str);
}
/**

View file

@ -17,42 +17,93 @@
package org.bitcoinj.base;
import org.bitcoinj.base.exceptions.AddressFormatException;
import org.bitcoinj.core.NetworkParameters;
import javax.annotation.Nullable;
/**
* Interface for parsing and validating address strings.
* Functional interface for address parsing. It takes a single parameter, but its behavior is context-specific. For example if the
* function was created with ({@link AddressParser#getDefault(Network)} it will only parse addresses for a single expected
* value of {@link Network}. Or, if created with {@link AddressParser#getDefault()} it will parse addresses matching any
* network. The default set of known networks is defined by {@link BitcoinNetwork}, but be aware that the {@link Address#network()} value
* is normalized (see {@link Address} for details.
*/
@FunctionalInterface
public interface AddressParser {
/**
* Parse an address that could be for any network
* Parse an address for any known/configured network
* @param addressString string representation of address
* @return A validated address object
* @throws AddressFormatException invalid address string
*/
Address parseAddressAnyNetwork(String addressString) throws AddressFormatException;
Address parseAddress(String addressString) throws AddressFormatException;
/**
* Parse an address and validate for specified network
* @param addressString string representation of address
* @param network the network the address string must represent
* @return A validated address object
* @throws AddressFormatException invalid address string or not valid for specified network
* @return The default parser for address and networks types built-in to bitcoinj.
*/
Address parseAddress(String addressString, Network network) throws AddressFormatException;
/**
* Functional interface for strict parsing. It takes a single parameter, like {@link AddressParser#parseAddressAnyNetwork(String)}
* but is used in a context where a specific {@link Network} has been specified. This interface may be
* implemented by creating a partial application of ({@link AddressParser#parseAddress(String, Network)} providing
* a fixed value for {@link Network}.
*/
@FunctionalInterface
interface Strict {
/**
* Parse an address in a strict context (e.g. the network must be valid)
* @param addressString string representation of address
* @return A validated address object
* @throws AddressFormatException invalid address string or not valid for network (provided by context)
*/
Address parseAddress(String addressString) throws AddressFormatException;
static AddressParser getDefault() {
return new DefaultAddressParserProvider().forKnownNetworks();
}
/**
* @param network the network to parse for
* @return The default (built-in) parser for network
*/
static AddressParser getDefault(Network network) {
return new DefaultAddressParserProvider().forNetwork(network);
}
/**
* Interface implemented by custom address parser providers.
*/
interface AddressParserProvider {
/**
* Return a parser that will parse valid addresses for all networks ({@link Network}) known by this provider.
* @return a parser for all networks known by this provider
*/
AddressParser forKnownNetworks();
/**
* Return a parser that will parse valid addresses for a given {@link Network}.
* @param network network to parse and validate addresses for
* @return a parser for the specified network
*/
AddressParser forNetwork(Network network);
}
/**
* Get a <i>legacy</i> address parser that knows about networks that have been
* dynamically added to the list maintained by {@link org.bitcoinj.params.Networks}.
* @return A parser for all known networks
*/
@Deprecated
static AddressParser getLegacy() {
return DefaultAddressParserProvider.fromNetworks().forKnownNetworks();
}
/**
* Get a <i>legacy</i> address parser that knows about networks that have been
* dynamically added to the list maintained by {@link org.bitcoinj.params.Networks}.
* @param network the network to parse for
* @return A parser that will throw for strings that are not valid for network.
*/
@Deprecated
static AddressParser getLegacy(Network network) {
return DefaultAddressParserProvider.fromNetworks().forNetwork(network);
}
/**
* Get a <i>legacy</i> address parser that knows about networks that have been
* dynamically added to the list maintained by {@link org.bitcoinj.params.Networks}.
* @param params the network to parser for, or {@code null} for all networks.
* @return A parser that will throw for strings that are not valid for network.
*/
@Deprecated
static AddressParser getLegacy(@Nullable NetworkParameters params) {
AddressParser.AddressParserProvider provider = DefaultAddressParserProvider.fromNetworks();
return (params == null)
? provider.forKnownNetworks()
: provider.forNetwork(params.network());
}
}

View file

@ -30,16 +30,16 @@ import java.util.List;
* Address parser that knows about the address types supported by bitcoinj core and is configurable
* with additional network types.
*/
public class DefaultAddressParser implements AddressParser {
class DefaultAddressParserProvider implements AddressParser.AddressParserProvider {
// Networks to try when parsing segwit addresses
public static final List<Network> DEFAULT_NETWORKS_SEGWIT = unmodifiableList(
static final List<Network> DEFAULT_NETWORKS_SEGWIT = unmodifiableList(
BitcoinNetwork.MAINNET,
BitcoinNetwork.TESTNET,
BitcoinNetwork.REGTEST);
// Networks to try when parsing legacy (base58) addresses
public static final List<Network> DEFAULT_NETWORKS_LEGACY = unmodifiableList(
static final List<Network> DEFAULT_NETWORKS_LEGACY = unmodifiableList(
BitcoinNetwork.MAINNET,
BitcoinNetwork.TESTNET);
@ -51,7 +51,7 @@ public class DefaultAddressParser implements AddressParser {
/**
* DefaultAddressParser with default network lists
*/
public DefaultAddressParser() {
DefaultAddressParserProvider() {
this(DEFAULT_NETWORKS_SEGWIT, DEFAULT_NETWORKS_LEGACY);
}
@ -60,26 +60,34 @@ public class DefaultAddressParser implements AddressParser {
* @param segwitNetworks Networks to search when parsing segwit addresses
* @param base58Networks Networks to search when parsing base58 addresses
*/
public DefaultAddressParser(List<Network> segwitNetworks, List<Network> base58Networks) {
DefaultAddressParserProvider(List<Network> segwitNetworks, List<Network> base58Networks) {
this.segwitNetworks = segwitNetworks;
this.base58Networks = base58Networks;
}
@Override
public AddressParser forKnownNetworks() {
return this::parseAddress;
}
@Override
public AddressParser forNetwork(Network network) {
return address -> this.parseAddress(address, network);
}
/**
* Dynamically create a new AddressParser using a snapshot of currently configured networks
* from Networks.get().
* @return A backward-compatible parser
*/
@Deprecated
public static DefaultAddressParser fromNetworks() {
static DefaultAddressParserProvider fromNetworks() {
List<Network> nets = Networks.get().stream()
.map(NetworkParameters::network)
.collect(StreamUtils.toUnmodifiableList());
return new DefaultAddressParser(nets, nets);
return new DefaultAddressParserProvider(nets, nets);
}
@Override
public Address parseAddressAnyNetwork(String addressString) throws AddressFormatException {
private Address parseAddress(String addressString) throws AddressFormatException {
try {
return parseBase58AnyNetwork(addressString);
} catch (AddressFormatException.WrongNetwork x) {
@ -96,8 +104,7 @@ public class DefaultAddressParser implements AddressParser {
}
}
@Override
public Address parseAddress(String addressString, Network network) throws AddressFormatException {
private Address parseAddress(String addressString, Network network) throws AddressFormatException {
try {
return LegacyAddress.fromBase58(addressString, network);
} catch (AddressFormatException.WrongNetwork x) {

View file

@ -174,10 +174,7 @@ public class LegacyAddress implements Address {
@Deprecated
public static LegacyAddress fromBase58(@Nullable NetworkParameters params, String base58)
throws AddressFormatException, AddressFormatException.WrongNetwork {
AddressParser parser = DefaultAddressParser.fromNetworks();
return (LegacyAddress) ((params != null)
? parser.parseAddress(base58, params.network())
: parser.parseAddressAnyNetwork(base58));
return (LegacyAddress) AddressParser.getLegacy(params).parseAddress(base58);
}
/**
@ -255,7 +252,7 @@ public class LegacyAddress implements Address {
*/
@Deprecated
public static NetworkParameters getParametersFromAddress(String address) throws AddressFormatException {
return NetworkParameters.fromAddress(DefaultAddressParser.fromNetworks().parseAddressAnyNetwork(address));
return NetworkParameters.fromAddress(AddressParser.getLegacy().parseAddress(address));
}
@Override

View file

@ -252,16 +252,12 @@ public class SegwitAddress implements Address {
* @return constructed address
* @throws AddressFormatException
* if something about the given bech32 address isn't right
* @deprecated Use {@link AddressParser#parseAddress(String, Network)} or {@link AddressParser#parseAddressAnyNetwork(String)}
* @deprecated Use {@link AddressParser}
*/
@Deprecated
public static SegwitAddress fromBech32(@Nullable NetworkParameters params, String bech32)
throws AddressFormatException {
AddressParser parser = DefaultAddressParser.fromNetworks();
return (SegwitAddress) (params != null
? parser.parseAddress(bech32, params.network())
: parser.parseAddressAnyNetwork(bech32)
);
return (SegwitAddress) AddressParser.getLegacy(params).parseAddress(bech32);
}
/**

View file

@ -16,12 +16,12 @@
package org.bitcoinj.uri;
import org.bitcoinj.base.AddressParser;
import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.Network;
import org.bitcoinj.base.exceptions.AddressFormatException;
import org.bitcoinj.base.Coin;
import org.bitcoinj.base.Address;
import org.bitcoinj.base.DefaultAddressParser;
import org.bitcoinj.core.NetworkParameters;
import javax.annotation.Nonnull;
@ -194,10 +194,10 @@ public class BitcoinURI {
if (!addressToken.isEmpty()) {
// Attempt to parse the addressToken as a Bitcoin address for this network
try {
DefaultAddressParser addressParser = new DefaultAddressParser();
Address address = network != null ?
addressParser.parseAddress(addressToken, network) :
addressParser.parseAddressAnyNetwork(addressToken);
AddressParser parser = network != null
? AddressParser.getDefault(network)
: AddressParser.getDefault();
Address address = parser.parseAddress(addressToken);
putWithValidation(FIELD_ADDRESS, address);
} catch (final AddressFormatException e) {
throw new BitcoinURIParseException("Bad address", e);

View file

@ -39,7 +39,6 @@ import org.bitcoinj.core.BlockChain;
import org.bitcoinj.core.BloomFilter;
import org.bitcoinj.base.Coin;
import org.bitcoinj.core.Context;
import org.bitcoinj.base.DefaultAddressParser;
import org.bitcoinj.crypto.ECKey;
import org.bitcoinj.core.FilteredBlock;
import org.bitcoinj.core.InsufficientMoneyException;
@ -183,9 +182,8 @@ import static org.bitcoinj.base.internal.Preconditions.checkState;
*/
public class Wallet extends BaseTaggableObject
implements NewBestBlockListener, TransactionReceivedInBlockListener, PeerFilterProvider,
KeyBag, TransactionBag, ReorganizeListener, AddressParser.Strict {
KeyBag, TransactionBag, ReorganizeListener, AddressParser {
private static final Logger log = LoggerFactory.getLogger(Wallet.class);
private static final AddressParser addressParser = new DefaultAddressParser();
// Ordering: lock > keyChainGroupLock. KeyChainGroup is protected separately to allow fast querying of current receive address
// even if the wallet itself is busy e.g. saving or processing a big reorg. Useful for reducing UI latency.
@ -248,6 +246,8 @@ public class Wallet extends BaseTaggableObject
protected final Network network;
protected final NetworkParameters params;
private final AddressParser addressParser;
@Nullable private Sha256Hash lastBlockSeenHash;
private int lastBlockSeenHeight;
@ -627,6 +627,7 @@ public class Wallet extends BaseTaggableObject
public Wallet(Network network, KeyChainGroup keyChainGroup) {
this.network = Objects.requireNonNull(network);
this.params = NetworkParameters.of(network);
this.addressParser = AddressParser.getDefault(network);
this.coinSelector = DefaultCoinSelector.get(network);
this.keyChainGroup = Objects.requireNonNull(keyChainGroup);
watchedScripts = new HashSet<>();
@ -691,7 +692,7 @@ public class Wallet extends BaseTaggableObject
*/
@Override
public Address parseAddress(String addressString) throws AddressFormatException {
return addressParser.parseAddress(addressString, network);
return addressParser.parseAddress(addressString);
}
/**

View file

@ -31,7 +31,7 @@ import static org.junit.Assert.assertEquals;
* the default comparators.
*/
public class AddressComparatorSortTest {
private static final AddressParser addressParser = new DefaultAddressParser();
private static final AddressParser addressParser = AddressParser.getDefault();
/**
* A manually sorted list of address for verifying sorting with our default comparator.
@ -50,7 +50,7 @@ public class AddressComparatorSortTest {
// Test net, Segwit
"tb1qrp33g0q5c5txsp9arysrx4k6zdkfs4nce4xj0gdcccefvpysxf3q0sl5k7",
"tb1qw508d6qejxtdg4y5r3zarvary0c5xw7kxpjzsx"
).map(addressParser::parseAddressAnyNetwork)
).map(addressParser::parseAddress)
.collect(StreamUtils.toUnmodifiableList());
@Test

View file

@ -31,7 +31,6 @@ import org.junit.Test;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import static org.junit.Assert.assertEquals;
@ -133,10 +132,10 @@ public class LegacyAddressTest {
@Test
public void getNetwork() {
AddressParser parser = new DefaultAddressParser();
Network mainNet = parser.parseAddressAnyNetwork("17kzeh4N8g49GFvdDzSf8PjaPfyoD1MndL").network();
AddressParser parser = AddressParser.getDefault();
Network mainNet = parser.parseAddress("17kzeh4N8g49GFvdDzSf8PjaPfyoD1MndL").network();
assertEquals(MAINNET, mainNet);
Network testNet = parser.parseAddressAnyNetwork("n4eA2nbYqErp7H6jebchxAN59DmNpksexv").network();
Network testNet = parser.parseAddress("n4eA2nbYqErp7H6jebchxAN59DmNpksexv").network();
assertEquals(TESTNET, testNet);
}
@ -148,17 +147,17 @@ public class LegacyAddressTest {
Networks.register(altNetParams);
try {
// Check if can parse address
Address altAddress = DefaultAddressParser.fromNetworks().parseAddressAnyNetwork("LLxSnHLN2CYyzB5eWTR9K9rS9uWtbTQFb6");
Address altAddress = AddressParser.getLegacy().parseAddress("LLxSnHLN2CYyzB5eWTR9K9rS9uWtbTQFb6");
assertEquals(altNetParams.getId(), altAddress.network().id());
// Check if main network works as before
Address mainAddress = new DefaultAddressParser().parseAddressAnyNetwork("17kzeh4N8g49GFvdDzSf8PjaPfyoD1MndL");
Address mainAddress = AddressParser.getLegacy(MAINNET).parseAddress("17kzeh4N8g49GFvdDzSf8PjaPfyoD1MndL");
assertEquals(MAINNET.id(), mainAddress.network().id());
} finally {
// Unregister network. Do this in a finally block so other tests don't fail if the try block fails to complete
Networks.unregister(altNetParams);
}
try {
DefaultAddressParser.fromNetworks().parseAddressAnyNetwork("LLxSnHLN2CYyzB5eWTR9K9rS9uWtbTQFb6");
AddressParser.getLegacy().parseAddress("LLxSnHLN2CYyzB5eWTR9K9rS9uWtbTQFb6");
fail();
} catch (AddressFormatException e) { }
}
@ -169,20 +168,20 @@ public class LegacyAddressTest {
NetworkParameters altNetParams = new MockAltNetworkParams();
// Create a parser that knows about the new network (this does not modify global state)
List<Network> nets = new ArrayList<>(DefaultAddressParser.DEFAULT_NETWORKS_LEGACY);
List<Network> nets = new ArrayList<>(DefaultAddressParserProvider.DEFAULT_NETWORKS_LEGACY);
nets.add(altNetParams.network());
AddressParser customParser = new DefaultAddressParser(DefaultAddressParser.DEFAULT_NETWORKS_SEGWIT, nets);
AddressParser customParser = new DefaultAddressParserProvider(DefaultAddressParserProvider.DEFAULT_NETWORKS_SEGWIT, nets).forKnownNetworks();
// Unfortunately for NetworkParameters.of() to work properly we still have to modify gobal state
Networks.register(altNetParams);
try {
// Check if can parse address
Address altAddress = customParser.parseAddressAnyNetwork("LLxSnHLN2CYyzB5eWTR9K9rS9uWtbTQFb6");
Address altAddress = customParser.parseAddress("LLxSnHLN2CYyzB5eWTR9K9rS9uWtbTQFb6");
assertEquals(altNetParams.getId(), altAddress.network().id());
// Check if main network works with custom parser
Address mainAddress = customParser.parseAddressAnyNetwork("17kzeh4N8g49GFvdDzSf8PjaPfyoD1MndL");
Address mainAddress = customParser.parseAddress("17kzeh4N8g49GFvdDzSf8PjaPfyoD1MndL");
assertEquals(MAINNET.id(), mainAddress.network().id());
} finally {
@ -190,9 +189,8 @@ public class LegacyAddressTest {
Networks.unregister(altNetParams);
}
try {
new DefaultAddressParser().parseAddressAnyNetwork("LLxSnHLN2CYyzB5eWTR9K9rS9uWtbTQFb6");
AddressParser.getLegacy().parseAddress("LLxSnHLN2CYyzB5eWTR9K9rS9uWtbTQFb6");
fail();
} catch (AddressFormatException e) { }
}
@ -207,11 +205,11 @@ public class LegacyAddressTest {
assertEquals(testNetP2SHAddress.getVersion(), NetworkParameters.of(TESTNET).getP2SHHeader());
assertEquals(ScriptType.P2SH, testNetP2SHAddress.getOutputScriptType());
AddressParser parser = new DefaultAddressParser();
AddressParser parser = AddressParser.getDefault();
// Test that we can determine what network a P2SH address belongs to
Network mainNet = parser.parseAddressAnyNetwork("35b9vsyH1KoFT5a5KtrKusaCcPLkiSo1tU").network();
Network mainNet = parser.parseAddress("35b9vsyH1KoFT5a5KtrKusaCcPLkiSo1tU").network();
assertEquals(MAINNET, mainNet);
Network testNet = parser.parseAddressAnyNetwork("2MuVSxtfivPKJe93EC1Tb9UhJtGhsoWEHCe").network();
Network testNet = parser.parseAddress("2MuVSxtfivPKJe93EC1Tb9UhJtGhsoWEHCe").network();
assertEquals(TESTNET, testNet);
// Test that we can convert them from hashes

View file

@ -35,7 +35,7 @@ import static org.bitcoinj.base.BitcoinNetwork.SIGNET;
import static org.bitcoinj.base.BitcoinNetwork.REGTEST;
public class SegwitAddressTest {
private static final AddressParser addressParser = new DefaultAddressParser();
private static final AddressParser addressParser = AddressParser.getDefault();
@Test
public void equalsContract() {
@ -118,7 +118,7 @@ public class SegwitAddressTest {
public void example_p2wpkh_regtest_any_network() {
String bcrt1_bech32 = "bcrt1qspfueag7fvty7m8htuzare3xs898zvh30fttu2";
Address address = addressParser.parseAddressAnyNetwork(bcrt1_bech32);
Address address = addressParser.parseAddress(bcrt1_bech32);
assertEquals(REGTEST, address.network());
assertEquals("00148053ccf51e4b164f6cf75f05d1e62681ca7132f1",
@ -145,7 +145,7 @@ public class SegwitAddressTest {
@Test
public void validAddresses() {
for (AddressData valid : VALID_ADDRESSES) {
SegwitAddress address = (SegwitAddress) addressParser.parseAddressAnyNetwork(valid.address);
SegwitAddress address = (SegwitAddress) addressParser.parseAddress(valid.address);
assertEquals(valid.expectedNetwork, address.network());
assertEquals(valid.expectedScriptPubKey,
@ -203,7 +203,7 @@ public class SegwitAddressTest {
public void invalidAddresses() {
for (String invalid : INVALID_ADDRESSES) {
try {
addressParser.parseAddressAnyNetwork(invalid);
addressParser.parseAddress(invalid);
fail(invalid);
} catch (AddressFormatException x) {
// expected
@ -239,17 +239,17 @@ public class SegwitAddressTest {
@Test(expected = AddressFormatException.InvalidDataLength.class)
public void fromBech32_version0_invalidLength() {
addressParser.parseAddressAnyNetwork("BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P");
addressParser.parseAddress("BC1QR508D6QEJXTDG4Y5R3ZARVARYV98GJ9P");
}
@Test(expected = AddressFormatException.InvalidDataLength.class)
public void fromBech32_tooShort() {
addressParser.parseAddressAnyNetwork("bc1rw5uspcuh");
addressParser.parseAddress("bc1rw5uspcuh");
}
@Test(expected = AddressFormatException.InvalidDataLength.class)
public void fromBech32_tooLong() {
addressParser.parseAddressAnyNetwork("bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90");
addressParser.parseAddress("bc10w508d6qejxtdg4y5r3zarvary0c5xw7kw508d6qejxtdg4y5r3zarvary0c5xw7kw5rljs90");
}
@Test(expected = AddressFormatException.InvalidDataLength.class)
@ -270,7 +270,7 @@ public class SegwitAddressTest {
@Test(expected = AddressFormatException.InvalidPrefix.class)
public void fromBech32_invalidHrp() {
addressParser.parseAddressAnyNetwork("tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty");
addressParser.parseAddress("tc1qw508d6qejxtdg4y5r3zarvary0c5xw7kg3g4ty");
}
@Test(expected = AddressFormatException.WrongNetwork.class)

View file

@ -1,7 +1,6 @@
package org.bitcoinj.crypto.utils;
import org.bitcoinj.base.AddressParser;
import org.bitcoinj.base.DefaultAddressParser;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.params.MainNetParams;
import org.bitcoinj.params.TestNet3Params;
@ -75,10 +74,10 @@ public class MessageVerifyUtilsTest {
@Test
public void testMessageSignatureVerification() {
final AddressParser addressParser = new DefaultAddressParser();
final AddressParser addressParser = AddressParser.getDefault(testVector.networkParameters.network());
try {
MessageVerifyUtils.verifyMessage(
addressParser.parseAddress(testVector.address, testVector.networkParameters.network()),
addressParser.parseAddress(testVector.address),
testVector.message,
testVector.signature
);

View file

@ -16,9 +16,9 @@
package org.bitcoinj.uri;
import org.bitcoinj.base.AddressParser;
import org.bitcoinj.base.BitcoinNetwork;
import org.bitcoinj.base.Address;
import org.bitcoinj.base.DefaultAddressParser;
import org.bitcoinj.base.LegacyAddress;
import org.bitcoinj.core.NetworkParameters;
import org.bitcoinj.params.Networks;
@ -63,7 +63,7 @@ public class BitcoinURITest {
@Test
public void testConvertToBitcoinURI() {
Address goodAddress = new DefaultAddressParser().parseAddress(MAINNET_GOOD_ADDRESS, MAINNET);
Address goodAddress = AddressParser.getDefault(MAINNET).parseAddress(MAINNET_GOOD_ADDRESS);
// simple example
assertEquals("bitcoin:" + MAINNET_GOOD_ADDRESS + "?amount=12.34&label=Hello&message=AMessage", BitcoinURI.convertToBitcoinURI(goodAddress, parseCoin("12.34"), "Hello", "AMessage"));
@ -112,7 +112,7 @@ public class BitcoinURITest {
@Test
public void testConvertToBitcoinURI_segwit() {
Address segwitAddress = new DefaultAddressParser().parseAddress(MAINNET_GOOD_SEGWIT_ADDRESS, MAINNET);
Address segwitAddress = AddressParser.getDefault(MAINNET).parseAddress(MAINNET_GOOD_SEGWIT_ADDRESS);
assertEquals("bitcoin:" + MAINNET_GOOD_SEGWIT_ADDRESS + "?message=segwit%20rules", BitcoinURI.convertToBitcoinURI(
segwitAddress, null, null, "segwit rules"));
}

View file

@ -22,7 +22,6 @@ import org.bitcoinj.base.Address;
import org.bitcoinj.base.Coin;
import org.bitcoinj.base.AddressParser;
import org.bitcoinj.core.Context;
import org.bitcoinj.base.DefaultAddressParser;
import org.bitcoinj.core.Transaction;
import org.bitcoinj.kits.WalletAppKit;
import org.bitcoinj.utils.BriefLogFormatter;
@ -46,7 +45,6 @@ public class ForwardingService implements Closeable {
static final String USAGE = "Usage: address-to-forward-to [mainnet|testnet|signet|regtest]";
static final int REQUIRED_CONFIRMATIONS = 1;
static final int MAX_CONNECTIONS = 4;
private final AddressParser addressParser = new DefaultAddressParser();
private final BitcoinNetwork network;
private final Address forwardingAddress;
private volatile WalletAppKit kit;
@ -84,10 +82,10 @@ public class ForwardingService implements Closeable {
if (args.length >= 2) {
// If network was specified, validate address against network
network = BitcoinNetwork.fromString(args[1]).orElseThrow();
forwardingAddress = addressParser.parseAddress(args[0], network);
forwardingAddress = AddressParser.getDefault(network).parseAddress(args[0]);
} else {
// Else network not-specified, extract network from address
forwardingAddress = addressParser.parseAddressAnyNetwork(args[0]);
forwardingAddress = AddressParser.getDefault().parseAddress(args[0]);
network = (BitcoinNetwork) forwardingAddress.network();
}
}

View file

@ -28,11 +28,11 @@ import org.bitcoinj.walletfx.utils.TextFieldValidator;
* if the address is invalid for those params, and enable/disable the nodes.
*/
public class BitcoinAddressValidator {
private final AddressParser.Strict parser;
private final AddressParser parser;
private Node[] nodes;
public BitcoinAddressValidator(AddressParser.Strict parser, TextField field, Node... nodes) {
public BitcoinAddressValidator(AddressParser parser, TextField field, Node... nodes) {
this.parser = parser;
this.nodes = nodes;