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 9481ed21..73d3c2cf 100644 --- a/core/src/main/java/com/google/bitcoin/core/TransactionOutput.java +++ b/core/src/main/java/com/google/bitcoin/core/TransactionOutput.java @@ -153,6 +153,15 @@ public class TransactionOutput extends ChildMessage implements Serializable { return value; } + /** + * Sets the value of this output in nanocoins. + */ + public void setValue(BigInteger value) { + checkNotNull(value); + unCache(); + this.value = value; + } + int getIndex() { checkNotNull(parentTransaction); for (int i = 0; i < parentTransaction.getOutputs().size(); i++) { diff --git a/core/src/main/java/com/google/bitcoin/core/Utils.java b/core/src/main/java/com/google/bitcoin/core/Utils.java index b9d3effd..c692b332 100644 --- a/core/src/main/java/com/google/bitcoin/core/Utils.java +++ b/core/src/main/java/com/google/bitcoin/core/Utils.java @@ -27,6 +27,7 @@ import java.math.BigInteger; import java.nio.charset.Charset; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; +import java.util.Arrays; import java.util.Date; import java.util.concurrent.locks.ReentrantLock; @@ -447,6 +448,15 @@ public class Utils { return out; } + /** + * Creates a copy of bytes and appends b to the end of it + */ + public static byte[] appendByte(byte[] bytes, byte b) { + byte[] result = Arrays.copyOf(bytes, bytes.length + 1); + result[result.length - 1] = b; + return result; + } + /** * Attempts to parse the given string as arbitrary-length hex or base58 and then return the results, or null if * neither parse was successful. diff --git a/core/src/main/java/com/google/bitcoin/script/Script.java b/core/src/main/java/com/google/bitcoin/script/Script.java index fef9b724..7f82c693 100644 --- a/core/src/main/java/com/google/bitcoin/script/Script.java +++ b/core/src/main/java/com/google/bitcoin/script/Script.java @@ -345,8 +345,12 @@ public class Script { } return sigOps; } - - static int decodeFromOpN(byte opcode) { + + /** + * Converts an opcode to its int representation + * @throws IllegalArgumentException If the opcode is not an OP_N opcode + */ + public static int decodeFromOpN(byte opcode) throws IllegalArgumentException { return decodeFromOpN((int)opcode); } static int decodeFromOpN(int opcode) { diff --git a/core/src/main/java/com/google/bitcoin/script/ScriptBuilder.java b/core/src/main/java/com/google/bitcoin/script/ScriptBuilder.java index c86273ad..6b6fe836 100644 --- a/core/src/main/java/com/google/bitcoin/script/ScriptBuilder.java +++ b/core/src/main/java/com/google/bitcoin/script/ScriptBuilder.java @@ -20,6 +20,7 @@ import com.google.bitcoin.core.Address; import com.google.bitcoin.core.ECKey; import com.google.bitcoin.core.Transaction; import com.google.common.collect.Lists; +import com.google.bitcoin.core.Utils; import java.util.Arrays; import java.util.List; @@ -78,22 +79,16 @@ public class ScriptBuilder { return new ScriptBuilder().data(key.getPubKey()).op(OP_CHECKSIG).build(); } - private static byte[] appendByte(byte[] buf, byte flags) { - byte[] result = Arrays.copyOf(buf, buf.length + 1); - result[result.length - 1] = flags; - return result; - } - /** Creates a scriptSig that can redeem a pay-to-address output. */ public static Script createInputScript(ECKey.ECDSASignature signature, ECKey pubKey, int sigHashFlags) { byte[] pubkeyBytes = pubKey.getPubKey(); - byte[] sigBytes = appendByte(signature.encodeToDER(), (byte) sigHashFlags); + byte[] sigBytes = Utils.appendByte(signature.encodeToDER(), (byte) sigHashFlags); return new ScriptBuilder().data(sigBytes).data(pubkeyBytes).build(); } /** Creates a scriptSig that can redeem a pay-to-pubkey output. */ public static Script createInputScript(ECKey.ECDSASignature signature, int sigHashFlags) { - byte[] sigBytes = appendByte(signature.encodeToDER(), (byte) sigHashFlags); + byte[] sigBytes = Utils.appendByte(signature.encodeToDER(), (byte) sigHashFlags); return new ScriptBuilder().data(sigBytes).build(); } @@ -119,7 +114,17 @@ public class ScriptBuilder { ScriptBuilder builder = new ScriptBuilder(); builder.smallNum(0); // Work around a bug in CHECKMULTISIG that is now a required part of the protocol. for (ECKey.ECDSASignature signature : signatures) - builder.data(appendByte(signature.encodeToDER(),(byte) ((sigHash.ordinal() + 1) | (anyoneCanPay ? 0x80 : 0)))); + builder.data(Utils.appendByte(signature.encodeToDER(),(byte) ((sigHash.ordinal() + 1) | (anyoneCanPay ? 0x80 : 0)))); + return builder.build(); + } + + /** Create a program that satisfies an OP_CHECKMULTISIG program, for when the signatures may not have the same SIGHASH/anyoneCanPay flags */ + public static Script createMultiSigInputScript(List signatures) { + checkArgument(signatures.size() <= 16); + ScriptBuilder builder = new ScriptBuilder(); + builder.smallNum(0); // Work around a bug in CHECKMULTISIG that is now a required part of the protocol. + for (byte[] signature : signatures) + builder.data(signature); return builder.build(); } }