Skip to content

Commit

Permalink
Coin: Remove chain-specific coin limit. Add some checks for arithmeti…
Browse files Browse the repository at this point in the history
…c over/underflows instead.
  • Loading branch information
schildbach committed Dec 13, 2015
1 parent 3ab1d58 commit 44ca39b
Show file tree
Hide file tree
Showing 4 changed files with 27 additions and 48 deletions.
4 changes: 0 additions & 4 deletions core/src/main/java/org/bitcoinj/core/Coin.java
Original file line number Diff line number Diff line change
Expand Up @@ -84,9 +84,6 @@ public final class Coin implements Monetary, Comparable<Coin>, Serializable {
public final long value;

private Coin(final long satoshis) {
long maxSatoshis = COIN_VALUE * NetworkParameters.MAX_COINS;
checkArgument(-maxSatoshis <= satoshis && satoshis <= maxSatoshis,
"%s satoshis exceeds maximum possible quantity of Bitcoin.", satoshis);
this.value = satoshis;
}

Expand Down Expand Up @@ -115,7 +112,6 @@ public static Coin valueOf(final int coins, final int cents) {
checkArgument(cents >= 0);
checkArgument(coins >= 0);
final Coin coin = COIN.multiply(coins).add(CENT.multiply(cents));
checkArgument(coin.compareTo(NetworkParameters.MAX_MONEY) <= 0);
return coin;
}

Expand Down
2 changes: 2 additions & 0 deletions core/src/main/java/org/bitcoinj/uri/BitcoinURI.java
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,8 @@ private void parseParameters(@Nullable NetworkParameters params, String addressT
// Decode the amount (contains an optional decimal component to 8dp).
try {
Coin amount = Coin.parseCoin(valueToken);
if (params != null && amount.isGreaterThan(params.getMaxMoney()))
throw new BitcoinURIParseException("Max number of coins exceeded");
if (amount.signum() < 0)
throw new ArithmeticException("Negative coins specified");
putWithValidation(FIELD_AMOUNT, amount);
Expand Down
45 changes: 25 additions & 20 deletions core/src/test/java/org/bitcoinj/core/CoinTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,6 @@
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail;

import org.junit.Assert;
import org.junit.Test;

public class CoinTest {
Expand Down Expand Up @@ -53,21 +52,10 @@ public void testValueOf() {
assertEquals(NEGATIVE_SATOSHI, valueOf(-1));
assertEquals(MAX_MONEY, valueOf(MAX_MONEY.value));
assertEquals(MAX_MONEY.negate(), valueOf(MAX_MONEY.value * -1));
try {
valueOf(MAX_MONEY.value + 1);
org.junit.Assert.fail("should not have accepted too-great a monetary value");
} catch (IllegalArgumentException e) {
}
try {
valueOf( (MAX_MONEY.value * -1) - 1);
org.junit.Assert.fail("should not have accepted too-little a monetary value");
} catch (IllegalArgumentException e) {
}

try {
valueOf(Long.MIN_VALUE);
fail();
} catch (IllegalArgumentException e) {}
valueOf(MAX_MONEY.value + 1);
valueOf((MAX_MONEY.value * -1) - 1);
valueOf(Long.MAX_VALUE);
valueOf(Long.MIN_VALUE);

try {
valueOf(1, -1);
Expand Down Expand Up @@ -99,6 +87,26 @@ public void testOperators() {
assertFalse(valueOf(2).isLessThan(valueOf(1)));
}

@Test(expected = ArithmeticException.class)
public void testMultiplicationOverflow() {
Coin.valueOf(Long.MAX_VALUE).multiply(2);
}

@Test(expected = ArithmeticException.class)
public void testMultiplicationUnderflow() {
Coin.valueOf(Long.MIN_VALUE).multiply(2);
}

@Test(expected = ArithmeticException.class)
public void testAdditionOverflow() {
Coin.valueOf(Long.MAX_VALUE).add(Coin.SATOSHI);
}

@Test(expected = ArithmeticException.class)
public void testSubstractionUnderflow() {
Coin.valueOf(Long.MIN_VALUE).subtract(Coin.SATOSHI);
}

@Test
public void testToFriendlyString() {
assertEquals("1.00 BTC", COIN.toFriendlyString());
Expand All @@ -123,10 +131,7 @@ public void testToPlainString() {
assertEquals("54321.12345", parseCoin("54321.12345").toPlainString());
assertEquals("654321.123456", parseCoin("654321.123456").toPlainString());
assertEquals("7654321.1234567", parseCoin("7654321.1234567").toPlainString());
try {
assertEquals("87654321.12345678", parseCoin("87654321.12345678").toPlainString());
Assert.fail(); // More than MAX_MONEY
} catch (Exception e) {}
assertEquals("87654321.12345678", parseCoin("87654321.12345678").toPlainString());

// check there are no trailing zeros
assertEquals("1", parseCoin("1.0").toPlainString());
Expand Down
24 changes: 0 additions & 24 deletions core/src/test/java/org/bitcoinj/utils/ExchangeRateTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -55,30 +55,6 @@ public void currencyCodeMismatch() throws Exception {
rate.fiatToCoin(Fiat.parseFiat("USD", "1"));
}

@Test(expected = ArithmeticException.class)
public void fiatToCoinTooLarge() throws Exception {
ExchangeRate rate = new ExchangeRate(Fiat.parseFiat("XXX", "1"));
rate.fiatToCoin(Fiat.parseFiat("XXX", "21000001"));
}

@Test(expected = ArithmeticException.class)
public void fiatToCoinTooSmall() throws Exception {
ExchangeRate rate = new ExchangeRate(Fiat.parseFiat("XXX", "1"));
rate.fiatToCoin(Fiat.parseFiat("XXX", "-21000001"));
}

@Test(expected = ArithmeticException.class)
public void coinToFiatTooLarge() throws Exception {
ExchangeRate rate = new ExchangeRate(Fiat.parseFiat("XXX", "1000000000"));
rate.coinToFiat(Coin.parseCoin("1000000"));
}

@Test(expected = ArithmeticException.class)
public void coinToFiatTooSmall() throws Exception {
ExchangeRate rate = new ExchangeRate(Fiat.parseFiat("XXX", "1000000000"));
rate.coinToFiat(Coin.parseCoin("-1000000"));
}

@Test(expected = IllegalArgumentException.class)
public void constructMissingCurrencyCode() {
new ExchangeRate(Fiat.valueOf(null, 1));
Expand Down

0 comments on commit 44ca39b

Please sign in to comment.