From acd0faaec71da5564b7a60d4a3543dac5bc6c803 Mon Sep 17 00:00:00 2001 From: Andreas Schildbach Date: Thu, 6 Feb 2025 18:47:11 +0100 Subject: [PATCH] ScriptBuilder: if pushing an empty data, use data() not smallNum() Pushing an empty data is *not* a no-op: an item is added to the stack. So that empty array should be represented in the data part of the script chunk. This makes behaviour consistent with script parsing, and input signing expects the empty array as a placeholder for a missing signature. This reverts 07682145e3fbce4b278def8ab86003d2dc447442 from 2015! Also adds a test. --- .../org/bitcoinj/script/ScriptBuilder.java | 5 +---- .../bitcoinj/script/ScriptBuilderTest.java | 22 +++++++++++++++++++ 2 files changed, 23 insertions(+), 4 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/script/ScriptBuilder.java b/core/src/main/java/org/bitcoinj/script/ScriptBuilder.java index a27d65fa9..e2a86241f 100644 --- a/core/src/main/java/org/bitcoinj/script/ScriptBuilder.java +++ b/core/src/main/java/org/bitcoinj/script/ScriptBuilder.java @@ -115,10 +115,7 @@ public class ScriptBuilder { /** Adds a copy of the given byte array as a data element (i.e. PUSHDATA) at the end of the program. */ public ScriptBuilder data(byte[] data) { - if (data.length == 0) - return smallNum(0); - else - return data(chunks.size(), data); + return data(chunks.size(), data); } /** Adds a copy of the given byte array as a data element (i.e. PUSHDATA) at the given index in the program. */ diff --git a/core/src/test/java/org/bitcoinj/script/ScriptBuilderTest.java b/core/src/test/java/org/bitcoinj/script/ScriptBuilderTest.java index 31214e723..390df0e5d 100644 --- a/core/src/test/java/org/bitcoinj/script/ScriptBuilderTest.java +++ b/core/src/test/java/org/bitcoinj/script/ScriptBuilderTest.java @@ -18,14 +18,36 @@ package org.bitcoinj.script; import org.junit.Test; +import static org.bitcoinj.script.ScriptOpCodes.OP_0; import static org.bitcoinj.script.ScriptOpCodes.OP_FALSE; import static org.bitcoinj.script.ScriptOpCodes.OP_TRUE; import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; public class ScriptBuilderTest { + @Test + public void emptyPushData() { + Script script = new ScriptBuilder().data(new byte[0]).build(); + ScriptChunk chunk = script.chunks().get(0); + assertEquals(OP_0, chunk.opcode); + assertNotNull(chunk.data); + assertEquals(0, chunk.data.length); + + byte[] serialized = script.program(); + assertArrayEquals(new byte[] { + 0x00 // Pushed data + }, serialized); + + Script parsedScript = Script.parse(script.program()); + ScriptChunk parsedChunk = parsedScript.chunks().get(0); + assertEquals(OP_0, parsedChunk.opcode); + assertNotNull(parsedChunk.data); + assertEquals(0, parsedChunk.data.length); + } + @Test public void testNumber() { for (int i = -100; i <= 100; i++) {