3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-01-30 23:02:15 +00:00

Give VarInt a concept of originally serialized size.

VarInts have multiple encodings, and during parsing we need to know
the size of the actually encoded form, not the size of the optimal
encoding.
This commit is contained in:
Matt Corallo 2012-12-30 13:47:35 -05:00 committed by Mike Hearn
parent 95b5e0d894
commit 009939f9be
3 changed files with 29 additions and 6 deletions

View File

@ -439,7 +439,7 @@ public abstract class Message implements Serializable {
long readVarInt(int offset) {
VarInt varint = new VarInt(bytes, cursor + offset);
cursor += offset + varint.getSizeInBytes();
cursor += offset + varint.getOriginalSizeInBytes();
return varint.value;
}
@ -462,7 +462,7 @@ public abstract class Message implements Serializable {
cursor += 1;
return "";
}
cursor += varInt.getSizeInBytes();
cursor += varInt.getOriginalSizeInBytes();
byte[] characters = new byte[(int) varInt.value];
System.arraycopy(bytes, cursor, characters, 0, characters.length);
cursor += characters.length;

View File

@ -444,7 +444,7 @@ public class Transaction extends ChildMessage implements Serializable {
varint = new VarInt(buf, cursor);
long txInCount = varint.value;
cursor += varint.getSizeInBytes();
cursor += varint.getOriginalSizeInBytes();
for (i = 0; i < txInCount; i++) {
// 36 = length of previous_outpoint
@ -452,19 +452,19 @@ public class Transaction extends ChildMessage implements Serializable {
varint = new VarInt(buf, cursor);
scriptLen = varint.value;
// 4 = length of sequence field (unint32)
cursor += scriptLen + 4 + varint.getSizeInBytes();
cursor += scriptLen + 4 + varint.getOriginalSizeInBytes();
}
varint = new VarInt(buf, cursor);
long txOutCount = varint.value;
cursor += varint.getSizeInBytes();
cursor += varint.getOriginalSizeInBytes();
for (i = 0; i < txOutCount; i++) {
// 8 = length of tx value field (uint64)
cursor += 8;
varint = new VarInt(buf, cursor);
scriptLen = varint.value;
cursor += scriptLen + varint.getSizeInBytes();
cursor += scriptLen + varint.getOriginalSizeInBytes();
}
// 4 = length of lock_time field (uint32)
return cursor - offset + 4;

View File

@ -20,9 +20,11 @@ import static com.google.bitcoin.core.Utils.isLessThanUnsigned;
public class VarInt {
public final long value;
private final int originallyEncodedSize;
public VarInt(long value) {
this.value = value;
originallyEncodedSize = getSizeInBytes();
}
// BitCoin has its own varint format, known in the C++ source as "compact size".
@ -32,23 +34,41 @@ public class VarInt {
if (first < 253) {
// 8 bits.
val = first;
originallyEncodedSize = 1;
} else if (first == 253) {
// 16 bits.
val = (0xFF & buf[offset + 1]) | ((0xFF & buf[offset + 2]) << 8);
originallyEncodedSize = 3;
} else if (first == 254) {
// 32 bits.
val = Utils.readUint32(buf, offset + 1);
originallyEncodedSize = 5;
} else {
// 64 bits.
val = Utils.readUint32(buf, offset + 1) | (Utils.readUint32(buf, offset + 5) << 32);
originallyEncodedSize = 9;
}
this.value = val;
}
/**
* Gets the number of bytes used to encode this originally if deserialized from a byte array.
* Otherwise returns the minimum encoded size
*/
public int getOriginalSizeInBytes() {
return originallyEncodedSize;
}
/**
* Gets the minimum encoded size of the value stored in this VarInt
*/
public int getSizeInBytes() {
return sizeOf(value);
}
/**
* Gets the minimum encoded size of the given value.
*/
public static int sizeOf(int value) {
// Java doesn't have the actual value of MAX_INT, as all types in Java are signed.
if (value < 253)
@ -58,6 +78,9 @@ public class VarInt {
return 5; // 1 marker + 4 data bytes
}
/**
* Gets the minimum encoded size of the given value.
*/
public static int sizeOf(long value) {
// Java doesn't have the actual value of MAX_INT, as all types in Java are signed.
if (isLessThanUnsigned(value, 253))