Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

RLP: adapting to changes in Solidity version 0.5.0 #8

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
122 changes: 62 additions & 60 deletions contracts/src/codec/RLP.sol
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
pragma solidity ^0.4.6;

/**
* @title RLPReader
*
Expand Down Expand Up @@ -28,27 +30,27 @@ library RLP {

/* Iterator */

function next(Iterator memory self) internal constant returns (RLPItem memory subItem) {
function next(Iterator memory self) internal view returns (RLPItem memory subItem) {
if(hasNext(self)) {
var ptr = self._unsafe_nextPtr;
var itemLength = _itemLength(ptr);
uint ptr = self._unsafe_nextPtr;
uint itemLength = _itemLength(ptr);
subItem._unsafe_memPtr = ptr;
subItem._unsafe_length = itemLength;
self._unsafe_nextPtr = ptr + itemLength;
}
else
throw;
revert();
}

function next(Iterator memory self, bool strict) internal constant returns (RLPItem memory subItem) {
function next(Iterator memory self, bool strict) internal view returns (RLPItem memory subItem) {
subItem = next(self);
if(strict && !_validate(subItem))
throw;
revert();
return;
}

function hasNext(Iterator memory self) internal constant returns (bool) {
var item = self._unsafe_item;
function hasNext(Iterator memory self) internal view returns (bool) {
RLPItem memory item = self._unsafe_item;
return self._unsafe_nextPtr < item._unsafe_memPtr + item._unsafe_length;
}

Expand All @@ -57,7 +59,7 @@ library RLP {
/// @dev Creates an RLPItem from an array of RLP encoded bytes.
/// @param self The RLP encoded bytes.
/// @return An RLPItem
function toRLPItem(bytes memory self) internal constant returns (RLPItem memory) {
function toRLPItem(bytes memory self) internal view returns (RLPItem memory) {
uint len = self.length;
if (len == 0) {
return RLPItem(0, 0);
Expand All @@ -73,31 +75,31 @@ library RLP {
/// @param self The RLP encoded bytes.
/// @param strict Will throw if the data is not RLP encoded.
/// @return An RLPItem
function toRLPItem(bytes memory self, bool strict) internal constant returns (RLPItem memory) {
var item = toRLPItem(self);
function toRLPItem(bytes memory self, bool strict) internal view returns (RLPItem memory) {
RLPItem memory item = toRLPItem(self);
if(strict) {
uint len = self.length;
if(_payloadOffset(item) > len)
throw;
revert();
if(_itemLength(item._unsafe_memPtr) != len)
throw;
revert();
if(!_validate(item))
throw;
revert();
}
return item;
}

/// @dev Check if the RLP item is null.
/// @param self The RLP item.
/// @return 'true' if the item is null.
function isNull(RLPItem memory self) internal constant returns (bool ret) {
function isNull(RLPItem memory self) internal view returns (bool ret) {
return self._unsafe_length == 0;
}

/// @dev Check if the RLP item is a list.
/// @param self The RLP item.
/// @return 'true' if the item is a list.
function isList(RLPItem memory self) internal constant returns (bool ret) {
function isList(RLPItem memory self) internal view returns (bool ret) {
if (self._unsafe_length == 0)
return false;
uint memPtr = self._unsafe_memPtr;
Expand All @@ -109,7 +111,7 @@ library RLP {
/// @dev Check if the RLP item is data.
/// @param self The RLP item.
/// @return 'true' if the item is data.
function isData(RLPItem memory self) internal constant returns (bool ret) {
function isData(RLPItem memory self) internal view returns (bool ret) {
if (self._unsafe_length == 0)
return false;
uint memPtr = self._unsafe_memPtr;
Expand All @@ -121,7 +123,7 @@ library RLP {
/// @dev Check if the RLP item is empty (string or list).
/// @param self The RLP item.
/// @return 'true' if the item is null.
function isEmpty(RLPItem memory self) internal constant returns (bool ret) {
function isEmpty(RLPItem memory self) internal view returns (bool ret) {
if(isNull(self))
return false;
uint b0;
Expand All @@ -135,7 +137,7 @@ library RLP {
/// @dev Get the number of items in an RLP encoded list.
/// @param self The RLP item.
/// @return The number of items.
function items(RLPItem memory self) internal constant returns (uint) {
function items(RLPItem memory self) internal view returns (uint) {
if (!isList(self))
return 0;
uint b0;
Expand All @@ -156,9 +158,9 @@ library RLP {
/// @dev Create an iterator.
/// @param self The RLP item.
/// @return An 'Iterator' over the item.
function iterator(RLPItem memory self) internal constant returns (Iterator memory it) {
function iterator(RLPItem memory self) internal view returns (Iterator memory it) {
if (!isList(self))
throw;
revert();
uint ptr = self._unsafe_memPtr + _payloadOffset(self);
it._unsafe_item = self;
it._unsafe_nextPtr = ptr;
Expand All @@ -167,8 +169,8 @@ library RLP {
/// @dev Return the RLP encoded bytes.
/// @param self The RLPItem.
/// @return The bytes.
function toBytes(RLPItem memory self) internal constant returns (bytes memory bts) {
var len = self._unsafe_length;
function toBytes(RLPItem memory self) internal returns (bytes memory bts) {
uint len = self._unsafe_length;
if (len == 0)
return;
bts = new bytes(len);
Expand All @@ -179,10 +181,10 @@ library RLP {
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toData(RLPItem memory self) internal constant returns (bytes memory bts) {
function toData(RLPItem memory self) internal returns (bytes memory bts) {
if(!isData(self))
throw;
var (rStartPos, len) = _decode(self);
revert();
(uint rStartPos, uint len) = _decode(self);
bts = new bytes(len);
_copyToBytes(rStartPos, bts, len);
}
Expand All @@ -191,12 +193,12 @@ library RLP {
/// Warning: This is inefficient, as it requires that the list is read twice.
/// @param self The RLP item.
/// @return Array of RLPItems.
function toList(RLPItem memory self) internal constant returns (RLPItem[] memory list) {
function toList(RLPItem memory self) internal view returns (RLPItem[] memory list) {
if(!isList(self))
throw;
var numItems = items(self);
revert();
uint numItems = items(self);
list = new RLPItem[](numItems);
var it = iterator(self);
Iterator memory it = iterator(self);
uint idx;
while(hasNext(it)) {
list[idx] = next(it);
Expand All @@ -208,10 +210,10 @@ library RLP {
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toAscii(RLPItem memory self) internal constant returns (string memory str) {
function toAscii(RLPItem memory self) internal returns (string memory str) {

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why is this not view?

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah because _copyToBytes still uses jumps.

if(!isData(self))
throw;
var (rStartPos, len) = _decode(self);
revert();
(uint rStartPos, uint len) = _decode(self);
bytes memory bts = new bytes(len);
_copyToBytes(rStartPos, bts, len);
str = string(bts);
Expand All @@ -221,12 +223,12 @@ library RLP {
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toUint(RLPItem memory self) internal constant returns (uint data) {
function toUint(RLPItem memory self) internal view returns (uint data) {
if(!isData(self))
throw;
var (rStartPos, len) = _decode(self);
revert();
(uint rStartPos, uint len) = _decode(self);
if (len > 32 || len == 0)
throw;
revert();
assembly {
data := div(mload(rStartPos), exp(256, sub(32, len)))
}
Expand All @@ -236,32 +238,32 @@ library RLP {
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toBool(RLPItem memory self) internal constant returns (bool data) {
function toBool(RLPItem memory self) internal view returns (bool data) {
if(!isData(self))
throw;
var (rStartPos, len) = _decode(self);
revert();
(uint rStartPos, uint len) = _decode(self);
if (len != 1)
throw;
revert();
uint temp;
assembly {
temp := byte(0, mload(rStartPos))
}
if (temp > 1)
throw;
revert();
return temp == 1 ? true : false;
}

/// @dev Decode an RLPItem into a byte. This will not work if the
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toByte(RLPItem memory self) internal constant returns (byte data) {
function toByte(RLPItem memory self) internal view returns (byte data) {
if(!isData(self))
throw;
var (rStartPos, len) = _decode(self);
revert();
(uint rStartPos, uint len) = _decode(self);
if (len != 1)
throw;
uint temp;
revert();
uint8 temp;
assembly {
temp := byte(0, mload(rStartPos))
}
Expand All @@ -272,35 +274,35 @@ library RLP {
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toInt(RLPItem memory self) internal constant returns (int data) {
function toInt(RLPItem memory self) internal view returns (int data) {
return int(toUint(self));
}

/// @dev Decode an RLPItem into a bytes32. This will not work if the
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toBytes32(RLPItem memory self) internal constant returns (bytes32 data) {
function toBytes32(RLPItem memory self) internal view returns (bytes32 data) {
return bytes32(toUint(self));
}

/// @dev Decode an RLPItem into an address. This will not work if the
/// RLPItem is a list.
/// @param self The RLPItem.
/// @return The decoded string.
function toAddress(RLPItem memory self) internal constant returns (address data) {
function toAddress(RLPItem memory self) internal view returns (address data) {
if(!isData(self))
throw;
var (rStartPos, len) = _decode(self);
revert();
(uint rStartPos, uint len) = _decode(self);
if (len != 20)
throw;
revert();
assembly {
data := div(mload(rStartPos), exp(256, 12))
}
}

// Get the payload offset.
function _payloadOffset(RLPItem memory self) private constant returns (uint) {
function _payloadOffset(RLPItem memory self) private view returns (uint) {
if(self._unsafe_length == 0)
return 0;
uint b0;
Expand All @@ -318,7 +320,7 @@ library RLP {
}

// Get the full length of an RLP item.
function _itemLength(uint memPtr) private constant returns (uint len) {
function _itemLength(uint memPtr) private view returns (uint len) {
uint b0;
assembly {
b0 := byte(0, mload(memPtr))
Expand Down Expand Up @@ -346,9 +348,9 @@ library RLP {
}

// Get start position and length of the data.
function _decode(RLPItem memory self) private constant returns (uint memPtr, uint len) {
function _decode(RLPItem memory self) private view returns (uint memPtr, uint len) {
if(!isData(self))
throw;
revert();
uint b0;
uint start = self._unsafe_memPtr;
assembly {
Expand All @@ -374,7 +376,7 @@ library RLP {
}

// Assumes that enough memory has been allocated to store in target.
function _copyToBytes(uint btsPtr, bytes memory tgt, uint btsLen) private constant {
function _copyToBytes(uint btsPtr, bytes memory tgt, uint btsLen) private {
// Exploiting the fact that 'tgt' was the last thing to be allocated,
// we can write entire words, and just overwrite any excess.
assembly {
Expand All @@ -398,7 +400,7 @@ library RLP {
}

// Check that an RLP item is valid.
function _validate(RLPItem memory self) private constant returns (bool ret) {
function _validate(RLPItem memory self) private view returns (bool ret) {
// Check that RLP is well-formed.
uint b0;
uint b1;
Expand All @@ -411,4 +413,4 @@ library RLP {
return false;
return true;
}
}
}