Commit 609662bb authored by Andreas Bigger's avatar Andreas Bigger

Port RLP contracts to triple slash natspec styling

parent 677bff37
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.8; pragma solidity ^0.8.8;
/** /// @custom:attribution https://github.com/hamdiallam/Solidity-RLP
* @custom:attribution https://github.com/hamdiallam/Solidity-RLP /// @title RLPReader
* @title RLPReader /// @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted
* @notice RLPReader is a library for parsing RLP-encoded byte arrays into Solidity types. Adapted /// from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with
* from Solidity-RLP (https://github.com/hamdiallam/Solidity-RLP) by Hamdi Allam with /// various tweaks to improve readability.
* various tweaks to improve readability.
*/
library RLPReader { library RLPReader {
/** /// @notice Custom pointer type to avoid confusion between pointers and uint256s.
* Custom pointer type to avoid confusion between pointers and uint256s.
*/
type MemoryPointer is uint256; type MemoryPointer is uint256;
/** /// @notice RLP item types.
* @notice RLP item types. /// @custom:value DATA_ITEM Represents an RLP data item (NOT a list).
* /// @custom:value LIST_ITEM Represents an RLP list item.
* @custom:value DATA_ITEM Represents an RLP data item (NOT a list).
* @custom:value LIST_ITEM Represents an RLP list item.
*/
enum RLPItemType { enum RLPItemType {
DATA_ITEM, DATA_ITEM,
LIST_ITEM LIST_ITEM
} }
/** /// @notice Struct representing an RLP item.
* @notice Struct representing an RLP item. /// @custom:field length Length of the RLP item.
* /// @custom:field ptr Pointer to the RLP item in memory.
* @custom:field length Length of the RLP item.
* @custom:field ptr Pointer to the RLP item in memory.
*/
struct RLPItem { struct RLPItem {
uint256 length; uint256 length;
MemoryPointer ptr; MemoryPointer ptr;
} }
/** /// @notice Max list length that this library will accept.
* @notice Max list length that this library will accept.
*/
uint256 internal constant MAX_LIST_LENGTH = 32; uint256 internal constant MAX_LIST_LENGTH = 32;
/** /// @notice Converts bytes to a reference to memory position and length.
* @notice Converts bytes to a reference to memory position and length. /// @param _in Input bytes to convert.
* /// @return out_ Output memory reference.
* @param _in Input bytes to convert. function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory out_) {
*
* @return Output memory reference.
*/
function toRLPItem(bytes memory _in) internal pure returns (RLPItem memory) {
// Empty arrays are not RLP items. // Empty arrays are not RLP items.
require( require(
_in.length > 0, _in.length > 0,
...@@ -60,17 +44,13 @@ library RLPReader { ...@@ -60,17 +44,13 @@ library RLPReader {
ptr := add(_in, 32) ptr := add(_in, 32)
} }
return RLPItem({ length: _in.length, ptr: ptr }); out_ = RLPItem({ length: _in.length, ptr: ptr });
} }
/** /// @notice Reads an RLP list value into a list of RLP items.
* @notice Reads an RLP list value into a list of RLP items. /// @param _in RLP list value.
* /// @return out_ Decoded RLP list items.
* @param _in RLP list value. function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory out_) {
*
* @return Decoded RLP list items.
*/
function readList(RLPItem memory _in) internal pure returns (RLPItem[] memory) {
(uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in); (uint256 listOffset, uint256 listLength, RLPItemType itemType) = _decodeLength(_in);
require( require(
...@@ -87,7 +67,7 @@ library RLPReader { ...@@ -87,7 +67,7 @@ library RLPReader {
// writing to the length. Since we can't know the number of RLP items without looping over // writing to the length. Since we can't know the number of RLP items without looping over
// the entire input, we'd have to loop twice to accurately size this array. It's easier to // the entire input, we'd have to loop twice to accurately size this array. It's easier to
// simply set a reasonable maximum list length and decrease the size before we finish. // simply set a reasonable maximum list length and decrease the size before we finish.
RLPItem[] memory out = new RLPItem[](MAX_LIST_LENGTH); out_ = new RLPItem[](MAX_LIST_LENGTH);
uint256 itemCount = 0; uint256 itemCount = 0;
uint256 offset = listOffset; uint256 offset = listOffset;
...@@ -101,7 +81,7 @@ library RLPReader { ...@@ -101,7 +81,7 @@ library RLPReader {
// We don't need to check itemCount < out.length explicitly because Solidity already // We don't need to check itemCount < out.length explicitly because Solidity already
// handles this check on our behalf, we'd just be wasting gas. // handles this check on our behalf, we'd just be wasting gas.
out[itemCount] = RLPItem({ out_[itemCount] = RLPItem({
length: itemLength + itemOffset, length: itemLength + itemOffset,
ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset) ptr: MemoryPointer.wrap(MemoryPointer.unwrap(_in.ptr) + offset)
}); });
...@@ -112,31 +92,21 @@ library RLPReader { ...@@ -112,31 +92,21 @@ library RLPReader {
// Decrease the array size to match the actual item count. // Decrease the array size to match the actual item count.
assembly { assembly {
mstore(out, itemCount) mstore(out_, itemCount)
} }
return out;
} }
/** /// @notice Reads an RLP list value into a list of RLP items.
* @notice Reads an RLP list value into a list of RLP items. /// @param _in RLP list value.
* /// @return out_ Decoded RLP list items.
* @param _in RLP list value. function readList(bytes memory _in) internal pure returns (RLPItem[] memory out_) {
* out_ = readList(toRLPItem(_in));
* @return Decoded RLP list items.
*/
function readList(bytes memory _in) internal pure returns (RLPItem[] memory) {
return readList(toRLPItem(_in));
} }
/** /// @notice Reads an RLP bytes value into bytes.
* @notice Reads an RLP bytes value into bytes. /// @param _in RLP bytes value.
* /// @return out_ Decoded bytes.
* @param _in RLP bytes value. function readBytes(RLPItem memory _in) internal pure returns (bytes memory out_) {
*
* @return Decoded bytes.
*/
function readBytes(RLPItem memory _in) internal pure returns (bytes memory) {
(uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in); (uint256 itemOffset, uint256 itemLength, RLPItemType itemType) = _decodeLength(_in);
require( require(
...@@ -149,47 +119,35 @@ library RLPReader { ...@@ -149,47 +119,35 @@ library RLPReader {
"RLPReader: bytes value contains an invalid remainder" "RLPReader: bytes value contains an invalid remainder"
); );
return _copy(_in.ptr, itemOffset, itemLength); out_ = _copy(_in.ptr, itemOffset, itemLength);
} }
/** /// @notice Reads an RLP bytes value into bytes.
* @notice Reads an RLP bytes value into bytes. /// @param _in RLP bytes value.
* /// @return out_ Decoded bytes.
* @param _in RLP bytes value. function readBytes(bytes memory _in) internal pure returns (bytes memory out_) {
* out_ = readBytes(toRLPItem(_in));
* @return Decoded bytes.
*/
function readBytes(bytes memory _in) internal pure returns (bytes memory) {
return readBytes(toRLPItem(_in));
} }
/** /// @notice Reads the raw bytes of an RLP item.
* @notice Reads the raw bytes of an RLP item. /// @param _in RLP item to read.
* /// @return out_ Raw RLP bytes.
* @param _in RLP item to read. function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory out_) {
* out_ = _copy(_in.ptr, 0, _in.length);
* @return Raw RLP bytes.
*/
function readRawBytes(RLPItem memory _in) internal pure returns (bytes memory) {
return _copy(_in.ptr, 0, _in.length);
} }
/** /// @notice Decodes the length of an RLP item.
* @notice Decodes the length of an RLP item. /// @param _in RLP item to decode.
* /// @return offset_ Offset of the encoded data.
* @param _in RLP item to decode. /// @return length_ Length of the encoded data.
* /// @return type_ RLP item type (LIST_ITEM or DATA_ITEM).
* @return Offset of the encoded data.
* @return Length of the encoded data.
* @return RLP item type (LIST_ITEM or DATA_ITEM).
*/
function _decodeLength(RLPItem memory _in) function _decodeLength(RLPItem memory _in)
private private
pure pure
returns ( returns (
uint256, uint256 offset_,
uint256, uint256 length_,
RLPItemType RLPItemType type_
) )
{ {
// Short-circuit if there's nothing to decode, note that we perform this check when // Short-circuit if there's nothing to decode, note that we perform this check when
...@@ -315,23 +273,19 @@ library RLPReader { ...@@ -315,23 +273,19 @@ library RLPReader {
} }
} }
/** /// @notice Copies the bytes from a memory location.
* @notice Copies the bytes from a memory location. /// @param _src Pointer to the location to read from.
* /// @param _offset Offset to start reading from.
* @param _src Pointer to the location to read from. /// @param _length Number of bytes to read.
* @param _offset Offset to start reading from. /// @return out_ Copied bytes.
* @param _length Number of bytes to read.
*
* @return Copied bytes.
*/
function _copy( function _copy(
MemoryPointer _src, MemoryPointer _src,
uint256 _offset, uint256 _offset,
uint256 _length uint256 _length
) private pure returns (bytes memory) { ) private pure returns (bytes memory out_) {
bytes memory out = new bytes(_length); out_ = new bytes(_length);
if (_length == 0) { if (_length == 0) {
return out; return out_;
} }
// Mostly based on Solidity's copy_memory_to_memory: // Mostly based on Solidity's copy_memory_to_memory:
...@@ -339,7 +293,7 @@ library RLPReader { ...@@ -339,7 +293,7 @@ library RLPReader {
// https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114 // https://github.com/ethereum/solidity/blob/34dd30d71b4da730488be72ff6af7083cf2a91f6/libsolidity/codegen/YulUtilFunctions.cpp#L102-L114
uint256 src = MemoryPointer.unwrap(_src) + _offset; uint256 src = MemoryPointer.unwrap(_src) + _offset;
assembly { assembly {
let dest := add(out, 32) let dest := add(out_, 32)
let i := 0 let i := 0
for { for {
...@@ -353,7 +307,5 @@ library RLPReader { ...@@ -353,7 +307,5 @@ library RLPReader {
mstore(add(dest, _length), 0) mstore(add(dest, _length), 0)
} }
} }
return out;
} }
} }
// SPDX-License-Identifier: MIT // SPDX-License-Identifier: MIT
pragma solidity ^0.8.0; pragma solidity ^0.8.0;
/** /// @custom:attribution https://github.com/bakaoh/solidity-rlp-encode
* @custom:attribution https://github.com/bakaoh/solidity-rlp-encode /// @title RLPWriter
* @title RLPWriter /// @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's
* @author RLPWriter is a library for encoding Solidity types to RLP bytes. Adapted from Bakaoh's /// RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor
* RLPEncode library (https://github.com/bakaoh/solidity-rlp-encode) with minor /// modifications to improve legibility.
* modifications to improve legibility.
*/
library RLPWriter { library RLPWriter {
/** /// @notice RLP encodes a byte string.
* @notice RLP encodes a byte string. /// @param _in The byte string to encode.
* /// @return out_ The RLP encoded string in bytes.
* @param _in The byte string to encode. function writeBytes(bytes memory _in) internal pure returns (bytes memory out_) {
*
* @return The RLP encoded string in bytes.
*/
function writeBytes(bytes memory _in) internal pure returns (bytes memory) {
bytes memory encoded;
if (_in.length == 1 && uint8(_in[0]) < 128) { if (_in.length == 1 && uint8(_in[0]) < 128) {
encoded = _in; out_ = _in;
} else { } else {
encoded = abi.encodePacked(_writeLength(_in.length, 128), _in); out_ = abi.encodePacked(_writeLength(_in.length, 128), _in);
} }
return encoded;
} }
/** /// @notice RLP encodes a list of RLP encoded byte byte strings.
* @notice RLP encodes a list of RLP encoded byte byte strings. /// @param _in The list of RLP encoded byte strings.
* /// @return list_ The RLP encoded list of items in bytes.
* @param _in The list of RLP encoded byte strings. function writeList(bytes[] memory _in) internal pure returns (bytes memory list_) {
* list_ = _flatten(_in);
* @return The RLP encoded list of items in bytes. list_ = abi.encodePacked(_writeLength(list_.length, 192), list_);
*/
function writeList(bytes[] memory _in) internal pure returns (bytes memory) {
bytes memory list = _flatten(_in);
return abi.encodePacked(_writeLength(list.length, 192), list);
} }
/** /// @notice RLP encodes a string.
* @notice RLP encodes a string. /// @param _in The string to encode.
* /// @return out_ The RLP encoded string in bytes.
* @param _in The string to encode. function writeString(string memory _in) internal pure returns (bytes memory out_) {
* out_ = writeBytes(bytes(_in));
* @return The RLP encoded string in bytes.
*/
function writeString(string memory _in) internal pure returns (bytes memory) {
return writeBytes(bytes(_in));
} }
/** /// @notice RLP encodes an address.
* @notice RLP encodes an address. /// @param _in The address to encode.
* /// @return out_ The RLP encoded address in bytes.
* @param _in The address to encode. function writeAddress(address _in) internal pure returns (bytes memory out_) {
* out_ = writeBytes(abi.encodePacked(_in));
* @return The RLP encoded address in bytes.
*/
function writeAddress(address _in) internal pure returns (bytes memory) {
return writeBytes(abi.encodePacked(_in));
} }
/** /// @notice RLP encodes a uint.
* @notice RLP encodes a uint. /// @param _in The uint256 to encode.
* /// @return out_ The RLP encoded uint256 in bytes.
* @param _in The uint256 to encode. function writeUint(uint256 _in) internal pure returns (bytes memory out_) {
* out_ = writeBytes(_toBinary(_in));
* @return The RLP encoded uint256 in bytes.
*/
function writeUint(uint256 _in) internal pure returns (bytes memory) {
return writeBytes(_toBinary(_in));
} }
/** /// @notice RLP encodes a bool.
* @notice RLP encodes a bool. /// @param _in The bool to encode.
* /// @return out_ The RLP encoded bool in bytes.
* @param _in The bool to encode. function writeBool(bool _in) internal pure returns (bytes memory out_) {
* out_ = new bytes(1);
* @return The RLP encoded bool in bytes. out_[0] = (_in ? bytes1(0x01) : bytes1(0x80));
*/
function writeBool(bool _in) internal pure returns (bytes memory) {
bytes memory encoded = new bytes(1);
encoded[0] = (_in ? bytes1(0x01) : bytes1(0x80));
return encoded;
} }
/** /// @notice Encode the first byte and then the `len` in binary form if `length` is more than 55.
* @notice Encode the first byte and then the `len` in binary form if `length` is more than 55. /// @param _len The length of the string or the payload.
* /// @param _offset 128 if item is string, 192 if item is list.
* @param _len The length of the string or the payload. /// @return out_ RLP encoded bytes.
* @param _offset 128 if item is string, 192 if item is list. function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory out_) {
*
* @return RLP encoded bytes.
*/
function _writeLength(uint256 _len, uint256 _offset) private pure returns (bytes memory) {
bytes memory encoded;
if (_len < 56) { if (_len < 56) {
encoded = new bytes(1); out_ = new bytes(1);
encoded[0] = bytes1(uint8(_len) + uint8(_offset)); out_[0] = bytes1(uint8(_len) + uint8(_offset));
} else { } else {
uint256 lenLen; uint256 lenLen;
uint256 i = 1; uint256 i = 1;
...@@ -108,24 +71,18 @@ library RLPWriter { ...@@ -108,24 +71,18 @@ library RLPWriter {
i *= 256; i *= 256;
} }
encoded = new bytes(lenLen + 1); out_ = new bytes(lenLen + 1);
encoded[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55); out_[0] = bytes1(uint8(lenLen) + uint8(_offset) + 55);
for (i = 1; i <= lenLen; i++) { for (i = 1; i <= lenLen; i++) {
encoded[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256)); out_[i] = bytes1(uint8((_len / (256**(lenLen - i))) % 256));
} }
} }
return encoded;
} }
/** /// @notice Encode integer in big endian binary form with no leading zeroes.
* @notice Encode integer in big endian binary form with no leading zeroes. /// @param _x The integer to encode.
* /// @return out_ RLP encoded bytes.
* @param _x The integer to encode. function _toBinary(uint256 _x) private pure returns (bytes memory out_) {
*
* @return RLP encoded bytes.
*/
function _toBinary(uint256 _x) private pure returns (bytes memory) {
bytes memory b = abi.encodePacked(_x); bytes memory b = abi.encodePacked(_x);
uint256 i = 0; uint256 i = 0;
...@@ -135,22 +92,17 @@ library RLPWriter { ...@@ -135,22 +92,17 @@ library RLPWriter {
} }
} }
bytes memory res = new bytes(32 - i); out_ = new bytes(32 - i);
for (uint256 j = 0; j < res.length; j++) { for (uint256 j = 0; j < out_.length; j++) {
res[j] = b[i++]; out_[j] = b[i++];
} }
return res;
} }
/** /// @custom:attribution https://github.com/Arachnid/solidity-stringutils
* @custom:attribution https://github.com/Arachnid/solidity-stringutils /// @notice Copies a piece of memory to another location.
* @notice Copies a piece of memory to another location. /// @param _dest Destination location.
* /// @param _src Source location.
* @param _dest Destination location. /// @param _len Length of memory to copy.
* @param _src Source location.
* @param _len Length of memory to copy.
*/
function _memcpy( function _memcpy(
uint256 _dest, uint256 _dest,
uint256 _src, uint256 _src,
...@@ -179,15 +131,11 @@ library RLPWriter { ...@@ -179,15 +131,11 @@ library RLPWriter {
} }
} }
/** /// @custom:attribution https://github.com/sammayo/solidity-rlp-encoder
* @custom:attribution https://github.com/sammayo/solidity-rlp-encoder /// @notice Flattens a list of byte strings into one byte string.
* @notice Flattens a list of byte strings into one byte string. /// @param _list List of byte strings to flatten.
* /// @return out_ The flattened byte string.
* @param _list List of byte strings to flatten. function _flatten(bytes[] memory _list) private pure returns (bytes memory out_) {
*
* @return The flattened byte string.
*/
function _flatten(bytes[] memory _list) private pure returns (bytes memory) {
if (_list.length == 0) { if (_list.length == 0) {
return new bytes(0); return new bytes(0);
} }
...@@ -198,10 +146,10 @@ library RLPWriter { ...@@ -198,10 +146,10 @@ library RLPWriter {
len += _list[i].length; len += _list[i].length;
} }
bytes memory flattened = new bytes(len); out_ = new bytes(len);
uint256 flattenedPtr; uint256 flattenedPtr;
assembly { assembly {
flattenedPtr := add(flattened, 0x20) flattenedPtr := add(out_, 0x20)
} }
for (i = 0; i < _list.length; i++) { for (i = 0; i < _list.length; i++) {
...@@ -215,7 +163,5 @@ library RLPWriter { ...@@ -215,7 +163,5 @@ library RLPWriter {
_memcpy(flattenedPtr, listPtr, item.length); _memcpy(flattenedPtr, listPtr, item.length);
flattenedPtr += _list[i].length; flattenedPtr += _list[i].length;
} }
return flattened;
} }
} }
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment