Skip to content

Commit

Permalink
Merge pull request #2647 from rsksmart/vovchyk/native-cont-impv
Browse files Browse the repository at this point in the history
perf: improve decoding in CallTransaction
  • Loading branch information
Vovchyk authored Oct 4, 2024
2 parents 1f56dc4 + 39f9c56 commit 4084daf
Show file tree
Hide file tree
Showing 19 changed files with 545 additions and 224 deletions.
5 changes: 2 additions & 3 deletions rskj-core/src/main/java/co/rsk/core/types/bytes/Bytes.java
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,6 @@

import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Arrays;
import java.util.Objects;

/**
Expand Down Expand Up @@ -140,8 +139,8 @@ public byte byteAt(int index) {
}

@Override
public byte[] copyArrayOfRange(int from, int to) {
return Arrays.copyOfRange(byteArray, from, to);
public void arraycopy(int srcPos, byte[] dest, int destPos, int length) {
System.arraycopy(byteArray, srcPos, dest, destPos, length);
}

@Override
Expand Down
84 changes: 77 additions & 7 deletions rskj-core/src/main/java/co/rsk/core/types/bytes/BytesSlice.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,11 +18,62 @@

package co.rsk.core.types.bytes;

import java.util.Arrays;

/**
* A {@link BytesSlice} is a subsequence of bytes backed by another broader byte sequence.
*/
public interface BytesSlice extends HexPrintableBytes {

/**
* Copies an array from the {@link BytesSlice} source, beginning at the
* specified position, to the specified position of the destination array.
* A subsequence of array components are copied from this instance to the
* destination array referenced by {@code dest}. The number of components
* copied is equal to the {@code length} argument. The components at
* positions {@code srcPos} through {@code srcPos+length-1} in the source
* array are copied into positions {@code destPos} through
* {@code destPos+length-1}, respectively, of the destination
* array.
* <p>
* If the underlying byte array and {@code dest} argument refer to the
* same array object, then the copying is performed as if the
* components at positions {@code srcPos} through
* {@code srcPos+length-1} were first copied to a temporary
* array with {@code length} components and then the contents of
* the temporary array were copied into positions
* {@code destPos} through {@code destPos+length-1} of the
* destination array.
* <p>
* If {@code dest} is {@code null}, then a
* {@code NullPointerException} is thrown.
* <p>
* Otherwise, if any of the following is true, an
* {@code IndexOutOfBoundsException} is
* thrown and the destination is not modified:
* <ul>
* <li>The {@code srcPos} argument is negative.
* <li>The {@code destPos} argument is negative.
* <li>The {@code length} argument is negative.
* <li>{@code srcPos+length} is greater than
* {@code src.length}, the length of the source array.
* <li>{@code destPos+length} is greater than
* {@code dest.length}, the length of the destination array.
* </ul>
*
* <p>
* Note: this method mimics behaviour of {@link System#arraycopy(Object, int, Object, int, int)}
*
* @param srcPos starting position in the source array.
* @param dest the destination array.
* @param destPos starting position in the destination data.
* @param length the number of array elements to be copied.
* @throws IndexOutOfBoundsException if copying would cause
* access of data outside array bounds.
* @throws NullPointerException if {@code dest} is {@code null}.
*/
void arraycopy(int srcPos, byte[] dest, int destPos, int length);

/**
* Copies the specified range of the specified array into a new array.
* The initial index of the range (<tt>from</tt>) must lie between zero
Expand All @@ -37,17 +88,30 @@ public interface BytesSlice extends HexPrintableBytes {
* greater than or equal to <tt>original.length - from</tt>. The length
* of the returned array will be <tt>to - from</tt>.
*
* <p>
* Note: this method mimics behaviour of {@link Arrays#copyOfRange(Object[], int, int)}
*
* @param from the initial index of the range to be copied, inclusive
* @param to the final index of the range to be copied, exclusive.
* (This index may lie outside the array.)
* @return a new array containing the specified range from the original array,
* truncated or padded with zeros to obtain the required length
* @throws ArrayIndexOutOfBoundsException if {@code from < 0}
* @throws IndexOutOfBoundsException if {@code from < 0}
* or {@code from > original.length}
* @throws IllegalArgumentException if <tt>from &gt; to</tt>
* @throws NullPointerException if <tt>original</tt> is null
*/
byte[] copyArrayOfRange(int from, int to);
default byte[] copyArrayOfRange(int from, int to) {
if (from < 0 || from > length()) {
throw new IndexOutOfBoundsException("invalid 'from': " + from);
}
int newLength = to - from;
if (newLength < 0) {
throw new IllegalArgumentException(from + " > " + to);
}
byte[] copy = new byte[newLength];
arraycopy(from, copy, 0, Math.min(length() - from, newLength));
return copy;
}

default byte[] copyArray() {
return copyArrayOfRange(0, length());
Expand Down Expand Up @@ -104,11 +168,17 @@ public byte byteAt(int index) {
}

@Override
public byte[] copyArrayOfRange(int from, int to) {
if (from < 0 || from > to || to > length()) {
throw new IndexOutOfBoundsException("invalid 'from' and/or 'to': [" + from + ";" + to + ")");
public void arraycopy(int srcPos, byte[] dest, int destPos, int length) {
if (length < 0) {
throw new IndexOutOfBoundsException("invalid 'length': " + length);
}
if (srcPos < 0 || srcPos + length > length()) {
throw new IndexOutOfBoundsException("invalid 'srcPos' and/or 'length': [" + srcPos + ";" + length + ")");
}
if (destPos < 0 || destPos + length > dest.length) {
throw new IndexOutOfBoundsException("invalid 'destPos' and/or 'length': [" + destPos + ";" + length + ")");
}
return originBytes.copyArrayOfRange(this.from + from, this.from + to);
originBytes.arraycopy(this.from + srcPos, dest, destPos, length);
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,7 +77,7 @@ public String toFormattedString(@Nonnull HexPrintableBytes printableBytes, int o
}

if (length > 32) {
return printableBytes.toHexString(off, 15) + ".." + printableBytes.toHexString(off + length - 15, 15);
return printableBytes.toHexString(off, 16) + ".." + printableBytes.toHexString(off + length - 15, 15);
}
return printableBytes.toHexString(off, length);
}
Expand Down
2 changes: 2 additions & 0 deletions rskj-core/src/main/java/co/rsk/util/StringUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ public class StringUtils {

private static final int DEFAULT_MAX_LEN = 64;

private StringUtils() { /* hidden */ }

public static String trim(@Nullable String src) {
return trim(src, DEFAULT_MAX_LEN);
}
Expand Down
23 changes: 12 additions & 11 deletions rskj-core/src/main/java/org/ethereum/core/CallTransaction.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
}
}
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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;
Expand All @@ -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() {
Expand Down
27 changes: 14 additions & 13 deletions rskj-core/src/main/java/org/ethereum/solidity/SolidityType.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
}

Expand Down Expand Up @@ -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++) {
Expand Down Expand Up @@ -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();
Expand Down Expand Up @@ -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);
Expand All @@ -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);
}
}
Expand Down Expand Up @@ -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());
}
}
Expand All @@ -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());
}
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);
}
}
Expand Down
Loading

0 comments on commit 4084daf

Please sign in to comment.