From 47cc7df427cd1a55830dfc14105d7e06ae850bc8 Mon Sep 17 00:00:00 2001 From: Haofan Zheng Date: Wed, 10 May 2023 19:03:44 -0700 Subject: [PATCH] Moved rlp into libs dir --- .gitmodules | 4 + contracts/DecentServerCert.sol | 2 +- contracts/rlp/Helper.sol | 208 ------------------- contracts/rlp/LICENSE | 201 ------------------- contracts/rlp/README.md | 10 - contracts/rlp/RLPReader.sol | 354 --------------------------------- libs/Solidity-RLP | 1 + tests/RLP/RLP_test.sol | 2 +- 8 files changed, 7 insertions(+), 775 deletions(-) delete mode 100644 contracts/rlp/Helper.sol delete mode 100644 contracts/rlp/LICENSE delete mode 100644 contracts/rlp/README.md delete mode 100644 contracts/rlp/RLPReader.sol create mode 160000 libs/Solidity-RLP diff --git a/.gitmodules b/.gitmodules index 2c09ac9..2a07678 100644 --- a/.gitmodules +++ b/.gitmodules @@ -10,3 +10,7 @@ path = libs/base64 url = https://github.com/Brechtpd/base64.git branch = main +[submodule "libs/Solidity-RLP"] + path = libs/Solidity-RLP + url = https://github.com/hamdiallam/Solidity-RLP.git + branch = master diff --git a/contracts/DecentServerCert.sol b/contracts/DecentServerCert.sol index 6f8f29a..7f8cb26 100644 --- a/contracts/DecentServerCert.sol +++ b/contracts/DecentServerCert.sol @@ -9,7 +9,7 @@ import {IASReportCert} from "./IASReportCert.sol"; import {Interface_IASReportCertMgr} from "./Interface_IASReportCertMgr.sol"; import {LibSecp256k1Sha256} from "./LibSecp256k1Sha256.sol"; import {OIDs} from "./Constants.sol"; -import {RLPReader} from "./rlp/RLPReader.sol"; +import {RLPReader} from "../libs/Solidity-RLP/contracts/RLPReader.sol"; import {X509CertNodes} from "./X509CertNodes.sol"; import {X509Extension} from "./X509Extension.sol"; diff --git a/contracts/rlp/Helper.sol b/contracts/rlp/Helper.sol deleted file mode 100644 index 59d7c17..0000000 --- a/contracts/rlp/Helper.sol +++ /dev/null @@ -1,208 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -pragma solidity >=0.5.0 <=0.8.18; - -/* -* Used to proxy function calls to the RLPReader for testing -*/ -import "./RLPReader.sol"; - -contract Helper { - using RLPReader for bytes; - using RLPReader for uint; - using RLPReader for RLPReader.RLPItem; - using RLPReader for RLPReader.Iterator; - - function isList(bytes memory item) public pure returns (bool) { - RLPReader.RLPItem memory rlpItem = item.toRlpItem(); - return rlpItem.isList(); - } - - function itemLength(bytes memory item) public pure returns (uint) { - uint memPtr; - assembly { - memPtr := add(item, 0x20) - } - - return _itemLength(memPtr); - } - - function rlpLen(bytes memory item) public pure returns (uint) { - RLPReader.RLPItem memory rlpItem = item.toRlpItem(); - return rlpItem.rlpLen(); - } - - function payloadLocation(bytes memory item) public pure returns ( - uint payloadMemPtr, - uint payloadLen, - uint itemMemPtr - ) { - RLPReader.RLPItem memory rlpItem = item.toRlpItem(); - (uint memPtr, uint len) = rlpItem.payloadLocation(); - return (memPtr, len, rlpItem.memPtr); - } - - function numItems(bytes memory item) public pure returns (uint) { - RLPReader.RLPItem[] memory rlpItem = item.toRlpItem().toList(); - return rlpItem.length; - } - - function rlpBytesKeccak256(bytes memory item) public pure returns (bytes32) { - RLPReader.RLPItem memory rlpItem = item.toRlpItem(); - return rlpItem.rlpBytesKeccak256(); - } - - function payloadKeccak256(bytes memory item) public pure returns (bytes32) { - RLPReader.RLPItem memory rlpItem = item.toRlpItem(); - return rlpItem.payloadKeccak256(); - } - - function toRlpBytes(bytes memory item) public pure returns (bytes memory) { - RLPReader.RLPItem memory rlpItem = item.toRlpItem(); - return rlpItem.toRlpBytes(); - } - - function toBytes(bytes memory item) public pure returns (bytes memory) { - RLPReader.RLPItem memory rlpItem = item.toRlpItem(); - return rlpItem.toBytes(); - } - - function toUint(bytes memory item) public pure returns (uint) { - RLPReader.RLPItem memory rlpItem = item.toRlpItem(); - return rlpItem.toUint(); - } - - function toUintStrict(bytes memory item) public pure returns (uint) { - RLPReader.RLPItem memory rlpItem = item.toRlpItem(); - return rlpItem.toUintStrict(); - } - - function toAddress(bytes memory item) public pure returns (address) { - RLPReader.RLPItem memory rlpItem = item.toRlpItem(); - return rlpItem.toAddress(); - } - - function toBoolean(bytes memory item) public pure returns (bool) { - RLPReader.RLPItem memory rlpItem = item.toRlpItem(); - return rlpItem.toBoolean(); - } - - function bytesToString(bytes memory item) public pure returns (string memory) { - RLPReader.RLPItem memory rlpItem = item.toRlpItem(); - return string(rlpItem.toBytes()); - } - - function toIterator(bytes memory item) public pure { - // we just care that this does not revert - item.toRlpItem().iterator(); - } - - // expects [["somestring"]] - function nestedIteration(bytes memory item) public pure returns (string memory) { - RLPReader.Iterator memory iter = item.toRlpItem().iterator(); - RLPReader.Iterator memory subIter = iter.next().iterator(); - string memory result = string(subIter.next().toBytes()); - - require(!iter.hasNext()); - require(!subIter.hasNext()); - - return result; - } - - function toBlockHeader(bytes memory rlpHeader) public pure returns ( - bytes32 parentHash, bytes32 sha3Uncles, bytes32 stateRoot, bytes32 transactionsRoot, bytes32 receiptsRoot, - uint difficulty, uint number, uint gasLimit, uint gasUsed, uint timestamp, uint nonce) { - - RLPReader.Iterator memory it = rlpHeader.toRlpItem().iterator(); - uint idx; - while(it.hasNext()) { - if ( idx == 0 ) parentHash = bytes32(it.next().toUint()); - else if ( idx == 1 ) sha3Uncles = bytes32(it.next().toUint()); - else if ( idx == 3 ) stateRoot = bytes32(it.next().toUint()); - else if ( idx == 4 ) transactionsRoot = bytes32(it.next().toUint()); - else if ( idx == 5 ) receiptsRoot = bytes32(it.next().toUint()); - else if ( idx == 7 ) difficulty = it.next().toUint(); - else if ( idx == 8 ) number = it.next().toUint(); - else if ( idx == 9 ) gasLimit = it.next().toUint(); - else if ( idx == 10 ) gasUsed = it.next().toUint(); - else if ( idx == 11 ) timestamp = it.next().toUint(); - else if ( idx == 14 ) nonce = it.next().toUint(); - else it.next(); - - idx++; - } - } - - /* custom destructuring */ - - function customDestructure(bytes memory item) public pure returns (address, bool, uint) { - // first three elements follow the return types in order. Ignore the rest - RLPReader.RLPItem[] memory items = item.toRlpItem().toList(); - return (items[0].toAddress(), items[1].toBoolean(), items[2].toUint()); - } - - function customNestedDestructure(bytes memory item) public pure returns (address, uint) { - RLPReader.RLPItem[] memory items = item.toRlpItem().toList(); - items = items[0].toList(); - return (items[0].toAddress(), items[1].toUint()); - } - - // expects [[bytes, bytes]] - function customNestedDestructureKeccak(bytes memory item) public pure returns (bytes32, bytes32) { - RLPReader.RLPItem[] memory items = item.toRlpItem().toList(); - items = items[0].toList(); - return (items[0].payloadKeccak256(), items[1].payloadKeccak256()); - } - - function customNestedToRlpBytes(bytes memory item) public pure returns (bytes memory) { - RLPReader.RLPItem[] memory items = item.toRlpItem().toList(); - return items[0].toRlpBytes(); - } - - /* Copied verbatim from the reader contract due to scope */ - uint8 constant STRING_SHORT_START = 0x80; - uint8 constant STRING_LONG_START = 0xb8; - uint8 constant LIST_SHORT_START = 0xc0; - uint8 constant LIST_LONG_START = 0xf8; - function _itemLength(uint memPtr) private pure returns (uint) { - uint itemLen; - uint byte0; - assembly { - byte0 := byte(0, mload(memPtr)) - } - - if (byte0 < STRING_SHORT_START) - itemLen = 1; - - else if (byte0 < STRING_LONG_START) - itemLen = byte0 - STRING_SHORT_START + 1; - - else if (byte0 < LIST_SHORT_START) { - assembly { - let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is - memPtr := add(memPtr, 1) // skip over the first byte - - /* 32 byte word size */ - let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len - itemLen := add(dataLen, add(byteLen, 1)) - } - } - - else if (byte0 < LIST_LONG_START) { - itemLen = byte0 - LIST_SHORT_START + 1; - } - - else { - assembly { - let byteLen := sub(byte0, 0xf7) - memPtr := add(memPtr, 1) - - let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length - itemLen := add(dataLen, add(byteLen, 1)) - } - } - - return itemLen; - } -} - diff --git a/contracts/rlp/LICENSE b/contracts/rlp/LICENSE deleted file mode 100644 index 3d33284..0000000 --- a/contracts/rlp/LICENSE +++ /dev/null @@ -1,201 +0,0 @@ - Apache License - Version 2.0, January 2004 - http://www.apache.org/licenses/ - - TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION - - 1. Definitions. - - "License" shall mean the terms and conditions for use, reproduction, - and distribution as defined by Sections 1 through 9 of this document. - - "Licensor" shall mean the copyright owner or entity authorized by - the copyright owner that is granting the License. - - "Legal Entity" shall mean the union of the acting entity and all - other entities that control, are controlled by, or are under common - control with that entity. For the purposes of this definition, - "control" means (i) the power, direct or indirect, to cause the - direction or management of such entity, whether by contract or - otherwise, or (ii) ownership of fifty percent (50%) or more of the - outstanding shares, or (iii) beneficial ownership of such entity. - - "You" (or "Your") shall mean an individual or Legal Entity - exercising permissions granted by this License. - - "Source" form shall mean the preferred form for making modifications, - including but not limited to software source code, documentation - source, and configuration files. - - "Object" form shall mean any form resulting from mechanical - transformation or translation of a Source form, including but - not limited to compiled object code, generated documentation, - and conversions to other media types. - - "Work" shall mean the work of authorship, whether in Source or - Object form, made available under the License, as indicated by a - copyright notice that is included in or attached to the work - (an example is provided in the Appendix below). - - "Derivative Works" shall mean any work, whether in Source or Object - form, that is based on (or derived from) the Work and for which the - editorial revisions, annotations, elaborations, or other modifications - represent, as a whole, an original work of authorship. For the purposes - of this License, Derivative Works shall not include works that remain - separable from, or merely link (or bind by name) to the interfaces of, - the Work and Derivative Works thereof. - - "Contribution" shall mean any work of authorship, including - the original version of the Work and any modifications or additions - to that Work or Derivative Works thereof, that is intentionally - submitted to Licensor for inclusion in the Work by the copyright owner - or by an individual or Legal Entity authorized to submit on behalf of - the copyright owner. For the purposes of this definition, "submitted" - means any form of electronic, verbal, or written communication sent - to the Licensor or its representatives, including but not limited to - communication on electronic mailing lists, source code control systems, - and issue tracking systems that are managed by, or on behalf of, the - Licensor for the purpose of discussing and improving the Work, but - excluding communication that is conspicuously marked or otherwise - designated in writing by the copyright owner as "Not a Contribution." - - "Contributor" shall mean Licensor and any individual or Legal Entity - on behalf of whom a Contribution has been received by Licensor and - subsequently incorporated within the Work. - - 2. Grant of Copyright License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - copyright license to reproduce, prepare Derivative Works of, - publicly display, publicly perform, sublicense, and distribute the - Work and such Derivative Works in Source or Object form. - - 3. Grant of Patent License. Subject to the terms and conditions of - this License, each Contributor hereby grants to You a perpetual, - worldwide, non-exclusive, no-charge, royalty-free, irrevocable - (except as stated in this section) patent license to make, have made, - use, offer to sell, sell, import, and otherwise transfer the Work, - where such license applies only to those patent claims licensable - by such Contributor that are necessarily infringed by their - Contribution(s) alone or by combination of their Contribution(s) - with the Work to which such Contribution(s) was submitted. If You - institute patent litigation against any entity (including a - cross-claim or counterclaim in a lawsuit) alleging that the Work - or a Contribution incorporated within the Work constitutes direct - or contributory patent infringement, then any patent licenses - granted to You under this License for that Work shall terminate - as of the date such litigation is filed. - - 4. Redistribution. You may reproduce and distribute copies of the - Work or Derivative Works thereof in any medium, with or without - modifications, and in Source or Object form, provided that You - meet the following conditions: - - (a) You must give any other recipients of the Work or - Derivative Works a copy of this License; and - - (b) You must cause any modified files to carry prominent notices - stating that You changed the files; and - - (c) You must retain, in the Source form of any Derivative Works - that You distribute, all copyright, patent, trademark, and - attribution notices from the Source form of the Work, - excluding those notices that do not pertain to any part of - the Derivative Works; and - - (d) If the Work includes a "NOTICE" text file as part of its - distribution, then any Derivative Works that You distribute must - include a readable copy of the attribution notices contained - within such NOTICE file, excluding those notices that do not - pertain to any part of the Derivative Works, in at least one - of the following places: within a NOTICE text file distributed - as part of the Derivative Works; within the Source form or - documentation, if provided along with the Derivative Works; or, - within a display generated by the Derivative Works, if and - wherever such third-party notices normally appear. The contents - of the NOTICE file are for informational purposes only and - do not modify the License. You may add Your own attribution - notices within Derivative Works that You distribute, alongside - or as an addendum to the NOTICE text from the Work, provided - that such additional attribution notices cannot be construed - as modifying the License. - - You may add Your own copyright statement to Your modifications and - may provide additional or different license terms and conditions - for use, reproduction, or distribution of Your modifications, or - for any such Derivative Works as a whole, provided Your use, - reproduction, and distribution of the Work otherwise complies with - the conditions stated in this License. - - 5. Submission of Contributions. Unless You explicitly state otherwise, - any Contribution intentionally submitted for inclusion in the Work - by You to the Licensor shall be under the terms and conditions of - this License, without any additional terms or conditions. - Notwithstanding the above, nothing herein shall supersede or modify - the terms of any separate license agreement you may have executed - with Licensor regarding such Contributions. - - 6. Trademarks. This License does not grant permission to use the trade - names, trademarks, service marks, or product names of the Licensor, - except as required for reasonable and customary use in describing the - origin of the Work and reproducing the content of the NOTICE file. - - 7. Disclaimer of Warranty. Unless required by applicable law or - agreed to in writing, Licensor provides the Work (and each - Contributor provides its Contributions) on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or - implied, including, without limitation, any warranties or conditions - of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A - PARTICULAR PURPOSE. You are solely responsible for determining the - appropriateness of using or redistributing the Work and assume any - risks associated with Your exercise of permissions under this License. - - 8. Limitation of Liability. In no event and under no legal theory, - whether in tort (including negligence), contract, or otherwise, - unless required by applicable law (such as deliberate and grossly - negligent acts) or agreed to in writing, shall any Contributor be - liable to You for damages, including any direct, indirect, special, - incidental, or consequential damages of any character arising as a - result of this License or out of the use or inability to use the - Work (including but not limited to damages for loss of goodwill, - work stoppage, computer failure or malfunction, or any and all - other commercial damages or losses), even if such Contributor - has been advised of the possibility of such damages. - - 9. Accepting Warranty or Additional Liability. While redistributing - the Work or Derivative Works thereof, You may choose to offer, - and charge a fee for, acceptance of support, warranty, indemnity, - or other liability obligations and/or rights consistent with this - License. However, in accepting such obligations, You may act only - on Your own behalf and on Your sole responsibility, not on behalf - of any other Contributor, and only if You agree to indemnify, - defend, and hold each Contributor harmless for any liability - incurred by, or claims asserted against, such Contributor by reason - of your accepting any such warranty or additional liability. - - END OF TERMS AND CONDITIONS - - APPENDIX: How to apply the Apache License to your work. - - To apply the Apache License to your work, attach the following - boilerplate notice, with the fields enclosed by brackets "[]" - replaced with your own identifying information. (Don't include - the brackets!) The text should be enclosed in the appropriate - comment syntax for the file format. We also recommend that a - file or class name and description of purpose be included on the - same "printed page" as the copyright notice for easier - identification within third-party archives. - - Copyright [yyyy] [name of copyright owner] - - 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. \ No newline at end of file diff --git a/contracts/rlp/README.md b/contracts/rlp/README.md deleted file mode 100644 index f1fe162..0000000 --- a/contracts/rlp/README.md +++ /dev/null @@ -1,10 +0,0 @@ -# rlp - -## Source - -The contracts in this directory are derived from -[https://github.com/hamdiallam/Solidity-RLP](https://github.com/hamdiallam/Solidity-RLP). - -Since we only need a small subset of the code from the source, -the necessary contracts are included here directly instead of via -Git submodules. diff --git a/contracts/rlp/RLPReader.sol b/contracts/rlp/RLPReader.sol deleted file mode 100644 index 6606e0a..0000000 --- a/contracts/rlp/RLPReader.sol +++ /dev/null @@ -1,354 +0,0 @@ -// SPDX-License-Identifier: Apache-2.0 - -/* - * @author Hamdi Allam hamdi.allam97@gmail.com - * Please reach out with any questions or concerns - */ -pragma solidity >=0.5.10 <0.9.0; - -library RLPReader { - uint8 constant STRING_SHORT_START = 0x80; - uint8 constant STRING_LONG_START = 0xb8; - uint8 constant LIST_SHORT_START = 0xc0; - uint8 constant LIST_LONG_START = 0xf8; - uint8 constant WORD_SIZE = 32; - - struct RLPItem { - uint256 len; - uint256 memPtr; - } - - struct Iterator { - RLPItem item; // Item that's being iterated over. - uint256 nextPtr; // Position of the next item in the list. - } - - /* - * @dev Returns the next element in the iteration. Reverts if it has not next element. - * @param self The iterator. - * @return The next element in the iteration. - */ - function next(Iterator memory self) internal pure returns (RLPItem memory) { - require(hasNext(self)); - - uint256 ptr = self.nextPtr; - uint256 itemLength = _itemLength(ptr); - self.nextPtr = ptr + itemLength; - - return RLPItem(itemLength, ptr); - } - - /* - * @dev Returns true if the iteration has more elements. - * @param self The iterator. - * @return true if the iteration has more elements. - */ - function hasNext(Iterator memory self) internal pure returns (bool) { - RLPItem memory item = self.item; - return self.nextPtr < item.memPtr + item.len; - } - - /* - * @param item RLP encoded bytes - */ - function toRlpItem(bytes memory item) internal pure returns (RLPItem memory) { - uint256 memPtr; - assembly { - memPtr := add(item, 0x20) - } - - return RLPItem(item.length, memPtr); - } - - /* - * @dev Create an iterator. Reverts if item is not a list. - * @param self The RLP item. - * @return An 'Iterator' over the item. - */ - function iterator(RLPItem memory self) internal pure returns (Iterator memory) { - require(isList(self)); - - uint256 ptr = self.memPtr + _payloadOffset(self.memPtr); - return Iterator(self, ptr); - } - - /* - * @param the RLP item. - */ - function rlpLen(RLPItem memory item) internal pure returns (uint256) { - return item.len; - } - - /* - * @param the RLP item. - * @return (memPtr, len) pair: location of the item's payload in memory. - */ - function payloadLocation(RLPItem memory item) internal pure returns (uint256, uint256) { - uint256 offset = _payloadOffset(item.memPtr); - uint256 memPtr = item.memPtr + offset; - uint256 len = item.len - offset; // data length - return (memPtr, len); - } - - /* - * @param the RLP item. - */ - function payloadLen(RLPItem memory item) internal pure returns (uint256) { - (, uint256 len) = payloadLocation(item); - return len; - } - - /* - * @param the RLP item containing the encoded list. - */ - function toList(RLPItem memory item) internal pure returns (RLPItem[] memory) { - require(isList(item)); - - uint256 items = numItems(item); - RLPItem[] memory result = new RLPItem[](items); - - uint256 memPtr = item.memPtr + _payloadOffset(item.memPtr); - uint256 dataLen; - for (uint256 i = 0; i < items; i++) { - dataLen = _itemLength(memPtr); - result[i] = RLPItem(dataLen, memPtr); - memPtr = memPtr + dataLen; - } - - return result; - } - - // @return indicator whether encoded payload is a list. negate this function call for isData. - function isList(RLPItem memory item) internal pure returns (bool) { - if (item.len == 0) return false; - - uint8 byte0; - uint256 memPtr = item.memPtr; - assembly { - byte0 := byte(0, mload(memPtr)) - } - - if (byte0 < LIST_SHORT_START) return false; - return true; - } - - /* - * @dev A cheaper version of keccak256(toRlpBytes(item)) that avoids copying memory. - * @return keccak256 hash of RLP encoded bytes. - */ - function rlpBytesKeccak256(RLPItem memory item) internal pure returns (bytes32) { - uint256 ptr = item.memPtr; - uint256 len = item.len; - bytes32 result; - assembly { - result := keccak256(ptr, len) - } - return result; - } - - /* - * @dev A cheaper version of keccak256(toBytes(item)) that avoids copying memory. - * @return keccak256 hash of the item payload. - */ - function payloadKeccak256(RLPItem memory item) internal pure returns (bytes32) { - (uint256 memPtr, uint256 len) = payloadLocation(item); - bytes32 result; - assembly { - result := keccak256(memPtr, len) - } - return result; - } - - /** RLPItem conversions into data types **/ - - // @returns raw rlp encoding in bytes - function toRlpBytes(RLPItem memory item) internal pure returns (bytes memory) { - bytes memory result = new bytes(item.len); - if (result.length == 0) return result; - - uint256 ptr; - assembly { - ptr := add(0x20, result) - } - - copy(item.memPtr, ptr, item.len); - return result; - } - - // any non-zero byte except "0x80" is considered true - function toBoolean(RLPItem memory item) internal pure returns (bool) { - require(item.len == 1); - uint256 result; - uint256 memPtr = item.memPtr; - assembly { - result := byte(0, mload(memPtr)) - } - - // SEE Github Issue #5. - // Summary: Most commonly used RLP libraries (i.e Geth) will encode - // "0" as "0x80" instead of as "0". We handle this edge case explicitly - // here. - if (result == 0 || result == STRING_SHORT_START) { - return false; - } else { - return true; - } - } - - function toAddress(RLPItem memory item) internal pure returns (address) { - // 1 byte for the length prefix - require(item.len == 21); - - return address(uint160(toUint(item))); - } - - function toUint(RLPItem memory item) internal pure returns (uint256) { - require(item.len > 0 && item.len <= 33); - - (uint256 memPtr, uint256 len) = payloadLocation(item); - - uint256 result; - assembly { - result := mload(memPtr) - - // shift to the correct location if neccesary - if lt(len, 32) { - result := div(result, exp(256, sub(32, len))) - } - } - - return result; - } - - // enforces 32 byte length - function toUintStrict(RLPItem memory item) internal pure returns (uint256) { - // one byte prefix - require(item.len == 33); - - uint256 result; - uint256 memPtr = item.memPtr + 1; - assembly { - result := mload(memPtr) - } - - return result; - } - - function toBytes(RLPItem memory item) internal pure returns (bytes memory) { - require(item.len > 0); - - (uint256 memPtr, uint256 len) = payloadLocation(item); - bytes memory result = new bytes(len); - - uint256 destPtr; - assembly { - destPtr := add(0x20, result) - } - - copy(memPtr, destPtr, len); - return result; - } - - /* - * Private Helpers - */ - - // @return number of payload items inside an encoded list. - function numItems(RLPItem memory item) private pure returns (uint256) { - if (item.len == 0) return 0; - - uint256 count = 0; - uint256 currPtr = item.memPtr + _payloadOffset(item.memPtr); - uint256 endPtr = item.memPtr + item.len; - while (currPtr < endPtr) { - currPtr = currPtr + _itemLength(currPtr); // skip over an item - count++; - } - - return count; - } - - // @return entire rlp item byte length - function _itemLength(uint256 memPtr) private pure returns (uint256) { - uint256 itemLen; - uint256 byte0; - assembly { - byte0 := byte(0, mload(memPtr)) - } - - if (byte0 < STRING_SHORT_START) { - itemLen = 1; - } else if (byte0 < STRING_LONG_START) { - itemLen = byte0 - STRING_SHORT_START + 1; - } else if (byte0 < LIST_SHORT_START) { - assembly { - let byteLen := sub(byte0, 0xb7) // # of bytes the actual length is - memPtr := add(memPtr, 1) // skip over the first byte - - /* 32 byte word size */ - let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to get the len - itemLen := add(dataLen, add(byteLen, 1)) - } - } else if (byte0 < LIST_LONG_START) { - itemLen = byte0 - LIST_SHORT_START + 1; - } else { - assembly { - let byteLen := sub(byte0, 0xf7) - memPtr := add(memPtr, 1) - - let dataLen := div(mload(memPtr), exp(256, sub(32, byteLen))) // right shifting to the correct length - itemLen := add(dataLen, add(byteLen, 1)) - } - } - - return itemLen; - } - - // @return number of bytes until the data - function _payloadOffset(uint256 memPtr) private pure returns (uint256) { - uint256 byte0; - assembly { - byte0 := byte(0, mload(memPtr)) - } - - if (byte0 < STRING_SHORT_START) { - return 0; - } else if (byte0 < STRING_LONG_START || (byte0 >= LIST_SHORT_START && byte0 < LIST_LONG_START)) { - return 1; - } else if (byte0 < LIST_SHORT_START) { - // being explicit - return byte0 - (STRING_LONG_START - 1) + 1; - } else { - return byte0 - (LIST_LONG_START - 1) + 1; - } - } - - /* - * @param src Pointer to source - * @param dest Pointer to destination - * @param len Amount of memory to copy from the source - */ - function copy(uint256 src, uint256 dest, uint256 len) private pure { - if (len == 0) return; - - // copy as many word sizes as possible - for (; len >= WORD_SIZE; len -= WORD_SIZE) { - assembly { - mstore(dest, mload(src)) - } - - src += WORD_SIZE; - dest += WORD_SIZE; - } - - if (len > 0) { - // left over bytes. Mask is used to remove unwanted bytes from the word - uint256 mask = 256**(WORD_SIZE - len) - 1; - assembly { - let srcpart := and(mload(src), not(mask)) // zero out src - let destpart := and(mload(dest), mask) // retrieve the bytes - mstore(dest, or(destpart, srcpart)) - } - } - } -} diff --git a/libs/Solidity-RLP b/libs/Solidity-RLP new file mode 160000 index 0000000..871a9ad --- /dev/null +++ b/libs/Solidity-RLP @@ -0,0 +1 @@ +Subproject commit 871a9ad330e2e00c870cb01a09c410528f772e98 diff --git a/tests/RLP/RLP_test.sol b/tests/RLP/RLP_test.sol index 9505a4b..043c903 100644 --- a/tests/RLP/RLP_test.sol +++ b/tests/RLP/RLP_test.sol @@ -10,7 +10,7 @@ import "remix_tests.sol"; import "remix_accounts.sol"; -import {RLPReader} from "../../contracts/rlp/RLPReader.sol"; +import {RLPReader} from "../../libs/Solidity-RLP/contracts/RLPReader.sol"; contract RLPTest {