Skip to content

Commit 51bb448

Browse files
authored
add ut for scale integer (#420)
* add ut for scale integer * add address encode/decode
1 parent 9d93873 commit 51bb448

File tree

6 files changed

+356
-22
lines changed

6 files changed

+356
-22
lines changed

sdk-codec/src/main/java/org/fisco/bcos/sdk/codec/datatypes/IntType.java

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -9,22 +9,20 @@ public IntType(String typePrefix, int bitSize, BigInteger value) {
99
super(typePrefix + bitSize, value, bitSize);
1010
if (!valid(bitSize, value)) {
1111
throw new UnsupportedOperationException(
12-
"Bitsize must be 8 bit aligned, and in range 0 < bitSize <= 256, and in valid range, bitSize: "
12+
"Bit size must be 8 bit aligned, and the bitLength must be no larger than "
1313
+ bitSize
14+
+ ". Current bytes size:"
15+
+ value.toByteArray().length
1416
+ ", value:"
1517
+ value);
1618
}
1719
}
1820

1921
boolean valid(int bitSize, BigInteger value) {
20-
return isValidBitSize(bitSize) && isValidBitCount(bitSize, value);
22+
return isValidBitSize(bitSize);
2123
}
2224

2325
static boolean isValidBitSize(int bitSize) {
2426
return bitSize % 8 == 0 && bitSize > 0 && bitSize <= MAX_BIT_LENGTH;
2527
}
26-
27-
private static boolean isValidBitCount(int bitSize, BigInteger value) {
28-
return value.bitLength() <= bitSize;
29-
}
3028
}

sdk-codec/src/main/java/org/fisco/bcos/sdk/codec/scale/ScaleCodecReader.java

Lines changed: 9 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -79,23 +79,22 @@ public BigInteger decodeInteger(boolean signed, int bytesSize) {
7979
}
8080
byte[] resultBytes = readByteArray(bytesSize);
8181
ArrayUtils.reverse(resultBytes);
82-
int pos = 0;
83-
for (; pos < resultBytes.length; pos++) {
84-
if (resultBytes[pos] != 0) {
85-
break;
86-
}
87-
}
88-
int length = resultBytes.length - pos;
89-
byte[] result = new byte[length];
90-
System.arraycopy(resultBytes, pos, result, 0, length);
91-
BigInteger value = new BigInteger(result);
82+
BigInteger value = new BigInteger(resultBytes);
9283
if (value.compareTo(BigInteger.ZERO) < 0 && signed == false) {
9384
BigInteger minOverflowUnsignedValue = BigInteger.valueOf((1 << (bytesSize * 8)));
9485
return value.add(minOverflowUnsignedValue);
9586
}
9687
return value;
9788
}
9889

