Skip to content

Commit

Permalink
perf: improve mem reading in Memory
Browse files Browse the repository at this point in the history
  • Loading branch information
Vovchyk committed Aug 2, 2024
1 parent 584788b commit e6bdfac
Show file tree
Hide file tree
Showing 22 changed files with 241 additions and 92 deletions.
42 changes: 42 additions & 0 deletions rskj-core/src/main/java/co/rsk/core/types/bytes/BoundaryUtils.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
* This file is part of RskJ
* Copyright (C) 2024 RSK Labs Ltd.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/

package co.rsk.core.types.bytes;

public class BoundaryUtils {

private BoundaryUtils() { /* hidden */ }

public static void checkArraycopyParams(int srcLength, int srcPos, byte[] dest, int destPos, int length) {
if (length < 0) {
throw new IndexOutOfBoundsException("invalid 'length': " + length);
}
if (srcPos < 0 || srcPos + length > srcLength) {
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 + ")");
}
}

public static void checkArrayIndexParam(int srcLength, int index) {
if (index < 0 || index >= srcLength) {
throw new IndexOutOfBoundsException("invalid index: " + index);
}
}
}
11 changes: 0 additions & 11 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 @@ -18,7 +18,6 @@

package co.rsk.core.types.bytes;

import org.ethereum.util.ByteUtil;
import org.ethereum.util.FastByteComparisons;

import javax.annotation.Nonnull;
Expand Down Expand Up @@ -143,16 +142,6 @@ public void arraycopy(int srcPos, byte[] dest, int destPos, int length) {
System.arraycopy(byteArray, srcPos, dest, destPos, length);
}

@Override
public String toHexString() {
return ByteUtil.toHexString(byteArray);
}

@Override
public String toHexString(int off, int length) {
return ByteUtil.toHexString(byteArray, off, length);
}

@Nonnull
@Override
public byte[] asUnsafeByteArray() {
Expand Down
63 changes: 38 additions & 25 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 @@ -128,6 +128,42 @@ default Bytes copyBytes() {
default BytesSlice slice(int from, int to) {
return new BytesSliceImpl(this, from, to);
}

static boolean equals(BytesSlice a, BytesSlice b) {
if (a == b) {
return true;
}
if (a == null || b == null) {
return false;
}

int aLen = a.length();
if (b.length() != aLen) {
return false;
}

for (int i = 0; i < aLen; i++) {
if (a.byteAt(i) != b.byteAt(i)) {
return false;
}
}

return true;
}

static int hashCode(BytesSlice bytesSlice) {
if (bytesSlice == null) {
return 0;
}

int result = 1;
int len = bytesSlice.length();
for (int i = 0; i < len; i++) {
result = 31 * result + bytesSlice.byteAt(i);
}

return result;
}
}

class BytesSliceImpl implements BytesSlice {
Expand Down Expand Up @@ -161,39 +197,16 @@ public int length() {

@Override
public byte byteAt(int index) {
if (index < 0 || index >= length()) {
throw new IndexOutOfBoundsException("invalid index: " + index);
}
BoundaryUtils.checkArrayIndexParam(length(), index);
return originBytes.byteAt(from + index);
}

@Override
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 + ")");
}
BoundaryUtils.checkArraycopyParams(length(), srcPos, dest, destPos, length);
originBytes.arraycopy(this.from + srcPos, dest, destPos, length);
}

@Override
public String toHexString(int off, int length) {
if (off < 0 || length < 0 || off + length > length()) {
throw new IndexOutOfBoundsException("invalid 'off' and/or 'length': " + off + "; " + length);
}
return originBytes.toHexString(from + off, length);
}

@Override
public String toHexString() {
return toHexString(0, length());
}

@Override
public String toString() {
return toPrintableString();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,9 +62,27 @@ default String toJsonHexFormattedString() {
return toPrintableString(SIMPLE_JSON_HEX_FORMATTER);
}

String toHexString(int off, int length);
default String toHexString(int off, int length) {
return toHexStringV2(off, length);
}

default String toHexString() {
return toHexString(0, length());
}

default String toHexStringV2(int off, int length) {
if (off < 0 || length < 0 || off + length > length()) {
throw new IndexOutOfBoundsException("invalid 'off' and/or 'length': " + off + "; " + length);
}

String toHexString();
StringBuilder sb = new StringBuilder(length * 2);
for (int i = off; i < off + length; i++) {
byte b = byteAt(i);
sb.append(Character.forDigit((b >> 4) & 0xF, 16));
sb.append(Character.forDigit((b & 0xF), 16));
}
return sb.toString();
}
}

