3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-13 18:55:52 +00:00

Coin: Remove chain-specific coin limit. Add some checks for arithmetic over/underflows instead.

This commit is contained in:
Andreas Schildbach 2015-12-02 10:27:27 +01:00
parent 3ab1d5811d
commit 44ca39bfd7
4 changed files with 27 additions and 48 deletions

View File

@ -84,9 +84,6 @@ public final class Coin implements Monetary, Comparable<Coin>, Serializable {
public final long value; public final long value;
private Coin(final long satoshis) { 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; this.value = satoshis;
} }
@ -115,7 +112,6 @@ public final class Coin implements Monetary, Comparable<Coin>, Serializable {
checkArgument(cents >= 0); checkArgument(cents >= 0);
checkArgument(coins >= 0); checkArgument(coins >= 0);
final Coin coin = COIN.multiply(coins).add(CENT.multiply(cents)); final Coin coin = COIN.multiply(coins).add(CENT.multiply(cents));
checkArgument(coin.compareTo(NetworkParameters.MAX_MONEY) <= 0);
return coin; return coin;
} }

View File

@ -219,6 +219,8 @@ public class BitcoinURI {
// Decode the amount (contains an optional decimal component to 8dp). // Decode the amount (contains an optional decimal component to 8dp).
try { try {
Coin amount = Coin.parseCoin(valueToken); Coin amount = Coin.parseCoin(valueToken);
if (params != null && amount.isGreaterThan(params.getMaxMoney()))
throw new BitcoinURIParseException("Max number of coins exceeded");
if (amount.signum() < 0) if (amount.signum() < 0)
throw new ArithmeticException("Negative coins specified"); throw new ArithmeticException("Negative coins specified");
putWithValidation(FIELD_AMOUNT, amount); putWithValidation(FIELD_AMOUNT, amount);

View File

@ -24,7 +24,6 @@ import static org.junit.Assert.assertTrue;
import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertFalse;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import org.junit.Assert;
import org.junit.Test; import org.junit.Test;
public class CoinTest { public class CoinTest {
@ -53,21 +52,10 @@ public class CoinTest {
assertEquals(NEGATIVE_SATOSHI, valueOf(-1)); assertEquals(NEGATIVE_SATOSHI, valueOf(-1));
assertEquals(MAX_MONEY, valueOf(MAX_MONEY.value)); assertEquals(MAX_MONEY, valueOf(MAX_MONEY.value));
assertEquals(MAX_MONEY.negate(), valueOf(MAX_MONEY.value * -1)); assertEquals(MAX_MONEY.negate(), valueOf(MAX_MONEY.value * -1));
try { valueOf(MAX_MONEY.value + 1);
valueOf(MAX_MONEY.value + 1); valueOf((MAX_MONEY.value * -1) - 1);
org.junit.Assert.fail("should not have accepted too-great a monetary value"); valueOf(Long.MAX_VALUE);
} catch (IllegalArgumentException e) { valueOf(Long.MIN_VALUE);
}
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) {}
try { try {
valueOf(1, -1); valueOf(1, -1);
@ -99,6 +87,26 @@ public class CoinTest {
assertFalse(valueOf(2).isLessThan(valueOf(1))); 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 @Test
public void testToFriendlyString() { public void testToFriendlyString() {
assertEquals("1.00 BTC", COIN.toFriendlyString()); assertEquals("1.00 BTC", COIN.toFriendlyString());
@ -123,10 +131,7 @@ public class CoinTest {
assertEquals("54321.12345", parseCoin("54321.12345").toPlainString()); assertEquals("54321.12345", parseCoin("54321.12345").toPlainString());
assertEquals("654321.123456", parseCoin("654321.123456").toPlainString()); assertEquals("654321.123456", parseCoin("654321.123456").toPlainString());
assertEquals("7654321.1234567", parseCoin("7654321.1234567").toPlainString()); assertEquals("7654321.1234567", parseCoin("7654321.1234567").toPlainString());
try { assertEquals("87654321.12345678", parseCoin("87654321.12345678").toPlainString());
assertEquals("87654321.12345678", parseCoin("87654321.12345678").toPlainString());
Assert.fail(); // More than MAX_MONEY
} catch (Exception e) {}
// check there are no trailing zeros // check there are no trailing zeros
assertEquals("1", parseCoin("1.0").toPlainString()); assertEquals("1", parseCoin("1.0").toPlainString());

View File

@ -55,30 +55,6 @@ public class ExchangeRateTest {
rate.fiatToCoin(Fiat.parseFiat("USD", "1")); 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) @Test(expected = IllegalArgumentException.class)
public void constructMissingCurrencyCode() { public void constructMissingCurrencyCode() {
new ExchangeRate(Fiat.valueOf(null, 1)); new ExchangeRate(Fiat.valueOf(null, 1));