TransactionWitness: Store pushes in a List<byte[]>

This is a pre-requisite to fix the exploit to its initial size
This commit is contained in:
Oscar Guindzberg
2018-05-08 13:44:39 -03:00
parent 002fe8184c
commit a6c356c403
2 changed files with 29 additions and 16 deletions

View File

@@ -23,28 +23,31 @@ import java.util.List;
public class TransactionWitness { public class TransactionWitness {
public static final TransactionWitness EMPTY = new TransactionWitness(0); public static final TransactionWitness EMPTY = new TransactionWitness(0);
private final byte[][] pushes; private final List<byte[]> pushes;
public TransactionWitness(int pushCount) { public TransactionWitness(int pushCount) {
pushes = new byte[pushCount][]; pushes = new ArrayList<>(pushCount);
} }
public byte[] getPush(int i) { public byte[] getPush(int i) {
return pushes[i]; return pushes.get(i);
} }
public int getPushCount() { public int getPushCount() {
return pushes.length; return pushes.size();
} }
public void setPush(int i, byte[] value) { 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 { protected void bitcoinSerializeToStream(OutputStream stream) throws IOException {
stream.write(new VarInt(pushes.length).encode()); stream.write(new VarInt(pushes.size()).encode());
for (int i = 0; i < pushes.length; i++) { for (int i = 0; i < pushes.size(); i++) {
byte[] push = pushes[i]; byte[] push = pushes.get(i);
stream.write(new VarInt(push.length).encode()); stream.write(new VarInt(push.length).encode());
stream.write(push); stream.write(push);
} }
@@ -55,10 +58,12 @@ public class TransactionWitness {
List<String> stringPushes = new ArrayList<>(); List<String> stringPushes = new ArrayList<>();
for (int j = 0; j < this.getPushCount(); j++) { for (int j = 0; j < this.getPushCount(); j++) {
byte[] push = this.getPush(j); byte[] push = this.getPush(j);
if (push != null) { if (push == null) {
stringPushes.add(Utils.HEX.encode(push));
} else {
stringPushes.add("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); return Utils.SPACE_JOINER.join(stringPushes);
@@ -69,11 +74,19 @@ public class TransactionWitness {
if (this == o) return true; if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false; if (o == null || getClass() != o.getClass()) return false;
TransactionWitness other = (TransactionWitness) o; 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 @Override
public int hashCode() { 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;
} }
} }

View File

@@ -25,12 +25,12 @@ public class TransactionWitnessTest {
assertEquals("", w1.toString()); assertEquals("", w1.toString());
TransactionWitness w2 = new TransactionWitness(2); TransactionWitness w2 = new TransactionWitness(2);
assertEquals("NULL NULL", w2.toString()); assertEquals("", w2.toString());
TransactionWitness w3 = new TransactionWitness(3); TransactionWitness w3 = new TransactionWitness(3);
w3.setPush(0, Utils.HEX.decode("123aaa")); w3.setPush(0, Utils.HEX.decode("123aaa"));
w3.setPush(1, Utils.HEX.decode("123bbb")); w3.setPush(1, Utils.HEX.decode("123bbb"));
w3.setPush(2, Utils.HEX.decode("123ccc")); w3.setPush(3, Utils.HEX.decode("123ccc"));
assertEquals("123aaa 123bbb 123ccc", w3.toString()); assertEquals("123aaa 123bbb EMPTY 123ccc", w3.toString());
} }
} }