From ec1a8be5587275d29b7127e76773ef55d3b7cb71 Mon Sep 17 00:00:00 2001 From: mbaxter Date: Tue, 20 Nov 2018 15:04:16 -0500 Subject: [PATCH] Remove unnecessary RlpInput and RlpOutput classes (#287) --- .../p2p/discovery/internal/Packet.java | 19 +++- .../ethereum/rlp/AbstractRLPOutput.java | 25 ++-- .../ethereum/rlp/BytesValueRLPInput.java | 7 +- .../pantheon/ethereum/rlp/FileRLPInput.java | 107 ------------------ .../pegasys/pantheon/ethereum/rlp/RLP.java | 4 +- .../ethereum/rlp/VertxBufferRLPInput.java | 96 ---------------- .../ethereum/rlp/VertxBufferRLPOutput.java | 40 ------- .../pantheon/util/bytes/BytesValue.java | 15 +++ 8 files changed, 54 insertions(+), 259 deletions(-) delete mode 100644 ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/FileRLPInput.java delete mode 100644 ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/VertxBufferRLPInput.java delete mode 100644 ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/VertxBufferRLPOutput.java diff --git a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/Packet.java b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/Packet.java index c7931e6b49..c886286438 100644 --- a/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/Packet.java +++ b/ethereum/p2p/src/main/java/tech/pegasys/pantheon/ethereum/p2p/discovery/internal/Packet.java @@ -21,9 +21,9 @@ import tech.pegasys.pantheon.crypto.SECP256K1; import tech.pegasys.pantheon.crypto.SECP256K1.PublicKey; import tech.pegasys.pantheon.crypto.SECP256K1.Signature; import tech.pegasys.pantheon.ethereum.p2p.discovery.PeerDiscoveryPacketDecodingException; +import tech.pegasys.pantheon.ethereum.rlp.BytesValueRLPOutput; import tech.pegasys.pantheon.ethereum.rlp.RLP; import tech.pegasys.pantheon.ethereum.rlp.RLPException; -import tech.pegasys.pantheon.ethereum.rlp.VertxBufferRLPOutput; import tech.pegasys.pantheon.util.bytes.BytesValue; import tech.pegasys.pantheon.util.bytes.MutableBytesValue; import tech.pegasys.pantheon.util.uint.UInt256Bytes; @@ -122,7 +122,7 @@ public class Packet { public Buffer encode() { final BytesValue encodedSignature = encodeSignature(signature); - final VertxBufferRLPOutput encodedData = new VertxBufferRLPOutput(); + final BytesValueRLPOutput encodedData = new BytesValueRLPOutput(); data.writeTo(encodedData); final Buffer buffer = @@ -130,10 +130,23 @@ public class Packet { hash.appendTo(buffer); encodedSignature.appendTo(buffer); buffer.appendByte(type.getValue()); - encodedData.appendEncoded(buffer); + appendEncoded(encodedData, buffer); return buffer; } + protected void appendEncoded(final BytesValueRLPOutput encoded, final Buffer buffer) { + final int size = encoded.encodedSize(); + if (size == 0) { + return; + } + + // We want to append to the buffer, and Buffer always grows to accommodate anything writing, + // so we write the last byte we know we'll need to make it resize accordingly. + final int start = buffer.length(); + buffer.setByte(start + size - 1, (byte) 0); + encoded.writeEncoded(MutableBytesValue.wrapBuffer(buffer, start, size)); + } + @SuppressWarnings("unchecked") public Optional getPacketData(final Class expectedPacketType) { if (data == null || !data.getClass().equals(expectedPacketType)) { diff --git a/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/AbstractRLPOutput.java b/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/AbstractRLPOutput.java index 2b71665296..a3515586ac 100644 --- a/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/AbstractRLPOutput.java +++ b/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/AbstractRLPOutput.java @@ -141,7 +141,12 @@ abstract class AbstractRLPOutput implements RLPOutput { return payloadSizes[0]; } - protected void writeEncoded(final MutableBytesValue res) { + /** + * Write the rlp encoded value to the provided {@link MutableBytesValue} + * + * @param mutableBytesValue the value to which the rlp-data will be written + */ + public void writeEncoded(final MutableBytesValue mutableBytesValue) { // Special case where we encode only a single non-list item (note that listsCount is initially // set to 1, so listsCount == 1 really mean no list explicitly added to the output). if (listsCount == 1) { @@ -152,15 +157,15 @@ abstract class AbstractRLPOutput implements RLPOutput { final int finalOffset; // Single non-list value. if (rlpEncoded.get(0)) { - value.copyTo(res, 0); + value.copyTo(mutableBytesValue, 0); finalOffset = value.size(); } else { - finalOffset = writeElement(value, res, 0); + finalOffset = writeElement(value, mutableBytesValue, 0); } checkState( - finalOffset == res.size(), + finalOffset == mutableBytesValue.size(), "Expected single element RLP encode to be of size %s but was of size %s.", - res.size(), + mutableBytesValue.size(), finalOffset); return; } @@ -171,19 +176,19 @@ abstract class AbstractRLPOutput implements RLPOutput { final BytesValue value = values.get(i); if (value == LIST_MARKER) { final int payloadSize = payloadSizes[++listIdx]; - offset = writeListHeader(payloadSize, res, offset); + offset = writeListHeader(payloadSize, mutableBytesValue, offset); } else if (rlpEncoded.get(i)) { - value.copyTo(res, offset); + value.copyTo(mutableBytesValue, offset); offset += value.size(); } else { - offset = writeElement(value, res, offset); + offset = writeElement(value, mutableBytesValue, offset); } } checkState( - offset == res.size(), + offset == mutableBytesValue.size(), "Expected RLP encoding to be of size %s but was of size %s.", - res.size(), + mutableBytesValue.size(), offset); } } diff --git a/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/BytesValueRLPInput.java b/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/BytesValueRLPInput.java index 57313e2578..9c65ff4eaa 100644 --- a/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/BytesValueRLPInput.java +++ b/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/BytesValueRLPInput.java @@ -25,9 +25,14 @@ public class BytesValueRLPInput extends AbstractRLPInput { private final BytesValue value; public BytesValueRLPInput(final BytesValue value, final boolean lenient) { + this(value, lenient, true); + } + + public BytesValueRLPInput( + final BytesValue value, final boolean lenient, final boolean shouldFitExactly) { super(lenient); this.value = value; - init(value.size(), true); + init(value.size(), shouldFitExactly); } @Override diff --git a/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/FileRLPInput.java b/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/FileRLPInput.java deleted file mode 100644 index 6716d89ee9..0000000000 --- a/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/FileRLPInput.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright 2018 ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package tech.pegasys.pantheon.ethereum.rlp; - -import static com.google.common.base.Preconditions.checkArgument; -import static com.google.common.base.Preconditions.checkNotNull; - -import tech.pegasys.pantheon.util.bytes.Bytes32; -import tech.pegasys.pantheon.util.bytes.BytesValue; -import tech.pegasys.pantheon.util.bytes.BytesValues; - -import java.io.File; -import java.io.IOException; -import java.math.BigInteger; -import java.nio.ByteBuffer; -import java.nio.channels.FileChannel; - -/** An {@link RLPInput} that reads RLP encoded data from a {@link File}. */ -public class FileRLPInput extends AbstractRLPInput { - - // The RLP encoded data. - private final FileChannel file; - - public FileRLPInput(final FileChannel file, final boolean lenient) throws IOException { - super(lenient); - checkNotNull(file); - checkArgument(file.isOpen()); - this.file = file; - - init(file.size(), false); - } - - @Override - protected byte inputByte(final long offset) { - try { - final ByteBuffer buf = ByteBuffer.wrap(new byte[1]); - - file.read(buf, offset); - final byte b = buf.get(0); - return b; - } catch (final IOException e) { - throw new RuntimeException(e); - } - } - - @Override - protected BytesValue inputSlice(final long offset, final int length) { - try { - final byte[] bytes = new byte[length]; - final ByteBuffer buf = ByteBuffer.wrap(bytes); - file.read(buf, offset); - return BytesValue.of(bytes); - } catch (final IOException e) { - throw new RuntimeException(e); - } - } - - @Override - protected Bytes32 inputSlice32(final long offset) { - return Bytes32.wrap(inputSlice(offset, 32), 0); - } - - @Override - protected String inputHex(final long offset, final int length) { - return inputSlice(offset, length).toString().substring(2); - } - - @Override - protected BigInteger getUnsignedBigInteger(final long offset, final int length) { - return BytesValues.asUnsignedBigInteger(inputSlice(offset, length)); - } - - @Override - protected int getInt(final long offset) { - return inputSlice(offset, Integer.BYTES).getInt(0); - } - - @Override - protected long getLong(final long offset) { - return inputSlice(offset, Long.BYTES).getLong(0); - } - - @Override - public BytesValue raw() { - throw new UnsupportedOperationException("raw() not supported on a Channel"); - } - - /** @return Offset of the current item */ - public long currentOffset() { - return currentItem; - } - - @Override - public void setTo(final long item) { - super.setTo(item); - } -} diff --git a/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/RLP.java b/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/RLP.java index cfeb702044..993d6b8480 100644 --- a/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/RLP.java +++ b/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/RLP.java @@ -77,8 +77,8 @@ public abstract class RLP { * deeply nested corruption/malformation of the input will not be detected by this method * call, but only later when the input is read. */ - public static VertxBufferRLPInput input(final Buffer buffer, final int offset) { - return new VertxBufferRLPInput(buffer, offset, false); + public static BytesValueRLPInput input(final Buffer buffer, final int offset) { + return new BytesValueRLPInput(BytesValue.wrapBuffer(buffer, offset), false, false); } /** diff --git a/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/VertxBufferRLPInput.java b/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/VertxBufferRLPInput.java deleted file mode 100644 index 598783c8ad..0000000000 --- a/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/VertxBufferRLPInput.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright 2018 ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package tech.pegasys.pantheon.ethereum.rlp; - -import tech.pegasys.pantheon.util.bytes.Bytes32; -import tech.pegasys.pantheon.util.bytes.BytesValue; -import tech.pegasys.pantheon.util.bytes.BytesValues; - -import java.math.BigInteger; - -import io.vertx.core.buffer.Buffer; - -/** A {@link RLPInput} that decode RLP encoded data stored in a Vert.x {@link Buffer}. */ -public class VertxBufferRLPInput extends AbstractRLPInput { - - // The RLP encoded data. - private final Buffer buffer; - // Offset in buffer from which to read. - private final int bufferOffset; - - /** - * A new {@link RLPInput} that decodes data from the provided buffer. - * - * @param buffer The buffer from which to read RLP data. - * @param bufferOffset The offset in {@code buffer} in which the data to decode starts. - * @param lenient Whether the created decoded should be lenient, that is ignore non-fatal - * malformation in the input. - */ - public VertxBufferRLPInput(final Buffer buffer, final int bufferOffset, final boolean lenient) { - super(lenient); - this.buffer = buffer; - this.bufferOffset = bufferOffset; - init(buffer.length(), false); - } - - /** - * The total size of the encoded data in the {@link Buffer} wrapped by this object. - * - * @return The total size of the encoded data that this input decodes (note that this value never - * changes, it is not the size of data remaining to decode, but the size to decode at creation - * time). - */ - public int encodedSize() { - return Math.toIntExact(size); - } - - @Override - protected byte inputByte(final long offset) { - return buffer.getByte(Math.toIntExact(bufferOffset + offset)); - } - - @Override - protected BytesValue inputSlice(final long offset, final int length) { - return BytesValue.wrapBuffer(buffer, Math.toIntExact(bufferOffset + offset), length); - } - - @Override - protected Bytes32 inputSlice32(final long offset) { - return Bytes32.wrap(inputSlice(offset, Bytes32.SIZE), 0); - } - - @Override - protected String inputHex(final long offset, final int length) { - return inputSlice(offset, length).toString().substring(2); - } - - @Override - protected BigInteger getUnsignedBigInteger(final long offset, final int length) { - return BytesValues.asUnsignedBigInteger(inputSlice(offset, length)); - } - - @Override - protected int getInt(final long offset) { - return buffer.getInt(Math.toIntExact(bufferOffset + offset)); - } - - @Override - protected long getLong(final long offset) { - return buffer.getLong(Math.toIntExact(bufferOffset + offset)); - } - - @Override - public BytesValue raw() { - return BytesValue.wrap(buffer.getBytes()); - } -} diff --git a/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/VertxBufferRLPOutput.java b/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/VertxBufferRLPOutput.java deleted file mode 100644 index 173df7e6f6..0000000000 --- a/ethereum/rlp/src/main/java/tech/pegasys/pantheon/ethereum/rlp/VertxBufferRLPOutput.java +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2018 ConsenSys AG. - * - * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on - * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the - * specific language governing permissions and limitations under the License. - */ -package tech.pegasys.pantheon.ethereum.rlp; - -import tech.pegasys.pantheon.util.bytes.MutableBytesValue; - -import io.vertx.core.buffer.Buffer; - -/** - * A {@link RLPOutput} that writes/appends the result of RLP encoding to a Vert.x {@link Buffer}. - */ -public class VertxBufferRLPOutput extends AbstractRLPOutput { - /** - * Appends the RLP-encoded data written to this output to the provided Vert.x {@link Buffer}. - * - * @param buffer The buffer to which to append the data to. - */ - public void appendEncoded(final Buffer buffer) { - final int size = encodedSize(); - if (size == 0) { - return; - } - - // We want to append to the buffer, and Buffer always grows to accommodate anything writing, - // so we write the last byte we know we'll need to make it resize accordingly. - final int start = buffer.length(); - buffer.setByte(start + size - 1, (byte) 0); - writeEncoded(MutableBytesValue.wrapBuffer(buffer, start, size)); - } -} diff --git a/util/src/main/java/tech/pegasys/pantheon/util/bytes/BytesValue.java b/util/src/main/java/tech/pegasys/pantheon/util/bytes/BytesValue.java index 89c37f5544..72dee29c30 100644 --- a/util/src/main/java/tech/pegasys/pantheon/util/bytes/BytesValue.java +++ b/util/src/main/java/tech/pegasys/pantheon/util/bytes/BytesValue.java @@ -139,6 +139,21 @@ public interface BytesValue extends Comparable { return wrapBuffer(buffer, 0, buffer.length()); } + /** + * Wraps a full Vert.x {@link Buffer} as a {@link BytesValue}. + * + *

Note that as the buffer is wrapped, any change to the content of that buffer may be + * reflected in the returned value. + * + * @param buffer The buffer to wrap. + * @param offset The offset in {@code buffer} from which to expose the bytes in the returned + * value. That is, {@code wrapBuffer(buffer, i, 1).get(0) == buffer.getByte(i)}. + * @return A {@link BytesValue} that exposes the bytes of {@code buffer}. + */ + static BytesValue wrapBuffer(final Buffer buffer, final int offset) { + return wrapBuffer(buffer, offset, buffer.length() - offset); + } + /** * Wraps a slice of a Vert.x {@link Buffer} as a {@link BytesValue}. *