Skip to content
This repository has been archived by the owner on Sep 26, 2019. It is now read-only.

Add additional RLP tests #332

Merged
merged 6 commits into from
Nov 29, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
*/
package tech.pegasys.pantheon.ethereum.rlp;

import tech.pegasys.pantheon.ethereum.rlp.util.RLPTestUtil;
import tech.pegasys.pantheon.util.bytes.BytesValue;

import java.util.ArrayList;
Expand Down Expand Up @@ -62,16 +63,16 @@ private static Object generateAndRecurse(
@Setup(Level.Trial)
public void prepare() {
toEncode = generate(depth, width, size);
toDecode = RLP.encode(toEncode);
toDecode = RLPTestUtil.encode(toEncode);
}

@Benchmark
public BytesValue getBenchmarkEncoding() {
return RLP.encode(toEncode);
return RLPTestUtil.encode(toEncode);
}

@Benchmark
public Object getBenchmarkDecoding() {
return RLP.decode(toDecode);
return RLPTestUtil.decode(toDecode);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,6 @@
import tech.pegasys.pantheon.util.bytes.BytesValue;
import tech.pegasys.pantheon.util.bytes.MutableBytesValue;

import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;

import io.vertx.core.buffer.Buffer;
Expand Down Expand Up @@ -81,65 +79,6 @@ public static BytesValueRLPInput input(final Buffer buffer, final int offset) {
return new BytesValueRLPInput(BytesValue.wrapBuffer(buffer, offset), false, false);
}

/**
* Fully decodes a RLP encoded value.
*
* <p>This method is mostly intended for testing as it is often more convenient <b>and</b>
* efficient to use a {@link RLPInput} (through {@link #input(BytesValue)}) instead.
*
* @param value The RLP encoded value to decode.
* @return The output of decoding {@code value}. It will be either directly a {@link BytesValue},
* or a list whose elements are either {@link BytesValue}, or similarly composed sub-lists.
* @throws RLPException if {@code value} is not a properly formed RLP encoding.
*/
public static Object decode(final BytesValue value) {
return decode(input(value));
}

private static Object decode(final RLPInput in) {
if (!in.nextIsList()) {
return in.readBytesValue();
}

final int size = in.enterList();
final List<Object> l = new ArrayList<>(size);
for (int i = 0; i < size; i++) l.add(decode(in));
in.leaveList();
return l;
}

/**
* Fully RLP encode an object consisting of recursive lists of {@link BytesValue}.
*
* <p>This method is mostly intended for testing as it is often more convenient <b>and</b>
* efficient to use a {@link RLPOutput} (through {@link #encode(Consumer)} for instance) instead.
*
* @param obj An object that must be either directly a {@link BytesValue}, or a list whose
* elements are either {@link BytesValue}, or similarly composed sub-lists.
* @return The RLP encoding corresponding to {@code obj}.
* @throws IllegalArgumentException if {@code obj} is not a valid input (not entirely composed
* from lists and {@link BytesValue}).
*/
public static BytesValue encode(final Object obj) {
final BytesValueRLPOutput out = new BytesValueRLPOutput();
encode(obj, out);
return out.encoded();
}

private static void encode(final Object obj, final RLPOutput out) {
if (obj instanceof BytesValue) {
out.writeBytesValue((BytesValue) obj);
} else if (obj instanceof List) {
final List<?> l = (List<?>) obj;
out.startList();
for (final Object o : l) encode(o, out);
out.endList();
} else {
throw new IllegalArgumentException(
format("Invalid input type %s for RLP encoding", obj.getClass()));
}
}

/**
* Creates a {@link RLPOutput}, pass it to the provided consumer for writing, and then return the
* RLP encoded result of that writing.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,19 @@ static int extractSize(final IntUnaryOperator getter, final int offset, final in
}

/** Read from the provided offset a size of the provided length, assuming this is enough bytes. */
static int extractSizeFromLong(
static int extractSizeFromLongItem(
final LongUnaryOperator getter, final long offset, final int sizeLength) {
String oversizedErrorMessage =
"RLP item at offset "
+ offset
+ " with size value consuming "
+ sizeLength
+ " bytes exceeds max supported size of "
+ Integer.MAX_VALUE;
if (sizeLength > 4) {
throw new RLPException(oversizedErrorMessage);
}

long res = 0;
int shift = 0;
for (int i = 0; i < sizeLength; i++) {
Expand All @@ -77,9 +88,7 @@ static int extractSizeFromLong(
try {
return Math.toIntExact(res);
} catch (final ArithmeticException e) {
final String msg =
"unable to extract size from long at offset " + offset + ", sizeLen=" + sizeLength;
throw new RLPException(msg, e);
throw new RLPException(oversizedErrorMessage, e);
}
}

Expand Down Expand Up @@ -139,7 +148,7 @@ private static int readLongSize(
throw new MalformedRLPInputException("Malformed RLP item: size of payload has leading zeros");
}

final int res = RLPDecodingHelpers.extractSizeFromLong(byteGetter, item + 1, sizeLength);
final int res = RLPDecodingHelpers.extractSizeFromLongItem(byteGetter, item + 1, sizeLength);

// We should not have had the size written separately if it was less than 56 bytes long.
if (res < 56) {
Expand All @@ -166,7 +175,15 @@ static class RLPElementMetadata {

/** @return the size of the byte string holding the rlp-encoded value and metadata */
int getEncodedSize() {
return Math.toIntExact(elementEnd() - elementStart + 1);
long encodedSize = elementEnd() - elementStart + 1;
try {
return Math.toIntExact(encodedSize);
} catch (ArithmeticException e) {
String errorMessage =
String.format(
"RLP item exceeds max supported size of %d: %d", Integer.MAX_VALUE, encodedSize);
throw new RLPException(errorMessage, e);
}
}

/**
Expand Down
Loading