From a6c356c403ccd658684a01608660bb6abe3e891c Mon Sep 17 00:00:00 2001 From: Oscar Guindzberg Date: Tue, 8 May 2018 13:44:39 -0300 Subject: [PATCH] TransactionWitness: Store pushes in a List This is a pre-requisite to fix the exploit to its initial size --- .../org/bitcoinj/core/TransactionWitness.java | 39 ++++++++++++------- .../bitcoinj/core/TransactionWitnessTest.java | 6 +-- 2 files changed, 29 insertions(+), 16 deletions(-) diff --git a/core/src/main/java/org/bitcoinj/core/TransactionWitness.java b/core/src/main/java/org/bitcoinj/core/TransactionWitness.java index 4b3ac09c..05c15286 100644 --- a/core/src/main/java/org/bitcoinj/core/TransactionWitness.java +++ b/core/src/main/java/org/bitcoinj/core/TransactionWitness.java @@ -23,28 +23,31 @@ import java.util.List; public class TransactionWitness { public static final TransactionWitness EMPTY = new TransactionWitness(0); - private final byte[][] pushes; + private final List pushes; public TransactionWitness(int pushCount) { - pushes = new byte[pushCount][]; + pushes = new ArrayList<>(pushCount); } public byte[] getPush(int i) { - return pushes[i]; + return pushes.get(i); } public int getPushCount() { - return pushes.length; + return pushes.size(); } public void setPush(int i, byte[] value) { - pushes[i] = value; + while (i >= pushes.size()) { + pushes.add(new byte[]{}); + } + pushes.set(i, value); } protected void bitcoinSerializeToStream(OutputStream stream) throws IOException { - stream.write(new VarInt(pushes.length).encode()); - for (int i = 0; i < pushes.length; i++) { - byte[] push = pushes[i]; + stream.write(new VarInt(pushes.size()).encode()); + for (int i = 0; i < pushes.size(); i++) { + byte[] push = pushes.get(i); stream.write(new VarInt(push.length).encode()); stream.write(push); } @@ -55,10 +58,12 @@ public class TransactionWitness { List stringPushes = new ArrayList<>(); for (int j = 0; j < this.getPushCount(); j++) { byte[] push = this.getPush(j); - if (push != null) { - stringPushes.add(Utils.HEX.encode(push)); - } else { + if (push == null) { stringPushes.add("NULL"); + } else if (push.length == 0) { + stringPushes.add("EMPTY"); + } else { + stringPushes.add(Utils.HEX.encode(push)); } } return Utils.SPACE_JOINER.join(stringPushes); @@ -69,11 +74,19 @@ public class TransactionWitness { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; TransactionWitness other = (TransactionWitness) o; - return Arrays.deepEquals(pushes, other.pushes); + if (pushes.size() != other.pushes.size()) return false; + for (int i = 0; i < pushes.size(); i++) { + if (!Arrays.equals(pushes.get(i), other.pushes.get(i))) return false; + } + return true; } @Override public int hashCode() { - return Arrays.deepHashCode(pushes); + int hashCode = 1; + for (byte[] push : pushes) { + hashCode = 31 * hashCode + (push == null ? 0 : Arrays.hashCode(push)); + } + return hashCode; } } diff --git a/core/src/test/java/org/bitcoinj/core/TransactionWitnessTest.java b/core/src/test/java/org/bitcoinj/core/TransactionWitnessTest.java index 7e11ae96..b737bebd 100644 --- a/core/src/test/java/org/bitcoinj/core/TransactionWitnessTest.java +++ b/core/src/test/java/org/bitcoinj/core/TransactionWitnessTest.java @@ -25,12 +25,12 @@ public class TransactionWitnessTest { assertEquals("", w1.toString()); TransactionWitness w2 = new TransactionWitness(2); - assertEquals("NULL NULL", w2.toString()); + assertEquals("", w2.toString()); TransactionWitness w3 = new TransactionWitness(3); w3.setPush(0, Utils.HEX.decode("123aaa")); w3.setPush(1, Utils.HEX.decode("123bbb")); - w3.setPush(2, Utils.HEX.decode("123ccc")); - assertEquals("123aaa 123bbb 123ccc", w3.toString()); + w3.setPush(3, Utils.HEX.decode("123ccc")); + assertEquals("123aaa 123bbb EMPTY 123ccc", w3.toString()); } }