diff --git a/core/src/main/java/com/google/bitcoin/core/Coin.java b/core/src/main/java/com/google/bitcoin/core/Coin.java index 1f9a6ecb..f75f79ff 100644 --- a/core/src/main/java/com/google/bitcoin/core/Coin.java +++ b/core/src/main/java/com/google/bitcoin/core/Coin.java @@ -82,20 +82,20 @@ public final class Coin implements Comparable, Serializable { return new Coin(LongMath.checkedSubtract(this.value, value.value)); } - public Coin multiply(final Coin value) { - return new Coin(LongMath.checkedMultiply(this.value, value.value)); + public Coin multiply(final long factor) { + return new Coin(LongMath.checkedMultiply(this.value, factor)); } - public Coin multiply(final long value) { - return new Coin(LongMath.checkedMultiply(this.value, value)); + public Coin divide(final long divisor) { + return new Coin(this.value / divisor); } - public Coin divide(final Coin value) { - return new Coin(this.value / value.value); + public Coin[] divideAndRemainder(final long divisor) { + return new Coin[] { new Coin(this.value / divisor), new Coin(this.value % divisor) }; } - public Coin[] divideAndRemainder(final Coin value) { - return new Coin[] { new Coin(this.value / value.value), new Coin(this.value % value.value) }; + public long divide(final Coin divisor) { + return this.value / divisor.value; } public Coin shiftLeft(final int n) { @@ -156,10 +156,9 @@ public final class Coin implements Comparable, Serializable { checkArgument(cents < 100); checkArgument(cents >= 0); checkArgument(coins >= 0); - checkArgument(coins < NetworkParameters.MAX_MONEY.divide(COIN).longValue()); - Coin bi = Coin.valueOf(coins).multiply(COIN); - bi = bi.add(Coin.valueOf(cents).multiply(CENT)); - return bi; + final Coin coin = COIN.multiply(coins).add(CENT.multiply(cents)); + checkArgument(coin.compareTo(NetworkParameters.MAX_MONEY) <= 0); + return coin; } /** diff --git a/core/src/main/java/com/google/bitcoin/core/NetworkParameters.java b/core/src/main/java/com/google/bitcoin/core/NetworkParameters.java index 85a6e95c..09e90736 100644 --- a/core/src/main/java/com/google/bitcoin/core/NetworkParameters.java +++ b/core/src/main/java/com/google/bitcoin/core/NetworkParameters.java @@ -133,7 +133,7 @@ public abstract class NetworkParameters implements Serializable { /** * The maximum money to be generated */ - public static final Coin MAX_MONEY = new Coin("21000000", 10).multiply(COIN); + public static final Coin MAX_MONEY = COIN.multiply(21000000); /** Alias for TestNet3Params.get(), use that instead. */ @Deprecated diff --git a/core/src/main/java/com/google/bitcoin/core/TransactionOutput.java b/core/src/main/java/com/google/bitcoin/core/TransactionOutput.java index e3f5f7cd..95d67634 100644 --- a/core/src/main/java/com/google/bitcoin/core/TransactionOutput.java +++ b/core/src/main/java/com/google/bitcoin/core/TransactionOutput.java @@ -205,7 +205,7 @@ public class TransactionOutput extends ChildMessage implements Serializable { // clients wrongness in order to ensure we're considered standard. A better formula would either estimate the // size of data needed to satisfy all different script types, or just hard code 33 below. final long size = this.bitcoinSerialize().length + 148; - Coin[] nonDustAndRemainder = feePerKbRequired.multiply(size).divideAndRemainder(Coin.valueOf(1000)); + Coin[] nonDustAndRemainder = feePerKbRequired.multiply(size).divideAndRemainder(1000); return nonDustAndRemainder[1].equals(Coin.ZERO) ? nonDustAndRemainder[0] : nonDustAndRemainder[0].add(Coin.ONE); } @@ -215,7 +215,7 @@ public class TransactionOutput extends ChildMessage implements Serializable { * {@link Transaction#MIN_NONDUST_OUTPUT}. */ public Coin getMinNonDustValue() { - return getMinNonDustValue(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(3))); + return getMinNonDustValue(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(3)); } /** diff --git a/core/src/main/java/com/google/bitcoin/core/Wallet.java b/core/src/main/java/com/google/bitcoin/core/Wallet.java index 2c9ee20b..7bc21483 100644 --- a/core/src/main/java/com/google/bitcoin/core/Wallet.java +++ b/core/src/main/java/com/google/bitcoin/core/Wallet.java @@ -2448,7 +2448,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha // Check if we need additional fee due to the transaction's size int size = tx.bitcoinSerialize().length; size += estimateBytesForSigning(coinSelection); - Coin fee = baseFee.add(Coin.valueOf((size / 1000) + 1).multiply(feePerKb)); + Coin fee = baseFee.add(feePerKb.multiply((size / 1000) + 1)); output.setValue(output.getValue().subtract(fee)); // Check if we need additional fee due to the output's value if (output.getValue().compareTo(Coin.CENT) < 0 && fee.compareTo(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE) < 0) @@ -3564,7 +3564,7 @@ public class Wallet extends BaseTaggableObject implements Serializable, BlockCha Coin fees = req.fee == null ? Coin.ZERO : req.fee; if (lastCalculatedSize > 0) { // If the size is exactly 1000 bytes then we'll over-pay, but this should be rare. - fees = fees.add(Coin.valueOf((lastCalculatedSize / 1000) + 1).multiply(req.feePerKb)); + fees = fees.add(req.feePerKb.multiply((lastCalculatedSize / 1000) + 1)); } else { fees = fees.add(req.feePerKb); // First time around the loop. } diff --git a/core/src/test/java/com/google/bitcoin/core/WalletTest.java b/core/src/test/java/com/google/bitcoin/core/WalletTest.java index 06c0d28c..6024c093 100644 --- a/core/src/test/java/com/google/bitcoin/core/WalletTest.java +++ b/core/src/test/java/com/google/bitcoin/core/WalletTest.java @@ -1562,7 +1562,7 @@ public class WalletTest extends TestWithWallet { // We optimize for priority, so the output selected should be the largest one assertEquals(Coin.COIN, spend6.getOutput(0).getValue().add(spend6.getOutput(1).getValue())); - SendRequest request7 = SendRequest.to(notMyAddr, Coin.COIN.subtract(CENT.subtract(Coin.valueOf(2)).multiply(Coin.valueOf(2)))); + SendRequest request7 = SendRequest.to(notMyAddr, Coin.COIN.subtract(CENT.subtract(Coin.valueOf(2)).multiply(2))); request7.tx.addOutput(CENT.subtract(ONE), notMyAddr); wallet.completeTx(request7); assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, request7.fee); @@ -1782,13 +1782,13 @@ public class WalletTest extends TestWithWallet { request20.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE; wallet.completeTx(request20); // 4kb tx. - assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(4)), request20.fee); + assertEquals(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(4), request20.fee); assertEquals(2, request20.tx.getInputs().size()); Coin outValue20 = ZERO; for (TransactionOutput out : request20.tx.getOutputs()) outValue20 = outValue20.add(out.getValue()); // This time the fee we wanted to pay was more, so that should be what we paid - assertEquals(outValue20, COIN.add(CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(4)))); + assertEquals(outValue20, COIN.add(CENT).subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(4))); // Same as request 19, but make the change 0 (so it doesnt force fee) and make us require min fee as a // result of an output < CENT. @@ -1820,7 +1820,7 @@ public class WalletTest extends TestWithWallet { // Now reset request19 and give it a fee per kb request25.tx.clearInputs(); request25 = SendRequest.forTx(request25.tx); - request25.feePerKb = CENT.divide(Coin.valueOf(3)); + request25.feePerKb = CENT.divide(3); request25.ensureMinRequiredFee = false; request25.shuffleOutputs = false; wallet.completeTx(request25); @@ -1875,7 +1875,7 @@ public class WalletTest extends TestWithWallet { // Generate a ton of small outputs StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, notMyAddr), BigInteger.ONE, 1); int i = 0; - while (i <= CENT.divide(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).longValue()) { + while (i <= CENT.divide(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE)) { Transaction tx = createFakeTxWithChangeAddress(params, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, myAddress, notMyAddr); tx.getInput(0).setSequenceNumber(i++); // Keep every transaction unique wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i); @@ -1912,13 +1912,13 @@ public class WalletTest extends TestWithWallet { // SendRequest request4 = SendRequest.to(notMyAddr, CENT.add(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE).subtract(ONE)); - request4.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.divide(Coin.valueOf(request3.tx.bitcoinSerialize().length)); + request4.feePerKb = Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.divide(request3.tx.bitcoinSerialize().length); wallet.completeTx(request4); assertEquals(ONE, request4.fee); assertEquals(request4.tx.getInputs().size(), i - 2); // We should have spent all inputs - 2 // Give us a few more inputs... - while (wallet.getBalance().compareTo(CENT.shiftLeft(1)) < 0) { + while (wallet.getBalance().compareTo(CENT.multiply(2)) < 0) { Transaction tx3 = createFakeTxWithChangeAddress(params, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE, myAddress, notMyAddr); tx3.getInput(0).setSequenceNumber(i++); // Keep every transaction unique wallet.receiveFromBlock(tx3, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i); @@ -1956,8 +1956,8 @@ public class WalletTest extends TestWithWallet { // Generate a ton of small outputs StoredBlock block = new StoredBlock(makeSolvedTestBlock(blockStore, notMyAddr), BigInteger.ONE, 1); int i = 0; - while (i <= CENT.divide(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.TEN)).longValue()) { - Transaction tx = createFakeTxWithChangeAddress(params, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.TEN), myAddress, notMyAddr); + while (i <= CENT.divide(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(10))) { + Transaction tx = createFakeTxWithChangeAddress(params, Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(10), myAddress, notMyAddr); tx.getInput(0).setSequenceNumber(i++); // Keep every transaction unique wallet.receiveFromBlock(tx, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, i); } @@ -2006,7 +2006,7 @@ public class WalletTest extends TestWithWallet { wallet.receiveFromBlock(tx3, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 2); // Create a transaction who's max size could be up to 1000 (if signatures were maximum size) - SendRequest request1 = SendRequest.to(notMyAddr, COIN.subtract(CENT.multiply(Coin.valueOf(17)))); + SendRequest request1 = SendRequest.to(notMyAddr, COIN.subtract(CENT.multiply(17))); for (int i = 0; i < 16; i++) request1.tx.addOutput(CENT, notMyAddr); request1.tx.addOutput(new TransactionOutput(params, request1.tx, CENT, new byte[16])); @@ -2025,7 +2025,7 @@ public class WalletTest extends TestWithWallet { wallet.receiveFromBlock(tx4, block, AbstractBlockChain.NewBlockType.BEST_CHAIN, 3); // Create a transaction who's max size could be up to 1000 (if signatures were maximum size) - SendRequest request2 = SendRequest.to(notMyAddr, COIN.subtract(CENT.multiply(Coin.valueOf(17)))); + SendRequest request2 = SendRequest.to(notMyAddr, COIN.subtract(CENT.multiply(17))); for (int i = 0; i < 16; i++) request2.tx.addOutput(CENT, notMyAddr); request2.tx.addOutput(new TransactionOutput(params, request2.tx, CENT, new byte[16])); diff --git a/core/src/test/java/com/google/bitcoin/protocols/channels/ChannelConnectionTest.java b/core/src/test/java/com/google/bitcoin/protocols/channels/ChannelConnectionTest.java index fa939273..4eabc1f8 100644 --- a/core/src/test/java/com/google/bitcoin/protocols/channels/ChannelConnectionTest.java +++ b/core/src/test/java/com/google/bitcoin/protocols/channels/ChannelConnectionTest.java @@ -519,11 +519,11 @@ public class ChannelConnectionTest extends TestWithWallet { // Now check that if the server has a lower min size than what we are willing to spend, we do actually open // a channel of that size. - sendMoneyToWallet(COIN.multiply(TEN), AbstractBlockChain.NewBlockType.BEST_CHAIN); + sendMoneyToWallet(COIN.multiply(10), AbstractBlockChain.NewBlockType.BEST_CHAIN); pair = ChannelTestUtils.makeRecorders(serverWallet, mockBroadcaster); server = pair.server; - final Coin myValue = COIN.multiply(TEN); + final Coin myValue = COIN.multiply(10); client = new PaymentChannelClient(wallet, myKey, myValue, Sha256Hash.ZERO_HASH, pair.clientRecorder); client.connectionOpen(); server.connectionOpen(); diff --git a/core/src/test/java/com/google/bitcoin/protocols/channels/PaymentChannelStateTest.java b/core/src/test/java/com/google/bitcoin/protocols/channels/PaymentChannelStateTest.java index 0489e1f2..d812ca88 100644 --- a/core/src/test/java/com/google/bitcoin/protocols/channels/PaymentChannelStateTest.java +++ b/core/src/test/java/com/google/bitcoin/protocols/channels/PaymentChannelStateTest.java @@ -95,7 +95,7 @@ public class PaymentChannelStateTest extends TestWithWallet { @Test public void stateErrors() throws Exception { PaymentChannelClientState channelState = new PaymentChannelClientState(wallet, myKey, serverKey, - COIN.multiply(TEN), 20); + COIN.multiply(10), 20); assertEquals(PaymentChannelClientState.State.NEW, channelState.getState()); try { channelState.getMultisigContract(); @@ -165,7 +165,7 @@ public class PaymentChannelStateTest extends TestWithWallet { assertFalse(clientWalletMultisigContract.getInput(0).getConnectedOutput().getSpentBy().getParentTransaction().getHash().equals(refund.getHash())); // Both client and server are now in the ready state. Simulate a few micropayments of 0.005 bitcoins. - Coin size = halfCoin.divide(Coin.TEN).divide(Coin.TEN); + Coin size = halfCoin.divide(100); Coin totalPayment = Coin.ZERO; for (int i = 0; i < 4; i++) { byte[] signature = clientState.incrementPaymentBy(size).signature.encodeToBitcoin(); @@ -195,10 +195,10 @@ public class PaymentChannelStateTest extends TestWithWallet { // Create a block with the payment transaction in it and give it to both wallets chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), reserializedCloseTx)); - assertEquals(size.multiply(Coin.valueOf(5)), serverWallet.getBalance()); + assertEquals(size.multiply(5), serverWallet.getBalance()); assertEquals(0, serverWallet.getPendingTransactions().size()); - assertEquals(COIN.subtract(size.multiply(Coin.valueOf(5))), wallet.getBalance()); + assertEquals(COIN.subtract(size.multiply(5)), wallet.getBalance()); assertEquals(0, wallet.getPendingTransactions().size()); assertEquals(3, wallet.getTransactions(false).size()); @@ -234,12 +234,12 @@ public class PaymentChannelStateTest extends TestWithWallet { assertEquals(PaymentChannelServerState.State.WAITING_FOR_REFUND_TRANSACTION, serverState.getState()); clientState = new PaymentChannelClientState(wallet, myKey, ECKey.fromPublicOnly(serverKey.getPubKey()), - CENT.divide(Coin.valueOf(2)), EXPIRE_TIME); + CENT.divide(2), EXPIRE_TIME); assertEquals(PaymentChannelClientState.State.NEW, clientState.getState()); - assertEquals(CENT.divide(Coin.valueOf(2)), clientState.getTotalValue()); + assertEquals(CENT.divide(2), clientState.getTotalValue()); clientState.initiate(); // We will have to pay min_tx_fee twice - both the multisig contract and the refund tx - assertEquals(clientState.getRefundTxFees(), Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(2))); + assertEquals(clientState.getRefundTxFees(), Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(2)); assertEquals(PaymentChannelClientState.State.INITIATED, clientState.getState()); // Send the refund tx from client to server and get back the signature. @@ -270,8 +270,8 @@ public class PaymentChannelStateTest extends TestWithWallet { assertEquals(PaymentChannelServerState.State.READY, serverState.getState()); // Pay a tiny bit - serverState.incrementPayment(CENT.divide(Coin.valueOf(2)).subtract(CENT.divide(TEN)), - clientState.incrementPaymentBy(CENT.divide(TEN)).signature.encodeToBitcoin()); + serverState.incrementPayment(CENT.divide(2).subtract(CENT.divide(10)), + clientState.incrementPaymentBy(CENT.divide(10)).signature.encodeToBitcoin()); // Advance time until our we get close enough to lock time that server should rebroadcast Utils.rollMockClock(60*60*22); @@ -314,7 +314,7 @@ public class PaymentChannelStateTest extends TestWithWallet { chain.add(makeSolvedTestBlock(blockStore.getChainHead().getHeader(), multisigContract,clientBroadcastedRefund)); // Make sure we actually had to pay what initialize() told us we would - assertEquals(wallet.getBalance(), CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(2)))); + assertEquals(wallet.getBalance(), CENT.subtract(Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(2))); try { // After its expired, we cant still increment payment @@ -452,7 +452,7 @@ public class PaymentChannelStateTest extends TestWithWallet { assertEquals(PaymentChannelServerState.State.READY, serverState.getState()); // Both client and server are now in the ready state. Simulate a few micropayments of 0.005 bitcoins. - Coin size = halfCoin.divide(Coin.TEN).divide(Coin.TEN); + Coin size = halfCoin.divide(100); Coin totalPayment = Coin.ZERO; try { clientState.incrementPaymentBy(COIN); @@ -561,7 +561,7 @@ public class PaymentChannelStateTest extends TestWithWallet { assertEquals(PaymentChannelClientState.State.NEW, clientState.getState()); // We'll have to pay REFERENCE_DEFAULT_MIN_TX_FEE twice (multisig+refund), and we'll end up getting back nearly nothing... clientState.initiate(); - assertEquals(clientState.getRefundTxFees(), Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(Coin.valueOf(2))); + assertEquals(clientState.getRefundTxFees(), Transaction.REFERENCE_DEFAULT_MIN_TX_FEE.multiply(2)); assertEquals(PaymentChannelClientState.State.INITIATED, clientState.getState()); // Now actually use a more useful CENT @@ -704,8 +704,8 @@ public class PaymentChannelStateTest extends TestWithWallet { assertTrue(e.getMessage().contains("more in fees")); } - signature = clientState.incrementPaymentBy(Coin.ONE.shiftLeft(1)).signature.encodeToBitcoin(); - totalRefund = totalRefund.subtract(Coin.ONE.shiftLeft(1)); + signature = clientState.incrementPaymentBy(Coin.valueOf(2)).signature.encodeToBitcoin(); + totalRefund = totalRefund.subtract(Coin.valueOf(2)); serverState.incrementPayment(totalRefund, signature); // And settle the channel. @@ -773,7 +773,7 @@ public class PaymentChannelStateTest extends TestWithWallet { assertFalse(clientWalletMultisigContract.getInput(0).getConnectedOutput().getSpentBy().getParentTransaction().getHash().equals(refund.getHash())); // Both client and server are now in the ready state. Simulate a few micropayments of 0.005 bitcoins. - Coin size = halfCoin.divide(Coin.TEN).divide(Coin.TEN); + Coin size = halfCoin.divide(100); Coin totalPayment = Coin.ZERO; for (int i = 0; i < 5; i++) { byte[] signature = clientState.incrementPaymentBy(size).signature.encodeToBitcoin(); diff --git a/core/src/test/java/com/google/bitcoin/wallet/DefaultCoinSelectorTest.java b/core/src/test/java/com/google/bitcoin/wallet/DefaultCoinSelectorTest.java index 99fb0e93..1dc770aa 100644 --- a/core/src/test/java/com/google/bitcoin/wallet/DefaultCoinSelectorTest.java +++ b/core/src/test/java/com/google/bitcoin/wallet/DefaultCoinSelectorTest.java @@ -97,7 +97,7 @@ public class DefaultCoinSelectorTest extends TestWithWallet { Transaction t1 = checkNotNull(sendMoneyToWallet(COIN, AbstractBlockChain.NewBlockType.BEST_CHAIN)); // Padding block. wallet.notifyNewBestBlock(FakeTxBuilder.createFakeBlock(blockStore).storedBlock); - final Coin TWO_COINS = COIN.multiply(Coin.valueOf(2)); + final Coin TWO_COINS = COIN.multiply(2); Transaction t2 = checkNotNull(sendMoneyToWallet(TWO_COINS, AbstractBlockChain.NewBlockType.BEST_CHAIN)); Transaction t3 = checkNotNull(sendMoneyToWallet(CENT, AbstractBlockChain.NewBlockType.BEST_CHAIN)); diff --git a/examples/src/main/java/com/google/bitcoin/examples/ExamplePaymentChannelClient.java b/examples/src/main/java/com/google/bitcoin/examples/ExamplePaymentChannelClient.java index db28b222..e1767249 100644 --- a/examples/src/main/java/com/google/bitcoin/examples/ExamplePaymentChannelClient.java +++ b/examples/src/main/java/com/google/bitcoin/examples/ExamplePaymentChannelClient.java @@ -40,7 +40,6 @@ import java.util.concurrent.CountDownLatch; import java.util.concurrent.ExecutionException; import static com.google.bitcoin.core.Coin.CENT; -import static com.google.bitcoin.core.Coin.TEN; /** * Simple client that connects to the given host, opens a channel, and pays one cent. @@ -123,7 +122,7 @@ public class ExamplePaymentChannelClient { // we are not allowed to have payment channels that pay nothing at all. log.info("Success! Trying to make {} micropayments. Already paid {} satoshis on this channel", times, client.state().getValueSpent()); - final Coin MICROPAYMENT_SIZE = CENT.divide(TEN); + final Coin MICROPAYMENT_SIZE = CENT.divide(10); for (int i = 0; i < times; i++) { try { // Wait because the act of making a micropayment is async, and we're not allowed to overlap.