package io.emax.cosigner.bitcoin.bitcoindrpc; import io.emax.cosigner.bitcoin.bitcoindrpc.RawTransaction.VariableInt; import io.emax.cosigner.common.ByteUtilities; import java.math.BigInteger; public final class RawOutput { private long amount; private long scriptSize = 0; private String script = ""; public long getAmount() { return amount; } public void setAmount(long amount) { this.amount = amount; } public long getScriptSize() { return scriptSize; } public void setScriptSize(long scriptSize) { this.scriptSize = scriptSize; } public String getScript() { return script; } public void setScript(String script) { this.script = script; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + (int) (amount ^ (amount >>> 32)); result = prime * result + ((script == null) ? 0 : script.hashCode()); result = prime * result + (int) (scriptSize ^ (scriptSize >>> 32)); return result; } @Override public boolean equals(Object obj) { if (this == obj) { return true; } if (obj == null) { return false; } if (getClass() != obj.getClass()) { return false; } RawOutput other = (RawOutput) obj; if (amount != other.amount) { return false; } if (script == null) { if (other.script != null) { return false; } } else if (!script.equals(other.script)) { return false; } return scriptSize == other.scriptSize; } @Override public String toString() { return "RawOutput [amount=" + amount + ", scriptSize=" + scriptSize + ", script=" + script + "]"; } /** * Encodes this output into a hex string. * * @return Hex string represnting the output. */ public String encode() { String tx = ""; // Satoshis byte[] satoshiBytes = ByteUtilities.stripLeadingNullBytes(BigInteger.valueOf(getAmount()).toByteArray()); satoshiBytes = ByteUtilities.leftPad(satoshiBytes, 8, (byte) 0x00); satoshiBytes = ByteUtilities.flipEndian(satoshiBytes); tx += ByteUtilities.toHexString(satoshiBytes); // Script Size setScriptSize(getScript().length() / 2L); byte[] scriptSizeBytes = RawTransaction.writeVariableInt(getScriptSize()); tx += ByteUtilities.toHexString(scriptSizeBytes); // Script byte[] scriptBytes = ByteUtilities.toByteArray(getScript()); tx += ByteUtilities.toHexString(scriptBytes); return tx; } /** * Parses a hex string representing an output and converts it into a RawOutput * * @param txData String representing the output. * @return Corresponding output object. */ public static RawOutput parse(String txData) { RawOutput output = new RawOutput(); byte[] rawTx = ByteUtilities.toByteArray(txData); int buffPointer = 0; byte[] satoshiBytes = ByteUtilities.readBytes(rawTx, buffPointer, 8); buffPointer += 8; satoshiBytes = ByteUtilities.flipEndian(satoshiBytes); output.setAmount(new BigInteger(1, satoshiBytes).longValue()); VariableInt varScriptSize = RawTransaction.readVariableInt(rawTx, buffPointer); buffPointer += varScriptSize != null ? varScriptSize.getSize() : 0; output.setScriptSize(varScriptSize != null ? varScriptSize.getValue() : 0); byte[] scriptBytes = ByteUtilities.readBytes(rawTx, buffPointer, (int) output.getScriptSize()); output.setScript(ByteUtilities.toHexString(scriptBytes)); return output; } /** * Size of the output when encoded to a hex string. * * @return Size of the encoded output. */ public long getDataSize() { int sizeSize = RawTransaction.writeVariableInt(getScriptSize()).length; // Satoshis + scriptSize + Script return 8 + sizeSize + getScriptSize(); } /** * Creates a copy of this output. * * @return A copy of the current output. */ public RawOutput copy() { RawOutput output = new RawOutput(); output.setAmount(getAmount()); output.setScriptSize(getScriptSize()); output.setScript(getScript()); return output; } }