diff --git a/rskj-core/src/main/java/org/ethereum/core/CallTransaction.java b/rskj-core/src/main/java/org/ethereum/core/CallTransaction.java index 4c6cf7a8296..50750a55ba2 100644 --- a/rskj-core/src/main/java/org/ethereum/core/CallTransaction.java +++ b/rskj-core/src/main/java/org/ethereum/core/CallTransaction.java @@ -20,6 +20,8 @@ package org.ethereum.core; import co.rsk.core.RskAddress; +import co.rsk.core.types.bytes.Bytes; +import co.rsk.core.types.bytes.BytesSlice; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonGetter; import com.fasterxml.jackson.annotation.JsonInclude; @@ -36,7 +38,6 @@ import java.util.Arrays; import static java.lang.String.format; -import static org.apache.commons.lang3.ArrayUtils.subarray; import static org.apache.commons.lang3.StringUtils.stripEnd; import static org.ethereum.util.ByteUtil.longToBytesNoLeadZeroes; @@ -119,9 +120,9 @@ public static Type getType(String typeName) { */ public abstract byte[] encode(Object value); - public abstract Object decode(byte[] encoded, int offset); + public abstract Object decode(BytesSlice encoded, int offset); - public Object decode(byte[] encoded) { + public Object decode(BytesSlice encoded) { return decode(encoded, 0); } @@ -187,12 +188,12 @@ public byte[] encode(Object value) { } @Override - public Object decode(byte[] encoded, int offset) { + public Object decode(BytesSlice encoded, int offset) { return decodeInt(encoded, offset); } - public static BigInteger decodeInt(byte[] encoded, int offset) { - return new BigInteger(Arrays.copyOfRange(encoded, offset, offset + 32)); + public static BigInteger decodeInt(BytesSlice encoded, int offset) { + return new BigInteger(encoded.copyArrayOfRange(offset, offset + 32)); } public static byte[] encodeInt(int i) { @@ -222,7 +223,7 @@ public byte[] encode(Object value) { } @Override - public Object decode(byte[] encoded, int offset) { + public Object decode(BytesSlice encoded, int offset) { return Boolean.valueOf(((Number) super.decode(encoded, offset)).intValue() != 0); } } @@ -350,7 +351,7 @@ public Object[] decodeEventData(byte[] encodedData) { checkFunctionType(FunctionType.event); Param[] dataInputs = Arrays.stream(inputs).filter(i -> !i.indexed).toArray(Param[]::new); - return decode(encodedData, dataInputs); + return decode(Bytes.of(encodedData), dataInputs); } private void checkFunctionType(FunctionType expected) { @@ -405,7 +406,7 @@ public byte[] encodeOutputs(Object... args) { return encodeArguments(outputs, args); } - private Object[] decode(byte[] encoded, Param[] params) { + private Object[] decode(BytesSlice encoded, Param[] params) { Object[] ret = new Object[params.length]; int off = 0; @@ -421,11 +422,11 @@ private Object[] decode(byte[] encoded, Param[] params) { } public Object[] decode(byte[] encoded) { - return decode(subarray(encoded, 4, encoded.length), inputs); + return decode(Bytes.of(encoded).slice(4, encoded.length), inputs); } public Object[] decodeResult(byte[] encodedRet) { - return decode(encodedRet, outputs); + return decode(Bytes.of(encodedRet), outputs); } public String formatSignature() { diff --git a/rskj-core/src/main/java/org/ethereum/solidity/SolidityType.java b/rskj-core/src/main/java/org/ethereum/solidity/SolidityType.java index a4ef7aa34be..23d6197fc6c 100644 --- a/rskj-core/src/main/java/org/ethereum/solidity/SolidityType.java +++ b/rskj-core/src/main/java/org/ethereum/solidity/SolidityType.java @@ -20,6 +20,7 @@ package org.ethereum.solidity; import co.rsk.core.types.bytes.Bytes; +import co.rsk.core.types.bytes.BytesSlice; import com.fasterxml.jackson.annotation.JsonCreator; import com.fasterxml.jackson.annotation.JsonValue; import org.ethereum.util.ByteUtil; @@ -101,9 +102,9 @@ public static SolidityType getType(String typeName) { */ public abstract byte[] encode(Object value); - public abstract Object decode(byte[] encoded, int offset); + public abstract Object decode(BytesSlice encoded, int offset); - public Object decode(byte[] encoded) { + public Object decode(BytesSlice encoded) { return decode(encoded, 0); } @@ -196,7 +197,7 @@ public byte[] encodeList(List l) { } @Override - public Object[] decode(byte[] encoded, int offset) { + public Object[] decode(BytesSlice encoded, int offset) { Utils.validateArrayAllegedSize(encoded, offset, getFixedSize()); Object[] result = new Object[size]; for (int i = 0; i < size; i++) { @@ -247,8 +248,8 @@ public byte[] encodeList(List l) { } @Override - public Object decode(byte[] encoded, int origOffset) { - if (encoded.length == 0) { + public Object decode(BytesSlice encoded, int origOffset) { + if (encoded.length() == 0) { return new Object[0]; } int len = IntType.decodeInt(encoded, origOffset).intValue(); @@ -299,7 +300,7 @@ public byte[] encode(Object value) { } @Override - public Object decode(byte[] encoded, int offset) { + public Object decode(BytesSlice encoded, int offset) { int len = IntType.decodeInt(encoded, offset).intValue(); offset += IntType.INT_SIZE; return Utils.safeCopyOfRange(encoded, offset, len); @@ -325,7 +326,7 @@ public byte[] encode(Object value) { } @Override - public Object decode(byte[] encoded, int offset) { + public Object decode(BytesSlice encoded, int offset) { return new String((byte[]) super.decode(encoded, offset), StandardCharsets.UTF_8); } } @@ -357,7 +358,7 @@ public byte[] encode(Object value) { } @Override - public Object decode(byte[] encoded, int offset) { + public Object decode(BytesSlice encoded, int offset) { return Utils.safeCopyOfRange(encoded, offset, getFixedSize()); } } @@ -383,7 +384,7 @@ public byte[] encode(Object value) { } @Override - public Object decode(byte[] encoded, int offset) { + public Object decode(BytesSlice encoded, int offset) { BigInteger asBigInteger = (BigInteger) super.decode(encoded, offset); return DataWord.valueOf(asBigInteger.toByteArray()); } @@ -434,14 +435,14 @@ public byte[] encode(Object value) { } @Override - public Object decode(byte[] encoded, int offset) { + public Object decode(BytesSlice encoded, int offset) { return decodeInt(encoded, offset); } - public static BigInteger decodeInt(byte[] encoded, int offset) { + public static BigInteger decodeInt(BytesSlice encoded, int offset) { // This is here because getGasForData might send an empty payload which will produce an exception // But currently the bridge would return the cost of RELEASE_BTC in this situation - if (encoded.length == 0) { + if (encoded.length() == 0) { return BigInteger.ZERO; } return new BigInteger(Utils.safeCopyOfRange(encoded, offset, INT_SIZE)); @@ -474,7 +475,7 @@ public byte[] encode(Object value) { } @Override - public Object decode(byte[] encoded, int offset) { + public Object decode(BytesSlice encoded, int offset) { return Boolean.valueOf(((Number) super.decode(encoded, offset)).intValue() != 0); } } diff --git a/rskj-core/src/main/java/org/ethereum/util/Utils.java b/rskj-core/src/main/java/org/ethereum/util/Utils.java index a2d23853a51..1236b0caeea 100644 --- a/rskj-core/src/main/java/org/ethereum/util/Utils.java +++ b/rskj-core/src/main/java/org/ethereum/util/Utils.java @@ -19,6 +19,7 @@ package org.ethereum.util; +import co.rsk.core.types.bytes.BytesSlice; import org.bouncycastle.util.encoders.DecoderException; import org.bouncycastle.util.encoders.Hex; import java.lang.reflect.Array; @@ -206,15 +207,15 @@ public static boolean contains(List list, byte[] valueToFind) { return false; } - public static void validateArrayAllegedSize(byte[] data, int offset, int allegedSize) { - if (data.length < Math.addExact(allegedSize, offset)) { + public static void validateArrayAllegedSize(BytesSlice data, int offset, int allegedSize) { + if (data.length() < Math.addExact(allegedSize, offset)) { throw new IllegalArgumentException("The specified size exceeds the size of the payload"); } } - public static byte[] safeCopyOfRange(byte[] data, int from, int size) { + public static byte[] safeCopyOfRange(BytesSlice data, int from, int size) { validateArrayAllegedSize(data, from, size); - return Arrays.copyOfRange(data, from, from + size); + return data.copyArrayOfRange(from, from + size); } public static boolean isDecimalString(String s) { diff --git a/rskj-core/src/test/java/co/rsk/core/CallTransactionTest.java b/rskj-core/src/test/java/co/rsk/core/CallTransactionTest.java index e3320bf3380..4fe0c0c870b 100644 --- a/rskj-core/src/test/java/co/rsk/core/CallTransactionTest.java +++ b/rskj-core/src/test/java/co/rsk/core/CallTransactionTest.java @@ -18,6 +18,7 @@ package co.rsk.core; +import co.rsk.core.types.bytes.Bytes; import org.bouncycastle.util.encoders.Hex; import org.ethereum.core.CallTransaction; import org.ethereum.solidity.SolidityType; @@ -115,7 +116,7 @@ void decodeString() { // string 104, 101, 108, 108, 111, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }; - Assertions.assertEquals("hello", type.decode(toDecode)); + Assertions.assertEquals("hello", type.decode(Bytes.of(toDecode))); } @Test diff --git a/rskj-core/src/test/java/co/rsk/core/TransactionTest.java b/rskj-core/src/test/java/co/rsk/core/TransactionTest.java index 3985c64155d..6917aaf01e4 100644 --- a/rskj-core/src/test/java/co/rsk/core/TransactionTest.java +++ b/rskj-core/src/test/java/co/rsk/core/TransactionTest.java @@ -19,6 +19,7 @@ package co.rsk.core; import co.rsk.config.TestSystemProperties; +import co.rsk.core.types.bytes.Bytes; import co.rsk.peg.BridgeSupportFactory; import co.rsk.peg.RepositoryBtcBlockStoreWithCache; import org.bouncycastle.util.BigIntegers; @@ -283,7 +284,7 @@ protected ProgramResult executeTransaction(Transaction tx) { track.rollback(); - System.out.println("Return value: " + new CallTransaction.IntType("uint").decode(executor.getResult().getHReturn())); + System.out.println("Return value: " + new CallTransaction.IntType("uint").decode(Bytes.of(executor.getResult().getHReturn()))); } // now executing the JSON test transaction diff --git a/rskj-core/src/test/java/org/ethereum/core/TransactionTest.java b/rskj-core/src/test/java/org/ethereum/core/TransactionTest.java index ef7d3ecba56..2ed2e3ec93d 100644 --- a/rskj-core/src/test/java/org/ethereum/core/TransactionTest.java +++ b/rskj-core/src/test/java/org/ethereum/core/TransactionTest.java @@ -23,6 +23,7 @@ import co.rsk.core.RskAddress; import co.rsk.core.TransactionExecutorFactory; import co.rsk.core.genesis.TestGenesisLoader; +import co.rsk.core.types.bytes.Bytes; import co.rsk.crypto.Keccak256; import co.rsk.db.HashMapBlocksIndex; import co.rsk.db.MutableTrieImpl; @@ -508,7 +509,7 @@ protected ProgramResult executeTransaction(Transaction tx) { track.rollback(); - System.out.println("Return value: " + new CallTransaction.IntType("uint").decode(executor.getResult().getHReturn())); + System.out.println("Return value: " + new CallTransaction.IntType("uint").decode(Bytes.of(executor.getResult().getHReturn()))); } // now executing the JSON test transaction diff --git a/rskj-core/src/test/java/org/ethereum/solidity/SolidityTypeTest.java b/rskj-core/src/test/java/org/ethereum/solidity/SolidityTypeTest.java index 23258e97cfd..36659028521 100644 --- a/rskj-core/src/test/java/org/ethereum/solidity/SolidityTypeTest.java +++ b/rskj-core/src/test/java/org/ethereum/solidity/SolidityTypeTest.java @@ -1,5 +1,6 @@ package org.ethereum.solidity; +import co.rsk.core.types.bytes.Bytes; import org.junit.jupiter.api.Assertions; import org.junit.jupiter.api.Test; @@ -16,7 +17,7 @@ void TestDynamicArrayTypeWithInvalidDataSize() { input[31] = 0x10; // Indicating we should have 16 elements in the array should fail try { - dat.decode(input, 0); + dat.decode(Bytes.of(input), 0); Assertions.fail(); } catch (IllegalArgumentException e) { // Only acceptable exception @@ -35,7 +36,7 @@ void TestDynamicArrayTypeWithInvalidDataSize() { input[97] = 0x69; try { - dat.decode(input, 0); + dat.decode(Bytes.of(input), 0); Assertions.fail(); } catch (IllegalArgumentException e) { // Only acceptable exception @@ -60,7 +61,7 @@ void TestDynamicArrayTypeWithInvalidDataSize() { input[163] = 0x69; try { - dat.decode(input, 0); + dat.decode(Bytes.of(input), 0); Assertions.fail(); } catch (IllegalArgumentException e) { // Only acceptable exception @@ -96,7 +97,7 @@ void TestDynamicArrayTypeWithValidDataSize() { input[229] = 0x68; input[230] = 0x75; - Object[] ret = (Object[])dat.decode(input, 0); + Object[] ret = (Object[])dat.decode(Bytes.of(input), 0); Assertions.assertEquals(3, ret.length); Assertions.assertTrue(ret[0].toString().contains("hi")); Assertions.assertTrue(ret[1].toString().contains("ih")); @@ -114,7 +115,7 @@ void TestStaticArrayTypeWithInvalidSize() { // the actual data input[32] = 0x68; input[33] = 0x69; - dat.decode(input, 0); + dat.decode(Bytes.of(input), 0); Assertions.fail("should have failed"); } catch (IllegalArgumentException e) { @@ -130,7 +131,7 @@ void TestStaticArrayTypeWithInvalidSize() { // the actual data input[32] = 0x68; input[33] = 0x69; - dat.decode(input, 0); + dat.decode(Bytes.of(input), 0); Assertions.fail("should have failed"); } catch (IllegalArgumentException e) { @@ -149,7 +150,7 @@ void TestStaticArrayType() { input[32] = 0x68; input[33] = 0x69; - Object[] ret = dat.decode(input, 0); + Object[] ret = dat.decode(Bytes.of(input), 0); Assertions.assertEquals(1, ret.length); Assertions.assertTrue(ret[0].toString().contains("hi")); } @@ -159,7 +160,7 @@ void TestIntType() { // Should fail, the array is smaller than the offset we define try { byte[] input = new byte[] {0x4f, 0x4f}; - SolidityType.IntType.decodeInt(input, 12); + SolidityType.IntType.decodeInt(Bytes.of(input), 12); Assertions.fail("should have failed to deserialize the array"); } catch (IllegalArgumentException e) { // Only acceptable exception @@ -168,11 +169,11 @@ void TestIntType() { // Should get a valid number input[31] = 0x01; - BigInteger value = SolidityType.IntType.decodeInt(input, 0); + BigInteger value = SolidityType.IntType.decodeInt(Bytes.of(input), 0); Assertions.assertEquals(1, value.intValue()); // Should get a valid number - value = SolidityType.IntType.decodeInt(input, 32); + value = SolidityType.IntType.decodeInt(Bytes.of(input), 32); Assertions.assertEquals(0, value.intValue()); } diff --git a/rskj-core/src/test/java/org/ethereum/util/UtilsTest.java b/rskj-core/src/test/java/org/ethereum/util/UtilsTest.java index a42711cb4ec..bb301d035e1 100644 --- a/rskj-core/src/test/java/org/ethereum/util/UtilsTest.java +++ b/rskj-core/src/test/java/org/ethereum/util/UtilsTest.java @@ -19,12 +19,11 @@ package org.ethereum.util; -import org.apache.commons.lang3.tuple.Pair; -import org.junit.jupiter.api.Assertions; -import org.junit.jupiter.api.Test; - +import co.rsk.core.types.bytes.Bytes; import org.bouncycastle.util.Arrays; import org.bouncycastle.util.encoders.Hex; +import org.junit.jupiter.api.Assertions; +import org.junit.jupiter.api.Test; import java.math.BigInteger; @@ -112,7 +111,7 @@ void testAddressStringToBytes() { @Test void TestValidateArrayWithOffset() { - byte[] data = new byte[10]; + Bytes data = Bytes.of(new byte[10]); // Valid indices Utils.validateArrayAllegedSize(data, 1, 0); Utils.validateArrayAllegedSize(data, 8, 1); @@ -137,13 +136,13 @@ void TestValidateArrayWithOffset() { // Only type of exception expected } try { - Utils.validateArrayAllegedSize(new byte[0], 1, 0); + Utils.validateArrayAllegedSize(Bytes.of(new byte[0]), 1, 0); fail("should have failed"); } catch (IllegalArgumentException e) { // Only type of exception expected } - byte[] noData = null; + Bytes noData = null; try { Utils.validateArrayAllegedSize(noData, 1, 1); fail("should have failed"); @@ -156,33 +155,33 @@ void TestValidateArrayWithOffset() { @Test void TestSafeCopyOfRangeWithValidArrays() { - Assertions.assertDoesNotThrow(() -> Utils.safeCopyOfRange(new byte[2], 0, 1)); - Assertions.assertDoesNotThrow(() -> Utils.safeCopyOfRange(new byte[100], 97, 3)); - Assertions.assertDoesNotThrow(() -> Utils.safeCopyOfRange(new byte[0], 0, 0)); + Assertions.assertDoesNotThrow(() -> Utils.safeCopyOfRange(Bytes.of(new byte[2]), 0, 1)); + Assertions.assertDoesNotThrow(() -> Utils.safeCopyOfRange(Bytes.of(new byte[100]), 97, 3)); + Assertions.assertDoesNotThrow(() -> Utils.safeCopyOfRange(Bytes.of(new byte[0]), 0, 0)); } @Test void TestSafeCopyOfRangeWithInvalidArrays() { try { - Utils.safeCopyOfRange(new byte[2], 1, 2); + Utils.safeCopyOfRange(Bytes.of(new byte[2]), 1, 2); fail("should have failed"); } catch (IllegalArgumentException e){ } try { - Utils.safeCopyOfRange(new byte[100], 98, 3); + Utils.safeCopyOfRange(Bytes.of(new byte[100]), 98, 3); fail("should have failed"); } catch (IllegalArgumentException e){ } try { - Utils.safeCopyOfRange(new byte[0], 0, 1); + Utils.safeCopyOfRange(Bytes.of(new byte[0]), 0, 1); fail("should have failed"); } catch (IllegalArgumentException e){ } try { - Utils.safeCopyOfRange(new byte[0], 1, 0); + Utils.safeCopyOfRange(Bytes.of(new byte[0]), 1, 0); fail("should have failed"); } catch (IllegalArgumentException e){