diff --git a/core/src/main/java/org/bitcoinj/script/Script.java b/core/src/main/java/org/bitcoinj/script/Script.java index 6a7acc2e4cc..9407c4c9d03 100644 --- a/core/src/main/java/org/bitcoinj/script/Script.java +++ b/core/src/main/java/org/bitcoinj/script/Script.java @@ -378,14 +378,13 @@ public byte[] program() { if (program != null) // Don't round-trip as Bitcoin Core doesn't and it would introduce a mismatch. return Arrays.copyOf(program, program.length); - try { - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - for (ScriptChunk chunk : chunks) { - chunk.write(bos); - } - return bos.toByteArray(); - } catch (IOException e) { - throw new RuntimeException(e); // Cannot happen. + else { + int size = chunks.stream().mapToInt(ScriptChunk::size).sum(); + ByteBuffer buf = ByteBuffer.allocate(size); + chunks.forEach(chunk -> + buf.put(chunk.toByteArray()) + ); + return buf.array(); } } diff --git a/core/src/main/java/org/bitcoinj/script/ScriptChunk.java b/core/src/main/java/org/bitcoinj/script/ScriptChunk.java index 02f100a4b2b..42d5d6cf7a5 100644 --- a/core/src/main/java/org/bitcoinj/script/ScriptChunk.java +++ b/core/src/main/java/org/bitcoinj/script/ScriptChunk.java @@ -20,9 +20,9 @@ import org.bitcoinj.base.internal.ByteUtils; import javax.annotation.Nullable; -import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.OutputStream; +import java.nio.ByteBuffer; import java.util.Arrays; import java.util.Objects; @@ -105,44 +105,47 @@ public boolean isShortestPossiblePushData() { return opcode == OP_PUSHDATA4; } + /** + * @deprecated Use {@link #toByteArray()} + */ + @Deprecated public void write(OutputStream stream) throws IOException { + stream.write(toByteArray()); + } + + private void write(ByteBuffer buf) { if (isOpCode()) { checkState(data == null); - stream.write(opcode); + buf.put((byte) opcode); } else if (data != null) { if (opcode < OP_PUSHDATA1) { checkState(data.length == opcode); - stream.write(opcode); + buf.put((byte) opcode); } else if (opcode == OP_PUSHDATA1) { checkState(data.length <= 0xFF); - stream.write(OP_PUSHDATA1); - stream.write(data.length); + buf.put((byte) OP_PUSHDATA1); + buf.put((byte) data.length); } else if (opcode == OP_PUSHDATA2) { checkState(data.length <= 0xFFFF); - stream.write(OP_PUSHDATA2); - ByteUtils.writeInt16LE(data.length, stream); + buf.put((byte) OP_PUSHDATA2); + ByteUtils.writeInt16LE(data.length, buf); } else if (opcode == OP_PUSHDATA4) { checkState(data.length <= Script.MAX_SCRIPT_ELEMENT_SIZE); - stream.write(OP_PUSHDATA4); - ByteUtils.writeInt32LE(data.length, stream); + buf.put((byte) OP_PUSHDATA4); + ByteUtils.writeInt32LE(data.length, buf); } else { throw new RuntimeException("Unimplemented"); } - stream.write(data); + buf.put(data); } else { - stream.write(opcode); // smallNum + buf.put((byte) opcode); // smallNum } } public byte[] toByteArray() { - ByteArrayOutputStream stream = new ByteArrayOutputStream(); - try { - write(stream); - } catch (IOException e) { - // Should not happen as ByteArrayOutputStream does not throw IOException on write - throw new RuntimeException(e); - } - return stream.toByteArray(); + ByteBuffer buf = ByteBuffer.allocate(size()); + write(buf); + return buf.array(); } /*