diff --git a/contracts/MerklePatriciaProof.sol b/contracts/MerklePatriciaProof.sol index 61856c3..df2a088 100644 --- a/contracts/MerklePatriciaProof.sol +++ b/contracts/MerklePatriciaProof.sol @@ -16,7 +16,7 @@ library MerklePatriciaProof { * @param root The root hash of the trie. * @return The boolean validity of the proof. */ - function verify(bytes value, bytes encodedPath, bytes rlpParentNodes, bytes32 root) internal constant returns (bool) { + function verify(bytes memory value, bytes memory encodedPath, bytes memory rlpParentNodes, bytes32 root) internal pure returns (bool) { RLP.RLPItem memory item = RLP.toRLPItem(rlpParentNodes); RLP.RLPItem[] memory parentNodes = RLP.toList(item); @@ -71,7 +71,7 @@ library MerklePatriciaProof { } } - function _nibblesToTraverse(bytes encodedPartialPath, bytes path, uint pathPtr) private constant returns (uint) { + function _nibblesToTraverse(bytes memory encodedPartialPath, bytes memory path, uint pathPtr) private pure returns (uint) { uint len; // encodedPartialPath has elements that are each two hex characters (1 byte), but partialPath // and slicedPath have elements that are each one hex character (1 nibble) @@ -94,7 +94,7 @@ library MerklePatriciaProof { } // bytes b must be hp encoded - function _getNibbleArray(bytes b) private constant returns (bytes) { + function _getNibbleArray(bytes memory b) private pure returns (bytes memory) { bytes memory nibbles; if(b.length>0) { uint8 offset; @@ -116,7 +116,7 @@ library MerklePatriciaProof { return nibbles; } - function _getNthNibbleOfBytes(uint n, bytes str) private constant returns (byte) { + function _getNthNibbleOfBytes(uint n, bytes memory str) private pure returns (byte) { return byte(n%2==0 ? uint8(str[n/2])/0x10 : uint8(str[n/2])%0x10); } } diff --git a/contracts/RLP.sol b/contracts/RLP.sol index 439b206..6c02ee6 100644 --- a/contracts/RLP.sol +++ b/contracts/RLP.sol @@ -5,8 +5,8 @@ * * @author Andreas Olofsson (androlo1980@gmail.com) */ -library RLP { +library RLP { uint constant DATA_SHORT_START = 0x80; uint constant DATA_LONG_START = 0xB8; uint constant LIST_SHORT_START = 0xC0; @@ -28,27 +28,22 @@ library RLP { /* Iterator */ - function next(Iterator memory self) internal constant returns (RLPItem memory subItem) { - if(hasNext(self)) { - var ptr = self._unsafe_nextPtr; - var itemLength = _itemLength(ptr); - subItem._unsafe_memPtr = ptr; - subItem._unsafe_length = itemLength; - self._unsafe_nextPtr = ptr + itemLength; - } - else - throw; + function next(Iterator memory self) internal pure returns (RLPItem memory subItem) { + require(hasNext(self)); + uint256 ptr = self._unsafe_nextPtr; + uint256 itemLength = _itemLength(ptr); + subItem._unsafe_memPtr = ptr; + subItem._unsafe_length = itemLength; + self._unsafe_nextPtr = ptr + itemLength; } - function next(Iterator memory self, bool strict) internal constant returns (RLPItem memory subItem) { + function next(Iterator memory self, bool strict) internal pure returns (RLPItem memory subItem) { subItem = next(self); - if(strict && !_validate(subItem)) - throw; - return; + require(!strict || _validate(subItem)); } - function hasNext(Iterator memory self) internal constant returns (bool) { - var item = self._unsafe_item; + function hasNext(Iterator memory self) internal pure returns (bool) { + RLP.RLPItem memory item = self._unsafe_item; return self._unsafe_nextPtr < item._unsafe_memPtr + item._unsafe_length; } @@ -57,7 +52,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 pure returns (RLPItem memory) { uint len = self.length; if (len == 0) { return RLPItem(0, 0); @@ -73,16 +68,13 @@ 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 pure returns (RLPItem memory) { + RLP.RLPItem memory item = toRLPItem(self); if(strict) { uint len = self.length; - if(_payloadOffset(item) > len) - throw; - if(_itemLength(item._unsafe_memPtr) != len) - throw; - if(!_validate(item)) - throw; + require(_payloadOffset(item) <= len); + require(_itemLength(item._unsafe_memPtr) == len); + require(_validate(item)); } return item; } @@ -90,38 +82,42 @@ library RLP { /// @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 pure returns (bool) { 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 pure returns (bool) { if (self._unsafe_length == 0) return false; uint memPtr = self._unsafe_memPtr; + bool result; assembly { - ret := iszero(lt(byte(0, mload(memPtr)), 0xC0)) + result := iszero(lt(byte(0, mload(memPtr)), 0xC0)) } + return result; } /// @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 pure returns (bool) { if (self._unsafe_length == 0) return false; uint memPtr = self._unsafe_memPtr; + bool result; assembly { - ret := lt(byte(0, mload(memPtr)), 0xC0) + result := lt(byte(0, mload(memPtr)), 0xC0) } + return result; } /// @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) { + /// @return result 'true' if the item is null. + function isEmpty(RLPItem memory self) internal pure returns (bool) { if(isNull(self)) return false; uint b0; @@ -135,7 +131,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 pure returns (uint) { if (!isList(self)) return 0; uint b0; @@ -156,98 +152,99 @@ 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) { - if (!isList(self)) - throw; + function iterator(RLPItem memory self) internal pure returns (Iterator memory) { + require(isList(self)); uint ptr = self._unsafe_memPtr + _payloadOffset(self); + Iterator memory it; it._unsafe_item = self; it._unsafe_nextPtr = ptr; + return it; } /// @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; - if (len == 0) - return; + function toBytes(RLPItem memory self) internal pure returns (bytes memory) { + uint256 len = self._unsafe_length; + require(len != 0); + bytes memory bts; bts = new bytes(len); _copyToBytes(self._unsafe_memPtr, bts, len); + return bts; } /// @dev Decode an RLPItem into bytes. This will not work if the /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toData(RLPItem memory self) internal constant returns (bytes memory bts) { - if(!isData(self)) - throw; - var (rStartPos, len) = _decode(self); + function toData(RLPItem memory self) internal pure returns (bytes memory) { + require(isData(self)); + (uint256 rStartPos, uint256 len) = _decode(self); + bytes memory bts; bts = new bytes(len); _copyToBytes(rStartPos, bts, len); + return bts; } /// @dev Get the list of sub-items from an RLP encoded list. /// 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) { - if(!isList(self)) - throw; - var numItems = items(self); - list = new RLPItem[](numItems); - var it = iterator(self); + function toList(RLPItem memory self) internal pure returns (RLPItem[] memory) { + require(isList(self)); + uint256 numItems = items(self); + RLPItem[] memory list = new RLPItem[](numItems); + RLP.Iterator memory it = iterator(self); uint idx; while(hasNext(it)) { list[idx] = next(it); idx++; } + return list; } /// @dev Decode an RLPItem into an ascii string. This will not work if the /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toAscii(RLPItem memory self) internal constant returns (string memory str) { - if(!isData(self)) - throw; - var (rStartPos, len) = _decode(self); + function toAscii(RLPItem memory self) internal pure returns (string memory) { + require(isData(self)); + (uint256 rStartPos, uint256 len) = _decode(self); bytes memory bts = new bytes(len); _copyToBytes(rStartPos, bts, len); - str = string(bts); + string memory str = string(bts); + return str; } /// @dev Decode an RLPItem into a uint. This will not work if the /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toUint(RLPItem memory self) internal constant returns (uint data) { - if(!isData(self)) - throw; - var (rStartPos, len) = _decode(self); - if (len > 32 || len == 0) - throw; + function toUint(RLPItem memory self) internal pure returns (uint) { + require(isData(self)); + (uint256 rStartPos, uint256 len) = _decode(self); + require(len <= 32); + require(len != 0); + uint data; assembly { data := div(mload(rStartPos), exp(256, sub(32, len))) } + return data; } /// @dev Decode an RLPItem into a boolean. This will not work if the /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toBool(RLPItem memory self) internal constant returns (bool data) { - if(!isData(self)) - throw; - var (rStartPos, len) = _decode(self); - if (len != 1) - throw; + function toBool(RLPItem memory self) internal pure returns (bool) { + require(isData(self)); + (uint256 rStartPos, uint256 len) = _decode(self); + require(len == 1); uint temp; assembly { temp := byte(0, mload(rStartPos)) } - if (temp > 1) - throw; + require(temp <= 1); return temp == 1 ? true : false; } @@ -255,13 +252,11 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toByte(RLPItem memory self) internal constant returns (byte data) { - if(!isData(self)) - throw; - var (rStartPos, len) = _decode(self); - if (len != 1) - throw; - uint temp; + function toByte(RLPItem memory self) internal pure returns (byte) { + require(isData(self)); + (uint256 rStartPos, uint256 len) = _decode(self); + require(len == 1); + byte temp; assembly { temp := byte(0, mload(rStartPos)) } @@ -272,7 +267,7 @@ 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 pure returns (int) { return int(toUint(self)); } @@ -280,7 +275,7 @@ library RLP { /// 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 pure returns (bytes32) { return bytes32(toUint(self)); } @@ -288,19 +283,19 @@ library RLP { /// RLPItem is a list. /// @param self The RLPItem. /// @return The decoded string. - function toAddress(RLPItem memory self) internal constant returns (address data) { - if(!isData(self)) - throw; - var (rStartPos, len) = _decode(self); - if (len != 20) - throw; + function toAddress(RLPItem memory self) internal pure returns (address) { + require(isData(self)); + (uint256 rStartPos, uint256 len) = _decode(self); + require(len == 20); + address data; assembly { data := div(mload(rStartPos), exp(256, 12)) } + return data; } // Get the payload offset. - function _payloadOffset(RLPItem memory self) private constant returns (uint) { + function _payloadOffset(RLPItem memory self) private pure returns (uint) { if(self._unsafe_length == 0) return 0; uint b0; @@ -318,7 +313,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 pure returns (uint len) { uint b0; assembly { b0 := byte(0, mload(memPtr)) @@ -346,9 +341,8 @@ library RLP { } // Get start position and length of the data. - function _decode(RLPItem memory self) private constant returns (uint memPtr, uint len) { - if(!isData(self)) - throw; + function _decode(RLPItem memory self) private pure returns (uint memPtr, uint len) { + require(isData(self)); uint b0; uint start = self._unsafe_memPtr; assembly { @@ -357,7 +351,7 @@ library RLP { if (b0 < DATA_SHORT_START) { memPtr = start; len = 1; - return; + return (memPtr, len); } if (b0 < DATA_LONG_START) { len = self._unsafe_length - 1; @@ -370,35 +364,29 @@ library RLP { len = self._unsafe_length - 1 - bLen; memPtr = start + bLen + 1; } - return; + return (memPtr, len); } // 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 pure { // Exploiting the fact that 'tgt' was the last thing to be allocated, // we can write entire words, and just overwrite any excess. assembly { + let words := div(add(btsLen, 31), 32) + let rOffset := btsPtr + let wOffset := add(tgt, 0x20) + for { let i := 0 } eq(i, words) { i := add(i, 1) } { - let i := 0 // Start at arr + 0x20 - let words := div(add(btsLen, 31), 32) - let rOffset := btsPtr - let wOffset := add(tgt, 0x20) - tag_loop: - jumpi(end, eq(i, words)) - { - let offset := mul(i, 0x20) - mstore(add(wOffset, offset), mload(add(rOffset, offset))) - i := add(i, 1) - } - jump(tag_loop) - end: - mstore(add(tgt, add(0x20, mload(tgt))), 0) + let offset := mul(i, 0x20) + mstore(add(wOffset, offset), mload(add(rOffset, offset))) + i := add(i, 1) } + mstore(add(tgt, add(0x20, mload(tgt))), 0) } } // Check that an RLP item is valid. - function _validate(RLPItem memory self) private constant returns (bool ret) { + function _validate(RLPItem memory self) private pure returns (bool ret) { // Check that RLP is well-formed. uint b0; uint b1; @@ -410,5 +398,5 @@ library RLP { if(b0 == DATA_SHORT_START + 1 && b1 < DATA_SHORT_START) return false; return true; - } + } }