BitcoinURI: restore ability to parse URIs from any network

This includes a test.
This commit is contained in:
Andreas Schildbach 2023-04-20 14:56:48 +02:00
parent bf02dbfb96
commit 2b6b28a6b0
2 changed files with 27 additions and 10 deletions

View File

@ -108,7 +108,7 @@ public class BitcoinURI {
*/
public static BitcoinURI of(String uri) throws BitcoinURIParseException {
// TODO: Discover (via Service Loader mechanism) the correct Network from the URI string
return new BitcoinURI(uri, BitcoinNetwork.MAINNET);
return new BitcoinURI(uri, null);
}
/**
@ -119,7 +119,7 @@ public class BitcoinURI {
* @throws BitcoinURIParseException If the input fails Bitcoin URI syntax and semantic checks.
*/
public static BitcoinURI of(String uri, @Nonnull Network network) throws BitcoinURIParseException {
return new BitcoinURI(uri, network);
return new BitcoinURI(uri, Objects.requireNonNull(network));
}
/**
@ -134,14 +134,15 @@ public class BitcoinURI {
*/
@Deprecated
public BitcoinURI(@Nullable NetworkParameters params, String input) throws BitcoinURIParseException {
this(input, params != null ? params.network() : BitcoinNetwork.MAINNET);
this(input, params != null ? params.network() : null);
}
private BitcoinURI(String input, @Nonnull Network network) throws BitcoinURIParseException {
Objects.requireNonNull(network);
private BitcoinURI(String input, @Nullable Network network) throws BitcoinURIParseException {
Objects.requireNonNull(input);
String scheme = network.uriScheme();
String scheme = network != null ?
network.uriScheme() :
BitcoinNetwork.BITCOIN_SCHEME;
// Attempt to form the URI (fail fast syntax checking to official standards).
URI uri;
@ -188,12 +189,15 @@ public class BitcoinURI {
}
// Attempt to parse the rest of the URI parameters.
parseParameters(network, nameValuePairTokens);
parseParameters(nameValuePairTokens);
if (!addressToken.isEmpty()) {
// Attempt to parse the addressToken as a Bitcoin address for this network
try {
Address address = new DefaultAddressParser().parseAddress(addressToken, network);
DefaultAddressParser addressParser = new DefaultAddressParser();
Address address = network != null ?
addressParser.parseAddress(addressToken, network) :
addressParser.parseAddressAnyNetwork(addressToken);
putWithValidation(FIELD_ADDRESS, address);
} catch (final AddressFormatException e) {
throw new BitcoinURIParseException("Bad address", e);
@ -206,11 +210,10 @@ public class BitcoinURI {
}
/**
* @param network The network
* @param nameValuePairTokens The tokens representing the name value pairs (assumed to be
* separated by '=' e.g. 'amount=0.2')
*/
private void parseParameters(Network network, String[] nameValuePairTokens) throws BitcoinURIParseException {
private void parseParameters(String[] nameValuePairTokens) throws BitcoinURIParseException {
// Attempt to decode the rest of the tokens into a parameter map.
for (String nameValuePairToken : nameValuePairTokens) {
final int sepIndex = nameValuePairToken.indexOf('=');

View File

@ -47,6 +47,20 @@ public class BitcoinURITest {
private static final String MAINNET_GOOD_SEGWIT_ADDRESS = "bc1qw508d6qejxtdg4y5r3zarvary0c5xw7kv8f3t4";
private static final String BITCOIN_SCHEME = BitcoinNetwork.BITCOIN_SCHEME;
@Test
public void of_anyNetwork() throws Exception {
BitcoinURI uri1 = BitcoinURI.of("bitcoin:" + MAINNET_GOOD_ADDRESS);
assertEquals(BitcoinNetwork.MAINNET, uri1.getAddress().network());
BitcoinURI uri2 = BitcoinURI.of("bitcoin:" + MAINNET_GOOD_SEGWIT_ADDRESS);
assertEquals(BitcoinNetwork.MAINNET, uri2.getAddress().network());
BitcoinURI uri3 = BitcoinURI.of("bitcoin:mutDLVyes4YNWkL4j8g9oUsSUSTtnt13hP");
assertEquals(BitcoinNetwork.TESTNET, uri3.getAddress().network());
BitcoinURI uri4 = BitcoinURI.of("bitcoin:tb1qn96rzewt04q0vtnh8lh0kelekkj2lpjh29lg6x");
assertEquals(BitcoinNetwork.TESTNET, uri4.getAddress().network());
BitcoinURI uri5 = BitcoinURI.of("BITCOIN:TB1QN96RZEWT04Q0VTNH8LH0KELEKKJ2LPJH29LG6X");
assertEquals(BitcoinNetwork.TESTNET, uri5.getAddress().network());
}
@Test
public void testConvertToBitcoinURI() {
Address goodAddress = new DefaultAddressParser().parseAddress(MAINNET_GOOD_ADDRESS, MAINNET);