3
0
mirror of https://github.com/Qortal/altcoinj.git synced 2025-02-12 10:15:52 +00:00

Fixed VarInt serialization bug for the 0xffffffff number. Fixed VarInt sizeOf bug for the 0xffffffff number and added tests for VarInt edge cases.

The 4294967295 number (0xffffffff) was incorrectly serialized because the UnsignedInteger.MAX_VALUE.longValue() helper returned 4294967295 instead of expected 4294967296.

The VarInt.sizeOf() incorrectly returned 9 instead of 5 for the 4294967295 (0xffffffff) number.

See https://en.bitcoin.it/wiki/Protocol_specification#Variable_length_integer
This commit is contained in:
Piotr Włodarek 2014-06-19 22:28:52 +02:00 committed by Andreas Schildbach
parent ae3acdfefd
commit 3dfaf54e28
3 changed files with 27 additions and 6 deletions

View File

@ -185,6 +185,13 @@ public class Utils {
return UnsignedLongs.compare(n1, n2) < 0;
}
/**
* Work around lack of unsigned types in Java.
*/
public static boolean isLessThanOrEqualToUnsigned(long n1, long n2) {
return UnsignedLongs.compare(n1, n2) <= 0;
}
/**
* Hex encoding used throughout the framework. Use with HEX.encode(byte[]) or HEX.decode(CharSequence).
*/

View File

@ -16,9 +16,8 @@
package com.google.bitcoin.core;
import com.google.common.primitives.UnsignedInteger;
import static com.google.bitcoin.core.Utils.isLessThanUnsigned;
import static com.google.bitcoin.core.Utils.isLessThanOrEqualToUnsigned;
/**
* A variable-length encoded integer using Satoshis encoding.
@ -88,9 +87,9 @@ public class VarInt {
public static int sizeOf(long value) {
if (isLessThanUnsigned(value, 253))
return 1;
else if (isLessThanUnsigned(value, 65536))
else if (isLessThanOrEqualToUnsigned(value, 0xFFFFL))
return 3; // 1 marker + 2 data bytes
else if (isLessThanUnsigned(value, UnsignedInteger.MAX_VALUE.longValue()))
else if (isLessThanOrEqualToUnsigned(value, 0xFFFFFFFFL))
return 5; // 1 marker + 4 data bytes
else
return 9; // 1 marker + 8 data bytes
@ -99,9 +98,9 @@ public class VarInt {
public byte[] encode() {
if (isLessThanUnsigned(value, 253)) {
return new byte[]{(byte) value};
} else if (isLessThanUnsigned(value, 65536)) {
} else if (isLessThanOrEqualToUnsigned(value, 0xFFFFL)) {
return new byte[]{(byte) 253, (byte) (value), (byte) (value >> 8)};
} else if (isLessThanUnsigned(value, UnsignedInteger.MAX_VALUE.longValue())) {
} else if (isLessThanOrEqualToUnsigned(value, 0xFFFFFFFFL)) {
byte[] bytes = new byte[5];
bytes[0] = (byte) 254;
Utils.uint32ToByteArrayLE(value, bytes, 1);

View File

@ -33,6 +33,13 @@ public class VarIntTest extends TestCase {
assertEquals(64000, new VarInt(a.encode(), 0).value);
}
public void testShortFFFF() throws Exception {
VarInt a = new VarInt(0xFFFFL);
assertEquals(3, a.getSizeInBytes());
assertEquals(3, a.encode().length);
assertEquals(0xFFFFL, new VarInt(a.encode(), 0).value);
}
public void testInts() throws Exception {
VarInt a = new VarInt(0xAABBCCDDL);
assertEquals(5, a.getSizeInBytes());
@ -41,6 +48,14 @@ public class VarIntTest extends TestCase {
assertEquals(0xAABBCCDDL, 0xFFFFFFFFL & new VarInt(bytes, 0).value);
}
public void testIntFFFFFFFF() throws Exception {
VarInt a = new VarInt(0xFFFFFFFFL);
assertEquals(5, a.getSizeInBytes());
assertEquals(5, a.encode().length);
byte[] bytes = a.encode();
assertEquals(0xFFFFFFFFL, 0xFFFFFFFFL & new VarInt(bytes, 0).value);
}
public void testLong() throws Exception {
VarInt a = new VarInt(0xCAFEBABEDEADBEEFL);
assertEquals(9, a.getSizeInBytes());