/** Similar to parseCoin, but allows for inexact representations to be rounded */ public static Coin parseCoinInexact(final String str) { return Coin.valueOf( new BigDecimal(str) .movePointRight(SMALLEST_UNIT_EXPONENT) .setScale(0, BigDecimal.ROUND_HALF_UP) .toBigInteger() .longValue()); }
@GuardedBy("lock") private void receiveUpdatePaymentMessage(Protos.UpdatePayment msg, boolean sendAck) throws VerificationException, ValueOutOfRangeException, InsufficientMoneyException { log.info("Got a payment update"); Coin lastBestPayment = state.getBestValueToMe(); final Coin refundSize = Coin.valueOf(msg.getClientChangeValue()); boolean stillUsable = state.incrementPayment(refundSize, msg.getSignature().toByteArray()); Coin bestPaymentChange = state.getBestValueToMe().subtract(lastBestPayment); ListenableFuture<ByteString> ackInfoFuture = null; if (bestPaymentChange.signum() > 0) { ByteString info = (msg.hasInfo()) ? msg.getInfo() : null; ackInfoFuture = conn.paymentIncrease(bestPaymentChange, state.getBestValueToMe(), info); } if (sendAck) { final Protos.TwoWayChannelMessage.Builder ack = Protos.TwoWayChannelMessage.newBuilder(); ack.setType(Protos.TwoWayChannelMessage.MessageType.PAYMENT_ACK); if (ackInfoFuture == null) { conn.sendToClient(ack.build()); } else { Futures.addCallback( ackInfoFuture, new FutureCallback<ByteString>() { @Override public void onSuccess(@Nullable ByteString result) { if (result != null) ack.setPaymentAck(ack.getPaymentAckBuilder().setInfo(result)); conn.sendToClient(ack.build()); } @Override public void onFailure(Throwable t) { log.info("Failed retrieving paymentIncrease info future"); error( "Failed processing payment update", Protos.Error.ErrorCode.OTHER, CloseReason.UPDATE_PAYMENT_FAILED); } }); } } if (!stillUsable) { log.info("Channel is now fully exhausted, closing/initiating settlement"); settlePayment(CloseReason.CHANNEL_EXHAUSTED); } }
/** Represents a monetary Bitcoin value. This class is immutable. */ public final class Coin implements Monetary, Comparable<Coin>, Serializable { /** * Number of decimals for one Peercoin. This constant is useful for quick adapting to other coins * because a lot of constants derive from it. */ public static final int SMALLEST_UNIT_EXPONENT = 6; /** The number of satoshis equal to one peercoin. */ private static final long COIN_VALUE = LongMath.pow(10, SMALLEST_UNIT_EXPONENT); /** Zero Peercoins. */ public static final Coin ZERO = Coin.valueOf(0); /** One Peercoin. */ public static final Coin COIN = Coin.valueOf(COIN_VALUE); /** 0.01 Peercoins. This unit is not really used much. */ public static final Coin CENT = COIN.divide(100); /** 0.001 Peercoins, also known as 1 mPPC. */ public static final Coin MILLICOIN = COIN.divide(1000); /** 0.000001 Peercoin, also known as 1 µPPC or 1 uPPC. */ public static final Coin MICROCOIN = MILLICOIN.divide(1000); /** * A satoshi is the smallest unit that can be transferred. 1 million of them fit into a Peercoin. */ public static final Coin SATOSHI = Coin.valueOf(1); /** Represents a monetary value of minus one satoshi. */ public static final Coin NEGATIVE_SATOSHI = Coin.valueOf(-1); /** The number of satoshis of this monetary value. */ public final long value; private final long MAX_SATOSHIS = COIN_VALUE * NetworkParameters.MAX_COINS; private Coin(final long satoshis) { checkArgument( -MAX_SATOSHIS <= satoshis && satoshis <= MAX_SATOSHIS, "%s satoshis exceeds maximum possible quantity of Peercoin.", satoshis); this.value = satoshis; } public static Coin valueOf(final long satoshis) { return new Coin(satoshis); } @Override public int smallestUnitExponent() { return SMALLEST_UNIT_EXPONENT; } /** Returns the number of satoshis of this monetary value. */ @Override public long getValue() { return value; } /** Convert an amount expressed in the way humans are used to into satoshis. */ public static Coin valueOf(final int coins, final int cents) { checkArgument(cents < 100); 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; } /** * Parses an amount expressed in the way humans are used to. * * <p> * * <p>This takes string in a format understood by {@link BigDecimal#BigDecimal(String)}, for * example "0", "1", "0.10", "1.23E3", "1234.5E-5". * * @throws IllegalArgumentException if you try to specify fractional satoshis, or a value out of * range. */ public static Coin parseCoin(final String str) { return Coin.valueOf( new BigDecimal(str).movePointRight(SMALLEST_UNIT_EXPONENT).toBigIntegerExact().longValue()); } /** Similar to parseCoin, but allows for inexact representations to be rounded */ public static Coin parseCoinInexact(final String str) { return Coin.valueOf( new BigDecimal(str) .movePointRight(SMALLEST_UNIT_EXPONENT) .setScale(0, BigDecimal.ROUND_HALF_UP) .toBigInteger() .longValue()); } public Coin add(final Coin value) { return new Coin(LongMath.checkedAdd(this.value, value.value)); } public Coin subtract(final Coin value) { return new Coin(LongMath.checkedSubtract(this.value, value.value)); } public Coin multiply(final long factor) { return new Coin(LongMath.checkedMultiply(this.value, factor)); } public Coin divide(final long divisor) { return new Coin(this.value / divisor); } public Coin[] divideAndRemainder(final long divisor) { return new Coin[] {new Coin(this.value / divisor), new Coin(this.value % divisor)}; } public long divide(final Coin divisor) { return this.value / divisor.value; } /** * Returns true if and only if this instance represents a monetary value greater than zero, * otherwise false. */ public boolean isPositive() { return signum() == 1; } /** * Returns true if and only if this instance represents a monetary value less than zero, otherwise * false. */ public boolean isNegative() { return signum() == -1; } /** Returns true if and only if this instance represents zero monetary value, otherwise false. */ public boolean isZero() { return signum() == 0; } /** * Returns true if the monetary value represented by this instance is greater than that of the * given other Coin, otherwise false. */ public boolean isGreaterThan(Coin other) { return compareTo(other) > 0; } /** * Returns true if the monetary value represented by this instance is less than that of the given * other Coin, otherwise false. */ public boolean isLessThan(Coin other) { return compareTo(other) < 0; } public Coin shiftLeft(final int n) { return new Coin(this.value << n); } public Coin shiftRight(final int n) { return new Coin(this.value >> n); } @Override public int signum() { if (this.value == 0) return 0; return this.value < 0 ? -1 : 1; } public Coin negate() { return new Coin(-this.value); } /** * Returns the number of satoshis of this monetary value. It's deprecated in favour of accessing * {@link #value} directly. */ public long longValue() { return this.value; } private static final MonetaryFormat FRIENDLY_FORMAT = MonetaryFormat.PPC.minDecimals(2).repeatOptionalDecimals(1, 4).postfixCode(); /** * Returns the value as a 0.12 type string. More digits after the decimal place will be used if * necessary, but two will always be present. */ public String toFriendlyString() { return FRIENDLY_FORMAT.format(this).toString(); } private static final MonetaryFormat PLAIN_FORMAT = MonetaryFormat.PPC.minDecimals(0).repeatOptionalDecimals(1, 6).noCode(); /** * Returns the value as a plain string denominated in PPC. The result is unformatted with no * trailing zeroes. For instance, a value of 150000 satoshis gives an output string of "0.0015" * PPC */ public String toPlainString() { return PLAIN_FORMAT.format(this).toString(); } @Override public String toString() { return Long.toString(value); } @Override public boolean equals(final Object o) { if (o == this) return true; if (o == null || o.getClass() != getClass()) return false; final Coin other = (Coin) o; if (this.value != other.value) return false; return true; } @Override public int hashCode() { return (int) this.value; } @Override public int compareTo(final Coin other) { if (this.value == other.value) return 0; return this.value > other.value ? 1 : -1; } }
/** * Parses an amount expressed in the way humans are used to. * * <p> * * <p>This takes string in a format understood by {@link BigDecimal#BigDecimal(String)}, for * example "0", "1", "0.10", "1.23E3", "1234.5E-5". * * @throws IllegalArgumentException if you try to specify fractional satoshis, or a value out of * range. */ public static Coin parseCoin(final String str) { return Coin.valueOf( new BigDecimal(str).movePointRight(SMALLEST_UNIT_EXPONENT).toBigIntegerExact().longValue()); }