From aff7fda17d14951584cfe5622f2ee3996afd4162 Mon Sep 17 00:00:00 2001 From: Mike Hearn Date: Wed, 20 Apr 2011 15:47:41 +0000 Subject: [PATCH] Add a function/some tests for string to nanocoin conversions and vice-versa, along with a TODO to clean this whole thing up. Patch from Thilo Planz. Fixes issue 1. --- src/com/google/bitcoin/core/Utils.java | 32 +++++++++++++- tests/com/google/bitcoin/core/UtilsTest.java | 46 ++++++++++++++++++++ 2 files changed, 76 insertions(+), 2 deletions(-) create mode 100644 tests/com/google/bitcoin/core/UtilsTest.java diff --git a/src/com/google/bitcoin/core/Utils.java b/src/com/google/bitcoin/core/Utils.java index 9e0785fd..fb90aaa6 100644 --- a/src/com/google/bitcoin/core/Utils.java +++ b/src/com/google/bitcoin/core/Utils.java @@ -20,6 +20,7 @@ import com.google.bitcoin.bouncycastle.crypto.digests.RIPEMD160Digest; import java.io.IOException; import java.io.OutputStream; +import java.math.BigDecimal; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -30,9 +31,24 @@ import java.security.NoSuchAlgorithmException; */ @SuppressWarnings({"SameParameterValue"}) public class Utils { - /** How many nanocoins there are in a BitCoin. */ + // TODO: Replace this nanocoins business with something better. + + /** + * How many "nanocoins" there are in a BitCoin. + * + * A nanocoin is the smallest unit that can be transferred using BitCoin. + * The term nanocoin is very misleading, though, because there are only 100 million + * of them in a coin (whereas one would expect 1 billion. + */ public static final BigInteger COIN = new BigInteger("100000000", 10); - /** How many nanocoins there are in 0.01 BitCoins. */ + + /** + * How many "nanocoins" there are in 0.01 BitCoins. + * + * A nanocoin is the smallest unit that can be transferred using BitCoin. + * The term nanocoin is very misleading, though, because there are only 100 million + * of them in a coin (whereas one would expect 1 billion). + */ public static final BigInteger CENT = new BigInteger("1000000", 10); private static final boolean logging; @@ -49,6 +65,18 @@ public class Utils { return bi; } + /** + * Convert an amount expressed in the way humans are used to into nanocoins.

+ * + * This takes string in a format understood by {@link BigDecimal#BigDecimal(String)}, + * for example "0", "1", "0.10", "1.23E3", "1234.5E-5". + * + * @throws ArithmeticException if you try to specify fractional nanocoins + **/ + public static BigInteger toNanoCoins(String coins){ + return new BigDecimal(coins).movePointRight(8).toBigIntegerExact(); + } + public static void uint32ToByteArrayBE(long val, byte[] out, int offset) { out[offset + 0] = (byte) (0xFF & (val >> 24)); out[offset + 1] = (byte) (0xFF & (val >> 16)); diff --git a/tests/com/google/bitcoin/core/UtilsTest.java b/tests/com/google/bitcoin/core/UtilsTest.java new file mode 100644 index 00000000..7bf312a8 --- /dev/null +++ b/tests/com/google/bitcoin/core/UtilsTest.java @@ -0,0 +1,46 @@ +/** + * Copyright 2011 Thilo Planz + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.google.bitcoin.core; + +import static junit.framework.Assert.assertEquals; +import static junit.framework.Assert.fail; + +import org.junit.Test; + +public class UtilsTest { + + @Test + public void testToNanoCoins() { + // String version + assertEquals(Utils.CENT, Utils.toNanoCoins("0.01")); + assertEquals(Utils.CENT, Utils.toNanoCoins("1E-2")); + assertEquals(Utils.COIN.add(Utils.CENT), Utils.toNanoCoins("1.01")); + try { + Utils.toNanoCoins("2E-20"); + fail("should not have accepted fractional nanocoins"); + } catch (ArithmeticException e) { + } + + // int version + assertEquals(Utils.CENT, Utils.toNanoCoins(0, 1)); + + // TODO: should this really pass? + assertEquals(Utils.COIN.subtract(Utils.CENT), Utils.toNanoCoins(1, -1)); + assertEquals(Utils.COIN.negate(), Utils.toNanoCoins(-1, 0)); + assertEquals(Utils.COIN.negate(), Utils.toNanoCoins("-1")); + } +}