package org.ripple.power.txns.btc; import java.io.EOFException; /** * <p>A transaction input has the following format:</p> * <pre> * Size Field Description * === ===== =========== * 32 bytes TxOutHash Double SHA-256 hash of the transaction containing the output * to be used by this input * 4 bytes TxOutIndex Index of the output within the transaction * VarInt TxInScriptLength Script length * Variable TxInScript Script * 4 bytes TxInSeqNumber Input sequence number (irrelevant unless transaction LockTime is * non-zero) * </pre> * <p>All numbers are encoded in little-endian format (least-significant byte to most-significant byte)</p> */ public class TransactionInput implements ByteSerializable { /** The transaction output connected to this input */ private final OutPoint outPoint; /** Input script */ private byte[] scriptBytes; /** Input sequence number */ private final int seqNumber; /** Parent transaction */ private final Transaction tx; /** Transaction input index */ private final int txIndex; /** * Create a transaction input for the specified outpoint. * * @param tx Parent transaction * @param txIndex Transaction input index * @param outPoint Connected transaction output */ public TransactionInput(Transaction tx, int txIndex, OutPoint outPoint) { this.tx = tx; this.txIndex = txIndex; this.outPoint = outPoint; this.seqNumber = -1; this.scriptBytes = new byte[0]; } /** * Create a transaction input from the encoded byte stream * * @param tx Parent transaction * @param txIndex Transaction input index * @param inBuffer Input buffer * @throws EOFException Input stream is too short * @throws VerificationException Verification error */ public TransactionInput(Transaction tx, int txIndex, SerializedBuffer inBuffer) throws EOFException, VerificationException { this.tx = tx; this.txIndex = txIndex; // // Get the transaction output connected to this input // outPoint = new OutPoint(inBuffer); // // Get the script // scriptBytes = inBuffer.getBytes(); // // Get the sequence number // seqNumber = inBuffer.getInt(); } /** * Return the serialized transaction input * * @param outBuffer Output buffer * @return Output buffer */ @Override public SerializedBuffer getBytes(SerializedBuffer outBuffer) { outPoint.getBytes(outBuffer) .putVarInt(scriptBytes.length) .putBytes(scriptBytes) .putInt(seqNumber); return outBuffer; } /** * Returns the serialized transaction input * * @return Serialized transaction input */ @Override public byte[] getBytes() { SerializedBuffer buffer = new SerializedBuffer(); return getBytes(buffer).toByteArray(); } /** * Return the transaction containing this input * * @return Parent transaction */ public Transaction getTransaction() { return tx; } /** * Return the index of this input within the transaction inputs * * @return Transaction input index */ public int getIndex() { return txIndex; } /** * Get the transaction output connected to this input * * @return Transaction output */ public OutPoint getOutPoint() { return outPoint; } /** * Return the script bytes for this input * * @return Script bytes */ public byte[] getScriptBytes() { return scriptBytes; } /** * Set the script bytes for this input * * @param scriptBytes Script bytes */ public void setScriptBytes(byte[] scriptBytes) { this.scriptBytes = scriptBytes; } /** * Return the transaction sequence number * * @return Transaction sequence number */ public int getSeqNumber() { return seqNumber; } /** * Serialize this input for use in a transaction signature * * The scriptBytes are replaced by the supplied subScriptBytes. In addition, the sequence number * is set to zero for all hash types other than SIGHASH_ALL. * * @param index Index of the input being signed * @param hashType Hash type * @param subScriptBytes Replacement script bytes * @param outBuffer Output buffer */ public void serializeForSignature(int index, int hashType, byte[] subScriptBytes, SerializedBuffer outBuffer) { outPoint.getBytes(outBuffer) .putVarInt(subScriptBytes.length) .putBytes(subScriptBytes) .putInt(hashType==ScriptOpCodes.SIGHASH_ALL||index==txIndex ? seqNumber : 0); } }