90+
public BigInteger decodeInt256() {
91+
if (hasMore(32) == false) {
92+
throw new UnsupportedOperationException("decodeInt256 exception for not enough data");
93+
}
94+
byte[] data = readByteArray(32);
95+
return new BigInteger(data);
96+
}
97+
9998
public BigInteger decodeCompactInteger() {
10099
byte firstByte = readByte();
101100
int flag = ((int) (firstByte) & 0b00000011);

sdk-codec/src/main/java/org/fisco/bcos/sdk/codec/scale/ScaleCodecWriter.java

Lines changed: 35 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -76,13 +76,14 @@ private void encodeThirdCategory(BigInteger value) throws IOException {
7676
}
7777

7878
public void writeUnsignedInteger(BigInteger value, int valueByteSize) throws IOException {
79-
BigInteger maxSignedValue = BigInteger.valueOf((1 << (valueByteSize * 8 - 1)) - 1);
79+
BigInteger maxSignedValue =
80+
BigInteger.ONE.shiftLeft((valueByteSize * 8 - 1)).subtract(BigInteger.ONE);
8081
if (value.compareTo(maxSignedValue) <= 0) {
8182
writeInteger(value, valueByteSize);
8283
return;
8384
}
8485
// the highest bit is 1, convert to the negative
85-
BigInteger minOverflowUnsignedValue = BigInteger.valueOf((1 << (valueByteSize * 8)));
86+
BigInteger minOverflowUnsignedValue = BigInteger.ONE.shiftLeft(valueByteSize * 8);
8687
if (value.compareTo(minOverflowUnsignedValue) >= 0) {
8788
throw new UnsupportedOperationException(
8889
"writeInteger exception for overflow, value: " + value);
@@ -100,12 +101,44 @@ public void writeInteger(BigInteger value, int valueByteSize) throws IOException
100101
throw new UnsupportedOperationException(
101102
"writeInteger exception for overflow, value: " + value);
102103
}
104+
103105
for (int i = 0; i < byteValue.length; ++i) {
104106
byteArray[i] = byteValue[byteValue.length - i - 1];
105107
}
108+
// negative value(fill 0xff: -1)
109+
if (value.compareTo(BigInteger.ZERO) < 0) {
110+
for (int i = byteValue.length; i < valueByteSize; i++) {
111+
byteArray[i] = (byte) 0xff;
112+
}
113+
}
106114
writeByteArray(byteArray);
107115
}
108116

117+
public void writeBigInt256(boolean signed, BigInteger value) throws IOException {
118+
if (value.compareTo(BigInteger.ZERO) < 0 && !signed) {
119+
throw new UnsupportedOperationException(
120+
"Must provide positive data when using unsigned type");
121+
}
122+
// get bytes size
123+
byte[] valueBytes = value.toByteArray();
124+
byte size = (byte) (valueBytes.length);
125+
// when byteSize more than 16, encode as u256
126+
if (size > 32) {
127+
throw new UnsupportedOperationException(
128+
"Unsupported unsigned type with length more than 32 bytes");
129+
}
130+
byte[] encodedData = new byte[32];
131+
System.arraycopy(valueBytes, 0, encodedData, (32 - valueBytes.length), valueBytes.length);
132+
// extend 0xff
133+
if (signed && value.compareTo(BigInteger.ZERO) < 0) {
134+
for (int i = 0; i < (32 - valueBytes.length); i++) {
135+
encodedData[i] = (byte) 0xff;
136+
}
137+
}
138+
// write the big-endian data
139+
writeByteArray(encodedData);
140+
}
141+
109142
private void writeSecondCategory(BigInteger value) throws IOException {
110143
// only values from [kMinUint16, kMinUint32) can be put here
111144
long v = value.longValue();

sdk-codec/src/main/java/org/fisco/bcos/sdk/codec/scale/TypeDecoder.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
import java.util.function.BiFunction;
1313
import org.fisco.bcos.sdk.codec.Utils;
1414
import org.fisco.bcos.sdk.codec.datatypes.*;
15+
import org.fisco.bcos.sdk.codec.datatypes.generated.Uint160;
1516

1617
public class TypeDecoder {
1718
@SuppressWarnings("unchecked")
@@ -20,6 +21,8 @@ public static <T extends Type> T decode(ScaleCodecReader reader, Class<T> type)
2021
return (T) decodeNumeric(reader, (Class<NumericType>) type);
2122
} else if (Bool.class.isAssignableFrom(type)) {
2223
return (T) decodeBool(reader);
24+
} else if (Address.class.isAssignableFrom(type)) {
25+
return (T) decodeAddress(reader);
2326
} else if (Bytes.class.isAssignableFrom(type)
2427
|| DynamicBytes.class.isAssignableFrom(type)) {
2528
return (T) decodeBytes(reader, (Class<Bytes>) type);
@@ -39,6 +42,10 @@ public static <T extends Type> T decode(ScaleCodecReader reader, Class<T> type)
3942
}
4043
}
4144

45+
public static Address decodeAddress(ScaleCodecReader reader) {
46+
return new Address(decodeNumeric(reader, Uint160.class));
47+
}
48+
4249
public static <T extends NumericType> T decodeNumeric(ScaleCodecReader reader, Class<T> type) {
4350
try {
4451
int bitSize = 256;
@@ -69,7 +76,7 @@ public static <T extends NumericType> T decodeNumeric(ScaleCodecReader reader, C
6976
if (bytesSize >= 1 && bytesSize <= 16) {
7077
value = reader.decodeInteger(signedValue, bytesSize);
7178
} else {
72-
value = reader.decodeCompactInteger();
79+
value = reader.decodeInt256();
7380
}
7481
return type.getConstructor(BigInteger.class).newInstance(value);
7582
} catch (NoSuchMethodException

sdk-codec/src/main/java/org/fisco/bcos/sdk/codec/scale/TypeEncoder.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,8 @@ public static void encode(Type parameter, ScaleCodecWriter writer) throws IOExce
1313
encodeBool((Bool) parameter, writer);
1414
} else if (parameter instanceof BytesType) {
1515
encodeBytes((BytesType) parameter, writer);
16+
} else if (parameter instanceof Address) {
17+
encodeAddress((Address) parameter, writer);
1618
} else if (parameter instanceof Utf8String) {
1719
encodeString((Utf8String) parameter, writer);
1820
} else if (parameter instanceof StructType) {
@@ -25,20 +27,24 @@ public static void encode(Type parameter, ScaleCodecWriter writer) throws IOExce
2527
}
2628
}
2729

30+
public static void encodeAddress(Address address, ScaleCodecWriter writer) throws IOException {
31+
encodeNumeric(address.toUint160(), writer);
32+
}
33+
2834
public static void encodeNumeric(NumericType numericType, ScaleCodecWriter writer)
2935
throws IOException {
3036
int bitSize = numericType.getBitSize();
3137
int byteSize = bitSize / 8;
38+
boolean signedInteger = (numericType.getTypeAsString().contains("uint")) ? false : true;
3239
if (byteSize >= 1 && byteSize <= 16) {
33-
if (numericType.getTypeAsString().contains("uint")) {
40+
if (!signedInteger) {
3441
writer.writeUnsignedInteger(numericType.getValue(), byteSize);
3542
return;
3643
}
3744
writer.writeInteger(numericType.getValue(), byteSize);
3845
return;
3946
}
40-
// Note: modify with liquid u256 after modify the node
41-
writer.writeCompactInteger(numericType.getValue());
47+
writer.writeBigInt256(signedInteger, numericType.getValue());
4248
}
4349

4450
public static void encodeBool(Bool boolType, ScaleCodecWriter writer) throws IOException {

0 commit comments

Comments
 (0)