class PrintableBytesHexFormatter implements PrintableBytes.Formatter<HexPrintableBytes> {
Expand Down
8 changes: 7 additions & 1 deletion rskj-core/src/main/java/org/ethereum/crypto/HashUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,8 @@
package org.ethereum.crypto;

import co.rsk.core.RskAddress;
import co.rsk.core.types.bytes.Bytes;
import co.rsk.core.types.bytes.BytesSlice;
import org.bouncycastle.crypto.Digest;
import org.bouncycastle.crypto.digests.RIPEMD160Digest;
import org.ethereum.crypto.cryptohash.Keccak256;
Expand Down Expand Up @@ -59,6 +61,10 @@ public static byte[] sha256(byte[] input) {
}

public static byte[] keccak256(byte[] input) {
return keccak256(Bytes.of(input));
}

public static byte[] keccak256(BytesSlice input) {
Keccak256 digest = new Keccak256();
digest.update(input);
return digest.digest();
Expand Down Expand Up @@ -125,7 +131,7 @@ public static byte[] calcNewAddr(byte[] addr, byte[] nonce) {
* @param salt - salt to make different result addresses
* @return new address
*/
public static byte[] calcSaltAddr(RskAddress senderAddress, byte[] initCode, byte[] salt) {
public static byte[] calcSaltAddr(RskAddress senderAddress, BytesSlice initCode, byte[] salt) {
// 0xff is of length 1
// keccak-256 of the address is of length 32
// Then we add the lengths of the senderAddress and the salt
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@

package org.ethereum.crypto.cryptohash;

import co.rsk.core.types.bytes.BytesSlice;

/**
* <p>This interface documents the API for a hash function. This
* interface somewhat mimics the standard {@code
Expand Down Expand Up @@ -88,7 +90,7 @@ public interface Digest {
*
* @param inbuf the data bytes
*/
public void update(byte[] inbuf);
public void update(BytesSlice inbuf);

/**
* Insert some more bytes.
Expand All @@ -97,7 +99,7 @@ public interface Digest {
* @param off the data offset in {@code inbuf}
* @param len the data length (in bytes)
*/
public void update(byte[] inbuf, int off, int len);
public void update(BytesSlice inbuf, int off, int len);

/**
* Finalize the current hash computation and return the hash value
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,9 @@

package org.ethereum.crypto.cryptohash;

import co.rsk.core.types.bytes.Bytes;
import co.rsk.core.types.bytes.BytesSlice;

/**
* <p>This class is a template which can be used to implement hash
* functions. It takes care of some of the API, and also provides an
Expand Down Expand Up @@ -141,7 +144,8 @@ public byte[] digest()
/** @see org.ethereum.crypto.cryptohash.Digest */
public byte[] digest(byte[] input)
{
update(input, 0, input.length);
BytesSlice bytesSlice = Bytes.of(input);
update(bytesSlice, 0, bytesSlice.length());
return digest();
}

Expand Down Expand Up @@ -181,21 +185,20 @@ public void update(byte input)
}

/** @see org.ethereum.crypto.cryptohash.Digest */
public void update(byte[] input)
public void update(BytesSlice input)
{
update(input, 0, input.length);
update(input, 0, input.length());
}

/** @see org.ethereum.crypto.cryptohash.Digest */
public void update(byte[] input, int offset, int len)
public void update(BytesSlice input, int offset, int len)
{
while (len > 0) {
int copyLen = blockLen - inputLen;
if (copyLen > len) {
copyLen = len;
}
System.arraycopy(input, offset, inputBuf, inputLen,
copyLen);
input.arraycopy(offset, inputBuf, inputLen, copyLen);
offset += copyLen;
inputLen += copyLen;
len -= copyLen;
Expand Down
3 changes: 3 additions & 0 deletions rskj-core/src/main/java/org/ethereum/util/ByteUtil.java
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,8 @@

package org.ethereum.util;

import co.rsk.core.types.bytes.Bytes;
import co.rsk.core.types.bytes.BytesSlice;
import org.bouncycastle.util.encoders.Hex;
import org.ethereum.db.ByteArrayWrapper;

Expand All @@ -37,6 +39,7 @@ private ByteUtil() {
}

public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
public static final BytesSlice EMPTY_BYTES_SLICE = Bytes.of(EMPTY_BYTE_ARRAY);
private static final byte[] ZERO_BYTE_ARRAY = new byte[]{0};

/**
Expand Down
8 changes: 5 additions & 3 deletions rskj-core/src/main/java/org/ethereum/vm/CallCreate.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,26 +20,28 @@

package org.ethereum.vm;

import co.rsk.core.types.bytes.BytesSlice;

/**
* @author Roman Mandeleil
* @since 03.07.2014
*/
public class CallCreate {

final byte[] data;
final BytesSlice data;
final byte[] destination;
final long gasLimit;
final byte[] value;


public CallCreate(byte[] data, byte[] destination, long gasLimit, byte[] value) {
public CallCreate(BytesSlice data, byte[] destination, long gasLimit, byte[] value) {
this.data = data;
this.destination = destination;
this.gasLimit = gasLimit;
this.value = value;
}

public byte[] getData() {
public BytesSlice getData() {
return data;
}

Expand Down
6 changes: 3 additions & 3 deletions rskj-core/src/main/java/org/ethereum/vm/VM.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
import co.rsk.config.VmConfig;
import co.rsk.core.RskAddress;
import co.rsk.core.types.bytes.Bytes;
import co.rsk.core.types.bytes.BytesSlice;
import co.rsk.crypto.Keccak256;
import co.rsk.rpc.netty.ExecTimeoutContext;
import org.bouncycastle.util.BigIntegers;
Expand Down Expand Up @@ -627,7 +628,7 @@ protected void doSHA3() {
// EXECUTION PHASE
DataWord memOffsetData = program.stackPop();
DataWord lengthData = program.stackPop();
byte[] buffer = program.memoryChunk(memOffsetData.intValue(), lengthData.intValue());
BytesSlice buffer = program.memorySlice(memOffsetData.intValue(), lengthData.intValue());

byte[] encoded = HashUtil.keccak256(buffer);
DataWord word = DataWord.valueOf(encoded);
Expand Down Expand Up @@ -1191,8 +1192,7 @@ protected void doLOG(){
// Int32 address values guaranteed by previous MAX_MEMORY checks
byte[] data = program.memoryChunk(memStart.intValue(), memOffset.intValue());

LogInfo logInfo =
new LogInfo(address.getLast20Bytes(), topics, data);
LogInfo logInfo = new LogInfo(address.getLast20Bytes(), topics, data);

if (isLogEnabled) {
hint = logInfo.toString();
Expand Down
Loading

0 comments on commit e6bdfac

Please sign in to comment.