From b7cb4d8c47d2852f83b2a34dd5b868739322c2f0 Mon Sep 17 00:00:00 2001 From: Adam Mackler Date: Mon, 16 Jun 2014 11:41:32 -0400 Subject: [PATCH] `TransactionOutput` class private `value` member changed to type `long` from `Coin`. --- .../com/google/bitcoin/core/Transaction.java | 16 ++++++---- .../bitcoin/core/TransactionOutput.java | 30 +++++++++---------- 2 files changed, 25 insertions(+), 21 deletions(-) diff --git a/core/src/main/java/com/google/bitcoin/core/Transaction.java b/core/src/main/java/com/google/bitcoin/core/Transaction.java index 88d2f5cb..5751a6a9 100644 --- a/core/src/main/java/com/google/bitcoin/core/Transaction.java +++ b/core/src/main/java/com/google/bitcoin/core/Transaction.java @@ -1265,13 +1265,17 @@ public class Transaction extends ChildMessage implements Serializable { throw new VerificationException("Transaction larger than MAX_BLOCK_SIZE"); Coin valueOut = Coin.ZERO; - for (TransactionOutput output : outputs) { - if (output.getValue().signum() < 0) - throw new VerificationException("Transaction output negative"); - valueOut = valueOut.add(output.getValue()); - } - if (valueOut.compareTo(NetworkParameters.MAX_MONEY) > 0) + try { + for (TransactionOutput output : outputs) { + if (output.getValue().signum() < 0) + throw new VerificationException("Transaction output negative"); + valueOut = valueOut.add(output.getValue()); + } + } catch (IllegalStateException e) { + throw new VerificationException("A transaction output value exceeds maximum possible"); + } catch (IllegalArgumentException e) { throw new VerificationException("Total transaction output value greater than possible"); + } if (isCoinBase()) { if (inputs.get(0).getScriptBytes().length < 2 || inputs.get(0).getScriptBytes().length > 100) 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 6297cd10..65da90dc 100644 --- a/core/src/main/java/com/google/bitcoin/core/TransactionOutput.java +++ b/core/src/main/java/com/google/bitcoin/core/TransactionOutput.java @@ -44,7 +44,7 @@ public class TransactionOutput extends ChildMessage implements Serializable { // A transaction output has some value and a script used for authenticating that the redeemer is allowed to spend // this output. - private Coin value; + private long value; private byte[] scriptBytes; // The script bytes are parsed and turned into a Script on demand. @@ -114,7 +114,7 @@ public class TransactionOutput extends ChildMessage implements Serializable { // SIGHASH_SINGLE signatures, so unfortunately we have to allow that here. checkArgument(value.signum() >= 0 || value.equals(Coin.NEGATIVE_SATOSHI), "Negative values not allowed"); checkArgument(value.compareTo(NetworkParameters.MAX_MONEY) < 0, "Values larger than MAX_MONEY not allowed"); - this.value = value; + this.value = value.value; this.scriptBytes = scriptBytes; parentTransaction = parent; availableForSpending = true; @@ -137,11 +137,7 @@ public class TransactionOutput extends ChildMessage implements Serializable { @Override protected void parseLite() throws ProtocolException { - // TODO: There is no reason to use Coin for values, they are always smaller than 21 million * COIN - // The only reason to use Coin would be to properly read values from the reference implementation, however - // the reference implementation uses signed 64-bit integers for its values as well (though it probably shouldn't) - long outputValue = readInt64(); - value = Coin.valueOf(outputValue); + value = readInt64(); scriptLen = (int) readVarInt(); length = cursor - offset + scriptLen; } @@ -154,7 +150,8 @@ public class TransactionOutput extends ChildMessage implements Serializable { @Override protected void bitcoinSerializeToStream(OutputStream stream) throws IOException { checkNotNull(scriptBytes); - Utils.int64ToByteStreamLE(getValue().value, stream); + maybeParse(); + Utils.int64ToByteStreamLE(value, stream); // TODO: Move script serialization into the Script class, where it belongs. stream.write(new VarInt(scriptBytes.length).encode()); stream.write(scriptBytes); @@ -166,7 +163,11 @@ public class TransactionOutput extends ChildMessage implements Serializable { */ public Coin getValue() { maybeParse(); - return value; + try { + return Coin.valueOf(value); + } catch (IllegalArgumentException e) { + throw new IllegalStateException(e.getMessage(), e); + } } /** @@ -175,7 +176,7 @@ public class TransactionOutput extends ChildMessage implements Serializable { public void setValue(Coin value) { checkNotNull(value); unCache(); - this.value = value; + this.value = value.value; } int getIndex() { @@ -309,7 +310,7 @@ public class TransactionOutput extends ChildMessage implements Serializable { try { Script script = getScriptPubKey(); StringBuilder buf = new StringBuilder("TxOut of "); - buf.append(value.toFriendlyString()); + buf.append(Coin.valueOf(value).toFriendlyString()); if (script.isSentToAddress() || script.isPayToScriptHash()) buf.append(" to ").append(script.getToAddress(params)); else if (script.isSentToRawPubKey()) @@ -361,7 +362,7 @@ public class TransactionOutput extends ChildMessage implements Serializable { /** Returns a copy of the output detached from its containing transaction, if need be. */ public TransactionOutput duplicateDetached() { - return new TransactionOutput(params, null, value, org.spongycastle.util.Arrays.clone(scriptBytes)); + return new TransactionOutput(params, null, Coin.valueOf(value), org.spongycastle.util.Arrays.clone(scriptBytes)); } @Override @@ -372,7 +373,7 @@ public class TransactionOutput extends ChildMessage implements Serializable { TransactionOutput other = (TransactionOutput) o; if (!Arrays.equals(scriptBytes, other.scriptBytes)) return false; - if (value != null ? !value.equals(other.value) : other.value != null) return false; + if (value != other.value) return false; if (parentTransaction != null && parentTransaction != other.parentTransaction) return false; return true; @@ -380,8 +381,7 @@ public class TransactionOutput extends ChildMessage implements Serializable { @Override public int hashCode() { - int result = value != null ? value.hashCode() : 0; - result = 31 * result + (scriptBytes != null ? Arrays.hashCode(scriptBytes) : 0); + int result = 31 * (int) value + (scriptBytes != null ? Arrays.hashCode(scriptBytes) : 0); return result; } }