├── .gitignore ├── .travis.yml ├── Cargo.toml ├── LICENSE ├── README.md ├── bigint ├── Cargo.toml └── src │ ├── bytes.rs │ ├── gas.rs │ ├── hash │ ├── mod.rs │ └── rlp.rs │ ├── lib.rs │ ├── m256.rs │ ├── mi256.rs │ └── uint │ ├── mod.rs │ ├── rlp.rs │ └── tests.rs ├── block-core ├── Cargo.toml └── src │ ├── account.rs │ ├── lib.rs │ ├── log.rs │ └── transaction.rs ├── block ├── Cargo.toml ├── res │ └── genesis.json ├── src │ ├── address.rs │ ├── block.rs │ ├── header.rs │ ├── lib.rs │ ├── receipt.rs │ └── transaction.rs └── tests │ └── genesis.rs ├── bloom ├── Cargo.toml └── src │ └── lib.rs ├── hexutil ├── Cargo.toml └── src │ └── lib.rs ├── nightly.nix ├── rlp ├── Cargo.toml ├── LICENSE-APACHE2 ├── LICENSE-MIT ├── README.md ├── benches │ └── rlp.rs ├── license-header ├── src │ ├── common.rs │ ├── compression.rs │ ├── error.rs │ ├── impls.rs │ ├── lib.rs │ ├── rlpin.rs │ ├── stream.rs │ ├── traits.rs │ └── untrusted_rlp.rs └── tests │ └── tests.rs ├── shell.nix └── trie ├── Cargo.toml ├── rocksdb ├── Cargo.toml └── src │ └── lib.rs └── src ├── cache.rs ├── gc.rs ├── lib.rs ├── memory.rs ├── merkle ├── mod.rs ├── nibble.rs └── node.rs ├── mutable.rs └── ops ├── build.rs ├── delete.rs ├── get.rs ├── insert.rs └── mod.rs /.gitignore: -------------------------------------------------------------------------------- 1 | # Generated by Cargo 2 | # will have compiled files and executables 3 | **/target 4 | 5 | # Generated by Nix 6 | **/result 7 | 8 | # Remove Cargo.lock from gitignore if creating an executable, leave it for libraries 9 | # More information here http://doc.crates.io/guide.html#cargotoml-vs-cargolock 10 | Cargo.lock 11 | 12 | # These are backup files generated by rustfmt 13 | **/*.rs.bk 14 | 15 | # IDEA files 16 | .idea/ -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: rust 2 | rust: 3 | - stable 4 | - beta 5 | - nightly 6 | matrix: 7 | allow_failures: 8 | - rust: nightly 9 | script: 10 | - cargo test --release --all 11 | - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then cd rlp && cargo build --no-default-features && cd ..; fi 12 | - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then cd hexutil && cargo build --no-default-features && cd ..; fi 13 | - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then cd bigint && cargo build --no-default-features && cd ..; fi 14 | - if [ "$TRAVIS_RUST_VERSION" == "nightly" ]; then cd block-core && cargo build --no-default-features && cd ..; fi 15 | - cd block && cargo build --no-default-features --features rust-secp256k1 && cd .. 16 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "./rlp", 4 | "./bigint", 5 | "./hexutil", 6 | "./block", 7 | "./block-core", 8 | "./trie", 9 | "./trie/rocksdb", 10 | "./bloom", 11 | ] 12 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "{}" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright {yyyy} {name of copyright owner} 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Etcommon 2 | 3 | [![Build Status](https://travis-ci.org/ETCDEVTeam/etcommon-rs.svg?branch=master)](https://travis-ci.org/ETCDEVTeam/etcommon-rs) 4 | 5 | Apache-2 licensed common Ethereum structs shared by crates. Work-in-progress right now. 6 | 7 | ## List of Crates 8 | 9 | Below are all crates provided by the etcommon project. 10 | 11 | | Name | Description | Crates.io | Documentation | 12 | |------|:-----------:|:---------:|:-------------:| 13 | | etcommon-rlp | Recursive-length prefix encoding, decoding, and compression | [![crates.io](https://img.shields.io/crates/v/etcommon-rlp.svg)](https://crates.io/crates/etcommon-rlp) | [![Documentation](https://docs.rs/etcommon-rlp/badge.svg)](https://docs.rs/etcommon-rlp) | 14 | | etcommon-bigint | Big integer and hash implementation | [![crates.io](https://img.shields.io/crates/v/etcommon-bigint.svg)](https://crates.io/crates/etcommon-bigint) | [![Documentation](https://docs.rs/etcommon-bigint/badge.svg)](https://docs.rs/etcommon-bigint) | 15 | | etcommon-hexutil | Small hex decoding helpers | [![crates.io](https://img.shields.io/crates/v/etcommon-hexutil.svg)](https://crates.io/crates/etcommon-hexutil) | [![Documentation](https://docs.rs/etcommon-hexutil/badge.svg)](https://docs.rs/etcommon-hexutil) | 16 | | etcommon-bloom | Log bloom for Ethereum | [![crates.io](https://img.shields.io/crates/v/etcommon-bloom.svg)](https://crates.io/crates/etcommon-bloom) | [![Documentation](https://docs.rs/etcommon-bloom/badge.svg)](https://docs.rs/etcommon-bloom) | 17 | | etcommon-trie | Merkle Trie specialized for Ethereum | [![crates.io](https://img.shields.io/crates/v/etcommon-trie.svg)](https://crates.io/crates/etcommon-trie) | [![Documentation](https://docs.rs/etcommon-trie/badge.svg)](https://docs.rs/etcommon-trie) | 18 | | etcommon-block | Block, transaction and account structs for Ethereum | [![crates.io](https://img.shields.io/crates/v/etcommon-block.svg)](https://crates.io/crates/etcommon-block) | [![Documentation](https://docs.rs/etcommon-block/badge.svg)](https://docs.rs/etcommon-block) | 19 | | etcommon-block-core | Core block, transaction and account structs for Ethereum | [![crates.io](https://img.shields.io/crates/v/etcommon-block-core.svg)](https://crates.io/crates/etcommon-block-core) | [![Documentation](https://docs.rs/etcommon-block-core/badge.svg)](https://docs.rs/etcommon-block-core) | 20 | 21 | ## Rolling Release 22 | 23 | As `etcommon` will be depended on many other projects like SputnikVM and EASM, rolling release is necessary to keep up with the development speed. 24 | 25 | Note that rolling release will only happen for sub-crates like `etcommon-bigint`, `etcommon-rlp`, `etcommon-util`, etc. The top-level crate `etcommon` will follow the normal release process. 26 | -------------------------------------------------------------------------------- /bigint/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "etcommon-bigint" 3 | version = "0.2.10" 4 | license = "Apache-2.0" 5 | authors = ["Wei Tang "] 6 | description = "Big integer (256-bit and 512-bit) implementation for SputnikVM and other Ethereum Classic clients." 7 | repository = "https://github.com/ethereumproject/etcommon-rs" 8 | keywords = ["no_std"] 9 | 10 | [lib] 11 | name = "bigint" 12 | 13 | [dependencies] 14 | heapsize = { version = "0.4", optional = true } 15 | byteorder = { version = "1.0", default-features = false } 16 | rand = { version = "0.3.12", optional = true } 17 | libc = { version = "0.2", optional = true } 18 | etcommon-rlp = { version = "0.2", path = "../rlp", default-features = false, optional = true } 19 | etcommon-hexutil = { version = "0.2", path = "../hexutil", default-features = false, optional = true } 20 | 21 | [features] 22 | default = ["std", "rlp", "string"] 23 | heapsizeof = ["heapsize"] 24 | x64asm_arithmetic = [] 25 | rust_arithmetic = [] 26 | rlp = ["etcommon-rlp"] 27 | string = ["etcommon-hexutil"] 28 | std = ["byteorder/std", "rand", "libc", "etcommon-rlp/std", "etcommon-hexutil/std"] 29 | -------------------------------------------------------------------------------- /bigint/src/bytes.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "rlp")] 2 | use rlp::{Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp}; 3 | 4 | /// Maximum 256-bit byte-array that does not require heap allocation. 5 | #[derive(Eq, PartialEq, Debug, Copy, Clone, Hash)] 6 | pub struct B256(usize, [u8; 32]); 7 | 8 | impl B256 { 9 | pub fn new(value: &[u8]) -> Self { 10 | assert!(value.len() <= 32); 11 | let mut ret = [0u8; 32]; 12 | for i in 0..value.len() { 13 | ret[i] = value[i]; 14 | } 15 | B256(value.len(), ret) 16 | } 17 | } 18 | 19 | impl Default for B256 { 20 | fn default() -> B256 { 21 | B256(0, [0u8; 32]) 22 | } 23 | } 24 | 25 | #[cfg(feature = "rlp")] 26 | impl Encodable for B256 { 27 | fn rlp_append(&self, s: &mut RlpStream) { 28 | s.encoder().encode_value(&self.1[0..self.0]) 29 | } 30 | } 31 | 32 | #[cfg(feature = "rlp")] 33 | impl Decodable for B256 { 34 | fn decode(rlp: &UntrustedRlp) -> Result { 35 | rlp.decoder().decode_value(|bytes| { 36 | if bytes.len() > 32 { 37 | Err(DecoderError::Custom("More than 32 bytes")) 38 | } else { 39 | let mut ret = B256(0, [0u8; 32]); 40 | ret.0 = bytes.len(); 41 | for i in 0..bytes.len() { 42 | ret.1[i] = bytes[i]; 43 | } 44 | Ok(ret) 45 | } 46 | }) 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /bigint/src/gas.rs: -------------------------------------------------------------------------------- 1 | //! Gas capped at the maximum number of U256. It is practically 2 | //! impossible to obtain this number during a block formation. 3 | 4 | use super::{M256, U256}; 5 | #[cfg(feature = "string")] 6 | use hexutil::ParseHexError; 7 | #[cfg(feature = "rlp")] 8 | use rlp::{Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp}; 9 | 10 | #[cfg(feature = "std")] use std::ops::{Add, Sub, Mul, Div, Rem}; 11 | #[cfg(feature = "std")] use std::cmp::Ordering; 12 | #[cfg(feature = "std")] use std::str::FromStr; 13 | #[cfg(feature = "std")] use std::fmt; 14 | 15 | #[cfg(not(feature = "std"))] use core::ops::{Add, Sub, Mul, Div, Rem}; 16 | #[cfg(not(feature = "std"))] use core::cmp::Ordering; 17 | #[cfg(not(feature = "std"))] use core::str::FromStr; 18 | #[cfg(not(feature = "std"))] use core::fmt; 19 | 20 | #[derive(Eq, PartialEq, Debug, Copy, Clone, Hash)] 21 | pub struct Gas(U256); 22 | 23 | impl Gas { 24 | /// Zero value of Gas, 25 | pub fn zero() -> Gas { Gas(U256::zero()) } 26 | /// One value of Gas, 27 | pub fn one() -> Gas { Gas(U256::one()) } 28 | /// Maximum value of Gas, 29 | pub fn max_value() -> Gas { Gas(U256::max_value()) } 30 | /// Minimum value of Gas, 31 | pub fn min_value() -> Gas { Gas(U256::min_value()) } 32 | /// Bits required to represent this value. 33 | pub fn bits(self) -> usize { self.0.bits() } 34 | /// Equals `floor(log2(*))`. This is always an integer. 35 | pub fn log2floor(self) -> usize { self.0.log2floor() } 36 | /// Conversion to u32 with overflow checking 37 | /// 38 | /// # Panics 39 | /// 40 | /// Panics if the number is larger than 2^32. 41 | pub fn as_u32(&self) -> u32 { 42 | self.0.as_u32() 43 | } 44 | /// Conversion to u64 with overflow checking 45 | /// 46 | /// # Panics 47 | /// 48 | /// Panics if the number is larger than 2^64. 49 | pub fn as_u64(&self) -> u64 { 50 | self.0.as_u64() 51 | } 52 | /// Conversion to usize with overflow checking 53 | /// 54 | /// # Panics 55 | /// 56 | /// Panics if the number is larger than usize::max_value(). 57 | pub fn as_usize(&self) -> usize { 58 | self.0.as_usize() 59 | } 60 | } 61 | 62 | impl Default for Gas { fn default() -> Gas { Gas::zero() } } 63 | 64 | #[cfg(feature = "string")] 65 | impl FromStr for Gas { 66 | type Err = ParseHexError; 67 | 68 | fn from_str(s: &str) -> Result { 69 | U256::from_str(s).map(|s| Gas(s)) 70 | } 71 | } 72 | 73 | #[cfg(feature = "rlp")] 74 | impl Encodable for Gas { 75 | fn rlp_append(&self, s: &mut RlpStream) { 76 | self.0.rlp_append(s); 77 | } 78 | } 79 | 80 | #[cfg(feature = "rlp")] 81 | impl Decodable for Gas { 82 | fn decode(rlp: &UntrustedRlp) -> Result { 83 | Ok(Gas(U256::decode(rlp)?)) 84 | } 85 | } 86 | 87 | impl From for Gas { fn from(val: u64) -> Gas { Gas(U256::from(val)) } } 88 | impl Into for Gas { fn into(self) -> u64 { self.0.into() } } 89 | impl From for Gas { fn from(val: usize) -> Gas { Gas(U256::from(val)) } } 90 | impl<'a> From<&'a [u8]> for Gas { fn from(val: &'a [u8]) -> Gas { Gas(U256::from(val)) } } 91 | impl From for Gas { 92 | fn from(val: bool) -> Gas { 93 | if val { 94 | Gas::one() 95 | } else { 96 | Gas::zero() 97 | } 98 | } 99 | } 100 | impl From for Gas { fn from(val: U256) -> Gas { Gas(val) } } 101 | impl Into for Gas { fn into(self) -> U256 { self.0 } } 102 | impl From for Gas { 103 | fn from(val: M256) -> Gas { 104 | Gas(val.into()) 105 | } 106 | } 107 | impl Into for Gas { 108 | fn into(self) -> M256 { 109 | self.0.into() 110 | } 111 | } 112 | 113 | impl Ord for Gas { fn cmp(&self, other: &Gas) -> Ordering { self.0.cmp(&other.0) } } 114 | impl PartialOrd for Gas { 115 | fn partial_cmp(&self, other: &Gas) -> Option { 116 | self.0.partial_cmp(&other.0) 117 | } 118 | } 119 | 120 | impl Add for Gas { 121 | type Output = Gas; 122 | 123 | fn add(self, other: Gas) -> Gas { 124 | Gas(self.0.saturating_add(other.0)) 125 | } 126 | } 127 | 128 | impl Sub for Gas { 129 | type Output = Gas; 130 | 131 | fn sub(self, other: Gas) -> Gas { 132 | Gas(self.0 - other.0) 133 | } 134 | } 135 | 136 | impl Mul for Gas { 137 | type Output = Gas; 138 | 139 | fn mul(self, other: Gas) -> Gas { 140 | Gas(self.0.saturating_mul(other.0)) 141 | } 142 | } 143 | 144 | impl Div for Gas { 145 | type Output = Gas; 146 | 147 | fn div(self, other: Gas) -> Gas { 148 | Gas(self.0 / other.0) 149 | } 150 | } 151 | 152 | impl Rem for Gas { 153 | type Output = Gas; 154 | 155 | fn rem(self, other: Gas) -> Gas { 156 | Gas(self.0 % other.0) 157 | } 158 | } 159 | 160 | impl fmt::LowerHex for Gas { 161 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 162 | write!(f, "{:x}", self.0) 163 | } 164 | } 165 | 166 | impl fmt::UpperHex for Gas { 167 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 168 | write!(f, "{:X}", self.0) 169 | } 170 | } 171 | -------------------------------------------------------------------------------- /bigint/src/hash/rlp.rs: -------------------------------------------------------------------------------- 1 | use super::{H64, H128, H160, H256, H512, H520, H2048}; 2 | #[cfg(feature = "std")] use std::cmp; 3 | #[cfg(not(feature = "std"))] use core::cmp; 4 | use rlp::{RlpStream, Encodable, Decodable, DecoderError, UntrustedRlp}; 5 | 6 | macro_rules! impl_encodable_for_hash { 7 | ($name: ident) => { 8 | impl Encodable for $name { 9 | fn rlp_append(&self, s: &mut RlpStream) { 10 | s.encoder().encode_value(self); 11 | } 12 | } 13 | } 14 | } 15 | 16 | macro_rules! impl_decodable_for_hash { 17 | ($name: ident, $size: expr) => { 18 | impl Decodable for $name { 19 | fn decode(rlp: &UntrustedRlp) -> Result { 20 | rlp.decoder().decode_value(|bytes| match bytes.len().cmp(&$size) { 21 | cmp::Ordering::Less => Err(DecoderError::RlpIsTooShort), 22 | cmp::Ordering::Greater => Err(DecoderError::RlpIsTooBig), 23 | cmp::Ordering::Equal => { 24 | let mut t = [0u8; $size]; 25 | t.copy_from_slice(bytes); 26 | Ok($name(t)) 27 | } 28 | }) 29 | } 30 | } 31 | } 32 | } 33 | 34 | impl_encodable_for_hash!(H64); 35 | impl_encodable_for_hash!(H128); 36 | impl_encodable_for_hash!(H160); 37 | impl_encodable_for_hash!(H256); 38 | impl_encodable_for_hash!(H512); 39 | impl_encodable_for_hash!(H520); 40 | impl_encodable_for_hash!(H2048); 41 | 42 | impl_decodable_for_hash!(H64, 8); 43 | impl_decodable_for_hash!(H128, 16); 44 | impl_decodable_for_hash!(H160, 20); 45 | impl_decodable_for_hash!(H256, 32); 46 | impl_decodable_for_hash!(H512, 64); 47 | impl_decodable_for_hash!(H520, 65); 48 | impl_decodable_for_hash!(H2048, 256); 49 | -------------------------------------------------------------------------------- /bigint/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![deny(unused_import_braces, 2 | unused_comparisons, unused_must_use, 3 | unused_variables, non_shorthand_field_patterns, 4 | unreachable_code)] 5 | 6 | #![cfg_attr(asm_available, feature(asm))] 7 | 8 | #![cfg_attr(not(feature = "std"), no_std)] 9 | #![cfg_attr(all(not(feature = "std"), feature = "string"), feature(alloc))] 10 | 11 | #[cfg(all(not(feature = "std"), feature = "string"))] 12 | #[macro_use] 13 | extern crate alloc; 14 | 15 | #[cfg(feature = "rlp")] 16 | extern crate rlp; 17 | #[cfg(feature = "string")] 18 | extern crate hexutil; 19 | #[cfg(feature = "std")] 20 | extern crate rand; 21 | #[cfg(feature = "std")] 22 | extern crate libc; 23 | extern crate byteorder; 24 | 25 | #[cfg(feature="heapsizeof")] 26 | #[macro_use] extern crate heapsize; 27 | 28 | mod m256; 29 | mod mi256; 30 | mod uint; 31 | mod hash; 32 | mod bytes; 33 | mod gas; 34 | 35 | pub type Address = H160; 36 | 37 | pub use self::bytes::B256; 38 | pub use self::gas::Gas; 39 | pub use self::uint::{U128, U256, U512}; 40 | pub use self::m256::M256; 41 | pub use self::mi256::MI256; 42 | pub use self::hash::{H32, H64, H128, H160, H256, H264, H512, H520, H1024, H2048}; 43 | 44 | #[derive(Eq, PartialEq, Debug, Copy, Clone, Hash)] 45 | /// Sign of an integer. 46 | pub enum Sign { 47 | Minus, 48 | NoSign, 49 | Plus, 50 | } 51 | -------------------------------------------------------------------------------- /bigint/src/m256.rs: -------------------------------------------------------------------------------- 1 | //! Unsigned modulo 256-bit integer 2 | 3 | #[cfg(feature = "std")] use std::convert::{From, Into}; 4 | #[cfg(feature = "std")] use std::str::FromStr; 5 | #[cfg(feature = "std")] use std::ops::{Add, Sub, Not, Mul, Div, Shr, Shl, BitAnd, BitOr, BitXor, Rem}; 6 | #[cfg(feature = "std")] use std::cmp::Ordering; 7 | #[cfg(feature = "std")] use std::fmt; 8 | 9 | #[cfg(not(feature = "std"))] use core::convert::{From, Into}; 10 | #[cfg(not(feature = "std"))] use core::str::FromStr; 11 | #[cfg(not(feature = "std"))] use core::ops::{Add, Sub, Not, Mul, Div, Shr, Shl, BitAnd, BitOr, BitXor, Rem}; 12 | #[cfg(not(feature = "std"))] use core::cmp::Ordering; 13 | #[cfg(not(feature = "std"))] use core::fmt; 14 | 15 | #[cfg(feature = "string")] 16 | use hexutil::ParseHexError; 17 | #[cfg(feature = "rlp")] 18 | use rlp::{Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp}; 19 | use super::{U512, U256, H256, H160}; 20 | 21 | #[derive(Eq, PartialEq, Debug, Copy, Clone, Hash)] 22 | /// Represent an unsigned modulo 256-bit integer 23 | pub struct M256(pub U256); 24 | 25 | impl M256 { 26 | /// Zero value of M256, 27 | pub fn zero() -> M256 { M256(U256::zero()) } 28 | /// One value of M256, 29 | pub fn one() -> M256 { M256(U256::one()) } 30 | /// Maximum value of M256, 31 | pub fn max_value() -> M256 { M256(U256::max_value()) } 32 | /// Minimum value of M256, 33 | pub fn min_value() -> M256 { M256(U256::min_value()) } 34 | /// Bits required to represent this value. 35 | pub fn bits(self) -> usize { self.0.bits() } 36 | /// Equals `floor(log2(*))`. This is always an integer. 37 | pub fn log2floor(self) -> usize { self.0.log2floor() } 38 | /// Conversion to u32 with overflow checking 39 | /// 40 | /// # Panics 41 | /// 42 | /// Panics if the number is larger than 2^32. 43 | pub fn as_u32(&self) -> u32 { 44 | self.0.as_u32() 45 | } 46 | /// Conversion to u64 with overflow checking 47 | /// 48 | /// # Panics 49 | /// 50 | /// Panics if the number is larger than 2^64. 51 | pub fn as_u64(&self) -> u64 { 52 | self.0.as_u64() 53 | } 54 | /// Conversion to usize with overflow checking 55 | /// 56 | /// # Panics 57 | /// 58 | /// Panics if the number is larger than usize::max_value(). 59 | pub fn as_usize(&self) -> usize { 60 | self.0.as_usize() 61 | } 62 | /// Return specific byte. 63 | /// 64 | /// # Panics 65 | /// 66 | /// Panics if `index` exceeds the byte width of the number. 67 | #[inline] 68 | pub fn byte(&self, index: usize) -> u8 { 69 | self.0.byte(index) 70 | } 71 | /// Return specific byte in big-endian format. 72 | /// 73 | /// # Panics 74 | /// 75 | /// Panics if `index` exceeds the byte width of the number. 76 | #[inline] 77 | pub fn index(&self, index: usize) -> u8 { 78 | self.0.index(index) 79 | } 80 | } 81 | 82 | impl Default for M256 { fn default() -> M256 { M256::zero() } } 83 | 84 | #[cfg(feature = "string")] 85 | impl FromStr for M256 { 86 | type Err = ParseHexError; 87 | 88 | fn from_str(s: &str) -> Result { 89 | U256::from_str(s).map(|s| M256(s)) 90 | } 91 | } 92 | 93 | #[cfg(feature = "rlp")] 94 | impl Encodable for M256 { 95 | fn rlp_append(&self, s: &mut RlpStream) { 96 | self.0.rlp_append(s); 97 | } 98 | } 99 | 100 | #[cfg(feature = "rlp")] 101 | impl Decodable for M256 { 102 | fn decode(rlp: &UntrustedRlp) -> Result { 103 | Ok(M256(U256::decode(rlp)?)) 104 | } 105 | } 106 | 107 | impl From for M256 { fn from(val: u64) -> M256 { M256(U256::from(val)) } } 108 | impl Into for M256 { fn into(self) -> u64 { self.0.into() } } 109 | impl From for M256 { fn from(val: usize) -> M256 { M256(U256::from(val)) } } 110 | impl<'a> From<&'a [u8]> for M256 { fn from(val: &'a [u8]) -> M256 { M256(U256::from(val)) } } 111 | impl From for M256 { 112 | fn from(val: bool) -> M256 { 113 | if val { 114 | M256::one() 115 | } else { 116 | M256::zero() 117 | } 118 | } 119 | } 120 | impl From for M256 { fn from(val: U256) -> M256 { M256(val) } } 121 | impl Into for M256 { fn into(self) -> U256 { self.0 } } 122 | impl From for M256 { fn from(val: U512) -> M256 { M256(val.into()) } } 123 | impl Into for M256 { fn into(self) -> U512 { self.0.into() } } 124 | impl From for M256 { fn from(val: i32) -> M256 { (val as u64).into() } } 125 | impl From for M256 { 126 | fn from(val: H256) -> M256 { 127 | let inter: U256 = val.into(); 128 | inter.into() 129 | } 130 | } 131 | impl From for H256 { 132 | fn from(val: M256) -> H256 { 133 | let inter: U256 = val.into(); 134 | inter.into() 135 | } 136 | } 137 | impl From for M256 { 138 | fn from(val: H160) -> M256 { 139 | let inter: H256 = val.into(); 140 | inter.into() 141 | } 142 | } 143 | impl From for H160 { 144 | fn from(val: M256) -> H160 { 145 | let inter: H256 = val.into(); 146 | inter.into() 147 | } 148 | } 149 | 150 | impl Ord for M256 { fn cmp(&self, other: &M256) -> Ordering { self.0.cmp(&other.0) } } 151 | impl PartialOrd for M256 { 152 | fn partial_cmp(&self, other: &M256) -> Option { 153 | self.0.partial_cmp(&other.0) 154 | } 155 | } 156 | 157 | impl BitAnd for M256 { 158 | type Output = M256; 159 | 160 | fn bitand(self, other: M256) -> M256 { 161 | M256(self.0.bitand(other.0)) 162 | } 163 | } 164 | 165 | impl BitOr for M256 { 166 | type Output = M256; 167 | 168 | fn bitor(self, other: M256) -> M256 { 169 | M256(self.0.bitor(other.0)) 170 | } 171 | } 172 | 173 | impl BitXor for M256 { 174 | type Output = M256; 175 | 176 | fn bitxor(self, other: M256) -> M256 { 177 | M256(self.0.bitxor(other.0)) 178 | } 179 | } 180 | 181 | impl Shl for M256 { 182 | type Output = M256; 183 | 184 | fn shl(self, shift: usize) -> M256 { 185 | M256(self.0.shl(shift)) 186 | } 187 | } 188 | 189 | impl Shr for M256 { 190 | type Output = M256; 191 | 192 | fn shr(self, shift: usize) -> M256 { 193 | M256(self.0.shr(shift)) 194 | } 195 | } 196 | 197 | impl Add for M256 { 198 | type Output = M256; 199 | 200 | fn add(self, other: M256) -> M256 { 201 | let (o, _) = self.0.overflowing_add(other.0); 202 | M256(o) 203 | } 204 | } 205 | 206 | impl Sub for M256 { 207 | type Output = M256; 208 | 209 | fn sub(self, other: M256) -> M256 { 210 | if self.0 >= other.0 { 211 | M256(self.0 - other.0) 212 | } else { 213 | M256(U256::max_value() - other.0 + self.0 + U256::from(1u64)) 214 | } 215 | } 216 | } 217 | 218 | impl Mul for M256 { 219 | type Output = M256; 220 | 221 | fn mul(self, other: M256) -> M256 { 222 | let (o, _) = self.0.overflowing_mul(other.0); 223 | M256(o) 224 | } 225 | } 226 | 227 | impl Div for M256 { 228 | type Output = M256; 229 | 230 | fn div(self, other: M256) -> M256 { 231 | if other == M256::zero() { 232 | M256::zero() 233 | } else { 234 | M256(self.0.div(other.0)) 235 | } 236 | } 237 | } 238 | 239 | impl Rem for M256 { 240 | type Output = M256; 241 | 242 | fn rem(self, other: M256) -> M256 { 243 | if other == M256::zero() { 244 | M256::zero() 245 | } else { 246 | M256(self.0.rem(other.0)) 247 | } 248 | } 249 | } 250 | 251 | impl Not for M256 { 252 | type Output = M256; 253 | 254 | fn not(self) -> M256 { 255 | M256(self.0.not()) 256 | } 257 | } 258 | 259 | impl fmt::LowerHex for M256 { 260 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 261 | write!(f, "{:x}", self.0) 262 | } 263 | } 264 | 265 | impl fmt::UpperHex for M256 { 266 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 267 | write!(f, "{:X}", self.0) 268 | } 269 | } 270 | 271 | #[cfg(test)] 272 | mod tests { 273 | use super::M256; 274 | use std::str::FromStr; 275 | 276 | #[test] 277 | pub fn sub() { 278 | assert_eq!(M256::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap() - M256::from_str("0000000000000000000000000000000100000000000000000000000000000000").unwrap(), M256::from_str("ffffffffffffffffffffffffffffffff00000000000000000000000000000000").unwrap()); 279 | assert_eq!(M256::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap() - M256::from_str("0000000000000000000000000000000000000000000000000000000000000001").unwrap(), M256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()); 280 | assert_eq!(M256::from_str("0000000000000000000000000000000000000000000000000000000000000000").unwrap() - M256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap(), M256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap()); 281 | } 282 | } 283 | -------------------------------------------------------------------------------- /bigint/src/mi256.rs: -------------------------------------------------------------------------------- 1 | //! Signed modulo 256-bit integer 2 | 3 | #[cfg(feature = "std")] use std::convert::{From, Into}; 4 | #[cfg(feature = "std")] use std::ops::{Div, Rem}; 5 | #[cfg(feature = "std")] use std::cmp::Ordering; 6 | 7 | #[cfg(not(feature = "std"))] use core::convert::{From, Into}; 8 | #[cfg(not(feature = "std"))] use core::ops::{Div, Rem}; 9 | #[cfg(not(feature = "std"))] use core::cmp::Ordering; 10 | 11 | use super::{Sign, M256, U256}; 12 | 13 | const SIGN_BIT_MASK: M256 = M256(U256([0xffffffffffffffff, 0xffffffffffffffff, 14 | 0xffffffffffffffff, 0x7fffffffffffffff])); 15 | 16 | #[derive(Eq, PartialEq, Debug, Copy, Clone, Hash)] 17 | /// Represents a signed module 256-bit integer. 18 | pub struct MI256(pub Sign, pub M256); 19 | 20 | impl MI256 { 21 | /// Zero value of MI256. 22 | pub fn zero() -> MI256 { MI256(Sign::NoSign, M256::zero()) } 23 | /// One value of MI256. 24 | pub fn one() -> MI256 { MI256(Sign::Plus, M256::one()) } 25 | /// Maximum value of MI256. 26 | pub fn max_value() -> MI256 { MI256(Sign::Plus, M256::max_value() & SIGN_BIT_MASK) } 27 | /// Minimum value of MI256. 28 | pub fn min_value() -> MI256 { MI256(Sign::Minus, (M256::max_value() & SIGN_BIT_MASK) + M256::from(1u64)) } 29 | } 30 | 31 | impl Default for MI256 { fn default() -> MI256 { MI256::zero() } } 32 | impl From for MI256 { 33 | fn from(val: M256) -> MI256 { 34 | if val == M256::zero() { 35 | MI256::zero() 36 | } else if val & SIGN_BIT_MASK.into() == val { 37 | MI256(Sign::Plus, val) 38 | } else { 39 | MI256(Sign::Minus, !val + M256::from(1u64)) 40 | } 41 | } 42 | } 43 | impl Into for MI256 { 44 | fn into(self) -> M256 { 45 | let sign = self.0; 46 | if sign == Sign::NoSign { 47 | M256::zero() 48 | } else if sign == Sign::Plus { 49 | self.1 50 | } else { 51 | !self.1 + M256::from(1u64) 52 | } 53 | } 54 | } 55 | 56 | impl Ord for MI256 { 57 | fn cmp(&self, other: &MI256) -> Ordering { 58 | match (self.0, other.0) { 59 | (Sign::NoSign, Sign::NoSign) => Ordering::Equal, 60 | (Sign::NoSign, Sign::Plus) => Ordering::Less, 61 | (Sign::NoSign, Sign::Minus) => Ordering::Greater, 62 | (Sign::Minus, Sign::NoSign) => Ordering::Less, 63 | (Sign::Minus, Sign::Plus) => Ordering::Less, 64 | (Sign::Minus, Sign::Minus) => self.1.cmp(&other.1).reverse(), 65 | (Sign::Plus, Sign::Minus) => Ordering::Greater, 66 | (Sign::Plus, Sign::NoSign) => Ordering::Greater, 67 | (Sign::Plus, Sign::Plus) => self.1.cmp(&other.1), 68 | } 69 | } 70 | } 71 | 72 | impl PartialOrd for MI256 { 73 | fn partial_cmp(&self, other: &MI256) -> Option { 74 | Some(self.cmp(other)) 75 | } 76 | } 77 | 78 | impl Div for MI256 { 79 | type Output = MI256; 80 | 81 | fn div(self, other: MI256) -> MI256 { 82 | if other == MI256::zero() { 83 | return MI256::zero(); 84 | } 85 | 86 | if self == MI256::min_value() && other == MI256(Sign::Minus, M256::from(1u64)) { 87 | return MI256::min_value(); 88 | } 89 | 90 | let d = (self.1 / other.1) & SIGN_BIT_MASK.into(); 91 | 92 | if d == M256::zero() { 93 | return MI256::zero(); 94 | } 95 | 96 | match (self.0, other.0) { 97 | (Sign::Plus, Sign::Plus) | 98 | (Sign::Minus, Sign::Minus) => MI256(Sign::Plus, d), 99 | (Sign::Plus, Sign::Minus) | 100 | (Sign::Minus, Sign::Plus) => MI256(Sign::Minus, d), 101 | _ => MI256::zero() 102 | } 103 | } 104 | } 105 | 106 | impl Rem for MI256 { 107 | type Output = MI256; 108 | 109 | fn rem(self, other: MI256) -> MI256 { 110 | let r = (self.1 % other.1) & SIGN_BIT_MASK.into(); 111 | 112 | if r == M256::zero() { 113 | return MI256::zero() 114 | } 115 | 116 | MI256(self.0, r) 117 | } 118 | } 119 | 120 | #[cfg(test)] 121 | mod tests { 122 | use super::MI256; 123 | use m256::M256; 124 | use std::str::FromStr; 125 | 126 | #[test] 127 | pub fn sdiv() { 128 | assert_eq!(MI256::from(M256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap()) / MI256::from(M256::from_str("ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff").unwrap()), MI256::from(M256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap())); 129 | } 130 | 131 | #[test] 132 | pub fn m256() { 133 | let m256 = M256::from_str("8000000000000000000000000000000000000000000000000000000000000000").unwrap(); 134 | let mi256 = MI256::from(m256); 135 | let m256b: M256 = mi256.into(); 136 | assert_eq!(m256, m256b); 137 | } 138 | } 139 | -------------------------------------------------------------------------------- /bigint/src/uint/rlp.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2017 ETC Dev Team 2 | // Copyright 2015-2017 Parity Technologies 3 | // 4 | // Licensed under the Apache License, Version 2.0 or the MIT license 6 | // , at your 7 | // option. This file may not be copied, modified, or distributed 8 | // except according to those terms. 9 | 10 | use super::{U256, U128}; 11 | use rlp::{RlpStream, Encodable, Decodable, DecoderError, UntrustedRlp}; 12 | 13 | macro_rules! impl_encodable_for_uint { 14 | ($name: ident, $size: expr) => { 15 | impl Encodable for $name { 16 | fn rlp_append(&self, s: &mut RlpStream) { 17 | let leading_empty_bytes = $size - (self.bits() + 7) / 8; 18 | let mut buffer = [0u8; $size]; 19 | self.to_big_endian(&mut buffer); 20 | s.encoder().encode_value(&buffer[leading_empty_bytes..]); 21 | } 22 | } 23 | } 24 | } 25 | 26 | macro_rules! impl_decodable_for_uint { 27 | ($name: ident, $size: expr) => { 28 | impl Decodable for $name { 29 | fn decode(rlp: &UntrustedRlp) -> Result { 30 | rlp.decoder().decode_value(|bytes| { 31 | if !bytes.is_empty() && bytes[0] == 0 { 32 | Err(DecoderError::RlpInvalidIndirection) 33 | } else if bytes.len() <= $size { 34 | Ok($name::from(bytes)) 35 | } else { 36 | Err(DecoderError::RlpIsTooBig) 37 | } 38 | }) 39 | } 40 | } 41 | } 42 | } 43 | 44 | impl_encodable_for_uint!(U256, 32); 45 | impl_encodable_for_uint!(U128, 16); 46 | 47 | impl_decodable_for_uint!(U256, 32); 48 | impl_decodable_for_uint!(U128, 16); 49 | -------------------------------------------------------------------------------- /block-core/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "etcommon-block-core" 3 | version = "0.3.1" 4 | license = "Apache-2.0" 5 | authors = ["Wei Tang "] 6 | description = "Core block and transaction types for Ethereum." 7 | repository = "https://github.com/ethereumproject/etcommon-rs" 8 | keywords = ["no_std"] 9 | 10 | [lib] 11 | name = "block_core" 12 | 13 | [dependencies] 14 | sha3 = "0.6" 15 | etcommon-bigint = { version = "0.2", path = "../bigint", default-features = false, features = ["rlp", "string"] } 16 | etcommon-rlp = { version = "0.2", path = "../rlp", default-features = false } 17 | 18 | [dev-dependencies] 19 | rand = "0.3.12" 20 | etcommon-hexutil = "0.2" 21 | 22 | [features] 23 | default = ["std"] 24 | std = ["etcommon-bigint/std", "etcommon-rlp/std"] 25 | -------------------------------------------------------------------------------- /block-core/src/account.rs: -------------------------------------------------------------------------------- 1 | use rlp::{Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp}; 2 | use bigint::{H256, U256}; 3 | 4 | #[derive(Clone, Debug, PartialEq, Eq)] 5 | pub struct Account { 6 | pub nonce: U256, 7 | pub balance: U256, 8 | pub storage_root: H256, 9 | pub code_hash: H256, 10 | } 11 | 12 | impl Encodable for Account { 13 | fn rlp_append(&self, s: &mut RlpStream) { 14 | s.begin_list(4); 15 | s.append(&self.nonce); 16 | s.append(&self.balance); 17 | s.append(&self.storage_root); 18 | s.append(&self.code_hash); 19 | } 20 | } 21 | 22 | impl Decodable for Account { 23 | fn decode(rlp: &UntrustedRlp) -> Result { 24 | Ok(Self { 25 | nonce: rlp.val_at(0)?, 26 | balance: rlp.val_at(1)?, 27 | storage_root: rlp.val_at(2)?, 28 | code_hash: rlp.val_at(3)?, 29 | }) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /block-core/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | #![cfg_attr(not(feature = "std"), feature(alloc))] 3 | 4 | #[cfg(not(feature = "std"))] 5 | extern crate alloc; 6 | 7 | extern crate sha3; 8 | extern crate rlp; 9 | extern crate bigint; 10 | 11 | mod account; 12 | mod log; 13 | mod transaction; 14 | 15 | pub use transaction::*; 16 | pub use account::Account; 17 | pub use log::Log; 18 | -------------------------------------------------------------------------------- /block-core/src/log.rs: -------------------------------------------------------------------------------- 1 | use rlp::{Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp}; 2 | use bigint::{Address, H256}; 3 | 4 | #[cfg(not(feature = "std"))] 5 | use alloc::vec::Vec; 6 | 7 | #[derive(Clone, Debug, PartialEq, Eq)] 8 | pub struct Log { 9 | pub address: Address, 10 | pub topics: Vec, 11 | pub data: Vec, 12 | } 13 | 14 | impl Encodable for Log { 15 | fn rlp_append(&self, s: &mut RlpStream) { 16 | s.begin_list(3); 17 | s.append(&self.address); 18 | s.append_list(&self.topics); 19 | s.append(&self.data); 20 | } 21 | } 22 | 23 | impl Decodable for Log { 24 | fn decode(rlp: &UntrustedRlp) -> Result { 25 | Ok(Self { 26 | address: rlp.val_at(0)?, 27 | topics: rlp.list_at(1)?, 28 | data: rlp.val_at(2)?, 29 | }) 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /block-core/src/transaction.rs: -------------------------------------------------------------------------------- 1 | use rlp::{UntrustedRlp, DecoderError, RlpStream, Encodable, Decodable}; 2 | use bigint::{Address, U256, M256, H256}; 3 | use sha3::{Digest, Keccak256}; 4 | 5 | #[cfg(not(feature = "std"))] use alloc::vec::Vec; 6 | #[cfg(not(feature = "std"))] use alloc::rc::Rc; 7 | 8 | // Use transaction action so we can keep most of the common fields 9 | // without creating a large enum. 10 | #[derive(Clone, Copy, Debug, PartialEq, Eq)] 11 | pub enum TransactionAction { 12 | Call(Address), 13 | Create, 14 | /// CREATE2 transaction action with salt and code hash 15 | Create2(H256, M256), 16 | } 17 | 18 | impl TransactionAction { 19 | pub fn address(&self, caller: Address, nonce: U256) -> Address { 20 | match self { 21 | &TransactionAction::Call(address) => address, 22 | &TransactionAction::Create => { 23 | let mut rlp = RlpStream::new_list(2); 24 | rlp.append(&caller); 25 | rlp.append(&nonce); 26 | 27 | Address::from(M256::from(Keccak256::digest(rlp.out().as_slice()).as_slice())) 28 | }, 29 | &TransactionAction::Create2(salt, code_hash) => { 30 | let mut digest = Keccak256::new(); 31 | digest.input(&[0xff]); 32 | digest.input(&caller); 33 | digest.input(&salt); 34 | digest.input(&H256::from(code_hash)); 35 | let hash = digest.result(); 36 | Address::from(M256::from(&hash[12..])) 37 | } 38 | } 39 | } 40 | } 41 | 42 | const CREATE2_TAG: u8 = 0xc2; 43 | 44 | impl Encodable for TransactionAction { 45 | fn rlp_append(&self, s: &mut RlpStream) { 46 | match self { 47 | &TransactionAction::Call(address) => { 48 | s.encoder().encode_value(&address); 49 | }, 50 | &TransactionAction::Create => { 51 | s.encoder().encode_value(&[]) 52 | }, 53 | &TransactionAction::Create2(salt, code_hash) => { 54 | s.begin_list(3) 55 | .append(&CREATE2_TAG) 56 | .append(&salt) 57 | .append(&H256::from(code_hash)); 58 | } 59 | } 60 | } 61 | } 62 | 63 | impl Decodable for TransactionAction { 64 | fn decode(rlp: &UntrustedRlp) -> Result { 65 | let action = if rlp.is_empty() { 66 | TransactionAction::Create 67 | } else if let Ok(CREATE2_TAG) = rlp.val_at(0) { 68 | let salt: H256 = rlp.val_at(1)?; 69 | let code_hash: H256 = rlp.val_at(2)?; 70 | TransactionAction::Create2(salt, M256::from(code_hash)) 71 | } else { 72 | TransactionAction::Call(rlp.as_val()?) 73 | }; 74 | 75 | Ok(action) 76 | } 77 | } 78 | 79 | #[cfg(test)] 80 | mod tests { 81 | use super::*; 82 | use rlp; 83 | 84 | #[test] 85 | fn rlp_roundtrip_call() { 86 | let address = Address::from(M256::from(std::u64::MAX)); 87 | let action = TransactionAction::Call(address); 88 | let encoded = rlp::encode(&action); 89 | let decoded: TransactionAction = rlp::decode(&encoded); 90 | assert_eq!(action, decoded); 91 | } 92 | 93 | #[test] 94 | fn rlp_roundtrip_create() { 95 | let action = TransactionAction::Create; 96 | let encoded = rlp::encode(&action); 97 | let decoded: TransactionAction = rlp::decode(&encoded); 98 | assert_eq!(action, decoded); 99 | } 100 | 101 | #[test] 102 | fn rlp_roundtrip_create2() { 103 | let salt = H256::from(M256::from(std::i32::MAX)); 104 | let code_hash = M256::from(1024); 105 | let action = TransactionAction::Create2(salt, code_hash); 106 | let encoded = rlp::encode(&action); 107 | let decoded: TransactionAction = rlp::decode(&encoded); 108 | assert_eq!(action, decoded); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /block/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "etcommon-block" 3 | version = "0.5.2" 4 | license = "Apache-2.0" 5 | authors = ["Wei Tang "] 6 | description = "Block and transaction types for Ethereum." 7 | repository = "https://github.com/ethereumproject/etcommon-rs" 8 | 9 | [lib] 10 | name = "block" 11 | 12 | [dependencies] 13 | sha3 = "0.6" 14 | etcommon-block-core = { version = "0.3", path = "../block-core" } 15 | etcommon-bigint = { version = "0.2", path = "../bigint" } 16 | etcommon-rlp = { version = "0.2", path = "../rlp" } 17 | etcommon-bloom = { version = "0.2", path = "../bloom" } 18 | etcommon-trie = { version = "0.4", path = "../trie" } 19 | 20 | secp256k1-plus = { version = "0.5", optional = true } 21 | libsecp256k1 = { version = "0.1", optional = true } 22 | 23 | [dev-dependencies] 24 | rand = "0.3" 25 | serde = "1.0" 26 | serde_derive = "1.0" 27 | serde_json = "1.0" 28 | etcommon-hexutil = { version = "0.2", path = "../hexutil" } 29 | 30 | [features] 31 | default = ["c-secp256k1"] 32 | c-secp256k1 = ["secp256k1-plus"] 33 | rust-secp256k1 = ["libsecp256k1"] 34 | -------------------------------------------------------------------------------- /block/src/address.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "c-secp256k1")] 2 | use secp256k1::{SECP256K1, Error}; 3 | #[cfg(feature = "c-secp256k1")] 4 | use secp256k1::key::{PublicKey, SecretKey}; 5 | #[cfg(feature = "rust-secp256k1")] 6 | use secp256k1::{self, PublicKey, SecretKey, Error}; 7 | use bigint::{H256, Address}; 8 | use sha3::{Digest, Keccak256}; 9 | 10 | pub trait FromKey: Sized { 11 | fn from_public_key(key: &PublicKey) -> Self; 12 | fn from_secret_key(key: &SecretKey) -> Result; 13 | } 14 | 15 | impl FromKey for Address { 16 | #[cfg(feature = "c-secp256k1")] 17 | fn from_public_key(key: &PublicKey) -> Self { 18 | let hash = H256::from( 19 | Keccak256::digest(&key.serialize_vec(&SECP256K1, false)[1..]).as_slice()); 20 | Address::from(hash) 21 | } 22 | 23 | #[cfg(feature = "rust-secp256k1")] 24 | fn from_public_key(key: &PublicKey) -> Self { 25 | let hash = H256::from( 26 | Keccak256::digest(&key.serialize()[1..]).as_slice()); 27 | Address::from(hash) 28 | } 29 | 30 | #[cfg(feature = "c-secp256k1")] 31 | fn from_secret_key(key: &SecretKey) -> Result { 32 | let public_key = PublicKey::from_secret_key(&SECP256K1, key)?; 33 | Ok(Self::from_public_key(&public_key)) 34 | } 35 | 36 | #[cfg(feature = "rust-secp256k1")] 37 | fn from_secret_key(key: &SecretKey) -> Result { 38 | let public_key = PublicKey::from_secret_key(key); 39 | Ok(Self::from_public_key(&public_key)) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /block/src/block.rs: -------------------------------------------------------------------------------- 1 | use rlp::{self, Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp}; 2 | use bigint::{H256, U256}; 3 | use trie::FixedMemoryTrieMut; 4 | use sha3::{Keccak256, Digest}; 5 | use super::{Header, Transaction, Receipt}; 6 | 7 | pub fn transactions_root(transactions: &[Transaction]) -> H256 { 8 | let mut trie = FixedMemoryTrieMut::default(); 9 | for (i, transaction) in transactions.iter().enumerate() { 10 | trie.insert(&U256::from(i), transaction); 11 | } 12 | trie.root() 13 | } 14 | 15 | pub fn receipts_root(receipts: &[Receipt]) -> H256 { 16 | let mut trie = FixedMemoryTrieMut::default(); 17 | for (i, receipt) in receipts.iter().enumerate() { 18 | trie.insert(&U256::from(i), receipt); 19 | } 20 | trie.root() 21 | } 22 | 23 | pub fn ommers_hash(ommers: &[Header]) -> H256 { 24 | let encoded = rlp::encode_list(ommers).to_vec(); 25 | let hash = H256::from(Keccak256::digest(&encoded).as_slice()); 26 | hash 27 | } 28 | 29 | #[derive(Clone, Debug, PartialEq, Eq)] 30 | pub struct Block { 31 | pub header: Header, 32 | pub transactions: Vec, 33 | pub ommers: Vec
, 34 | } 35 | 36 | impl Block { 37 | pub fn is_basic_valid(&self) -> bool { 38 | if transactions_root(&self.transactions) != self.header.transactions_root { 39 | return false; 40 | } 41 | 42 | if ommers_hash(&self.ommers) != self.header.ommers_hash { 43 | return false; 44 | } 45 | 46 | return true; 47 | } 48 | } 49 | 50 | impl Encodable for Block { 51 | fn rlp_append(&self, s: &mut RlpStream) { 52 | s.begin_list(3); 53 | s.append(&self.header); 54 | s.append_list(&self.transactions); 55 | s.append_list(&self.ommers); 56 | } 57 | } 58 | 59 | impl Decodable for Block { 60 | fn decode(rlp: &UntrustedRlp) -> Result { 61 | Ok(Self { 62 | header: rlp.val_at(0)?, 63 | transactions: rlp.list_at(1)?, 64 | ommers: rlp.list_at(2)?, 65 | }) 66 | } 67 | } 68 | 69 | #[cfg(test)] 70 | mod tests { 71 | use rlp::{encode, decode}; 72 | use hexutil::read_hex; 73 | use bigint::{U256, H256, Address, Gas}; 74 | use block::Block; 75 | use TransactionAction; 76 | use std::str::FromStr; 77 | 78 | #[test] 79 | fn block_53165_rlp() { 80 | let raw = read_hex("f9050df901ffa037ecbfd908ece3c54fa5b9f8e1b4a6089139da1dc4b5013a46c5818304de47b3a05cd40176209a61f3b26f3b5b491f177b93a3c33c595d0be75c26c97bdb60e7a294a50ec0d39fa913e62f1bae7074e6f36caa71855ba0a1b07a1f98248efee3d2111fcf9dcb2c1ad9f961a192e02571c0b55e7539b427a0f739c0f6d17bcad52552bfe3a4950885222ae694750135a75f452efc033d425da0b61bbed645e5b6366521a5c3bddb98d788067dc7a0f1515bfe4bdad0fb63b188b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086016f2c8a34da82cfad8320f4018307a1208455c5e86b80a05fca8f6fce90e5f92549824d7b7d456cefafb92f223f97d60efee8e62522b9778870cee9238ebd5c31f8ecf8ea04850d9afee4208307a12094dc884e349103eaee4aef913d532cb5db2745f48b80b884de6f24bb0000000000000000000000008674c218f0351a62c3ba78c34fd2182a93da94e20000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000568656c6c6f0000000000000000000000000000000000000000000000000000001ba04f2dfebd7c0f712119678fdd5ce6abc357a91df2284edafa5dc1c7503bb2d5c6a023b85af577d777b5cc5af8a4ece80bf45ae9f0be7b8e166a91271deb938b72aff9021af90217a059c53a8471fdc848352699052890b6156753a94743cfb4dc3f921df67e16978aa01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d4934794f2d2aff1320476cb8c6b607199d23175cc595693a0bf6464bc0efe71b06723bf303cc661322eff513b247e714537d6593472ae76bea056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b901000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000086016f2c8ff18c82cfab8320f404808455c5e84b9b476574682f76312e302e312f77696e646f77732f676f312e342e32a0fc0a1197dee6cf57a6d8afeaa1d070462638d484e1f71266b114b9cc5d5a5b0e88f48a42a38b85ccf0").unwrap(); 81 | let block: Block = decode(&raw); 82 | assert_eq!(block.header.parent_hash, H256::from_str("37ecbfd908ece3c54fa5b9f8e1b4a6089139da1dc4b5013a46c5818304de47b3").unwrap()); 83 | assert_eq!(block.transactions[0].action, TransactionAction::Call(Address::from_str("0xdc884e349103eaee4aef913d532cb5db2745f48b").unwrap())); 84 | assert_eq!(block.transactions[0].gas_limit, Gas::from(500000u64)); 85 | assert_eq!(block.transactions[0].value, U256::zero()); 86 | assert_eq!(block.ommers[0].parent_hash, H256::from_str("59c53a8471fdc848352699052890b6156753a94743cfb4dc3f921df67e16978a").unwrap()); 87 | assert_eq!(block.ommers[0].beneficiary, Address::from_str("f2d2aff1320476cb8c6b607199d23175cc595693").unwrap()); 88 | assert_eq!(block, decode(&encode(&block).to_vec())); 89 | 90 | let encoded = encode(&block).to_vec(); 91 | assert_eq!(encoded, raw); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /block/src/header.rs: -------------------------------------------------------------------------------- 1 | use rlp::{self, Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp}; 2 | use bigint::{Address, Gas, H256, U256, B256, H64}; 3 | use bloom::LogsBloom; 4 | use std::cmp::Ordering; 5 | use sha3::{Keccak256, Digest}; 6 | use super::RlpHash; 7 | 8 | pub trait HeaderHash { 9 | fn parent_hash(&self) -> Option; 10 | fn header_hash(&self) -> H; 11 | } 12 | 13 | #[derive(Clone, Debug, PartialEq, Eq)] 14 | pub struct TotalHeader(pub Header, U256); 15 | 16 | impl TotalHeader { 17 | pub fn from_genesis(header: Header) -> TotalHeader { 18 | let diff = header.difficulty; 19 | TotalHeader(header, diff) 20 | } 21 | 22 | pub fn from_parent(header: Header, parent: &TotalHeader) -> TotalHeader { 23 | let diff = header.difficulty + parent.1; 24 | TotalHeader(header, diff) 25 | } 26 | 27 | pub fn total_difficulty(&self) -> U256 { 28 | self.1 29 | } 30 | } 31 | 32 | impl HeaderHash for TotalHeader { 33 | fn parent_hash(&self) -> Option { 34 | self.0.parent_hash() 35 | } 36 | 37 | fn header_hash(&self) -> H256 { 38 | self.0.header_hash() 39 | } 40 | } 41 | 42 | impl Into
for TotalHeader { 43 | fn into(self) -> Header { 44 | self.0 45 | } 46 | } 47 | 48 | impl Ord for TotalHeader { 49 | fn cmp(&self, other: &TotalHeader) -> Ordering { 50 | self.1.cmp(&other.1) 51 | } 52 | } 53 | 54 | impl PartialOrd for TotalHeader { 55 | fn partial_cmp(&self, other: &TotalHeader) -> Option { 56 | Some(self.cmp(other)) 57 | } 58 | } 59 | 60 | #[derive(Clone, Debug, PartialEq, Eq)] 61 | pub struct Header { 62 | pub parent_hash: H256, 63 | pub ommers_hash: H256, 64 | pub beneficiary: Address, 65 | pub state_root: H256, 66 | pub transactions_root: H256, 67 | pub receipts_root: H256, 68 | pub logs_bloom: LogsBloom, 69 | pub difficulty: U256, 70 | pub number: U256, 71 | pub gas_limit: Gas, 72 | pub gas_used: Gas, 73 | pub timestamp: u64, 74 | pub extra_data: B256, 75 | pub mix_hash: H256, 76 | pub nonce: H64, 77 | } 78 | 79 | impl HeaderHash for Header { 80 | fn parent_hash(&self) -> Option { 81 | if self.number == U256::zero() { 82 | None 83 | } else { 84 | Some(self.parent_hash) 85 | } 86 | } 87 | 88 | fn header_hash(&self) -> H256 { 89 | H256::from(Keccak256::digest(&rlp::encode(self).to_vec()).as_slice()) 90 | } 91 | } 92 | 93 | impl Header { 94 | pub fn partial_rlp_append(&self, s: &mut RlpStream) { 95 | s.begin_list(13); 96 | s.append(&self.parent_hash); 97 | s.append(&self.ommers_hash); 98 | s.append(&self.beneficiary); 99 | s.append(&self.state_root); 100 | s.append(&self.transactions_root); 101 | s.append(&self.receipts_root); 102 | s.append(&self.logs_bloom); 103 | s.append(&self.difficulty); 104 | s.append(&self.number); 105 | s.append(&self.gas_limit); 106 | s.append(&self.gas_used); 107 | s.append(&self.timestamp); 108 | s.append(&self.extra_data); 109 | } 110 | 111 | pub fn partial_hash(&self) -> H256 { 112 | let mut stream = RlpStream::new(); 113 | self.partial_rlp_append(&mut stream); 114 | H256::from(Keccak256::digest(&stream.drain()).as_slice()) 115 | } 116 | } 117 | 118 | impl Encodable for Header { 119 | fn rlp_append(&self, s: &mut RlpStream) { 120 | s.begin_list(15); 121 | s.append(&self.parent_hash); 122 | s.append(&self.ommers_hash); 123 | s.append(&self.beneficiary); 124 | s.append(&self.state_root); 125 | s.append(&self.transactions_root); 126 | s.append(&self.receipts_root); 127 | s.append(&self.logs_bloom); 128 | s.append(&self.difficulty); 129 | s.append(&self.number); 130 | s.append(&self.gas_limit); 131 | s.append(&self.gas_used); 132 | s.append(&self.timestamp); 133 | s.append(&self.extra_data); 134 | s.append(&self.mix_hash); 135 | s.append(&self.nonce); 136 | } 137 | } 138 | 139 | impl Decodable for Header { 140 | fn decode(rlp: &UntrustedRlp) -> Result { 141 | Ok(Self { 142 | parent_hash: rlp.val_at(0)?, 143 | ommers_hash: rlp.val_at(1)?, 144 | beneficiary: rlp.val_at(2)?, 145 | state_root: rlp.val_at(3)?, 146 | transactions_root: rlp.val_at(4)?, 147 | receipts_root: rlp.val_at(5)?, 148 | logs_bloom: rlp.val_at(6)?, 149 | difficulty: rlp.val_at(7)?, 150 | number: rlp.val_at(8)?, 151 | gas_limit: rlp.val_at(9)?, 152 | gas_used: rlp.val_at(10)?, 153 | timestamp: rlp.val_at(11)?, 154 | extra_data: rlp.val_at(12)?, 155 | mix_hash: rlp.val_at(13)?, 156 | nonce: rlp.val_at(14)?, 157 | }) 158 | } 159 | } 160 | 161 | impl RlpHash for Header { 162 | fn rlp_hash(&self) -> H256 { 163 | H256::from(Keccak256::digest(&rlp::encode(self)).as_slice()) 164 | } 165 | } 166 | 167 | #[cfg(test)] 168 | mod tests { 169 | use rlp::{encode, decode, Rlp}; 170 | use hexutil::read_hex; 171 | use bigint::{U256, H256, Address, Gas}; 172 | use bloom::LogsBloom; 173 | use header::Header; 174 | use std::str::FromStr; 175 | 176 | #[test] 177 | fn block_0_rlp() { 178 | let raw = read_hex("f90219f90214a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347940000000000000000000000000000000000000000a0d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b9010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000850400000000808213888080a011bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82faa00000000000000000000000000000000000000000000000000000000000000000880000000000000042c0c0").unwrap(); 179 | let block_raw = Rlp::new(&raw); 180 | let block: Header = block_raw.val_at(0); 181 | assert_eq!(block.number, U256::from(0u64)); 182 | 183 | let encoded = encode(&block).to_vec(); 184 | let encoded_ref: &[u8] = encoded.as_ref(); 185 | assert_eq!(encoded_ref, block_raw.at(0).as_raw()); 186 | } 187 | 188 | #[test] 189 | fn block_1_rlp() { 190 | let raw = read_hex("f90216f90211a0d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d493479405a56e2d52c817161883f50c441c3228cfe54d9fa0d67e4d450343046425ae4271474353857ab860dbc0a1dde64b41b5cd3a532bf3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008503ff80000001821388808455ba422499476574682f76312e302e302f6c696e75782f676f312e342e32a0969b900de27b6ac6a67742365dd65f55a0526c41fd18e1b16f1a1215c2e66f5988539bd4979fef1ec4c0c0").unwrap(); 191 | let block_raw = Rlp::new(&raw); 192 | let block: Header = block_raw.val_at(0); 193 | assert_eq!(block.parent_hash, H256::from_str("d4e56740f876aef8c010b86a40d5f56745a118d0906a34e69aec8c0db1cb8fa3").unwrap()); 194 | assert_eq!(block.ommers_hash, H256::from_str("1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347").unwrap()); 195 | assert_eq!(block.beneficiary, Address::from_str("05a56e2d52c817161883f50c441c3228cfe54d9f").unwrap()); 196 | assert_eq!(block.state_root, H256::from_str("d67e4d450343046425ae4271474353857ab860dbc0a1dde64b41b5cd3a532bf3").unwrap()); 197 | assert_eq!(block.transactions_root, H256::from_str("56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").unwrap()); 198 | assert_eq!(block.logs_bloom, LogsBloom::default()); 199 | assert_eq!(block.difficulty, U256::from(17171480576u64)); 200 | assert_eq!(block.number, U256::from(1u64)); 201 | assert_eq!(block.gas_limit, Gas::from(5000u64)); 202 | assert_eq!(block.gas_used, Gas::zero()); 203 | assert_eq!(block.timestamp, 1438269988u64); 204 | assert_eq!(block, decode(&encode(&block).to_vec())); 205 | 206 | let encoded = encode(&block).to_vec(); 207 | let encoded_ref: &[u8] = encoded.as_ref(); 208 | assert_eq!(encoded_ref, block_raw.at(0).as_raw()); 209 | } 210 | } 211 | -------------------------------------------------------------------------------- /block/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate bigint; 2 | extern crate rlp; 3 | extern crate bloom; 4 | extern crate secp256k1; 5 | extern crate sha3; 6 | extern crate trie; 7 | extern crate block_core; 8 | #[cfg(test)] extern crate hexutil; 9 | #[cfg(test)] extern crate rand; 10 | 11 | mod header; 12 | mod transaction; 13 | mod block; 14 | mod receipt; 15 | mod address; 16 | 17 | pub use block_core::*; 18 | pub use transaction::*; 19 | pub use header::{TotalHeader, Header, HeaderHash}; 20 | pub use block::{Block, transactions_root, receipts_root, ommers_hash}; 21 | pub use receipt::Receipt; 22 | pub use address::FromKey; 23 | 24 | use bigint::H256; 25 | 26 | pub trait RlpHash { 27 | fn rlp_hash(&self) -> H256; 28 | } 29 | -------------------------------------------------------------------------------- /block/src/receipt.rs: -------------------------------------------------------------------------------- 1 | use rlp::{Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp}; 2 | use bigint::{Gas, H256}; 3 | use bloom::LogsBloom; 4 | 5 | use super::Log; 6 | 7 | #[derive(Clone, Debug, PartialEq, Eq)] 8 | pub struct Receipt { 9 | pub state_root: H256, 10 | pub used_gas: Gas, 11 | pub logs_bloom: LogsBloom, 12 | pub logs: Vec, 13 | } 14 | 15 | impl Encodable for Receipt { 16 | fn rlp_append(&self, s: &mut RlpStream) { 17 | s.begin_list(4); 18 | s.append(&self.state_root); 19 | s.append(&self.used_gas); 20 | s.append(&self.logs_bloom); 21 | s.append_list(&self.logs); 22 | } 23 | } 24 | 25 | impl Decodable for Receipt { 26 | fn decode(rlp: &UntrustedRlp) -> Result { 27 | Ok(Self { 28 | state_root: rlp.val_at(0)?, 29 | used_gas: rlp.val_at(1)?, 30 | logs_bloom: rlp.val_at(2)?, 31 | logs: rlp.list_at(3)?, 32 | }) 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /block/src/transaction.rs: -------------------------------------------------------------------------------- 1 | #[cfg(feature = "c-secp256k1")] 2 | use secp256k1::{Message, Error, RecoverableSignature, RecoveryId, SECP256K1}; 3 | #[cfg(feature = "c-secp256k1")] 4 | use secp256k1::key::SecretKey; 5 | #[cfg(feature = "rust-secp256k1")] 6 | use secp256k1::{self, Message, Error, Signature, RecoveryId, SecretKey, PublicKey}; 7 | 8 | use rlp::{self, Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp}; 9 | use bigint::{Address, Gas, H256, U256}; 10 | use sha3::{Digest, Keccak256}; 11 | use address::FromKey; 12 | use std::str::FromStr; 13 | use super::{TransactionAction, RlpHash}; 14 | 15 | /// Refer to EIP155 related to chain ID. 16 | pub trait SignaturePatch { 17 | fn chain_id() -> Option; 18 | } 19 | 20 | /// Frontier signature patch without EIP155. 21 | pub struct GlobalSignaturePatch; 22 | impl SignaturePatch for GlobalSignaturePatch { 23 | fn chain_id() -> Option { None } 24 | } 25 | 26 | /// EIP155 Ethereum Classic chain. 27 | pub struct ClassicSignaturePatch; 28 | impl SignaturePatch for ClassicSignaturePatch { 29 | fn chain_id() -> Option { Some(61) } 30 | } 31 | 32 | /// Refer to Homestead transaction validation. 33 | pub trait ValidationPatch { 34 | fn require_low_s() -> bool; 35 | } 36 | 37 | /// Frontier validation patch. 38 | pub struct FrontierValidationPatch; 39 | impl ValidationPatch for FrontierValidationPatch { 40 | fn require_low_s() -> bool { false } 41 | } 42 | 43 | /// Homestead validation patch. 44 | pub struct HomesteadValidationPatch; 45 | impl ValidationPatch for HomesteadValidationPatch { 46 | fn require_low_s() -> bool { true } 47 | } 48 | 49 | #[derive(Clone, Debug, PartialEq, Eq)] 50 | pub struct TransactionSignature { 51 | pub v: u64, 52 | pub r: H256, 53 | pub s: H256, 54 | } 55 | 56 | impl TransactionSignature { 57 | pub fn standard_v(&self) -> u8 { 58 | let v = self.v; 59 | if v == 27 || v == 28 || v > 36 { 60 | ((v - 1) % 2) as u8 61 | } else { 62 | 4 63 | } 64 | } 65 | 66 | pub fn is_low_s(&self) -> bool { 67 | self.s <= H256::from_str("0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0").unwrap() 68 | } 69 | 70 | pub fn is_valid(&self) -> bool { 71 | self.standard_v() <= 1 && 72 | self.r < H256::from_str("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141").unwrap() && 73 | self.r >= H256::from(1) && 74 | self.s < H256::from_str("0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141").unwrap() && 75 | self.s >= H256::from(1) 76 | } 77 | 78 | pub fn chain_id(&self) -> Option { 79 | if self.v > 36 { 80 | Some((self.v - 35) / 2) 81 | } else { 82 | None 83 | } 84 | } 85 | 86 | #[cfg(feature = "c-secp256k1")] 87 | pub fn to_recoverable_signature(&self) -> Result { 88 | let mut sig = [0u8; 64]; 89 | sig[0..32].copy_from_slice(&self.r); 90 | sig[32..64].copy_from_slice(&self.s); 91 | 92 | RecoverableSignature::from_compact(&SECP256K1, &sig, RecoveryId::from_i32(self.standard_v() as i32)?) 93 | } 94 | 95 | #[cfg(feature = "rust-secp256k1")] 96 | pub fn to_recoverable_signature(&self) -> Result<(Signature, RecoveryId), Error> { 97 | let mut sig = [0u8; 64]; 98 | sig[0..32].copy_from_slice(&self.r); 99 | sig[32..64].copy_from_slice(&self.s); 100 | 101 | Ok((Signature::parse(&sig), RecoveryId::parse(self.standard_v() as u8)?)) 102 | } 103 | } 104 | 105 | pub struct UnsignedTransaction { 106 | pub nonce: U256, 107 | pub gas_price: Gas, 108 | pub gas_limit: Gas, 109 | pub action: TransactionAction, 110 | pub value: U256, 111 | pub input: Vec, 112 | } 113 | 114 | impl UnsignedTransaction { 115 | fn signing_rlp_append(&self, s: &mut RlpStream, chain_id: Option) { 116 | s.begin_list(if chain_id.is_some() { 9 } else { 6 }); 117 | s.append(&self.nonce); 118 | s.append(&self.gas_price); 119 | s.append(&self.gas_limit); 120 | s.append(&self.action); 121 | s.append(&self.value); 122 | s.append(&self.input); 123 | 124 | if let Some(chain_id) = chain_id { 125 | s.append(&chain_id); 126 | s.append(&0u8); 127 | s.append(&0u8); 128 | } 129 | } 130 | 131 | fn signing_hash(&self, chain_id: Option) -> H256 { 132 | let mut stream = RlpStream::new(); 133 | self.signing_rlp_append(&mut stream, chain_id); 134 | H256::from(Keccak256::digest(&stream.drain()).as_slice()) 135 | } 136 | 137 | pub fn sign(self, key: &SecretKey) -> Transaction { 138 | let hash = self.signing_hash(P::chain_id()); 139 | // hash is always MESSAGE_SIZE bytes. 140 | let msg = { 141 | #[cfg(feature = "c-secp256k1")] 142 | { Message::from_slice(&hash).unwrap() } 143 | #[cfg(feature = "rust-secp256k1")] 144 | { let mut a = [0u8; 32]; 145 | for i in 0..32 { 146 | a[i] = hash[i]; 147 | } 148 | Message::parse(&a) 149 | } 150 | }; 151 | 152 | // SecretKey and Message are always valid. 153 | let s = { 154 | #[cfg(feature = "c-secp256k1")] 155 | { SECP256K1.sign_recoverable(&msg, key).unwrap() } 156 | #[cfg(feature = "rust-secp256k1")] 157 | { secp256k1::sign(&msg, key).unwrap() } 158 | }; 159 | let (rid, sig) = { 160 | #[cfg(feature = "c-secp256k1")] 161 | { s.serialize_compact(&SECP256K1) } 162 | #[cfg(feature = "rust-secp256k1")] 163 | { (s.1, s.0.serialize()) } 164 | }; 165 | 166 | let sig = TransactionSignature { 167 | v: ({ 168 | #[cfg(feature = "c-secp256k1")] 169 | { rid.to_i32() } 170 | #[cfg(feature = "rust-secp256k1")] 171 | { let v: i32 = rid.into(); v } 172 | } + if let Some(n) = P::chain_id() { (35 + n * 2) as i32 } else { 27 }) as u64, 173 | r: H256::from(&sig[0..32]), 174 | s: H256::from(&sig[32..64]), 175 | }; 176 | 177 | Transaction { 178 | nonce: self.nonce, 179 | gas_price: self.gas_price, 180 | gas_limit: self.gas_limit, 181 | action: self.action, 182 | value: self.value, 183 | input: self.input, 184 | signature: sig, 185 | } 186 | } 187 | 188 | pub fn sign_global(self, key: &SecretKey) -> Transaction { 189 | self.sign::(key) 190 | } 191 | } 192 | 193 | impl From for UnsignedTransaction { 194 | fn from(val: Transaction) -> UnsignedTransaction { 195 | UnsignedTransaction { 196 | nonce: val.nonce, 197 | gas_price: val.gas_price, 198 | gas_limit: val.gas_limit, 199 | action: val.action, 200 | value: val.value, 201 | input: val.input, 202 | } 203 | } 204 | } 205 | 206 | #[derive(Clone, Debug, PartialEq, Eq)] 207 | pub struct Transaction { 208 | pub nonce: U256, 209 | pub gas_price: Gas, 210 | pub gas_limit: Gas, 211 | pub action: TransactionAction, 212 | pub value: U256, 213 | pub signature: TransactionSignature, 214 | pub input: Vec, // The input data, either data or init, depending on TransactionAction. 215 | } 216 | 217 | impl Transaction { 218 | pub fn caller(&self) -> Result { 219 | let unsigned = UnsignedTransaction::from((*self).clone()); 220 | let hash = unsigned.signing_hash(self.signature.chain_id()); 221 | let sig = self.signature.to_recoverable_signature()?; 222 | let public_key = { 223 | #[cfg(feature = "c-secp256k1")] 224 | { SECP256K1.recover(&Message::from_slice(&hash).unwrap(), &sig)? } 225 | #[cfg(feature = "rust-secp256k1")] 226 | { let mut a = [0u8; 32]; 227 | for i in 0..32 { 228 | a[i] = hash[i]; 229 | } 230 | secp256k1::recover(&Message::parse(&a), &sig.0, &sig.1)? 231 | } 232 | }; 233 | 234 | Ok(Address::from_public_key(&public_key)) 235 | } 236 | 237 | pub fn address(&self) -> Result { 238 | Ok(self.action.address(self.caller()?, self.nonce)) 239 | } 240 | 241 | pub fn is_basic_valid(&self) -> bool { 242 | if !self.signature.is_valid() { 243 | return false; 244 | } 245 | 246 | if self.signature.chain_id().is_some() && self.signature.chain_id() != P::chain_id() { 247 | return false; 248 | } 249 | 250 | if self.caller().is_err() { 251 | return false; 252 | } 253 | 254 | if Q::require_low_s() && !self.signature.is_low_s() { 255 | return false; 256 | } 257 | 258 | return true; 259 | } 260 | } 261 | 262 | impl Encodable for Transaction { 263 | fn rlp_append(&self, s: &mut RlpStream) { 264 | s.begin_list(9); 265 | s.append(&self.nonce); 266 | s.append(&self.gas_price); 267 | s.append(&self.gas_limit); 268 | s.append(&self.action); 269 | s.append(&self.value); 270 | s.append(&self.input); 271 | s.append(&self.signature.v); 272 | s.append(&self.signature.r); 273 | s.append(&self.signature.s); 274 | } 275 | } 276 | 277 | impl Decodable for Transaction { 278 | fn decode(rlp: &UntrustedRlp) -> Result { 279 | Ok(Self { 280 | nonce: rlp.val_at(0)?, 281 | gas_price: rlp.val_at(1)?, 282 | gas_limit: rlp.val_at(2)?, 283 | action: rlp.val_at(3)?, 284 | value: rlp.val_at(4)?, 285 | input: rlp.val_at(5)?, 286 | signature: TransactionSignature { 287 | v: rlp.val_at(6)?, 288 | r: rlp.val_at(7)?, 289 | s: rlp.val_at(8)?, 290 | }, 291 | }) 292 | } 293 | } 294 | 295 | impl RlpHash for Transaction { 296 | fn rlp_hash(&self) -> H256 { 297 | H256::from(Keccak256::digest(&rlp::encode(self)).as_slice()) 298 | } 299 | } 300 | 301 | #[cfg(test)] 302 | mod tests { 303 | use secp256k1::SECP256K1; 304 | use secp256k1::key::SecretKey; 305 | use bigint::{Address, Gas, U256}; 306 | use address::FromKey; 307 | use rand::os::OsRng; 308 | use super::{UnsignedTransaction, TransactionAction, ClassicSignaturePatch, 309 | HomesteadValidationPatch}; 310 | 311 | #[test] 312 | pub fn should_recover_address() { 313 | let mut rng = OsRng::new().unwrap(); 314 | let secret_key = SecretKey::new(&SECP256K1, &mut rng); 315 | let address = Address::from_secret_key(&secret_key); 316 | 317 | let unsigned = UnsignedTransaction { 318 | nonce: U256::zero(), 319 | gas_price: Gas::zero(), 320 | gas_limit: Gas::zero(), 321 | action: TransactionAction::Create, 322 | value: U256::zero(), 323 | input: Vec::new() 324 | }; 325 | let signed = unsigned.sign::(&secret_key); 326 | 327 | assert_eq!(signed.signature.chain_id(), Some(61)); 328 | assert!(signed.is_basic_valid::()); 329 | assert_eq!(signed.caller(), address); 330 | } 331 | } 332 | -------------------------------------------------------------------------------- /block/tests/genesis.rs: -------------------------------------------------------------------------------- 1 | #[macro_use] 2 | extern crate serde_derive; 3 | 4 | extern crate serde; 5 | extern crate serde_json; 6 | extern crate bigint; 7 | extern crate trie; 8 | extern crate block; 9 | extern crate sha3; 10 | extern crate rlp; 11 | extern crate rand; 12 | 13 | use bigint::{Address, H256, M256, U256}; 14 | use trie::{FixedSecureMemoryTrieMut, MemoryTrieMut, TrieMut}; 15 | use block::Account; 16 | use sha3::{Digest, Keccak256}; 17 | use rand::Rng; 18 | 19 | use std::str::FromStr; 20 | use std::collections::HashMap; 21 | 22 | fn build_db(map: &HashMap) -> MemoryTrieMut { 23 | let mut db: HashMap, Vec> = HashMap::new(); 24 | 25 | for (key, value) in map { 26 | db.insert(Keccak256::digest(key.as_ref()).as_slice().into(), rlp::encode(value).to_vec()); 27 | } 28 | 29 | MemoryTrieMut::build(&db) 30 | } 31 | 32 | #[test] 33 | pub fn test_genesis_root() { 34 | #[derive(Serialize, Deserialize, Debug)] 35 | struct JSONAccount { 36 | balance: String, 37 | } 38 | 39 | type StorageTrieMut = FixedSecureMemoryTrieMut; 40 | 41 | let genesis_accounts: HashMap = 42 | serde_json::from_str(include_str!("../res/genesis.json")).unwrap(); 43 | 44 | let accounts: Vec<(&String, &JSONAccount)> = genesis_accounts.iter().collect(); 45 | let mut account_trie: FixedSecureMemoryTrieMut = Default::default(); 46 | let mut account_db: HashMap = HashMap::new(); 47 | let mut addresses: Vec
= Vec::new(); 48 | 49 | for (key, value) in accounts { 50 | let address = Address::from_str(key).unwrap(); 51 | let balance = U256::from_dec_str(&value.balance).unwrap(); 52 | 53 | let account = Account { 54 | nonce: U256::zero(), 55 | balance: balance, 56 | storage_root: StorageTrieMut::default().root(), 57 | code_hash: H256::from(Keccak256::digest(&[]).as_slice()), 58 | }; 59 | 60 | account_trie.insert(&address, &account); 61 | account_db.insert(address, account); 62 | addresses.push(address); 63 | } 64 | 65 | let db_full = build_db(&account_db); 66 | assert_eq!(account_trie.root(), H256::from_str("0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544").unwrap()); 67 | assert_eq!(db_full.root(), H256::from_str("0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544").unwrap()); 68 | 69 | let db_full_raw: HashMap> = db_full.into(); 70 | let trie_full_raw: HashMap> = account_trie.clone().to_trie().into(); 71 | assert_eq!(db_full_raw, trie_full_raw); 72 | 73 | for _ in 0..(addresses.len() / 2) { 74 | let i = rand::thread_rng().gen_range(0, addresses.len()); 75 | 76 | let addr = addresses[i]; 77 | addresses.swap_remove(i); 78 | 79 | account_trie.delete(&addr); 80 | account_db.remove(&addr); 81 | } 82 | 83 | let db_half = build_db(&account_db); 84 | 85 | let db_half_raw: HashMap> = db_half.into(); 86 | let trie_half_raw: HashMap> = account_trie.clone().to_trie().into(); 87 | assert_eq!(db_half_raw, trie_half_raw); 88 | 89 | for addr in addresses { 90 | account_trie.delete(&addr); 91 | } 92 | assert_eq!(account_trie.root(), MemoryTrieMut::default().root()); 93 | 94 | let trie_empty_raw: HashMap> = account_trie.clone().to_trie().into(); 95 | assert_eq!(trie_empty_raw.len(), 0); 96 | } 97 | -------------------------------------------------------------------------------- /bloom/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "etcommon-bloom" 3 | version = "0.2.1" 4 | license = "Apache-2.0" 5 | authors = ["Wei Tang "] 6 | description = "Log bloom implementation for Ethereum." 7 | repository = "https://github.com/ethereumproject/etcommon-rs" 8 | 9 | [lib] 10 | name = "bloom" 11 | 12 | [dependencies] 13 | etcommon-rlp = { version = "0.2", path = "../rlp" } 14 | etcommon-bigint = { version = "0.2", path = "../bigint" } 15 | sha3 = "0.6" 16 | 17 | [dev-dependencies] 18 | etcommon-hexutil = "0.2" -------------------------------------------------------------------------------- /bloom/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Log bloom implementation for Ethereum 2 | 3 | extern crate bigint; 4 | extern crate rlp; 5 | #[cfg(test)] 6 | extern crate hexutil; 7 | extern crate sha3; 8 | 9 | use std::ops::BitOr; 10 | use bigint::H2048; 11 | use sha3::{Digest, Keccak256}; 12 | use rlp::{Encodable, Decodable, RlpStream, DecoderError, UntrustedRlp}; 13 | 14 | /// A log bloom for Ethereum 15 | #[derive(Clone, Debug, PartialEq, Eq)] 16 | pub struct LogsBloom(H2048); 17 | 18 | impl From for LogsBloom { 19 | fn from(val: H2048) -> LogsBloom { 20 | LogsBloom(val) 21 | } 22 | } 23 | 24 | impl Into for LogsBloom { 25 | fn into(self) -> H2048 { 26 | self.0 27 | } 28 | } 29 | 30 | impl Encodable for LogsBloom { 31 | fn rlp_append(&self, s: &mut RlpStream) { 32 | self.0.rlp_append(s); 33 | } 34 | } 35 | 36 | impl Decodable for LogsBloom { 37 | fn decode(rlp: &UntrustedRlp) -> Result { 38 | Ok(LogsBloom(H2048::decode(rlp)?)) 39 | } 40 | } 41 | 42 | impl Default for LogsBloom { 43 | fn default() -> LogsBloom { 44 | LogsBloom(H2048::zero()) 45 | } 46 | } 47 | 48 | impl BitOr for LogsBloom { 49 | type Output = LogsBloom; 50 | 51 | fn bitor(self, other: LogsBloom) -> LogsBloom { 52 | LogsBloom(self.0 | other.0) 53 | } 54 | } 55 | 56 | fn single_set(arr: &[u8]) -> H2048 { 57 | let mut r = H2048::zero(); 58 | let h = Keccak256::digest(arr); 59 | for i in [0usize, 2usize, 4usize].iter() { 60 | let m = (((h[*i] as usize) << 8) + (h[*i + 1] as usize)) % 2048; 61 | r[m / 8] = r[m / 8] | (1 << (m % 8)); 62 | } 63 | r 64 | } 65 | 66 | impl LogsBloom { 67 | /// Create a new log bloom 68 | pub fn new() -> LogsBloom { 69 | LogsBloom::default() 70 | } 71 | 72 | /// Set respective bits in the bloom with the array 73 | pub fn set(&mut self, arr: &[u8]) { 74 | self.0 = self.0 | single_set(arr); 75 | } 76 | 77 | /// Check that an array is in the bloom 78 | pub fn check(&self, arr: &[u8]) -> bool { 79 | let s = single_set(arr); 80 | self.0 & s == s 81 | } 82 | } 83 | 84 | #[cfg(test)] 85 | mod tests { 86 | use super::LogsBloom; 87 | use bigint::H2048; 88 | use hexutil::read_hex; 89 | 90 | #[test] 91 | fn test_bloom() { 92 | let mut bloom = LogsBloom::new(); 93 | bloom.set(&read_hex("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap()); 94 | assert!(bloom.check(&read_hex("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap())); 95 | 96 | let h: H2048 = bloom.into(); 97 | for i in [1323usize, 431usize, 1319usize].iter() { 98 | let v = 1 << (i % 8); 99 | assert!(h[i / 8] & v == v); 100 | } 101 | } 102 | } 103 | -------------------------------------------------------------------------------- /hexutil/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "etcommon-hexutil" 3 | version = "0.2.4" 4 | license = "Apache-2.0" 5 | authors = ["Wei Tang "] 6 | description = "Hex helper functions." 7 | repository = "https://github.com/ethereumproject/etcommon-rs" 8 | keywords = ["no_std"] 9 | 10 | [lib] 11 | name = "hexutil" 12 | 13 | [features] 14 | default = ["std"] 15 | std = [] -------------------------------------------------------------------------------- /hexutil/src/lib.rs: -------------------------------------------------------------------------------- 1 | #![cfg_attr(not(feature = "std"), no_std)] 2 | #![cfg_attr(not(feature = "std"), feature(alloc))] 3 | 4 | #[cfg(not(feature = "std"))] 5 | extern crate alloc; 6 | 7 | #[cfg(feature = "std")] 8 | use std::fmt::Write; 9 | 10 | #[cfg(not(feature = "std"))] 11 | use core::fmt::Write; 12 | #[cfg(not(feature = "std"))] 13 | use alloc::vec::Vec; 14 | #[cfg(not(feature = "std"))] 15 | use alloc::string::{ToString, String}; 16 | 17 | #[derive(Debug)] 18 | /// Errors exhibited from `read_hex`. 19 | pub enum ParseHexError { 20 | InvalidCharacter, 21 | TooLong, 22 | TooShort, 23 | Other 24 | } 25 | 26 | /// Return `s` without the `0x` at the beginning of it, if any. 27 | pub fn clean_0x(s: &str) -> &str { 28 | if s.starts_with("0x") { 29 | &s[2..] 30 | } else { 31 | s 32 | } 33 | } 34 | 35 | /// Parses a given hex string and return a list of bytes if 36 | /// succeeded. The string can optionally start by `0x`, which 37 | /// indicates that it is a hex representation. 38 | pub fn read_hex(s: &str) -> Result, ParseHexError> { 39 | if s.starts_with("0x") { 40 | return read_hex(&s[2..s.len()]); 41 | } 42 | 43 | if s.len() & 1 == 1 { 44 | let mut new_s = "0".to_string(); 45 | new_s.push_str(s); 46 | return read_hex(&new_s); 47 | } 48 | 49 | let mut res = Vec::::new(); 50 | 51 | let mut cur = 0; 52 | let mut len = 0; 53 | for c in s.chars() { 54 | len += 1; 55 | let v_option = c.to_digit(16); 56 | if v_option.is_none() { 57 | return Err(ParseHexError::InvalidCharacter); 58 | } 59 | let v = v_option.unwrap(); 60 | if len == 1 { 61 | cur += v * 16; 62 | } else { // len == 2 63 | cur += v; 64 | } 65 | if len == 2 { 66 | res.push(cur as u8); 67 | cur = 0; 68 | len = 0; 69 | } 70 | } 71 | 72 | return Ok(res); 73 | } 74 | 75 | /// Given a bytearray, get a Ethereum-compatible string hex. 76 | pub fn to_hex(a: &[u8]) -> String { 77 | let mut s = String::new(); 78 | write!(s, "0x").unwrap(); 79 | for v in a { 80 | write!(s, "{:02x}", *v).unwrap(); 81 | } 82 | s 83 | } 84 | 85 | #[cfg(test)] 86 | mod tests { 87 | use super::read_hex; 88 | 89 | #[test] 90 | fn read_hex_zero() { 91 | assert_eq!(read_hex("0x0").unwrap(), vec![0u8]); 92 | assert_eq!(read_hex("0").unwrap(), vec![0u8]); 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /nightly.nix: -------------------------------------------------------------------------------- 1 | let pkgs = ( 2 | let 3 | nixpkgs = import ; 4 | pkgs_ = (nixpkgs {}); 5 | rustOverlay = (pkgs_.fetchFromGitHub { 6 | owner = "mozilla"; 7 | repo = "nixpkgs-mozilla"; 8 | rev = "6179dd876578ca2931f864627598ede16ba6cdef"; 9 | sha256 = "1lim10a674621zayz90nhwiynlakxry8fyz1x209g9bdm38zy3av"; 10 | }); 11 | in (nixpkgs { 12 | overlays = [ 13 | (import (builtins.toPath "${rustOverlay}/rust-overlay.nix")) 14 | (self: super: { 15 | rust = { 16 | rustc = super.rustChannels.nightly.rust; 17 | cargo = super.rustChannels.nightly.cargo; 18 | }; 19 | rustPlatform = super.recurseIntoAttrs (super.makeRustPlatform { 20 | rustc = super.rustChannels.nightly.rust; 21 | cargo = super.rustChannels.nightly.cargo; 22 | }); 23 | }) 24 | ]; 25 | })); 26 | 27 | in with pkgs; 28 | 29 | stdenv.mkDerivation { 30 | name = "sputnikvm-env"; 31 | buildInputs = [ 32 | rustc cargo gdb 33 | ]; 34 | } 35 | -------------------------------------------------------------------------------- /rlp/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "etcommon-rlp" 3 | description = "Recursive-length prefix encoding, decoding, and compression" 4 | repository = "https://github.com/ethereumproject/etcommon-rs" 5 | license = "MIT/Apache-2.0" 6 | version = "0.2.5" 7 | authors = ["Parity Technologies ", "Wei Tang "] 8 | keywords = ["no_std"] 9 | 10 | [lib] 11 | name = "rlp" 12 | 13 | [dependencies] 14 | elastic-array-plus = { version = "0.10.0", default-features = false } 15 | lazy_static = { version = "1.4", optional = true } 16 | byteorder = { version = "1.0", default-features = false } 17 | etcommon-hexutil = { version = "0.2", path = "../hexutil", default-features = false } 18 | 19 | [features] 20 | default = ["std"] 21 | std = ["etcommon-hexutil/std", "byteorder/std", "lazy_static", "elastic-array-plus/std"] 22 | -------------------------------------------------------------------------------- /rlp/LICENSE-APACHE2: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /rlp/LICENSE-MIT: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015-2017 Parity Technologies 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy 4 | of this software and associated documentation files (the "Software"), to deal 5 | in the Software without restriction, including without limitation the rights 6 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 7 | copies of the Software, and to permit persons to whom the Software is 8 | furnished to do so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /rlp/README.md: -------------------------------------------------------------------------------- 1 | # RLP 2 | 3 | Recursive-length-prefix encoding, decoding, and compression in Rust. 4 | 5 | ## License 6 | 7 | Unlike most parts of Parity, which fall under the GPLv3, this package is dual-licensed under MIT/Apache2 at the user's choice. 8 | Find the associated license files in this directory as `LICENSE-MIT` and `LICENSE-APACHE2` respectively. 9 | -------------------------------------------------------------------------------- /rlp/benches/rlp.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! benchmarking for rlp 10 | //! should be started with: 11 | //! ```bash 12 | //! multirust run nightly cargo bench 13 | //! ``` 14 | 15 | #![feature(test)] 16 | 17 | extern crate test; 18 | extern crate sputnikvm_rlp as rlp; 19 | 20 | use test::Bencher; 21 | use rlp::{RlpStream, Rlp}; 22 | 23 | #[bench] 24 | fn bench_stream_u64_value(b: &mut Bencher) { 25 | b.iter(|| { 26 | // u64 27 | let mut stream = RlpStream::new(); 28 | stream.append(&0x1023456789abcdefu64); 29 | let _ = stream.out(); 30 | }); 31 | } 32 | 33 | #[bench] 34 | fn bench_decode_u64_value(b: &mut Bencher) { 35 | b.iter(|| { 36 | // u64 37 | let data = vec![0x88, 0x10, 0x23, 0x45, 0x67, 0x89, 0xab, 0xcd, 0xef]; 38 | let rlp = Rlp::new(&data); 39 | let _: u64 = rlp.as_val(); 40 | }); 41 | } 42 | 43 | #[bench] 44 | fn bench_stream_nested_empty_lists(b: &mut Bencher) { 45 | b.iter(|| { 46 | // [ [], [[]], [ [], [[]] ] ] 47 | let mut stream = RlpStream::new_list(3); 48 | stream.begin_list(0); 49 | stream.begin_list(1).begin_list(0); 50 | stream.begin_list(2).begin_list(0).begin_list(1).begin_list(0); 51 | let _ = stream.out(); 52 | }); 53 | } 54 | 55 | #[bench] 56 | fn bench_decode_nested_empty_lists(b: &mut Bencher) { 57 | b.iter(|| { 58 | // [ [], [[]], [ [], [[]] ] ] 59 | let data = vec![0xc7, 0xc0, 0xc1, 0xc0, 0xc3, 0xc0, 0xc1, 0xc0]; 60 | let rlp = Rlp::new(&data); 61 | let _v0: Vec = rlp.at(0).as_list(); 62 | let _v1: Vec = rlp.at(1).at(0).as_list(); 63 | let nested_rlp = rlp.at(2); 64 | let _v2a: Vec = nested_rlp.at(0).as_list(); 65 | let _v2b: Vec = nested_rlp.at(1).at(0).as_list(); 66 | }); 67 | } 68 | 69 | #[bench] 70 | fn bench_stream_1000_empty_lists(b: &mut Bencher) { 71 | b.iter(|| { 72 | let mut stream = RlpStream::new_list(1000); 73 | for _ in 0..1000 { 74 | stream.begin_list(0); 75 | } 76 | let _ = stream.out(); 77 | }); 78 | } 79 | -------------------------------------------------------------------------------- /rlp/license-header: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | -------------------------------------------------------------------------------- /rlp/src/common.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! Contains RLPs used for compression. 10 | 11 | use compression::InvalidRlpSwapper; 12 | 13 | #[cfg(feature = "std")] 14 | lazy_static! { 15 | /// Swapper for snapshot compression. 16 | pub static ref SNAPSHOT_RLP_SWAPPER: InvalidRlpSwapper<'static> = InvalidRlpSwapper::new(EMPTY_RLPS, INVALID_RLPS); 17 | } 18 | 19 | #[cfg(feature = "std")] 20 | lazy_static! { 21 | /// Swapper with common long RLPs, up to 127 can be added. 22 | pub static ref BLOCKS_RLP_SWAPPER: InvalidRlpSwapper<'static> = InvalidRlpSwapper::new(COMMON_RLPS, INVALID_RLPS); 23 | } 24 | 25 | static EMPTY_RLPS: &'static [&'static [u8]] = &[ 26 | // RLP of SHA3_NULL_RLP 27 | &[160, 86, 232, 31, 23, 27, 204, 85, 166, 255, 131, 69, 230, 146, 192, 248, 110, 91, 72, 224, 27, 153, 108, 173, 192, 1, 98, 47, 181, 227, 99, 180, 33], 28 | // RLP of SHA3_EMPTY 29 | &[160, 197, 210, 70, 1, 134, 247, 35, 60, 146, 126, 125, 178, 220, 199, 3, 192, 229, 0, 182, 83, 202, 130, 39, 59, 123, 250, 216, 4, 93, 133, 164, 112] 30 | ]; 31 | 32 | static COMMON_RLPS: &'static [&'static [u8]] = &[ 33 | // RLP of SHA3_NULL_RLP 34 | &[160, 86, 232, 31, 23, 27, 204, 85, 166, 255, 131, 69, 230, 146, 192, 248, 110, 91, 72, 224, 27, 153, 108, 173, 192, 1, 98, 47, 181, 227, 99, 180, 33], 35 | // RLP of SHA3_EMPTY 36 | &[160, 197, 210, 70, 1, 134, 247, 35, 60, 146, 126, 125, 178, 220, 199, 3, 192, 229, 0, 182, 83, 202, 130, 39, 59, 123, 250, 216, 4, 93, 133, 164, 112], 37 | // Other RLPs found in blocks DB using the test below. 38 | &[160, 29, 204, 77, 232, 222, 199, 93, 122, 171, 133, 181, 103, 182, 204, 212, 26, 211, 18, 69, 27, 148, 138, 116, 19, 240, 161, 66, 253, 64, 212, 147, 71], 39 | &[148, 50, 190, 52, 59, 148, 248, 96, 18, 77, 196, 254, 226, 120, 253, 203, 211, 140, 16, 45, 136], 40 | &[148, 82, 188, 68, 213, 55, 131, 9, 238, 42, 191, 21, 57, 191, 113, 222, 27, 125, 123, 227, 181], 41 | &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0] 42 | ]; 43 | 44 | static INVALID_RLPS: &'static [&'static [u8]] = &[&[0x81, 0x0], &[0x81, 0x1], &[0x81, 0x2], &[0x81, 0x3], &[0x81, 0x4], &[0x81, 0x5], &[0x81, 0x6], &[0x81, 0x7], &[0x81, 0x8], &[0x81, 0x9], &[0x81, 0xa], &[0x81, 0xb], &[0x81, 0xc], &[0x81, 0xd], &[0x81, 0xe], &[0x81, 0xf], &[0x81, 0x10], &[0x81, 0x11], &[0x81, 0x12], &[0x81, 0x13], &[0x81, 0x14], &[0x81, 0x15], &[0x81, 0x16], &[0x81, 0x17], &[0x81, 0x18], &[0x81, 0x19], &[0x81, 0x1a], &[0x81, 0x1b], &[0x81, 0x1c], &[0x81, 0x1d], &[0x81, 0x1e], &[0x81, 0x1f], &[0x81, 0x20], &[0x81, 0x21], &[0x81, 0x22], &[0x81, 0x23], &[0x81, 0x24], &[0x81, 0x25], &[0x81, 0x26], &[0x81, 0x27], &[0x81, 0x28], &[0x81, 0x29], &[0x81, 0x2a], &[0x81, 0x2b], &[0x81, 0x2c], &[0x81, 0x2d], &[0x81, 0x2e], &[0x81, 0x2f], &[0x81, 0x30], &[0x81, 0x31], &[0x81, 0x32], &[0x81, 0x33], &[0x81, 0x34], &[0x81, 0x35], &[0x81, 0x36], &[0x81, 0x37], &[0x81, 0x38], &[0x81, 0x39], &[0x81, 0x3a], &[0x81, 0x3b], &[0x81, 0x3c], &[0x81, 0x3d], &[0x81, 0x3e], &[0x81, 0x3f], &[0x81, 0x40], &[0x81, 0x41], &[0x81, 0x42], &[0x81, 0x43], &[0x81, 0x44], &[0x81, 0x45], &[0x81, 0x46], &[0x81, 0x47], &[0x81, 0x48], &[0x81, 0x49], &[0x81, 0x4a], &[0x81, 0x4b], &[0x81, 0x4c], &[0x81, 0x4d], &[0x81, 0x4e], &[0x81, 0x4f], &[0x81, 0x50], &[0x81, 0x51], &[0x81, 0x52], &[0x81, 0x53], &[0x81, 0x54], &[0x81, 0x55], &[0x81, 0x56], &[0x81, 0x57], &[0x81, 0x58], &[0x81, 0x59], &[0x81, 0x5a], &[0x81, 0x5b], &[0x81, 0x5c], &[0x81, 0x5d], &[0x81, 0x5e], &[0x81, 0x5f], &[0x81, 0x60], &[0x81, 0x61], &[0x81, 0x62], &[0x81, 0x63], &[0x81, 0x64], &[0x81, 0x65], &[0x81, 0x66], &[0x81, 0x67], &[0x81, 0x68], &[0x81, 0x69], &[0x81, 0x6a], &[0x81, 0x6b], &[0x81, 0x6c], &[0x81, 0x6d], &[0x81, 0x6e], &[0x81, 0x6f], &[0x81, 0x70], &[0x81, 0x71], &[0x81, 0x72], &[0x81, 0x73], &[0x81, 0x74], &[0x81, 0x75], &[0x81, 0x76], &[0x81, 0x77], &[0x81, 0x78], &[0x81, 0x79], &[0x81, 0x7a], &[0x81, 0x7b], &[0x81, 0x7c], &[0x81, 0x7d], &[0x81, 0x7e]]; 45 | -------------------------------------------------------------------------------- /rlp/src/compression.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | #[cfg(feature = "std")] use std::collections::{HashMap as Map}; 10 | #[cfg(not(feature = "std"))] use alloc::collections::{BTreeMap as Map}; 11 | use elastic_array::ElasticArray1024; 12 | #[cfg(feature = "std")] 13 | use common::{BLOCKS_RLP_SWAPPER, SNAPSHOT_RLP_SWAPPER}; 14 | use {UntrustedRlp, Compressible, encode, RlpStream}; 15 | 16 | /// Stores RLPs used for compression 17 | pub struct InvalidRlpSwapper<'a> { 18 | invalid_to_valid: Map<&'a [u8], &'a [u8]>, 19 | valid_to_invalid: Map<&'a [u8], &'a [u8]>, 20 | } 21 | 22 | impl<'a> InvalidRlpSwapper<'a> { 23 | /// Construct a swapper from a list of common RLPs 24 | pub fn new(rlps_to_swap: &[&'a [u8]], invalid_rlps: &[&'a [u8]]) -> Self { 25 | if rlps_to_swap.len() > 0x7e { 26 | panic!("Invalid usage, only 127 RLPs can be swappable."); 27 | } 28 | let mut invalid_to_valid = Map::new(); 29 | let mut valid_to_invalid = Map::new(); 30 | for (&rlp, &invalid) in rlps_to_swap.iter().zip(invalid_rlps.iter()) { 31 | invalid_to_valid.insert(invalid, rlp); 32 | valid_to_invalid.insert(rlp, invalid); 33 | } 34 | InvalidRlpSwapper { 35 | invalid_to_valid: invalid_to_valid, 36 | valid_to_invalid: valid_to_invalid 37 | } 38 | } 39 | /// Get a valid RLP corresponding to an invalid one 40 | fn get_valid(&self, invalid_rlp: &[u8]) -> Option<&[u8]> { 41 | self.invalid_to_valid.get(invalid_rlp).cloned() 42 | } 43 | /// Get an invalid RLP corresponding to a valid one 44 | fn get_invalid(&self, valid_rlp: &[u8]) -> Option<&[u8]> { 45 | self.valid_to_invalid.get(valid_rlp).cloned() 46 | } 47 | } 48 | 49 | /// Type of RLP indicating its origin database. 50 | pub enum RlpType { 51 | /// RLP used in blocks database. 52 | Blocks, 53 | /// RLP used in snapshots. 54 | Snapshot, 55 | } 56 | 57 | fn to_elastic(slice: &[u8]) -> ElasticArray1024 { 58 | let mut out = ElasticArray1024::new(); 59 | out.append_slice(slice); 60 | out 61 | } 62 | 63 | fn map_rlp(rlp: &UntrustedRlp, f: F) -> Option> where 64 | F: Fn(&UntrustedRlp) -> Option> { 65 | match rlp.iter() 66 | .fold((false, RlpStream::new_list(rlp.item_count().unwrap_or(0))), 67 | |(is_some, mut acc), subrlp| { 68 | let new = f(&subrlp); 69 | if let Some(ref insert) = new { 70 | acc.append_raw(&insert[..], 1); 71 | } else { 72 | acc.append_raw(subrlp.as_raw(), 1); 73 | } 74 | (is_some || new.is_some(), acc) 75 | }) { 76 | (true, s) => Some(s.drain()), 77 | _ => None, 78 | } 79 | } 80 | 81 | /// Replace common RLPs with invalid shorter ones. 82 | fn simple_compress(rlp: &UntrustedRlp, swapper: &InvalidRlpSwapper) -> ElasticArray1024 { 83 | if rlp.is_data() { 84 | to_elastic(swapper.get_invalid(rlp.as_raw()).unwrap_or_else(|| rlp.as_raw())) 85 | } else { 86 | map_rlp(rlp, |r| Some(simple_compress(r, swapper))).unwrap_or_else(|| to_elastic(rlp.as_raw())) 87 | } 88 | } 89 | 90 | /// Recover valid RLP from a compressed form. 91 | fn simple_decompress(rlp: &UntrustedRlp, swapper: &InvalidRlpSwapper) -> ElasticArray1024 { 92 | if rlp.is_data() { 93 | to_elastic(swapper.get_valid(rlp.as_raw()).unwrap_or_else(|| rlp.as_raw())) 94 | } else { 95 | map_rlp(rlp, |r| Some(simple_decompress(r, swapper))).unwrap_or_else(|| to_elastic(rlp.as_raw())) 96 | } 97 | } 98 | 99 | /// Replace common RLPs with invalid shorter ones, None if no compression achieved. 100 | /// Tries to compress data insides. 101 | fn deep_compress(rlp: &UntrustedRlp, swapper: &InvalidRlpSwapper) -> Option> { 102 | let simple_swap = || 103 | swapper.get_invalid(rlp.as_raw()).map(to_elastic); 104 | if rlp.is_data() { 105 | // Try to treat the inside as RLP. 106 | return match rlp.payload_info() { 107 | // Shortest decompressed account is 70, so simply try to swap the value. 108 | Ok(ref p) if p.value_len < 70 => simple_swap(), 109 | _ => { 110 | if let Ok(d) = rlp.data() { 111 | let internal_rlp = UntrustedRlp::new(d); 112 | if let Some(new_d) = deep_compress(&internal_rlp, swapper) { 113 | // If compressed put in a special list, with first element being invalid code. 114 | let mut rlp = RlpStream::new_list(2); 115 | rlp.append_raw(&[0x81, 0x7f], 1); 116 | rlp.append_raw(&new_d[..], 1); 117 | return Some(rlp.drain()); 118 | } 119 | } 120 | simple_swap() 121 | }, 122 | }; 123 | } 124 | // Iterate through RLP while checking if it has been compressed. 125 | map_rlp(rlp, |r| deep_compress(r, swapper)) 126 | } 127 | 128 | /// Recover valid RLP from a compressed form, None if no decompression achieved. 129 | /// Tries to decompress compressed data insides. 130 | fn deep_decompress(rlp: &UntrustedRlp, swapper: &InvalidRlpSwapper) -> Option> { 131 | let simple_swap = || 132 | swapper.get_valid(rlp.as_raw()).map(to_elastic); 133 | // Simply decompress data. 134 | if rlp.is_data() { return simple_swap(); } 135 | match rlp.item_count().unwrap_or(0) { 136 | // Look for special compressed list, which contains nested data. 137 | 2 if rlp.at(0).map(|r| r.as_raw() == &[0x81, 0x7f]).unwrap_or(false) => 138 | rlp.at(1).ok().map_or(simple_swap(), 139 | |r| deep_decompress(&r, swapper).map(|d| { let v = d.to_vec(); encode(&v) })), 140 | // Iterate through RLP while checking if it has been compressed. 141 | _ => map_rlp(rlp, |r| deep_decompress(r, swapper)), 142 | } 143 | } 144 | 145 | #[cfg(feature = "std")] 146 | impl<'a> Compressible for UntrustedRlp<'a> { 147 | type DataType = RlpType; 148 | 149 | fn compress(&self, t: RlpType) -> ElasticArray1024 { 150 | match t { 151 | RlpType::Snapshot => simple_compress(self, &SNAPSHOT_RLP_SWAPPER), 152 | RlpType::Blocks => deep_compress(self, &BLOCKS_RLP_SWAPPER).unwrap_or_else(|| to_elastic(self.as_raw())), 153 | } 154 | } 155 | 156 | fn decompress(&self, t: RlpType) -> ElasticArray1024 { 157 | match t { 158 | RlpType::Snapshot => simple_decompress(self, &SNAPSHOT_RLP_SWAPPER), 159 | RlpType::Blocks => deep_decompress(self, &BLOCKS_RLP_SWAPPER).unwrap_or_else(|| to_elastic(self.as_raw())), 160 | } 161 | } 162 | } 163 | 164 | #[cfg(test)] 165 | mod tests { 166 | use compression::InvalidRlpSwapper; 167 | use {UntrustedRlp, Compressible, RlpType}; 168 | 169 | #[test] 170 | fn invalid_rlp_swapper() { 171 | let to_swap: &[&[u8]] = &[&[0x83, b'c', b'a', b't'], &[0x83, b'd', b'o', b'g']]; 172 | let invalid_rlp: &[&[u8]] = &[&[0x81, 0x00], &[0x81, 0x01]]; 173 | let swapper = InvalidRlpSwapper::new(to_swap, invalid_rlp); 174 | assert_eq!(Some(invalid_rlp[0]), swapper.get_invalid(&[0x83, b'c', b'a', b't'])); 175 | assert_eq!(None, swapper.get_invalid(&[0x83, b'b', b'a', b't'])); 176 | assert_eq!(Some(to_swap[1]), swapper.get_valid(invalid_rlp[1])); 177 | } 178 | 179 | #[test] 180 | fn simple_compression() { 181 | let basic_account_rlp = vec![248, 68, 4, 2, 160, 86, 232, 31, 23, 27, 204, 85, 166, 255, 131, 69, 230, 146, 192, 248, 110, 91, 72, 224, 27, 153, 108, 173, 192, 1, 98, 47, 181, 227, 99, 180, 33, 160, 197, 210, 70, 1, 134, 247, 35, 60, 146, 126, 125, 178, 220, 199, 3, 192, 229, 0, 182, 83, 202, 130, 39, 59, 123, 250, 216, 4, 93, 133, 164, 112]; 182 | let rlp = UntrustedRlp::new(&basic_account_rlp); 183 | let compressed = rlp.compress(RlpType::Snapshot).to_vec(); 184 | assert_eq!(compressed, vec![198, 4, 2, 129, 0, 129, 1]); 185 | let compressed_rlp = UntrustedRlp::new(&compressed); 186 | assert_eq!(compressed_rlp.decompress(RlpType::Snapshot).to_vec(), basic_account_rlp); 187 | } 188 | 189 | #[test] 190 | fn data_compression() { 191 | let data_basic_account_rlp = vec![184, 70, 248, 68, 4, 2, 160, 86, 232, 31, 23, 27, 204, 85, 166, 255, 131, 69, 230, 146, 192, 248, 110, 91, 72, 224, 27, 153, 108, 173, 192, 1, 98, 47, 181, 227, 99, 180, 33, 160, 197, 210, 70, 1, 134, 247, 35, 60, 146, 126, 125, 178, 220, 199, 3, 192, 229, 0, 182, 83, 202, 130, 39, 59, 123, 250, 216, 4, 93, 133, 164, 112]; 192 | let data_rlp = UntrustedRlp::new(&data_basic_account_rlp); 193 | let compressed = data_rlp.compress(RlpType::Blocks).to_vec(); 194 | assert_eq!(compressed, vec![201, 129, 127, 198, 4, 2, 129, 0, 129, 1]); 195 | let compressed_rlp = UntrustedRlp::new(&compressed); 196 | assert_eq!(compressed_rlp.decompress(RlpType::Blocks).to_vec(), data_basic_account_rlp); 197 | } 198 | 199 | #[test] 200 | fn nested_list_rlp() { 201 | let nested_basic_account_rlp = vec![228, 4, 226, 2, 160, 86, 232, 31, 23, 27, 204, 85, 166, 255, 131, 69, 230, 146, 192, 248, 110, 91, 72, 224, 27, 153, 108, 173, 192, 1, 98, 47, 181, 227, 99, 180, 33]; 202 | let nested_rlp = UntrustedRlp::new(&nested_basic_account_rlp); 203 | let compressed = nested_rlp.compress(RlpType::Blocks).to_vec(); 204 | assert_eq!(compressed, vec![197, 4, 195, 2, 129, 0]); 205 | let compressed_rlp = UntrustedRlp::new(&compressed); 206 | assert_eq!(compressed_rlp.decompress(RlpType::Blocks).to_vec(), nested_basic_account_rlp); 207 | let compressed = nested_rlp.compress(RlpType::Snapshot).to_vec(); 208 | assert_eq!(compressed, vec![197, 4, 195, 2, 129, 0]); 209 | let compressed_rlp = UntrustedRlp::new(&compressed); 210 | assert_eq!(compressed_rlp.decompress(RlpType::Snapshot).to_vec(), nested_basic_account_rlp); 211 | } 212 | 213 | #[test] 214 | fn malformed_rlp() { 215 | let malformed = vec![248, 81, 128, 128, 128, 128, 128, 160, 12, 51, 241, 93, 69, 218, 74, 138, 79, 115, 227, 44, 216, 81, 46, 132, 85, 235, 96, 45, 252, 48, 181, 29, 75, 141, 217, 215, 86, 160, 109, 130, 160, 140, 36, 93, 200, 109, 215, 100, 241, 246, 99, 135, 92, 168, 149, 170, 114, 9, 143, 4, 93, 25, 76, 54, 176, 119, 230, 170, 154, 105, 47, 121, 10, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128]; 216 | let malformed_rlp = UntrustedRlp::new(&malformed); 217 | assert_eq!(malformed_rlp.decompress(RlpType::Blocks).to_vec(), malformed); 218 | } 219 | } 220 | -------------------------------------------------------------------------------- /rlp/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | #[cfg(feature = "std")] use std::fmt; 10 | #[cfg(not(feature = "std"))] use core::fmt; 11 | 12 | #[cfg(feature = "std")] 13 | use std::error::Error as StdError; 14 | 15 | #[derive(Debug, PartialEq, Eq)] 16 | /// Error concerning the RLP decoder. 17 | pub enum DecoderError { 18 | /// Data has additional bytes at the end of the valid RLP fragment. 19 | RlpIsTooBig, 20 | /// Data has too few bytes for valid RLP. 21 | RlpIsTooShort, 22 | /// Expect an encoded list, RLP was something else. 23 | RlpExpectedToBeList, 24 | /// Expect encoded data, RLP was something else. 25 | RlpExpectedToBeData, 26 | /// Expected a different size list. 27 | RlpIncorrectListLen, 28 | /// Data length number has a prefixed zero byte, invalid for numbers. 29 | RlpDataLenWithZeroPrefix, 30 | /// List length number has a prefixed zero byte, invalid for numbers. 31 | RlpListLenWithZeroPrefix, 32 | /// Non-canonical (longer than necessary) representation used for data or list. 33 | RlpInvalidIndirection, 34 | /// Declared length is inconsistent with data specified after. 35 | RlpInconsistentLengthAndData, 36 | /// Custom rlp decoding error. 37 | Custom(&'static str), 38 | } 39 | 40 | #[cfg(feature = "std")] 41 | impl StdError for DecoderError { 42 | fn description(&self) -> &str { 43 | "builder error" 44 | } 45 | } 46 | 47 | impl fmt::Display for DecoderError { 48 | fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { 49 | fmt::Debug::fmt(&self, f) 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /rlp/src/impls.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | #[cfg(not(feature = "std"))]use alloc::vec::Vec; 10 | #[cfg(not(feature = "std"))]use alloc::string::String; 11 | 12 | #[cfg(feature = "std")] use std::{cmp, mem, str}; 13 | #[cfg(not(feature = "std"))] use core::{cmp, mem, str}; 14 | use byteorder::{ByteOrder, BigEndian}; 15 | use traits::{Encodable, Decodable}; 16 | use stream::RlpStream; 17 | use {UntrustedRlp, DecoderError}; 18 | 19 | pub fn decode_usize(bytes: &[u8]) -> Result { 20 | match bytes.len() { 21 | l if l <= mem::size_of::() => { 22 | if bytes[0] == 0 { 23 | return Err(DecoderError::RlpInvalidIndirection); 24 | } 25 | let mut res = 0usize; 26 | for i in 0..l { 27 | let shift = (l - 1 - i) * 8; 28 | res = res + ((bytes[i] as usize) << shift); 29 | } 30 | Ok(res) 31 | } 32 | _ => Err(DecoderError::RlpIsTooBig), 33 | } 34 | } 35 | 36 | impl Encodable for bool { 37 | fn rlp_append(&self, s: &mut RlpStream) { 38 | if *self { 39 | s.encoder().encode_value(&[1]); 40 | } else { 41 | s.encoder().encode_value(&[0]); 42 | } 43 | } 44 | } 45 | 46 | impl Decodable for bool { 47 | fn decode(rlp: &UntrustedRlp) -> Result { 48 | rlp.decoder().decode_value(|bytes| { 49 | match bytes.len() { 50 | 0 => Ok(false), 51 | 1 => Ok(bytes[0] != 0), 52 | _ => Err(DecoderError::RlpIsTooBig), 53 | } 54 | }) 55 | } 56 | } 57 | 58 | impl<'a> Encodable for &'a [u8] { 59 | fn rlp_append(&self, s: &mut RlpStream) { 60 | s.encoder().encode_value(self); 61 | } 62 | } 63 | 64 | impl Encodable for Vec { 65 | fn rlp_append(&self, s: &mut RlpStream) { 66 | s.encoder().encode_value(self); 67 | } 68 | } 69 | 70 | impl Decodable for Vec { 71 | fn decode(rlp: &UntrustedRlp) -> Result { 72 | rlp.decoder().decode_value(|bytes| { 73 | Ok(bytes.to_vec()) 74 | }) 75 | } 76 | } 77 | 78 | impl Encodable for Option where T: Encodable { 79 | fn rlp_append(&self, s: &mut RlpStream) { 80 | match *self { 81 | None => { 82 | s.begin_list(0); 83 | }, 84 | Some(ref value) => { 85 | s.begin_list(1); 86 | s.append(value); 87 | } 88 | } 89 | } 90 | } 91 | 92 | impl Decodable for Option where T: Decodable { 93 | fn decode(rlp: &UntrustedRlp) -> Result { 94 | let items = rlp.item_count()?; 95 | match items { 96 | 1 => rlp.val_at(0).map(Some), 97 | 0 => Ok(None), 98 | _ => Err(DecoderError::RlpIncorrectListLen), 99 | } 100 | } 101 | } 102 | 103 | impl Encodable for u8 { 104 | fn rlp_append(&self, s: &mut RlpStream) { 105 | if *self != 0 { 106 | s.encoder().encode_value(&[*self]); 107 | } else { 108 | s.encoder().encode_value(&[]); 109 | } 110 | } 111 | } 112 | 113 | impl Decodable for u8 { 114 | fn decode(rlp: &UntrustedRlp) -> Result { 115 | rlp.decoder().decode_value(|bytes| { 116 | match bytes.len() { 117 | 1 if bytes[0] != 0 => Ok(bytes[0]), 118 | 0 => Ok(0), 119 | 1 => Err(DecoderError::RlpInvalidIndirection), 120 | _ => Err(DecoderError::RlpIsTooBig), 121 | } 122 | }) 123 | } 124 | } 125 | 126 | macro_rules! impl_encodable_for_u { 127 | ($name: ident, $func: ident, $size: expr) => { 128 | impl Encodable for $name { 129 | fn rlp_append(&self, s: &mut RlpStream) { 130 | let leading_empty_bytes = self.leading_zeros() as usize / 8; 131 | let mut buffer = [0u8; $size]; 132 | BigEndian::$func(&mut buffer, *self); 133 | s.encoder().encode_value(&buffer[leading_empty_bytes..]); 134 | } 135 | } 136 | } 137 | } 138 | 139 | macro_rules! impl_decodable_for_u { 140 | ($name: ident) => { 141 | impl Decodable for $name { 142 | fn decode(rlp: &UntrustedRlp) -> Result { 143 | rlp.decoder().decode_value(|bytes| { 144 | match bytes.len() { 145 | 0 | 1 => u8::decode(rlp).map(|v| v as $name), 146 | l if l <= mem::size_of::<$name>() => { 147 | if bytes[0] == 0 { 148 | return Err(DecoderError::RlpInvalidIndirection); 149 | } 150 | let mut res = 0 as $name; 151 | for i in 0..l { 152 | let shift = (l - 1 - i) * 8; 153 | res = res + ((bytes[i] as $name) << shift); 154 | } 155 | Ok(res) 156 | } 157 | _ => Err(DecoderError::RlpIsTooBig), 158 | } 159 | }) 160 | } 161 | } 162 | } 163 | } 164 | 165 | impl_encodable_for_u!(u16, write_u16, 2); 166 | impl_encodable_for_u!(u32, write_u32, 4); 167 | impl_encodable_for_u!(u64, write_u64, 8); 168 | 169 | impl_decodable_for_u!(u16); 170 | impl_decodable_for_u!(u32); 171 | impl_decodable_for_u!(u64); 172 | 173 | impl Encodable for usize { 174 | fn rlp_append(&self, s: &mut RlpStream) { 175 | (*self as u64).rlp_append(s); 176 | } 177 | } 178 | 179 | impl Decodable for usize { 180 | fn decode(rlp: &UntrustedRlp) -> Result { 181 | u64::decode(rlp).map(|value| value as usize) 182 | } 183 | } 184 | 185 | macro_rules! impl_encodable_for_hash { 186 | ($name: ident) => { 187 | impl Encodable for $name { 188 | fn rlp_append(&self, s: &mut RlpStream) { 189 | s.encoder().encode_value(self); 190 | } 191 | } 192 | } 193 | } 194 | 195 | macro_rules! impl_decodable_for_hash { 196 | ($name: ident, $size: expr) => { 197 | impl Decodable for $name { 198 | fn decode(rlp: &UntrustedRlp) -> Result { 199 | rlp.decoder().decode_value(|bytes| match bytes.len().cmp(&$size) { 200 | cmp::Ordering::Less => Err(DecoderError::RlpIsTooShort), 201 | cmp::Ordering::Greater => Err(DecoderError::RlpIsTooBig), 202 | cmp::Ordering::Equal => { 203 | let mut t = [0u8; $size]; 204 | t.copy_from_slice(bytes); 205 | Ok($name(t)) 206 | } 207 | }) 208 | } 209 | } 210 | } 211 | } 212 | 213 | impl<'a> Encodable for &'a str { 214 | fn rlp_append(&self, s: &mut RlpStream) { 215 | s.encoder().encode_value(self.as_bytes()); 216 | } 217 | } 218 | 219 | impl Encodable for String { 220 | fn rlp_append(&self, s: &mut RlpStream) { 221 | s.encoder().encode_value(self.as_bytes()); 222 | } 223 | } 224 | 225 | impl Decodable for String { 226 | fn decode(rlp: &UntrustedRlp) -> Result { 227 | #[cfg(not(feature = "std"))] 228 | use alloc::borrow::ToOwned; 229 | 230 | rlp.decoder().decode_value(|bytes| { 231 | match str::from_utf8(bytes) { 232 | Ok(s) => Ok(s.to_owned()), 233 | // consider better error type here 234 | Err(_err) => Err(DecoderError::RlpExpectedToBeData), 235 | } 236 | }) 237 | } 238 | } 239 | -------------------------------------------------------------------------------- /rlp/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | #![cfg_attr(not(feature = "std"), no_std)] 10 | #![cfg_attr(not(feature = "std"), feature(alloc))] 11 | 12 | //! Recursive Length Prefix serialization crate. 13 | //! 14 | //! Allows encoding, decoding, and view onto rlp-slice 15 | //! 16 | //!# What should you use when? 17 | //! 18 | //!### Use `encode` function when: 19 | //! * You want to encode something inline. 20 | //! * You do not work on big set of data. 21 | //! * You want to encode whole data structure at once. 22 | //! 23 | //!### Use `decode` function when: 24 | //! * You want to decode something inline. 25 | //! * You do not work on big set of data. 26 | //! * You want to decode whole rlp at once. 27 | //! 28 | //!### Use `RlpStream` when: 29 | //! * You want to encode something in portions. 30 | //! * You encode a big set of data. 31 | //! 32 | //!### Use `Rlp` when: 33 | //! * You are working on trusted data (not corrupted). 34 | //! * You want to get view onto rlp-slice. 35 | //! * You don't want to decode whole rlp at once. 36 | //! 37 | //!### Use `UntrustedRlp` when: 38 | //! * You are working on untrusted data (~corrupted). 39 | //! * You need to handle data corruption errors. 40 | //! * You are working on input data. 41 | //! * You want to get view onto rlp-slice. 42 | //! * You don't want to decode whole rlp at once. 43 | 44 | extern crate byteorder; 45 | extern crate elastic_array; 46 | extern crate hexutil; 47 | 48 | #[cfg(not(feature = "std"))] 49 | extern crate alloc; 50 | 51 | #[cfg(feature = "std")] 52 | #[macro_use] 53 | extern crate lazy_static; 54 | 55 | mod traits; 56 | mod error; 57 | mod rlpin; 58 | mod untrusted_rlp; 59 | mod stream; 60 | mod compression; 61 | mod common; 62 | mod impls; 63 | 64 | #[cfg(not(feature = "std"))]use alloc::vec::Vec; 65 | #[cfg(not(feature = "std"))]use alloc::string::String; 66 | 67 | #[cfg(feature = "std")] use std::borrow::Borrow; 68 | #[cfg(not(feature = "std"))] use core::borrow::Borrow; 69 | 70 | use elastic_array::ElasticArray1024; 71 | 72 | pub use error::DecoderError; 73 | pub use traits::{Decodable, Encodable, Compressible}; 74 | pub use untrusted_rlp::{UntrustedRlp, UntrustedRlpIterator, PayloadInfo, Prototype}; 75 | pub use rlpin::{Rlp, RlpIterator}; 76 | pub use stream::RlpStream; 77 | pub use compression::RlpType; 78 | 79 | /// The RLP encoded empty data (used to mean "null value"). 80 | pub const NULL_RLP: [u8; 1] = [0x80; 1]; 81 | /// The RLP encoded empty list. 82 | pub const EMPTY_LIST_RLP: [u8; 1] = [0xC0; 1]; 83 | 84 | /// Shortcut function to decode trusted rlp 85 | /// 86 | /// ```rust 87 | /// extern crate rlp; 88 | /// 89 | /// fn main () { 90 | /// let data = vec![0x83, b'c', b'a', b't']; 91 | /// let animal: String = rlp::decode(&data); 92 | /// assert_eq!(animal, "cat".to_owned()); 93 | /// } 94 | /// ``` 95 | pub fn decode(bytes: &[u8]) -> T where T: Decodable { 96 | let rlp = Rlp::new(bytes); 97 | rlp.as_val() 98 | } 99 | 100 | pub fn decode_list(bytes: &[u8]) -> Vec where T: Decodable { 101 | let rlp = Rlp::new(bytes); 102 | rlp.as_list() 103 | } 104 | 105 | /// Shortcut function to encode structure into rlp. 106 | /// 107 | /// ```rust 108 | /// extern crate rlp; 109 | /// 110 | /// fn main () { 111 | /// let animal = "cat"; 112 | /// let out = rlp::encode(&animal).to_vec(); 113 | /// assert_eq!(out, vec![0x83, b'c', b'a', b't']); 114 | /// } 115 | /// ``` 116 | pub fn encode(object: &E) -> ElasticArray1024 where E: Encodable { 117 | let mut stream = RlpStream::new(); 118 | stream.append(object); 119 | stream.drain() 120 | } 121 | 122 | pub fn encode_list(object: &[K]) -> ElasticArray1024 where E: Encodable, K: Borrow { 123 | let mut stream = RlpStream::new(); 124 | stream.append_list(object); 125 | stream.drain() 126 | } 127 | -------------------------------------------------------------------------------- /rlp/src/rlpin.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | #[cfg(not(feature = "std"))]use alloc::vec::Vec; 10 | #[cfg(not(feature = "std"))]use alloc::string::String; 11 | 12 | #[cfg(feature = "std")] use std::fmt; 13 | #[cfg(not(feature = "std"))] use core::fmt; 14 | use {UntrustedRlp, PayloadInfo, Prototype, Decodable}; 15 | 16 | impl<'a> From> for Rlp<'a> { 17 | fn from(rlp: UntrustedRlp<'a>) -> Rlp<'a> { 18 | Rlp { rlp: rlp } 19 | } 20 | } 21 | 22 | /// Data-oriented view onto trusted rlp-slice. 23 | /// 24 | /// Unlikely to `UntrustedRlp` doesn't bother you with error 25 | /// handling. It assumes that you know what you are doing. 26 | #[derive(Debug)] 27 | pub struct Rlp<'a> { 28 | rlp: UntrustedRlp<'a> 29 | } 30 | 31 | impl<'a> fmt::Display for Rlp<'a> { 32 | fn fmt(&self, f: &mut fmt::Formatter) -> Result<(), fmt::Error> { 33 | write!(f, "{}", self.rlp) 34 | } 35 | } 36 | 37 | impl<'a, 'view> Rlp<'a> where 'a: 'view { 38 | /// Create a new instance of `Rlp` 39 | pub fn new(bytes: &'a [u8]) -> Rlp<'a> { 40 | Rlp { 41 | rlp: UntrustedRlp::new(bytes) 42 | } 43 | } 44 | 45 | /// The raw data of the RLP as slice. 46 | /// 47 | /// ```rust 48 | /// extern crate rlp; 49 | /// use rlp::*; 50 | /// 51 | /// fn main () { 52 | /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; 53 | /// let rlp = Rlp::new(&data); 54 | /// let dog = rlp.at(1).as_raw(); 55 | /// assert_eq!(dog, &[0x83, b'd', b'o', b'g']); 56 | /// } 57 | /// ``` 58 | pub fn as_raw(&'view self) -> &'a [u8] { 59 | self.rlp.as_raw() 60 | } 61 | 62 | /// Get the prototype of the RLP. 63 | pub fn prototype(&self) -> Prototype { 64 | self.rlp.prototype().unwrap() 65 | } 66 | 67 | /// Get payload info. 68 | pub fn payload_info(&self) -> PayloadInfo { 69 | self.rlp.payload_info().unwrap() 70 | } 71 | 72 | /// Get underlieing data. 73 | pub fn data(&'view self) -> &'a [u8] { 74 | self.rlp.data().unwrap() 75 | } 76 | 77 | /// Returns number of RLP items. 78 | /// 79 | /// ```rust 80 | /// extern crate rlp; 81 | /// use rlp::*; 82 | /// 83 | /// fn main () { 84 | /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; 85 | /// let rlp = Rlp::new(&data); 86 | /// assert_eq!(rlp.item_count(), 2); 87 | /// let view = rlp.at(1); 88 | /// assert_eq!(view.item_count(), 0); 89 | /// } 90 | /// ``` 91 | pub fn item_count(&self) -> usize { 92 | self.rlp.item_count().unwrap_or(0) 93 | } 94 | 95 | /// Returns the number of bytes in the data, or zero if it isn't data. 96 | /// 97 | /// ```rust 98 | /// extern crate rlp; 99 | /// use rlp::*; 100 | /// 101 | /// fn main () { 102 | /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; 103 | /// let rlp = Rlp::new(&data); 104 | /// assert_eq!(rlp.size(), 0); 105 | /// let view = rlp.at(1); 106 | /// assert_eq!(view.size(), 3); 107 | /// } 108 | /// ``` 109 | pub fn size(&self) -> usize { 110 | self.rlp.size() 111 | } 112 | 113 | /// Get view onto RLP-slice at index. 114 | /// 115 | /// Caches offset to given index, so access to successive 116 | /// slices is faster. 117 | /// 118 | /// ```rust 119 | /// extern crate rlp; 120 | /// use rlp::*; 121 | /// 122 | /// fn main () { 123 | /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; 124 | /// let rlp = Rlp::new(&data); 125 | /// let dog: String = rlp.at(1).as_val(); 126 | /// assert_eq!(dog, "dog".to_string()); 127 | /// } 128 | /// ``` 129 | pub fn at(&'view self, index: usize) -> Rlp<'a> { 130 | From::from(self.rlp.at(index).unwrap()) 131 | } 132 | 133 | /// No value 134 | /// 135 | /// ```rust 136 | /// extern crate rlp; 137 | /// use rlp::*; 138 | /// 139 | /// fn main () { 140 | /// let data = vec![]; 141 | /// let rlp = Rlp::new(&data); 142 | /// assert!(rlp.is_null()); 143 | /// } 144 | /// ``` 145 | pub fn is_null(&self) -> bool { 146 | self.rlp.is_null() 147 | } 148 | 149 | /// Contains a zero-length string or zero-length list. 150 | /// 151 | /// ```rust 152 | /// extern crate rlp; 153 | /// use rlp::*; 154 | /// 155 | /// fn main () { 156 | /// let data = vec![0xc0]; 157 | /// let rlp = Rlp::new(&data); 158 | /// assert!(rlp.is_empty()); 159 | /// } 160 | /// ``` 161 | pub fn is_empty(&self) -> bool { 162 | self.rlp.is_empty() 163 | } 164 | 165 | /// List value 166 | /// 167 | /// ```rust 168 | /// extern crate rlp; 169 | /// use rlp::*; 170 | /// 171 | /// fn main () { 172 | /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; 173 | /// let rlp = Rlp::new(&data); 174 | /// assert!(rlp.is_list()); 175 | /// } 176 | /// ``` 177 | pub fn is_list(&self) -> bool { 178 | self.rlp.is_list() 179 | } 180 | 181 | /// String value 182 | /// 183 | /// ```rust 184 | /// extern crate rlp; 185 | /// use rlp::*; 186 | /// 187 | /// fn main () { 188 | /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; 189 | /// let rlp = Rlp::new(&data); 190 | /// assert!(rlp.at(1).is_data()); 191 | /// } 192 | /// ``` 193 | pub fn is_data(&self) -> bool { 194 | self.rlp.is_data() 195 | } 196 | 197 | /// Int value 198 | /// 199 | /// ```rust 200 | /// extern crate rlp; 201 | /// use rlp::*; 202 | /// 203 | /// fn main () { 204 | /// let data = vec![0xc1, 0x10]; 205 | /// let rlp = Rlp::new(&data); 206 | /// assert_eq!(rlp.is_int(), false); 207 | /// assert_eq!(rlp.at(0).is_int(), true); 208 | /// } 209 | /// ``` 210 | pub fn is_int(&self) -> bool { 211 | self.rlp.is_int() 212 | } 213 | 214 | /// Get iterator over rlp-slices 215 | /// 216 | /// ```rust 217 | /// extern crate rlp; 218 | /// use rlp::*; 219 | /// 220 | /// fn main () { 221 | /// let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; 222 | /// let rlp = Rlp::new(&data); 223 | /// let strings: Vec = rlp.iter().map(| i | i.as_val()).collect(); 224 | /// } 225 | /// ``` 226 | pub fn iter(&'view self) -> RlpIterator<'a, 'view> { 227 | self.into_iter() 228 | } 229 | 230 | /// Decode data into an object 231 | pub fn as_val(&self) -> T where T: Decodable { 232 | self.rlp.as_val().expect("Unexpected rlp error") 233 | } 234 | 235 | pub fn as_list(&self) -> Vec where T: Decodable { 236 | self.iter().map(|rlp| rlp.as_val()).collect() 237 | } 238 | 239 | /// Decode data at given list index into an object 240 | pub fn val_at(&self, index: usize) -> T where T: Decodable { 241 | self.at(index).as_val() 242 | } 243 | 244 | pub fn list_at(&self, index: usize) -> Vec where T: Decodable { 245 | self.at(index).as_list() 246 | } 247 | } 248 | 249 | /// Iterator over trusted rlp-slice list elements. 250 | pub struct RlpIterator<'a, 'view> where 'a: 'view { 251 | rlp: &'view Rlp<'a>, 252 | index: usize 253 | } 254 | 255 | impl<'a, 'view> IntoIterator for &'view Rlp<'a> where 'a: 'view { 256 | type Item = Rlp<'a>; 257 | type IntoIter = RlpIterator<'a, 'view>; 258 | 259 | fn into_iter(self) -> Self::IntoIter { 260 | RlpIterator { 261 | rlp: self, 262 | index: 0, 263 | } 264 | } 265 | } 266 | 267 | impl<'a, 'view> Iterator for RlpIterator<'a, 'view> { 268 | type Item = Rlp<'a>; 269 | 270 | fn next(&mut self) -> Option> { 271 | let index = self.index; 272 | let result = self.rlp.rlp.at(index).ok().map(From::from); 273 | self.index += 1; 274 | result 275 | } 276 | } 277 | -------------------------------------------------------------------------------- /rlp/src/stream.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | #[cfg(not(feature = "std"))] use alloc::string::String; 10 | #[cfg(not(feature = "std"))] use alloc::vec::Vec; 11 | 12 | #[cfg(feature = "std")] use std::borrow::Borrow; 13 | #[cfg(not(feature = "std"))] use core::borrow::Borrow; 14 | use byteorder::{ByteOrder, BigEndian}; 15 | use elastic_array::{ElasticArray16, ElasticArray1024}; 16 | use traits::Encodable; 17 | 18 | #[derive(Debug, Copy, Clone)] 19 | struct ListInfo { 20 | position: usize, 21 | current: usize, 22 | max: Option, 23 | } 24 | 25 | impl ListInfo { 26 | fn new(position: usize, max: Option) -> ListInfo { 27 | ListInfo { 28 | position: position, 29 | current: 0, 30 | max: max, 31 | } 32 | } 33 | } 34 | 35 | /// Appendable rlp encoder. 36 | pub struct RlpStream { 37 | unfinished_lists: ElasticArray16, 38 | buffer: ElasticArray1024, 39 | finished_list: bool, 40 | } 41 | 42 | impl Default for RlpStream { 43 | fn default() -> Self { 44 | RlpStream::new() 45 | } 46 | } 47 | 48 | impl RlpStream { 49 | /// Initializes instance of empty `Stream`. 50 | pub fn new() -> Self { 51 | RlpStream { 52 | unfinished_lists: ElasticArray16::new(), 53 | buffer: ElasticArray1024::new(), 54 | finished_list: false, 55 | } 56 | } 57 | 58 | /// Initializes the `Stream` as a list. 59 | pub fn new_list(len: usize) -> Self { 60 | let mut stream = RlpStream::new(); 61 | stream.begin_list(len); 62 | stream 63 | } 64 | 65 | /// Appends value to the end of stream, chainable. 66 | /// 67 | /// ```rust 68 | /// extern crate rlp; 69 | /// use rlp::*; 70 | /// 71 | /// fn main () { 72 | /// let mut stream = RlpStream::new_list(2); 73 | /// stream.append(&"cat").append(&"dog"); 74 | /// let out = stream.out(); 75 | /// assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); 76 | /// } 77 | /// ``` 78 | pub fn append<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable { 79 | self.finished_list = false; 80 | value.rlp_append(self); 81 | if !self.finished_list { 82 | self.note_appended(1); 83 | } 84 | self 85 | } 86 | 87 | /// Appends list of values to the end of stream, chainable. 88 | pub fn append_list<'a, E, K>(&'a mut self, values: &[K]) -> &'a mut Self where E: Encodable, K: Borrow { 89 | self.begin_list(values.len()); 90 | for value in values { 91 | self.append(value.borrow()); 92 | } 93 | self 94 | } 95 | 96 | /// Appends value to the end of stream, but do not count it as an appended item. 97 | /// It's useful for wrapper types 98 | pub fn append_internal<'a, E>(&'a mut self, value: &E) -> &'a mut Self where E: Encodable { 99 | value.rlp_append(self); 100 | self 101 | } 102 | 103 | /// Declare appending the list of given size, chainable. 104 | /// 105 | /// ```rust 106 | /// extern crate rlp; 107 | /// use rlp::*; 108 | /// 109 | /// fn main () { 110 | /// let mut stream = RlpStream::new_list(2); 111 | /// stream.begin_list(2).append(&"cat").append(&"dog"); 112 | /// stream.append(&""); 113 | /// let out = stream.out(); 114 | /// assert_eq!(out, vec![0xca, 0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g', 0x80]); 115 | /// } 116 | /// ``` 117 | pub fn begin_list(&mut self, len: usize) -> &mut RlpStream { 118 | self.finished_list = false; 119 | match len { 120 | 0 => { 121 | // we may finish, if the appended list len is equal 0 122 | self.buffer.push(0xc0u8); 123 | self.note_appended(1); 124 | self.finished_list = true; 125 | }, 126 | _ => { 127 | // payload is longer than 1 byte only for lists > 55 bytes 128 | // by pushing always this 1 byte we may avoid unnecessary shift of data 129 | self.buffer.push(0); 130 | 131 | let position = self.buffer.len(); 132 | self.unfinished_lists.push(ListInfo::new(position, Some(len))); 133 | }, 134 | } 135 | 136 | // return chainable self 137 | self 138 | } 139 | 140 | 141 | /// Declare appending the list of unknown size, chainable. 142 | pub fn begin_unbounded_list(&mut self) -> &mut RlpStream { 143 | self.finished_list = false; 144 | // payload is longer than 1 byte only for lists > 55 bytes 145 | // by pushing always this 1 byte we may avoid unnecessary shift of data 146 | self.buffer.push(0); 147 | let position = self.buffer.len(); 148 | self.unfinished_lists.push(ListInfo::new(position, None)); 149 | // return chainable self 150 | self 151 | } 152 | 153 | /// Apends null to the end of stream, chainable. 154 | /// 155 | /// ```rust 156 | /// extern crate rlp; 157 | /// use rlp::*; 158 | /// 159 | /// fn main () { 160 | /// let mut stream = RlpStream::new_list(2); 161 | /// stream.append_empty_data().append_empty_data(); 162 | /// let out = stream.out(); 163 | /// assert_eq!(out, vec![0xc2, 0x80, 0x80]); 164 | /// } 165 | /// ``` 166 | pub fn append_empty_data(&mut self) -> &mut RlpStream { 167 | // self push raw item 168 | self.buffer.push(0x80); 169 | 170 | // try to finish and prepend the length 171 | self.note_appended(1); 172 | 173 | // return chainable self 174 | self 175 | } 176 | 177 | /// Appends raw (pre-serialised) RLP data. Use with caution. Chainable. 178 | pub fn append_raw<'a>(&'a mut self, bytes: &[u8], item_count: usize) -> &'a mut RlpStream { 179 | // push raw items 180 | self.buffer.append_slice(bytes); 181 | 182 | // try to finish and prepend the length 183 | self.note_appended(item_count); 184 | 185 | // return chainable self 186 | self 187 | } 188 | 189 | /// Appends raw (pre-serialised) RLP data. Checks for size oveflow. 190 | pub fn append_raw_checked<'a>(&'a mut self, bytes: &[u8], item_count: usize, max_size: usize) -> bool { 191 | if self.estimate_size(bytes.len()) > max_size { 192 | return false; 193 | } 194 | self.append_raw(bytes, item_count); 195 | true 196 | } 197 | 198 | /// Calculate total RLP size for appended payload. 199 | pub fn estimate_size<'a>(&'a self, add: usize) -> usize { 200 | let total_size = self.buffer.len() + add; 201 | let mut base_size = total_size; 202 | for list in &self.unfinished_lists[..] { 203 | let len = total_size - list.position; 204 | if len > 55 { 205 | let leading_empty_bytes = (len as u64).leading_zeros() as usize / 8; 206 | let size_bytes = 8 - leading_empty_bytes; 207 | base_size += size_bytes; 208 | } 209 | } 210 | base_size 211 | } 212 | 213 | 214 | /// Returns current RLP size in bytes for the data pushed into the list. 215 | pub fn len<'a>(&'a self) -> usize { 216 | self.estimate_size(0) 217 | } 218 | 219 | /// Clear the output stream so far. 220 | /// 221 | /// ```rust 222 | /// extern crate rlp; 223 | /// use rlp::*; 224 | /// 225 | /// fn main () { 226 | /// let mut stream = RlpStream::new_list(3); 227 | /// stream.append(&"cat"); 228 | /// stream.clear(); 229 | /// stream.append(&"dog"); 230 | /// let out = stream.out(); 231 | /// assert_eq!(out, vec![0x83, b'd', b'o', b'g']); 232 | /// } 233 | pub fn clear(&mut self) { 234 | // clear bytes 235 | self.buffer.clear(); 236 | 237 | // clear lists 238 | self.unfinished_lists.clear(); 239 | } 240 | 241 | /// Returns true if stream doesnt expect any more items. 242 | /// 243 | /// ```rust 244 | /// extern crate rlp; 245 | /// use rlp::*; 246 | /// 247 | /// fn main () { 248 | /// let mut stream = RlpStream::new_list(2); 249 | /// stream.append(&"cat"); 250 | /// assert_eq!(stream.is_finished(), false); 251 | /// stream.append(&"dog"); 252 | /// assert_eq!(stream.is_finished(), true); 253 | /// let out = stream.out(); 254 | /// assert_eq!(out, vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']); 255 | /// } 256 | pub fn is_finished(&self) -> bool { 257 | self.unfinished_lists.len() == 0 258 | } 259 | 260 | /// Get raw encoded bytes 261 | pub fn as_raw(&self) -> &[u8] { 262 | //&self.encoder.bytes 263 | &self.buffer 264 | } 265 | 266 | /// Streams out encoded bytes. 267 | /// 268 | /// panic! if stream is not finished. 269 | pub fn out(self) -> Vec { 270 | match self.is_finished() { 271 | //true => self.encoder.out().to_vec(), 272 | true => self.buffer.to_vec(), 273 | false => panic!() 274 | } 275 | } 276 | 277 | /// Try to finish lists 278 | fn note_appended(&mut self, inserted_items: usize) -> () { 279 | if self.unfinished_lists.len() == 0 { 280 | return; 281 | } 282 | 283 | let back = self.unfinished_lists.len() - 1; 284 | let should_finish = match self.unfinished_lists.get_mut(back) { 285 | None => false, 286 | Some(ref mut x) => { 287 | x.current += inserted_items; 288 | match x.max { 289 | Some(ref max) if x.current > *max => panic!("You cannot append more items then you expect!"), 290 | Some(ref max) => x.current == *max, 291 | _ => false, 292 | } 293 | } 294 | }; 295 | 296 | if should_finish { 297 | let x = self.unfinished_lists.pop().unwrap(); 298 | let len = self.buffer.len() - x.position; 299 | self.encoder().insert_list_payload(len, x.position); 300 | self.note_appended(1); 301 | } 302 | self.finished_list = should_finish; 303 | } 304 | 305 | pub fn encoder(&mut self) -> BasicEncoder { 306 | BasicEncoder::new(self) 307 | } 308 | 309 | /// Drain the object and return the underlying ElasticArray. 310 | pub fn drain(self) -> ElasticArray1024 { 311 | match self.is_finished() { 312 | true => self.buffer, 313 | false => panic!() 314 | } 315 | } 316 | 317 | /// Finalize current ubnbound list. Panics if no unbounded list has been opened. 318 | pub fn complete_unbounded_list(&mut self) { 319 | let list = self.unfinished_lists.pop().expect("No open list."); 320 | if list.max.is_some() { 321 | panic!("List type mismatch."); 322 | } 323 | let len = self.buffer.len() - list.position; 324 | self.encoder().insert_list_payload(len, list.position); 325 | self.note_appended(1); 326 | } 327 | } 328 | 329 | pub struct BasicEncoder<'a> { 330 | buffer: &'a mut ElasticArray1024, 331 | } 332 | 333 | impl<'a> BasicEncoder<'a> { 334 | fn new(stream: &'a mut RlpStream) -> Self { 335 | BasicEncoder { 336 | buffer: &mut stream.buffer 337 | } 338 | } 339 | 340 | fn insert_size(&mut self, size: usize, position: usize) -> u8 { 341 | let size = size as u32; 342 | let leading_empty_bytes = size.leading_zeros() as usize / 8; 343 | let size_bytes = 4 - leading_empty_bytes as u8; 344 | let mut buffer = [0u8; 4]; 345 | BigEndian::write_u32(&mut buffer, size); 346 | self.buffer.insert_slice(position, &buffer[leading_empty_bytes..]); 347 | size_bytes as u8 348 | } 349 | 350 | /// Inserts list prefix at given position 351 | fn insert_list_payload(&mut self, len: usize, pos: usize) { 352 | // 1 byte was already reserved for payload earlier 353 | match len { 354 | 0...55 => { 355 | self.buffer[pos - 1] = 0xc0u8 + len as u8; 356 | }, 357 | _ => { 358 | let inserted_bytes = self.insert_size(len, pos); 359 | self.buffer[pos - 1] = 0xf7u8 + inserted_bytes; 360 | } 361 | }; 362 | } 363 | 364 | /// Pushes encoded value to the end of buffer 365 | pub fn encode_value(&mut self, value: &[u8]) { 366 | match value.len() { 367 | // just 0 368 | 0 => self.buffer.push(0x80u8), 369 | // byte is its own encoding if < 0x80 370 | 1 if value[0] < 0x80 => self.buffer.push(value[0]), 371 | // (prefix + length), followed by the string 372 | len @ 1 ... 55 => { 373 | self.buffer.push(0x80u8 + len as u8); 374 | self.buffer.append_slice(value); 375 | } 376 | // (prefix + length of length), followed by the length, followd by the string 377 | len => { 378 | self.buffer.push(0); 379 | let position = self.buffer.len(); 380 | let inserted_bytes = self.insert_size(len, position); 381 | self.buffer[position - 1] = 0xb7 + inserted_bytes; 382 | self.buffer.append_slice(value); 383 | } 384 | } 385 | } 386 | } 387 | -------------------------------------------------------------------------------- /rlp/src/traits.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | //! Common RLP traits 10 | use elastic_array::ElasticArray1024; 11 | use {DecoderError, UntrustedRlp, RlpStream}; 12 | 13 | /// RLP decodable trait 14 | pub trait Decodable: Sized { 15 | /// Decode a value from RLP bytes 16 | fn decode(rlp: &UntrustedRlp) -> Result; 17 | } 18 | 19 | /// Structure encodable to RLP 20 | pub trait Encodable { 21 | /// Append a value to the stream 22 | fn rlp_append(&self, s: &mut RlpStream); 23 | 24 | /// Get rlp-encoded bytes for this instance 25 | fn rlp_bytes(&self) -> ElasticArray1024 { 26 | let mut s = RlpStream::new(); 27 | self.rlp_append(&mut s); 28 | s.drain() 29 | } 30 | } 31 | 32 | /// Trait for compressing and decompressing RLP by replacement of common terms. 33 | pub trait Compressible: Sized { 34 | /// Indicates the origin of RLP to be compressed. 35 | type DataType; 36 | 37 | /// Compress given RLP type using appropriate methods. 38 | fn compress(&self, t: Self::DataType) -> ElasticArray1024; 39 | /// Decompress given RLP type using appropriate methods. 40 | fn decompress(&self, t: Self::DataType) -> ElasticArray1024; 41 | } 42 | -------------------------------------------------------------------------------- /rlp/tests/tests.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2017 Parity Technologies 2 | // 3 | // Licensed under the Apache License, Version 2.0 or the MIT license 5 | // , at your 6 | // option. This file may not be copied, modified, or distributed 7 | // except according to those terms. 8 | 9 | extern crate rlp; 10 | 11 | use std::{fmt, cmp}; 12 | use rlp::{Encodable, Decodable, UntrustedRlp, RlpStream, DecoderError}; 13 | 14 | #[test] 15 | fn rlp_at() { 16 | let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; 17 | { 18 | let rlp = UntrustedRlp::new(&data); 19 | assert!(rlp.is_list()); 20 | let animals: Vec = rlp.as_list().unwrap(); 21 | assert_eq!(animals, vec!["cat".to_owned(), "dog".to_owned()]); 22 | 23 | let cat = rlp.at(0).unwrap(); 24 | assert!(cat.is_data()); 25 | assert_eq!(cat.as_raw(), &[0x83, b'c', b'a', b't']); 26 | assert_eq!(cat.as_val::().unwrap(), "cat".to_owned()); 27 | 28 | let dog = rlp.at(1).unwrap(); 29 | assert!(dog.is_data()); 30 | assert_eq!(dog.as_raw(), &[0x83, b'd', b'o', b'g']); 31 | assert_eq!(dog.as_val::().unwrap(), "dog".to_owned()); 32 | 33 | let cat_again = rlp.at(0).unwrap(); 34 | assert!(cat_again.is_data()); 35 | assert_eq!(cat_again.as_raw(), &[0x83, b'c', b'a', b't']); 36 | assert_eq!(cat_again.as_val::().unwrap(), "cat".to_owned()); 37 | } 38 | } 39 | 40 | #[test] 41 | fn rlp_at_err() { 42 | let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o']; 43 | { 44 | let rlp = UntrustedRlp::new(&data); 45 | assert!(rlp.is_list()); 46 | 47 | let cat_err = rlp.at(0).unwrap_err(); 48 | assert_eq!(cat_err, DecoderError::RlpIsTooShort); 49 | 50 | let dog_err = rlp.at(1).unwrap_err(); 51 | assert_eq!(dog_err, DecoderError::RlpIsTooShort); 52 | } 53 | } 54 | 55 | #[test] 56 | fn rlp_iter() { 57 | let data = vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g']; 58 | { 59 | let rlp = UntrustedRlp::new(&data); 60 | let mut iter = rlp.iter(); 61 | 62 | let cat = iter.next().unwrap(); 63 | assert!(cat.is_data()); 64 | assert_eq!(cat.as_raw(), &[0x83, b'c', b'a', b't']); 65 | 66 | let dog = iter.next().unwrap(); 67 | assert!(dog.is_data()); 68 | assert_eq!(dog.as_raw(), &[0x83, b'd', b'o', b'g']); 69 | 70 | let none = iter.next(); 71 | assert!(none.is_none()); 72 | 73 | let cat_again = rlp.at(0).unwrap(); 74 | assert!(cat_again.is_data()); 75 | assert_eq!(cat_again.as_raw(), &[0x83, b'c', b'a', b't']); 76 | } 77 | } 78 | 79 | struct ETestPair(T, Vec) where T: Encodable; 80 | 81 | fn run_encode_tests(tests: Vec>) 82 | where T: Encodable 83 | { 84 | for t in &tests { 85 | let res = rlp::encode(&t.0); 86 | assert_eq!(&res[..], &t.1[..]); 87 | } 88 | } 89 | 90 | struct VETestPair(Vec, Vec) where T: Encodable; 91 | 92 | fn run_encode_tests_list(tests: Vec>) 93 | where T: Encodable 94 | { 95 | for t in &tests { 96 | let res = rlp::encode_list(&t.0); 97 | assert_eq!(&res[..], &t.1[..]); 98 | } 99 | } 100 | 101 | #[test] 102 | fn encode_u16() { 103 | let tests = vec![ 104 | ETestPair(0u16, vec![0x80u8]), 105 | ETestPair(0x100, vec![0x82, 0x01, 0x00]), 106 | ETestPair(0xffff, vec![0x82, 0xff, 0xff]), 107 | ]; 108 | run_encode_tests(tests); 109 | } 110 | 111 | #[test] 112 | fn encode_u32() { 113 | let tests = vec![ 114 | ETestPair(0u32, vec![0x80u8]), 115 | ETestPair(0x10000, vec![0x83, 0x01, 0x00, 0x00]), 116 | ETestPair(0xffffff, vec![0x83, 0xff, 0xff, 0xff]), 117 | ]; 118 | run_encode_tests(tests); 119 | } 120 | 121 | #[test] 122 | fn encode_u64() { 123 | let tests = vec![ 124 | ETestPair(0u64, vec![0x80u8]), 125 | ETestPair(0x1000000, vec![0x84, 0x01, 0x00, 0x00, 0x00]), 126 | ETestPair(0xFFFFFFFF, vec![0x84, 0xff, 0xff, 0xff, 0xff]), 127 | ]; 128 | run_encode_tests(tests); 129 | } 130 | 131 | #[test] 132 | fn encode_str() { 133 | let tests = vec![ETestPair("cat", vec![0x83, b'c', b'a', b't']), 134 | ETestPair("dog", vec![0x83, b'd', b'o', b'g']), 135 | ETestPair("Marek", vec![0x85, b'M', b'a', b'r', b'e', b'k']), 136 | ETestPair("", vec![0x80]), 137 | ETestPair("Lorem ipsum dolor sit amet, consectetur adipisicing elit", 138 | vec![0xb8, 0x38, b'L', b'o', b'r', b'e', b'm', b' ', b'i', 139 | b'p', b's', b'u', b'm', b' ', b'd', b'o', b'l', b'o', 140 | b'r', b' ', b's', b'i', b't', b' ', b'a', b'm', b'e', 141 | b't', b',', b' ', b'c', b'o', b'n', b's', b'e', b'c', 142 | b't', b'e', b't', b'u', b'r', b' ', b'a', b'd', b'i', 143 | b'p', b'i', b's', b'i', b'c', b'i', b'n', b'g', b' ', 144 | b'e', b'l', b'i', b't'])]; 145 | run_encode_tests(tests); 146 | } 147 | 148 | /// Vec (Bytes) is treated as a single value 149 | #[test] 150 | fn encode_vector_u8() { 151 | let tests = vec![ 152 | ETestPair(vec![], vec![0x80]), 153 | ETestPair(vec![0u8], vec![0]), 154 | ETestPair(vec![0x15], vec![0x15]), 155 | ETestPair(vec![0x40, 0x00], vec![0x82, 0x40, 0x00]), 156 | ]; 157 | run_encode_tests(tests); 158 | } 159 | 160 | #[test] 161 | fn encode_vector_u64() { 162 | let tests = vec![ 163 | VETestPair(vec![], vec![0xc0]), 164 | VETestPair(vec![15u64], vec![0xc1, 0x0f]), 165 | VETestPair(vec![1, 2, 3, 7, 0xff], vec![0xc6, 1, 2, 3, 7, 0x81, 0xff]), 166 | VETestPair(vec![0xffffffff, 1, 2, 3, 7, 0xff], vec![0xcb, 0x84, 0xff, 0xff, 0xff, 0xff, 1, 2, 3, 7, 0x81, 0xff]), 167 | ]; 168 | run_encode_tests_list(tests); 169 | } 170 | 171 | #[test] 172 | fn encode_vector_str() { 173 | let tests = vec![VETestPair(vec!["cat", "dog"], 174 | vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'])]; 175 | run_encode_tests_list(tests); 176 | } 177 | 178 | struct DTestPair(T, Vec) where T: Decodable + fmt::Debug + cmp::Eq; 179 | 180 | struct VDTestPair(Vec, Vec) where T: Decodable + fmt::Debug + cmp::Eq; 181 | 182 | fn run_decode_tests(tests: Vec>) where T: Decodable + fmt::Debug + cmp::Eq { 183 | for t in &tests { 184 | let res: T = rlp::decode(&t.1); 185 | assert_eq!(res, t.0); 186 | } 187 | } 188 | 189 | fn run_decode_tests_list(tests: Vec>) where T: Decodable + fmt::Debug + cmp::Eq { 190 | for t in &tests { 191 | let res: Vec = rlp::decode_list(&t.1); 192 | assert_eq!(res, t.0); 193 | } 194 | } 195 | 196 | /// Vec (Bytes) is treated as a single value 197 | #[test] 198 | fn decode_vector_u8() { 199 | let tests = vec![ 200 | DTestPair(vec![], vec![0x80]), 201 | DTestPair(vec![0u8], vec![0]), 202 | DTestPair(vec![0x15], vec![0x15]), 203 | DTestPair(vec![0x40, 0x00], vec![0x82, 0x40, 0x00]), 204 | ]; 205 | run_decode_tests(tests); 206 | } 207 | 208 | #[test] 209 | fn decode_untrusted_u8() { 210 | let tests = vec![ 211 | DTestPair(0x0u8, vec![0x80]), 212 | DTestPair(0x77u8, vec![0x77]), 213 | DTestPair(0xccu8, vec![0x81, 0xcc]), 214 | ]; 215 | run_decode_tests(tests); 216 | } 217 | 218 | #[test] 219 | fn decode_untrusted_u16() { 220 | let tests = vec![ 221 | DTestPair(0x100u16, vec![0x82, 0x01, 0x00]), 222 | DTestPair(0xffffu16, vec![0x82, 0xff, 0xff]), 223 | ]; 224 | run_decode_tests(tests); 225 | } 226 | 227 | #[test] 228 | fn decode_untrusted_u32() { 229 | let tests = vec![ 230 | DTestPair(0x10000u32, vec![0x83, 0x01, 0x00, 0x00]), 231 | DTestPair(0xffffffu32, vec![0x83, 0xff, 0xff, 0xff]), 232 | ]; 233 | run_decode_tests(tests); 234 | } 235 | 236 | #[test] 237 | fn decode_untrusted_u64() { 238 | let tests = vec![ 239 | DTestPair(0x1000000u64, vec![0x84, 0x01, 0x00, 0x00, 0x00]), 240 | DTestPair(0xFFFFFFFFu64, vec![0x84, 0xff, 0xff, 0xff, 0xff]), 241 | ]; 242 | run_decode_tests(tests); 243 | } 244 | 245 | #[test] 246 | fn decode_untrusted_str() { 247 | let tests = vec![DTestPair("cat".to_owned(), vec![0x83, b'c', b'a', b't']), 248 | DTestPair("dog".to_owned(), vec![0x83, b'd', b'o', b'g']), 249 | DTestPair("Marek".to_owned(), 250 | vec![0x85, b'M', b'a', b'r', b'e', b'k']), 251 | DTestPair("".to_owned(), vec![0x80]), 252 | DTestPair("Lorem ipsum dolor sit amet, consectetur adipisicing elit" 253 | .to_owned(), 254 | vec![0xb8, 0x38, b'L', b'o', b'r', b'e', b'm', b' ', b'i', 255 | b'p', b's', b'u', b'm', b' ', b'd', b'o', b'l', b'o', 256 | b'r', b' ', b's', b'i', b't', b' ', b'a', b'm', b'e', 257 | b't', b',', b' ', b'c', b'o', b'n', b's', b'e', b'c', 258 | b't', b'e', b't', b'u', b'r', b' ', b'a', b'd', b'i', 259 | b'p', b'i', b's', b'i', b'c', b'i', b'n', b'g', b' ', 260 | b'e', b'l', b'i', b't'])]; 261 | run_decode_tests(tests); 262 | } 263 | 264 | #[test] 265 | fn decode_untrusted_vector_u64() { 266 | let tests = vec![ 267 | VDTestPair(vec![], vec![0xc0]), 268 | VDTestPair(vec![15u64], vec![0xc1, 0x0f]), 269 | VDTestPair(vec![1, 2, 3, 7, 0xff], vec![0xc6, 1, 2, 3, 7, 0x81, 0xff]), 270 | VDTestPair(vec![0xffffffff, 1, 2, 3, 7, 0xff], vec![0xcb, 0x84, 0xff, 0xff, 0xff, 0xff, 1, 2, 3, 7, 0x81, 0xff]), 271 | ]; 272 | run_decode_tests_list(tests); 273 | } 274 | 275 | #[test] 276 | fn decode_untrusted_vector_str() { 277 | let tests = vec![VDTestPair(vec!["cat".to_owned(), "dog".to_owned()], 278 | vec![0xc8, 0x83, b'c', b'a', b't', 0x83, b'd', b'o', b'g'])]; 279 | run_decode_tests_list(tests); 280 | } 281 | 282 | #[test] 283 | fn test_rlp_data_length_check() 284 | { 285 | let data = vec![0x84, b'c', b'a', b't']; 286 | let rlp = UntrustedRlp::new(&data); 287 | 288 | let as_val: Result = rlp.as_val(); 289 | assert_eq!(Err(DecoderError::RlpInconsistentLengthAndData), as_val); 290 | } 291 | 292 | #[test] 293 | fn test_rlp_long_data_length_check() 294 | { 295 | let mut data: Vec = vec![0xb8, 255]; 296 | for _ in 0..253 { 297 | data.push(b'c'); 298 | } 299 | 300 | let rlp = UntrustedRlp::new(&data); 301 | 302 | let as_val: Result = rlp.as_val(); 303 | assert_eq!(Err(DecoderError::RlpInconsistentLengthAndData), as_val); 304 | } 305 | 306 | #[test] 307 | fn test_the_exact_long_string() 308 | { 309 | let mut data: Vec = vec![0xb8, 255]; 310 | for _ in 0..255 { 311 | data.push(b'c'); 312 | } 313 | 314 | let rlp = UntrustedRlp::new(&data); 315 | 316 | let as_val: Result = rlp.as_val(); 317 | assert!(as_val.is_ok()); 318 | } 319 | 320 | #[test] 321 | fn test_rlp_2bytes_data_length_check() 322 | { 323 | let mut data: Vec = vec![0xb9, 2, 255]; // 512+255 324 | for _ in 0..700 { 325 | data.push(b'c'); 326 | } 327 | 328 | let rlp = UntrustedRlp::new(&data); 329 | 330 | let as_val: Result = rlp.as_val(); 331 | assert_eq!(Err(DecoderError::RlpInconsistentLengthAndData), as_val); 332 | } 333 | 334 | #[test] 335 | fn test_rlp_nested_empty_list_encode() { 336 | let mut stream = RlpStream::new_list(2); 337 | stream.append_list(&(Vec::new() as Vec)); 338 | stream.append(&40u32); 339 | assert_eq!(stream.drain()[..], [0xc2u8, 0xc0u8, 40u8][..]); 340 | } 341 | 342 | #[test] 343 | fn test_rlp_list_length_overflow() { 344 | let data: Vec = vec![0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00]; 345 | let rlp = UntrustedRlp::new(&data); 346 | let as_val: Result = rlp.val_at(0); 347 | assert_eq!(Err(DecoderError::RlpIsTooShort), as_val); 348 | } 349 | 350 | #[test] 351 | fn test_rlp_stream_size_limit() { 352 | for limit in 40 .. 270 { 353 | let item = [0u8; 1]; 354 | let mut stream = RlpStream::new(); 355 | while stream.append_raw_checked(&item, 1, limit) {} 356 | assert_eq!(stream.drain().len(), limit); 357 | } 358 | } 359 | 360 | #[test] 361 | fn test_rlp_stream_unbounded_list() { 362 | let mut stream = RlpStream::new(); 363 | stream.begin_unbounded_list(); 364 | stream.append(&40u32); 365 | stream.append(&41u32); 366 | assert!(!stream.is_finished()); 367 | stream.complete_unbounded_list(); 368 | assert!(stream.is_finished()); 369 | } 370 | 371 | -------------------------------------------------------------------------------- /shell.nix: -------------------------------------------------------------------------------- 1 | let pkgs = ( 2 | let 3 | nixpkgs = import ; 4 | pkgs_ = (nixpkgs {}); 5 | rustOverlay = (pkgs_.fetchFromGitHub { 6 | owner = "mozilla"; 7 | repo = "nixpkgs-mozilla"; 8 | rev = "6179dd876578ca2931f864627598ede16ba6cdef"; 9 | sha256 = "1lim10a674621zayz90nhwiynlakxry8fyz1x209g9bdm38zy3av"; 10 | }); 11 | in (nixpkgs { 12 | overlays = [ 13 | (import (builtins.toPath "${rustOverlay}/rust-overlay.nix")) 14 | (self: super: { 15 | rust = { 16 | rustc = super.rustChannels.stable.rust; 17 | cargo = super.rustChannels.stable.cargo; 18 | }; 19 | rustPlatform = super.recurseIntoAttrs (super.makeRustPlatform { 20 | rustc = super.rustChannels.stable.rust; 21 | cargo = super.rustChannels.stable.cargo; 22 | }); 23 | }) 24 | ]; 25 | })); 26 | 27 | in with pkgs; 28 | 29 | stdenv.mkDerivation { 30 | name = "sputnikvm-env"; 31 | buildInputs = [ 32 | rustc cargo gdb gcc pkgconfig 33 | ]; 34 | } 35 | -------------------------------------------------------------------------------- /trie/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "etcommon-trie" 3 | version = "0.4.0" 4 | license = "Apache-2.0" 5 | authors = ["Wei Tang "] 6 | description = "Lightweight Ethereum world state storage." 7 | repository = "https://github.com/ethereumproject/etcommon-rs" 8 | 9 | [lib] 10 | name = "trie" 11 | 12 | [dependencies] 13 | etcommon-bigint = { version = "0.2", path = "../bigint" } 14 | etcommon-rlp = { version = "0.2", path = "../rlp" } 15 | sha3 = "0.6" 16 | 17 | [dev-dependencies] 18 | etcommon-hexutil = "0.2" -------------------------------------------------------------------------------- /trie/rocksdb/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "etcommon-trie-rocksdb" 3 | version = "0.4.0" 4 | license = "Apache-2.0" 5 | authors = ["Wei Tang "] 6 | description = "Rocksdb adaptor for trie." 7 | repository = "https://github.com/ethereumproject/etcommon-rs" 8 | keywords = ["ethereum"] 9 | 10 | [lib] 11 | name = "trie_rocksdb" 12 | 13 | [dependencies] 14 | etcommon-trie = { version = "0.4", path = ".." } 15 | etcommon-bigint = { version = "0.2", path = "../../bigint" } 16 | parity-rocksdb = "0.5.0" -------------------------------------------------------------------------------- /trie/rocksdb/src/lib.rs: -------------------------------------------------------------------------------- 1 | extern crate trie; 2 | extern crate bigint; 3 | extern crate parity_rocksdb as rocksdb; 4 | 5 | use bigint::H256; 6 | use trie::{CachedDatabaseHandle, CachedHandle, Change, DatabaseHandle, TrieMut, get, insert, delete}; 7 | use rocksdb::{DB, Writable}; 8 | 9 | pub struct RocksDatabaseHandle<'a>(&'a DB); 10 | 11 | impl<'a> CachedDatabaseHandle for RocksDatabaseHandle<'a> { 12 | fn get(&self, key: H256) -> Vec { 13 | let value = self.0.get(key.as_ref()).unwrap().unwrap(); 14 | value.as_ref().into() 15 | } 16 | } 17 | 18 | impl<'a> RocksDatabaseHandle<'a> { 19 | pub fn new(db: &'a DB) -> Self { 20 | RocksDatabaseHandle(db) 21 | } 22 | } 23 | 24 | pub type RocksHandle<'a> = CachedHandle>; 25 | 26 | pub struct RocksMemoryTrieMut<'a> { 27 | handle: RocksHandle<'a>, 28 | change: Change, 29 | root: H256, 30 | db: &'a DB, 31 | cached: bool, 32 | } 33 | 34 | impl<'a, 'b> DatabaseHandle for &'b RocksMemoryTrieMut<'a> { 35 | fn get(&self, key: H256) -> &[u8] { 36 | if self.change.adds.contains_key(&key) { 37 | self.change.adds.get(&key).unwrap() 38 | } else { 39 | self.handle.get(key) 40 | } 41 | } 42 | } 43 | 44 | impl<'a> TrieMut for RocksMemoryTrieMut<'a> { 45 | fn root(&self) -> H256 { 46 | self.root 47 | } 48 | 49 | fn insert(&mut self, key: &[u8], value: &[u8]) { 50 | self.clear_cache(); 51 | 52 | let (new_root, change) = insert(self.root, &&*self, key, value); 53 | 54 | self.change.merge(&change); 55 | self.root = new_root; 56 | } 57 | 58 | fn delete(&mut self, key: &[u8]) { 59 | self.clear_cache(); 60 | 61 | let (new_root, change) = delete(self.root, &&*self, key); 62 | 63 | self.change.merge(&change); 64 | self.root = new_root; 65 | } 66 | 67 | fn get(&self, key: &[u8]) -> Option> { 68 | get(self.root, &self, key).map(|v| v.into()) 69 | } 70 | } 71 | 72 | impl<'a> RocksMemoryTrieMut<'a> { 73 | fn clear_cache(&mut self) { 74 | if !self.cached { 75 | self.handle = RocksHandle::new(RocksDatabaseHandle::new(self.db.clone())); 76 | } 77 | } 78 | 79 | pub fn new(db: &'a DB, root: H256, cached: bool) -> Self { 80 | Self { 81 | handle: RocksHandle::new(RocksDatabaseHandle::new(db.clone())), 82 | change: Change::default(), 83 | root, 84 | db, 85 | cached, 86 | } 87 | } 88 | 89 | pub fn new_cached(db: &'a DB, root: H256) -> Self { Self::new(db, root, true) } 90 | pub fn new_uncached(db: &'a DB, root: H256) -> Self { Self::new(db, root, false) } 91 | 92 | pub fn apply(self) -> Result<(), String> { 93 | for (key, value) in self.change.adds { 94 | self.db.put(key.as_ref(), &value)?; 95 | } 96 | 97 | for key in self.change.removes { 98 | self.db.delete(key.as_ref())?; 99 | } 100 | 101 | Ok(()) 102 | } 103 | } 104 | -------------------------------------------------------------------------------- /trie/src/cache.rs: -------------------------------------------------------------------------------- 1 | use super::merkle::MerkleNode; 2 | use bigint::H256; 3 | use rlp::Rlp; 4 | use std::collections::HashMap; 5 | use std::cell::{RefCell, UnsafeCell}; 6 | 7 | pub struct Cache { 8 | cache: UnsafeCell>>, 9 | map: RefCell>, 10 | } 11 | 12 | impl Cache { 13 | pub fn new() -> Cache { 14 | Cache { 15 | cache: UnsafeCell::new(Vec::new()), 16 | map: RefCell::new(HashMap::new()) 17 | } 18 | } 19 | 20 | pub fn insert<'a>(&'a self, key: H256, value: Vec) -> &'a [u8] { 21 | let cache = unsafe { &mut *self.cache.get() }; 22 | let index = cache.len(); 23 | self.map.borrow_mut().insert(key, index); 24 | cache.push(value); 25 | &cache[index] 26 | } 27 | 28 | pub fn get<'a>(&'a self, key: H256) -> Option<&'a [u8]> { 29 | let cache = unsafe { &mut *self.cache.get() }; 30 | let mut map = self.map.borrow_mut(); 31 | match map.get(&key) { 32 | Some(index) => Some(&cache[*index]), 33 | None => None, 34 | } 35 | } 36 | 37 | pub fn contains_key(&self, key: H256) -> bool { 38 | let mut map = self.map.borrow_mut(); 39 | map.contains_key(&key) 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /trie/src/gc.rs: -------------------------------------------------------------------------------- 1 | use bigint::H256; 2 | use {Change, TrieMut, DatabaseHandle, get, insert, delete}; 3 | 4 | pub trait ItemCounter { 5 | fn increase(&mut self, key: H256) -> usize; 6 | fn decrease(&mut self, key: H256) -> usize; 7 | } 8 | 9 | pub trait DatabaseMut { 10 | fn get(&self, key: H256) -> &[u8]; 11 | fn set(&mut self, key: H256, value: Option<&[u8]>); 12 | } 13 | 14 | impl<'a, D: DatabaseMut> DatabaseHandle for &'a D { 15 | fn get(&self, key: H256) -> &[u8] { 16 | DatabaseMut::get(*self, key) 17 | } 18 | } 19 | 20 | pub struct TrieCollection { 21 | database: D, 22 | counter: C, 23 | } 24 | 25 | impl TrieCollection { 26 | pub fn new(database: D, counter: C) -> Self { 27 | Self { database, counter } 28 | } 29 | 30 | pub fn trie_for<'a>(&'a self, root: H256) -> DatabaseTrieMut<'a, D> { 31 | DatabaseTrieMut { 32 | database: &self.database, 33 | change: Change::default(), 34 | root: root 35 | } 36 | } 37 | 38 | pub fn apply<'a>(&'a mut self, trie: DatabaseTrieMut<'a, D>) { 39 | for (key, value) in trie.change.adds { 40 | self.database.set(key, Some(&value)); 41 | self.counter.increase(key); 42 | } 43 | 44 | for key in trie.change.removes { 45 | let r = self.counter.decrease(key); 46 | if r == 0 { 47 | self.database.set(key, None); 48 | } 49 | } 50 | } 51 | } 52 | 53 | pub struct DatabaseTrieMut<'a, D: DatabaseMut + 'a> { 54 | database: &'a D, 55 | change: Change, 56 | root: H256, 57 | } 58 | 59 | impl<'a, D: DatabaseMut> TrieMut for DatabaseTrieMut<'a, D> { 60 | fn root(&self) -> H256 { 61 | self.root 62 | } 63 | 64 | fn insert(&mut self, key: &[u8], value: &[u8]) { 65 | let (new_root, change) = insert(self.root, &self.database, key, value); 66 | 67 | self.change.merge(&change); 68 | self.root = new_root; 69 | } 70 | 71 | fn delete(&mut self, key: &[u8]) { 72 | let (new_root, change) = delete(self.root, &self.database, key); 73 | 74 | self.change.merge(&change); 75 | self.root = new_root; 76 | } 77 | 78 | fn get(&self, key: &[u8]) -> Option> { 79 | get(self.root, &self.database, key).map(|v| v.into()) 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /trie/src/lib.rs: -------------------------------------------------------------------------------- 1 | //! Merkle trie implementation for Ethereum. 2 | 3 | extern crate bigint; 4 | extern crate rlp; 5 | extern crate sha3; 6 | #[cfg(test)] extern crate hexutil; 7 | 8 | use bigint::H256; 9 | use rlp::Rlp; 10 | use sha3::{Digest, Keccak256}; 11 | use std::collections::{HashMap, HashSet}; 12 | use merkle::{MerkleValue, MerkleNode}; 13 | use merkle::nibble::{self, NibbleVec, NibbleSlice, Nibble}; 14 | 15 | macro_rules! empty_nodes { 16 | () => ( 17 | [MerkleValue::Empty, MerkleValue::Empty, 18 | MerkleValue::Empty, MerkleValue::Empty, 19 | MerkleValue::Empty, MerkleValue::Empty, 20 | MerkleValue::Empty, MerkleValue::Empty, 21 | MerkleValue::Empty, MerkleValue::Empty, 22 | MerkleValue::Empty, MerkleValue::Empty, 23 | MerkleValue::Empty, MerkleValue::Empty, 24 | MerkleValue::Empty, MerkleValue::Empty] 25 | ) 26 | } 27 | 28 | macro_rules! empty_trie_hash { 29 | () => { 30 | { 31 | use std::str::FromStr; 32 | 33 | H256::from_str("0x56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421").unwrap() 34 | } 35 | } 36 | } 37 | 38 | pub mod merkle; 39 | pub mod gc; 40 | mod ops; 41 | mod memory; 42 | mod mutable; 43 | mod cache; 44 | 45 | use ops::{insert, delete, build, get}; 46 | use cache::Cache; 47 | 48 | pub use memory::*; 49 | pub use mutable::*; 50 | 51 | pub trait CachedDatabaseHandle { 52 | fn get(&self, key: H256) -> Vec; 53 | } 54 | 55 | pub struct CachedHandle { 56 | db: D, 57 | cache: Cache, 58 | } 59 | 60 | impl CachedHandle { 61 | pub fn new(db: D) -> Self { 62 | Self { 63 | db, 64 | cache: Cache::new(), 65 | } 66 | } 67 | } 68 | 69 | impl DatabaseHandle for CachedHandle { 70 | fn get(&self, key: H256) -> &[u8] { 71 | if !self.cache.contains_key(key) { 72 | self.cache.insert(key, self.db.get(key)) 73 | } else { 74 | self.cache.get(key).unwrap() 75 | } 76 | } 77 | } 78 | 79 | /// An immutable database handle. 80 | pub trait DatabaseHandle { 81 | /// Get a raw value from the database. 82 | fn get<'a>(&'a self, key: H256) -> &'a [u8]; 83 | } 84 | 85 | /// Change for a merkle trie operation. 86 | pub struct Change { 87 | /// Additions to the database. 88 | pub adds: HashMap>, 89 | /// Removals to the database. 90 | pub removes: HashSet, 91 | } 92 | 93 | impl Default for Change { 94 | fn default() -> Self { 95 | Change { 96 | adds: HashMap::new(), 97 | removes: HashSet::new(), 98 | } 99 | } 100 | } 101 | 102 | impl Change { 103 | /// Change to add a new raw value. 104 | pub fn add_raw(&mut self, key: H256, value: Vec) { 105 | self.adds.insert(key, value); 106 | self.removes.remove(&key); 107 | } 108 | 109 | /// Change to add a new node. 110 | pub fn add_node<'a, 'b, 'c>(&'a mut self, node: &'c MerkleNode<'b>) { 111 | let subnode = rlp::encode(node).to_vec(); 112 | let hash = H256::from(Keccak256::digest(&subnode).as_slice()); 113 | self.add_raw(hash, subnode); 114 | } 115 | 116 | /// Change to add a new node, and return the value added. 117 | pub fn add_value<'a, 'b, 'c>(&'a mut self, node: &'c MerkleNode<'b>) -> MerkleValue<'b> { 118 | if node.inlinable() { 119 | MerkleValue::Full(Box::new(node.clone())) 120 | } else { 121 | let subnode = rlp::encode(node).to_vec(); 122 | let hash = H256::from(Keccak256::digest(&subnode).as_slice()); 123 | self.add_raw(hash, subnode); 124 | MerkleValue::Hash(hash) 125 | } 126 | } 127 | 128 | /// Change to remove a raw key. 129 | pub fn remove_raw(&mut self, key: H256) { 130 | self.adds.remove(&key); 131 | self.removes.insert(key); 132 | } 133 | 134 | /// Change to remove a node. Return whether there's any node being 135 | /// removed. 136 | pub fn remove_node<'a, 'b, 'c>(&'a mut self, node: &'c MerkleNode<'b>) -> bool { 137 | if node.inlinable() { 138 | false 139 | } else { 140 | let subnode = rlp::encode(node).to_vec(); 141 | let hash = H256::from(Keccak256::digest(&subnode).as_slice()); 142 | self.remove_raw(hash); 143 | true 144 | } 145 | } 146 | 147 | /// Merge another change to this change. 148 | pub fn merge(&mut self, other: &Change) { 149 | for (key, value) in &other.adds { 150 | self.add_raw(*key, value.clone()); 151 | } 152 | 153 | for v in &other.removes { 154 | self.remove_raw(*v); 155 | } 156 | } 157 | } 158 | 159 | /// Get the empty trie hash for merkle trie. 160 | pub fn empty_trie_hash() -> H256 { 161 | empty_trie_hash!() 162 | } 163 | 164 | /// Insert to a merkle trie. Return the new root hash and the changes. 165 | pub fn insert( 166 | root: H256, database: &D, key: &[u8], value: &[u8] 167 | ) -> (H256, Change) { 168 | let mut change = Change::default(); 169 | let nibble = nibble::from_key(key); 170 | 171 | let (new, subchange) = if root == empty_trie_hash!() { 172 | insert::insert_by_empty(nibble, value) 173 | } else { 174 | let old = MerkleNode::decode(&Rlp::new(database.get(root))); 175 | change.remove_raw(root); 176 | insert::insert_by_node(old, nibble, value, database) 177 | }; 178 | change.merge(&subchange); 179 | change.add_node(&new); 180 | 181 | let hash = H256::from(Keccak256::digest(&rlp::encode(&new).to_vec()).as_slice()); 182 | (hash, change) 183 | } 184 | 185 | /// Insert to an empty merkle trie. Return the new root hash and the 186 | /// changes. 187 | pub fn insert_empty( 188 | key: &[u8], value: &[u8] 189 | ) -> (H256, Change) { 190 | let mut change = Change::default(); 191 | let nibble = nibble::from_key(key); 192 | 193 | let (new, subchange) = insert::insert_by_empty(nibble, value); 194 | change.merge(&subchange); 195 | change.add_node(&new); 196 | 197 | let hash = H256::from(Keccak256::digest(&rlp::encode(&new).to_vec()).as_slice()); 198 | (hash, change) 199 | } 200 | 201 | /// Delete a key from a markle trie. Return the new root hash and the 202 | /// changes. 203 | pub fn delete( 204 | root: H256, database: &D, key: &[u8] 205 | ) -> (H256, Change) { 206 | let mut change = Change::default(); 207 | let nibble = nibble::from_key(key); 208 | 209 | let (new, subchange) = if root == empty_trie_hash!() { 210 | return (root, change) 211 | } else { 212 | let old = MerkleNode::decode(&Rlp::new(database.get(root))); 213 | change.remove_raw(root); 214 | delete::delete_by_node(old, nibble, database) 215 | }; 216 | change.merge(&subchange); 217 | 218 | match new { 219 | Some(new) => { 220 | change.add_node(&new); 221 | 222 | let hash = H256::from(Keccak256::digest(&rlp::encode(&new).to_vec()).as_slice()); 223 | (hash, change) 224 | }, 225 | None => { 226 | (empty_trie_hash!(), change) 227 | }, 228 | } 229 | } 230 | 231 | /// Build a merkle trie from a map. Return the root hash and the 232 | /// changes. 233 | pub fn build(map: &HashMap, Vec>) -> (H256, Change) { 234 | let mut change = Change::default(); 235 | 236 | if map.len() == 0 { 237 | return (empty_trie_hash!(), change); 238 | } 239 | 240 | let mut node_map = HashMap::new(); 241 | for (key, value) in map { 242 | node_map.insert(nibble::from_key(key.as_ref()), value.as_ref()); 243 | } 244 | 245 | let (node, subchange) = build::build_node(&node_map); 246 | change.merge(&subchange); 247 | change.add_node(&node); 248 | 249 | let hash = H256::from(Keccak256::digest(&rlp::encode(&node).to_vec()).as_slice()); 250 | (hash, change) 251 | } 252 | 253 | /// Get a value given the root hash and the database. 254 | pub fn get<'a, 'b, D: DatabaseHandle>( 255 | root: H256, database: &'a D, key: &'b [u8] 256 | ) -> Option<&'a [u8]> { 257 | if root == empty_trie_hash!() { 258 | None 259 | } else { 260 | let nibble = nibble::from_key(key); 261 | let node = MerkleNode::decode(&Rlp::new(database.get(root))); 262 | get::get_by_node(node, nibble, database) 263 | } 264 | } 265 | -------------------------------------------------------------------------------- /trie/src/memory.rs: -------------------------------------------------------------------------------- 1 | use bigint::H256; 2 | use {DatabaseHandle, Change, insert, delete, build, get, 3 | TrieMut, FixedTrieMut, FixedSecureTrieMut, 4 | AnyTrieMut, AnySecureTrieMut, SecureTrieMut}; 5 | 6 | use std::collections::HashMap; 7 | 8 | impl<'a> DatabaseHandle for &'a HashMap> { 9 | fn get(&self, hash: H256) -> &[u8] { 10 | HashMap::get(self, &hash).unwrap() 11 | } 12 | } 13 | 14 | /// A memory-backed trie. 15 | #[derive(Clone, Debug)] 16 | pub struct MemoryTrieMut { 17 | database: HashMap>, 18 | root: H256, 19 | } 20 | 21 | /// A memory-backed trie where the value is operated on a fixed RLP 22 | /// value type. 23 | pub type FixedMemoryTrieMut = FixedTrieMut; 24 | /// A memory-backed trie where the key is hashed and the value is 25 | /// operated on a fixed RLP value type. 26 | pub type FixedSecureMemoryTrieMut = FixedSecureTrieMut; 27 | /// A memory-backed trie where the key is hashed. 28 | pub type SecureMemoryTrieMut = SecureTrieMut; 29 | /// A memory-backed trie where the value is operated on any RLP 30 | /// values. 31 | pub type AnyMemoryTrieMut = AnyTrieMut; 32 | /// A memory-backed trie where the key is hashed and the value is 33 | /// operated on any RLP values. 34 | pub type AnySecureMemoryTrieMut = AnySecureTrieMut; 35 | 36 | impl Default for MemoryTrieMut { 37 | fn default() -> Self { 38 | Self { 39 | database: HashMap::new(), 40 | root: empty_trie_hash!(), 41 | } 42 | } 43 | } 44 | 45 | impl Into>> for MemoryTrieMut { 46 | fn into(self) -> HashMap> { 47 | self.database 48 | } 49 | } 50 | 51 | impl TrieMut for MemoryTrieMut { 52 | fn root(&self) -> H256 { 53 | self.root 54 | } 55 | 56 | fn insert(&mut self, key: &[u8], value: &[u8]) { 57 | let (new_root, change) = insert(self.root, &&self.database, key, value); 58 | 59 | self.apply_change(change); 60 | self.root = new_root; 61 | } 62 | 63 | fn delete(&mut self, key: &[u8]) { 64 | let (new_root, change) = delete(self.root, &&self.database, key); 65 | 66 | self.apply_change(change); 67 | self.root = new_root; 68 | } 69 | 70 | fn get(&self, key: &[u8]) -> Option> { 71 | get(self.root, &&self.database, key).map(|v| v.into()) 72 | } 73 | } 74 | 75 | impl MemoryTrieMut { 76 | fn apply_change(&mut self, change: Change) { 77 | for add in change.adds { 78 | self.database.insert(add.0, add.1); 79 | } 80 | 81 | for remove in change.removes { 82 | self.database.remove(&remove); 83 | } 84 | } 85 | 86 | /// Build a memory trie from a map. 87 | pub fn build(map: &HashMap, Vec>) -> Self { 88 | let (new_root, change) = build(map); 89 | 90 | let mut ret = Self::default(); 91 | ret.apply_change(change); 92 | ret.root = new_root; 93 | 94 | ret 95 | } 96 | } 97 | 98 | #[cfg(test)] 99 | mod tests { 100 | use {TrieMut}; 101 | use super::MemoryTrieMut; 102 | use merkle::MerkleNode; 103 | use rlp::Rlp; 104 | 105 | use std::collections::HashMap; 106 | use std::str::FromStr; 107 | use std::cell::UnsafeCell; 108 | use bigint::H256; 109 | 110 | #[test] 111 | fn trie_middle_leaf() { 112 | let mut map = HashMap::new(); 113 | map.insert("key1aa".as_bytes().into(), "0123456789012345678901234567890123456789xxx".as_bytes().into()); 114 | map.insert("key1".as_bytes().into(), "0123456789012345678901234567890123456789Very_Long".as_bytes().into()); 115 | map.insert("key2bb".as_bytes().into(), "aval3".as_bytes().into()); 116 | map.insert("key2".as_bytes().into(), "short".as_bytes().into()); 117 | map.insert("key3cc".as_bytes().into(), "aval3".as_bytes().into()); 118 | map.insert("key3".as_bytes().into(), "1234567890123456789012345678901".as_bytes().into()); 119 | 120 | let mut btrie = MemoryTrieMut::build(&map); 121 | 122 | assert_eq!(btrie.root(), H256::from_str("0xcb65032e2f76c48b82b5c24b3db8f670ce73982869d38cd39a624f23d62a9e89").unwrap()); 123 | assert_eq!(btrie.get("key2bb".as_bytes()), Some("aval3".as_bytes().into())); 124 | assert_eq!(btrie.get("key2bbb".as_bytes()), None); 125 | 126 | let mut mtrie = MemoryTrieMut::default(); 127 | for (key, value) in &map { 128 | mtrie.insert(key, value); 129 | } 130 | 131 | assert_eq!(btrie.database, mtrie.database); 132 | 133 | mtrie.insert("key2bbb".as_bytes(), "aval4".as_bytes()); 134 | mtrie.delete("key2bbb".as_bytes()); 135 | 136 | assert_eq!(btrie.database, mtrie.database); 137 | 138 | for (key, value) in &map { 139 | mtrie.delete(key); 140 | } 141 | 142 | assert!(mtrie.database.len() == 0); 143 | assert!(mtrie.root == empty_trie_hash!()); 144 | } 145 | 146 | #[test] 147 | fn trie_two_keys() { 148 | let mut mtrie = MemoryTrieMut::default(); 149 | mtrie.insert("key1".as_bytes(), "aval1".as_bytes()); 150 | mtrie.insert("key2bb".as_bytes(), "aval3".as_bytes()); 151 | let db1 = mtrie.database.clone(); 152 | 153 | mtrie.insert("key2bbb".as_bytes(), "aval4".as_bytes()); 154 | mtrie.delete("key2bbb".as_bytes()); 155 | 156 | assert_eq!(db1, mtrie.database); 157 | } 158 | } 159 | -------------------------------------------------------------------------------- /trie/src/merkle/mod.rs: -------------------------------------------------------------------------------- 1 | //! Merkle types. 2 | 3 | pub mod nibble; 4 | mod node; 5 | 6 | use self::nibble::{Nibble, NibbleVec, NibbleSlice, NibbleType}; 7 | pub use self::node::{MerkleNode, MerkleValue}; 8 | -------------------------------------------------------------------------------- /trie/src/merkle/nibble.rs: -------------------------------------------------------------------------------- 1 | //! Merkle nibble types. 2 | 3 | use rlp::{RlpStream, Encodable, Decodable, Rlp, Prototype}; 4 | use std::ops::Deref; 5 | use std::cmp::min; 6 | use std::hash::{Hash, Hasher}; 7 | use std::fmt::{self, Debug, Formatter}; 8 | 9 | /// Represents a nibble. A 16-variant value. 10 | #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 11 | pub enum Nibble { 12 | N0, N1, N2, N3, N4, N5, N6, N7, 13 | N8, N9, N10, N11, N12, N13, N14, N15, 14 | } 15 | 16 | impl From for Nibble { 17 | fn from(val: usize) -> Nibble { 18 | match val { 19 | 0 => Nibble::N0, 1 => Nibble::N1, 2 => Nibble::N2, 3 => 20 | Nibble::N3, 4 => Nibble::N4, 5 => Nibble::N5, 6 => 21 | Nibble::N6, 7 => Nibble::N7, 8 => Nibble::N8, 9 => 22 | Nibble::N9, 10 => Nibble::N10, 11 => Nibble::N11, 12 => 23 | Nibble::N12, 13 => Nibble::N13, 14 => Nibble::N14, 15 => 24 | Nibble::N15, _ => panic!(), 25 | } 26 | } 27 | } 28 | 29 | impl Into for Nibble { 30 | fn into(self) -> usize { 31 | match self { 32 | Nibble::N0 => 0, Nibble::N1 => 1, Nibble::N2 => 2, 33 | Nibble::N3 => 3, Nibble::N4 => 4, Nibble::N5 => 5, 34 | Nibble::N6 => 6, Nibble::N7 => 7, Nibble::N8 => 8, 35 | Nibble::N9 => 9, Nibble::N10 => 10, Nibble::N11 => 11, 36 | Nibble::N12 => 12, Nibble::N13 => 13, Nibble::N14 => 14, 37 | Nibble::N15 => 15, 38 | } 39 | } 40 | } 41 | 42 | impl From for Nibble { 43 | fn from(val: u8) -> Nibble { 44 | match val { 45 | 0 => Nibble::N0, 1 => Nibble::N1, 2 => Nibble::N2, 3 => 46 | Nibble::N3, 4 => Nibble::N4, 5 => Nibble::N5, 6 => 47 | Nibble::N6, 7 => Nibble::N7, 8 => Nibble::N8, 9 => 48 | Nibble::N9, 10 => Nibble::N10, 11 => Nibble::N11, 12 => 49 | Nibble::N12, 13 => Nibble::N13, 14 => Nibble::N14, 15 => 50 | Nibble::N15, _ => panic!(), 51 | } 52 | } 53 | } 54 | 55 | impl Into for Nibble { 56 | fn into(self) -> u8 { 57 | match self { 58 | Nibble::N0 => 0, Nibble::N1 => 1, Nibble::N2 => 2, 59 | Nibble::N3 => 3, Nibble::N4 => 4, Nibble::N5 => 5, 60 | Nibble::N6 => 6, Nibble::N7 => 7, Nibble::N8 => 8, 61 | Nibble::N9 => 9, Nibble::N10 => 10, Nibble::N11 => 11, 62 | Nibble::N12 => 12, Nibble::N13 => 13, Nibble::N14 => 14, 63 | Nibble::N15 => 15, 64 | } 65 | } 66 | } 67 | 68 | /// A nibble type. 69 | #[derive(Debug, Clone, Copy, PartialEq, Eq)] 70 | pub enum NibbleType { 71 | Leaf, 72 | Extension 73 | } 74 | 75 | /// A nibble vector. 76 | pub type NibbleVec = Vec; 77 | /// A nibble slice. 78 | pub type NibbleSlice<'a> = &'a [Nibble]; 79 | 80 | /// Given a key, return the corresponding nibble. 81 | pub fn from_key(key: &[u8]) -> NibbleVec { 82 | let mut vec = NibbleVec::new(); 83 | 84 | for i in 0..(key.len()*2) { 85 | if i & 1 == 0 { // even 86 | vec.push(((key[i / 2] & 0xf0) >> 4).into()); 87 | } else { 88 | vec.push((key[i / 2] & 0x0f).into()); 89 | } 90 | } 91 | 92 | vec 93 | } 94 | 95 | /// Given a nibble, return the corresponding key. 96 | pub fn into_key(nibble: NibbleSlice) -> Vec { 97 | let mut ret = Vec::new(); 98 | 99 | for i in 0..nibble.len() { 100 | if i & 1 == 0 { // even 101 | let value: u8 = nibble[i].into(); 102 | ret.push(value << 4); 103 | } else { 104 | let value: u8 = nibble[i].into(); 105 | ret[i / 2] |= value; 106 | } 107 | } 108 | 109 | ret 110 | } 111 | 112 | /// Decode a nibble from RLP. 113 | pub fn decode(rlp: &Rlp) -> (NibbleVec, NibbleType) { 114 | let mut vec = NibbleVec::new(); 115 | 116 | let data = rlp.data(); 117 | let start_odd = if data[0] & 0b00010000 == 0b00010000 { true } else { false }; 118 | let start_index = if start_odd { 1 } else { 2 }; 119 | let is_leaf = data[0] & 0b00100000 == 0b00100000; 120 | 121 | let len = data.len() * 2; 122 | 123 | for i in start_index..len { 124 | if i & 1 == 0 { // even 125 | vec.push(((data[i / 2] & 0xf0) >> 4).into()); 126 | } else { 127 | vec.push((data[i / 2] & 0x0f).into()); 128 | } 129 | } 130 | 131 | (vec, if is_leaf { NibbleType::Leaf } else { NibbleType::Extension }) 132 | } 133 | 134 | /// Encode a nibble into the given RLP stream. 135 | pub fn encode(vec: NibbleSlice, typ: NibbleType, s: &mut RlpStream) { 136 | let mut ret: Vec = Vec::new(); 137 | 138 | if vec.len() & 1 == 0 { // even 139 | ret.push(0b00000000); 140 | 141 | for i in 0..vec.len() { 142 | if i & 1 == 0 { 143 | let v: u8 = vec[i].into(); 144 | ret.push(v << 4); 145 | } else { 146 | let end = ret.len() - 1; 147 | let v: u8 = vec[i].into(); 148 | ret[end] |= v; 149 | } 150 | } 151 | } else { 152 | ret.push(0b00010000); 153 | 154 | for i in 0..vec.len() { 155 | if i & 1 == 0 { 156 | let end = ret.len() - 1; 157 | let v: u8 = vec[i].into(); 158 | ret[end] |= v; 159 | } else { 160 | let v: u8 = vec[i].into(); 161 | ret.push(v << 4); 162 | } 163 | } 164 | } 165 | 166 | ret[0] |= match typ { 167 | NibbleType::Leaf => 0b00100000, 168 | NibbleType::Extension => 0b00000000 169 | }; 170 | 171 | s.append(&ret); 172 | } 173 | 174 | /// Common prefix for two nibbles. 175 | pub fn common<'a, 'b>(a: NibbleSlice<'a>, b: NibbleSlice<'b>) -> NibbleSlice<'a> { 176 | let mut common_len = 0; 177 | 178 | for i in 0..min(a.len(), b.len()) { 179 | if a[i] == b[i] { 180 | common_len += 1; 181 | } else { 182 | break; 183 | } 184 | } 185 | 186 | &a[0..common_len] 187 | } 188 | 189 | /// Common prefix for two nibbles. Return the sub nibbles. 190 | pub fn common_with_sub<'a, 'b>( 191 | a: NibbleSlice<'a>, b: NibbleSlice<'b> 192 | ) -> (NibbleSlice<'a>, NibbleVec, NibbleVec) { 193 | let common = common(a, b); 194 | let asub = a[common.len()..].into(); 195 | let bsub = b[common.len()..].into(); 196 | 197 | (common, asub, bsub) 198 | } 199 | 200 | /// Common prefix for all provided nibbles. 201 | pub fn common_all<'a, T: Iterator>>(mut iter: T) -> NibbleSlice<'a> { 202 | let first = match iter.next() { 203 | Some(val) => val, 204 | None => return &[], 205 | }; 206 | let second = match iter.next() { 207 | Some(val) => val, 208 | None => return first, 209 | }; 210 | 211 | let mut common_cur = common(first, second); 212 | for key in iter { 213 | common_cur = common(common_cur, key); 214 | } 215 | 216 | common_cur 217 | } 218 | 219 | #[cfg(test)] 220 | mod tests { 221 | use super::*; 222 | 223 | #[test] 224 | fn from_into_key() { 225 | let key = vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 244, 233, 188]; 226 | 227 | assert_eq!(key, into_key(&from_key(&key))); 228 | } 229 | } 230 | -------------------------------------------------------------------------------- /trie/src/mutable.rs: -------------------------------------------------------------------------------- 1 | use bigint::H256; 2 | use rlp::{self, Rlp}; 3 | use sha3::{Digest, Keccak256}; 4 | 5 | use std::marker::PhantomData; 6 | 7 | /// Represents a trie that is mutable. 8 | pub trait TrieMut { 9 | /// Get the root hash of the current trie. 10 | fn root(&self) -> H256; 11 | /// Insert a value to the trie. 12 | fn insert(&mut self, key: &[u8], value: &[u8]); 13 | /// Delete a value in the trie. 14 | fn delete(&mut self, key: &[u8]); 15 | /// Get a value in the trie. 16 | fn get(&self, key: &[u8]) -> Option>; 17 | } 18 | 19 | /// Represents a mutable trie that is operated on any RLP values. 20 | #[derive(Clone, Debug)] 21 | pub struct AnyTrieMut(T); 22 | 23 | impl Default for AnyTrieMut { 24 | fn default() -> Self { 25 | AnyTrieMut::new(T::default()) 26 | } 27 | } 28 | 29 | impl AnyTrieMut { 30 | /// Into the underlying TrieMut object. 31 | pub fn to_trie(self) -> T { 32 | self.0 33 | } 34 | 35 | /// Initialize a new mutable trie. 36 | pub fn new(trie: T) -> Self { 37 | AnyTrieMut(trie) 38 | } 39 | 40 | /// Get the root hash of the current trie. 41 | pub fn root(&self) -> H256 { 42 | self.0.root() 43 | } 44 | 45 | /// Insert a value to the trie. 46 | pub fn insert(&mut self, key: &K, value: &V) { 47 | let key = rlp::encode(key).to_vec(); 48 | let value = rlp::encode(value).to_vec(); 49 | 50 | self.0.insert(&key, &value) 51 | } 52 | 53 | /// Delete a value in the trie. 54 | pub fn delete(&mut self, key: &K) { 55 | let key = rlp::encode(key).to_vec(); 56 | 57 | self.0.delete(&key) 58 | } 59 | 60 | /// Get a value in the trie. 61 | pub fn get(&self, key: &K) -> Option { 62 | let key = rlp::encode(key).to_vec(); 63 | let value = self.0.get(&key); 64 | 65 | match value { 66 | Some(value) => Some(rlp::decode(&value)), 67 | None => None, 68 | } 69 | } 70 | } 71 | 72 | /// Represents a mutable trie that is operated on a fixed RLP value type. 73 | #[derive(Clone, Debug)] 74 | pub struct FixedTrieMut(AnyTrieMut, PhantomData<(K, V)>); 75 | 76 | impl Default for FixedTrieMut { 77 | fn default() -> Self { 78 | FixedTrieMut::new(T::default()) 79 | } 80 | } 81 | 82 | impl FixedTrieMut { 83 | /// Into the underlying TrieMut object. 84 | pub fn to_trie(self) -> T { 85 | self.0.to_trie() 86 | } 87 | 88 | /// Initialize a new mutable trie. 89 | pub fn new(trie: T) -> Self { 90 | FixedTrieMut(AnyTrieMut::new(trie), PhantomData) 91 | } 92 | 93 | /// Get the root hash of the current trie. 94 | pub fn root(&self) -> H256 { 95 | self.0.root() 96 | } 97 | 98 | /// Insert a value to the trie. 99 | pub fn insert(&mut self, key: &K, value: &V) { 100 | self.0.insert(key, value) 101 | } 102 | 103 | /// Delete a value in the trie. 104 | pub fn delete(&mut self, key: &K) { 105 | self.0.delete(key) 106 | } 107 | 108 | /// Get a value in the trie. 109 | pub fn get(&self, key: &K) -> Option { 110 | self.0.get(key) 111 | } 112 | } 113 | 114 | /// Represents a secure mutable trie where the key is hashed. 115 | #[derive(Clone, Debug)] 116 | pub struct SecureTrieMut(T); 117 | 118 | impl Default for SecureTrieMut { 119 | fn default() -> Self { 120 | SecureTrieMut::new(T::default()) 121 | } 122 | } 123 | 124 | impl SecureTrieMut { 125 | /// Into the underlying TrieMut object. 126 | pub fn to_trie(self) -> T { 127 | self.0 128 | } 129 | 130 | /// Initialize a new mutable trie. 131 | pub fn new(trie: T) -> Self { 132 | SecureTrieMut(trie) 133 | } 134 | 135 | fn secure_key>(key: &K) -> Vec { 136 | Keccak256::digest(key.as_ref()).as_slice().into() 137 | } 138 | 139 | /// Get the root hash of the current trie. 140 | pub fn root(&self) -> H256 { 141 | self.0.root() 142 | } 143 | 144 | /// Insert a value to the trie. 145 | pub fn insert>(&mut self, key: &K, value: &[u8]) { 146 | self.0.insert(&Self::secure_key(key), value) 147 | } 148 | 149 | /// Delete a value in the trie. 150 | pub fn delete>(&mut self, key: &K) { 151 | self.0.delete(&Self::secure_key(key)) 152 | } 153 | 154 | /// Get a value in the trie. 155 | pub fn get>(&self, key: &K) -> Option> { 156 | self.0.get(&Self::secure_key(key)) 157 | } 158 | } 159 | 160 | /// Represents a secure mutable trie where the key is hashed, and 161 | /// operated on any RLP values. 162 | #[derive(Clone, Debug)] 163 | pub struct AnySecureTrieMut(SecureTrieMut); 164 | 165 | impl Default for AnySecureTrieMut { 166 | fn default() -> Self { 167 | AnySecureTrieMut::new(T::default()) 168 | } 169 | } 170 | 171 | impl AnySecureTrieMut { 172 | /// Into the underlying TrieMut object. 173 | pub fn to_trie(self) -> T { 174 | self.0.to_trie() 175 | } 176 | 177 | /// Initialize a new mutable trie. 178 | pub fn new(trie: T) -> Self { 179 | AnySecureTrieMut(SecureTrieMut::new(trie)) 180 | } 181 | 182 | /// Get the root hash of the current trie. 183 | pub fn root(&self) -> H256 { 184 | self.0.root() 185 | } 186 | 187 | /// Insert a value to the trie. 188 | pub fn insert, V: rlp::Encodable>(&mut self, key: &K, value: &V) { 189 | self.0.insert(&key, &rlp::encode(value).to_vec()) 190 | } 191 | 192 | /// Delete a value in the trie. 193 | pub fn delete>(&mut self, key: &K) { 194 | self.0.delete(&key) 195 | } 196 | 197 | /// Get a value in the trie. 198 | pub fn get, V: rlp::Decodable>(&self, key: &K) -> Option { 199 | let value = self.0.get(&key); 200 | 201 | match value { 202 | Some(value) => Some(rlp::decode(&value)), 203 | None => None, 204 | } 205 | } 206 | } 207 | 208 | /// Represents a secure mutable trie where the key is hashed, and 209 | /// operated on a fixed RLP value type. 210 | #[derive(Clone, Debug)] 211 | pub struct FixedSecureTrieMut, V: rlp::Encodable + rlp::Decodable>(AnySecureTrieMut, PhantomData<(K, V)>); 212 | 213 | impl, V: rlp::Encodable + rlp::Decodable> Default for FixedSecureTrieMut { 214 | fn default() -> Self { 215 | FixedSecureTrieMut::new(T::default()) 216 | } 217 | } 218 | 219 | impl, V: rlp::Encodable + rlp::Decodable> FixedSecureTrieMut { 220 | /// Into the underlying TrieMut object. 221 | pub fn to_trie(self) -> T { 222 | self.0.to_trie() 223 | } 224 | 225 | /// Initialize a new mutable trie. 226 | pub fn new(trie: T) -> Self { 227 | FixedSecureTrieMut(AnySecureTrieMut::new(trie), PhantomData) 228 | } 229 | 230 | /// Get the root hash of the current trie. 231 | pub fn root(&self) -> H256 { 232 | self.0.root() 233 | } 234 | 235 | /// Insert a value to the trie. 236 | pub fn insert(&mut self, key: &K, value: &V) { 237 | self.0.insert(key, value) 238 | } 239 | 240 | /// Delete a value in the trie. 241 | pub fn delete(&mut self, key: &K) { 242 | self.0.delete(key) 243 | } 244 | 245 | /// Get a value in the trie. 246 | pub fn get(&self, key: &K) -> Option { 247 | self.0.get(key) 248 | } 249 | } 250 | -------------------------------------------------------------------------------- /trie/src/ops/build.rs: -------------------------------------------------------------------------------- 1 | use merkle::{MerkleValue, MerkleNode}; 2 | use merkle::nibble::{self, NibbleVec, NibbleSlice, Nibble}; 3 | use {Change, DatabaseHandle}; 4 | 5 | use std::collections::HashMap; 6 | 7 | use rlp::{self, Rlp}; 8 | 9 | fn make_submap<'a, 'b: 'a, T: Iterator>( 10 | common_len: usize, map: T 11 | ) -> HashMap { 12 | let mut submap = HashMap::new(); 13 | for (key, value) in map { 14 | submap.insert(key[common_len..].into(), value.clone()); 15 | } 16 | submap 17 | } 18 | 19 | pub fn build_value<'a>(node: MerkleNode<'a>) -> (MerkleValue<'a>, Change) { 20 | let mut change = Change::default(); 21 | let value = change.add_value(&node); 22 | 23 | (value, change) 24 | } 25 | 26 | pub fn build_node<'a>(map: &HashMap) -> (MerkleNode<'a>, Change) { 27 | let mut change = Change::default(); 28 | 29 | assert!(map.len() > 0); 30 | if map.len() == 1 { 31 | let key = map.keys().next().unwrap(); 32 | return (MerkleNode::Leaf(key.clone(), map.get(key).unwrap().clone()), change); 33 | } 34 | 35 | debug_assert!(map.len() > 1); 36 | let common = nibble::common_all(map.keys().map(|v| v.as_ref())); 37 | 38 | if common.len() > 0 { 39 | let submap = make_submap(common.len(), map.iter()); 40 | debug_assert!(submap.len() > 0); 41 | 42 | let (node, subchange) = build_node(&submap); 43 | change.merge(&subchange); 44 | 45 | let (value, subchange) = build_value(node); 46 | change.merge(&subchange); 47 | 48 | (MerkleNode::Extension(common.into(), value), change) 49 | } else { 50 | let mut nodes = empty_nodes!(); 51 | 52 | for i in 0..16 { 53 | let nibble: Nibble = i.into(); 54 | 55 | let submap = make_submap(1, map.iter().filter(|&(key, _value)| { 56 | key.len() > 0 && key[0] == nibble 57 | })); 58 | 59 | if submap.len() > 0 { 60 | let (node, subchange) = build_node(&submap); 61 | change.merge(&subchange); 62 | 63 | let (value, subchange) = build_value(node); 64 | change.merge(&subchange); 65 | 66 | nodes[i] = value; 67 | } 68 | } 69 | 70 | let additional = map.iter() 71 | .filter(|&(key, _value)| key.len() == 0).next() 72 | .map(|(_key, value)| value.clone()); 73 | 74 | (MerkleNode::Branch(nodes, additional), change) 75 | } 76 | } 77 | -------------------------------------------------------------------------------- /trie/src/ops/delete.rs: -------------------------------------------------------------------------------- 1 | use merkle::{MerkleValue, MerkleNode}; 2 | use merkle::nibble::{self, NibbleVec, NibbleSlice, Nibble}; 3 | use {Change, DatabaseHandle}; 4 | 5 | use rlp::{self, Rlp}; 6 | 7 | fn find_and_remove_child<'a, D: DatabaseHandle>( 8 | merkle: MerkleValue<'a>, database: &'a D 9 | ) -> (MerkleNode<'a>, Change) { 10 | let mut change = Change::default(); 11 | 12 | let node = match merkle { 13 | MerkleValue::Empty => panic!(), 14 | MerkleValue::Full(ref sub_node) => sub_node.as_ref().clone(), 15 | MerkleValue::Hash(h) => { 16 | let sub_node = MerkleNode::decode(&Rlp::new(database.get(h))); 17 | change.remove_raw(h); 18 | sub_node 19 | }, 20 | }; 21 | 22 | (node, change) 23 | } 24 | 25 | fn collapse_extension<'a>( 26 | node_nibble: NibbleVec, subnode: MerkleNode<'a> 27 | ) -> (MerkleNode<'a>, Change) { 28 | let mut change = Change::default(); 29 | 30 | let node = match subnode { 31 | MerkleNode::Leaf(mut sub_nibble, sub_value) => { 32 | let mut new_sub_nibble = node_nibble.clone(); 33 | new_sub_nibble.append(&mut sub_nibble); 34 | MerkleNode::Leaf(new_sub_nibble, sub_value) 35 | }, 36 | MerkleNode::Extension(mut sub_nibble, sub_value) => { 37 | debug_assert!(sub_value != MerkleValue::Empty); 38 | 39 | let mut new_sub_nibble = node_nibble.clone(); 40 | new_sub_nibble.append(&mut sub_nibble); 41 | MerkleNode::Extension(new_sub_nibble, sub_value) 42 | }, 43 | branch => { 44 | let subvalue = change.add_value(&branch); 45 | MerkleNode::Extension(node_nibble, subvalue) 46 | }, 47 | }; 48 | 49 | (node, change) 50 | } 51 | 52 | fn nonempty_node_count<'a, 'b>( 53 | nodes: &'b [MerkleValue<'a>; 16], additional: &'b Option<&'a [u8]> 54 | ) -> usize { 55 | additional.iter().count() + 56 | nodes.iter().filter(|v| v != &&MerkleValue::Empty).count() 57 | } 58 | 59 | fn collapse_branch<'a, D: DatabaseHandle>( 60 | node_nodes: [MerkleValue<'a>; 16], node_additional: Option<&'a [u8]>, 61 | database: &'a D 62 | ) -> (MerkleNode<'a>, Change) { 63 | let mut change = Change::default(); 64 | 65 | let value_count = nonempty_node_count(&node_nodes, &node_additional); 66 | 67 | let node = match value_count { 68 | 0 => panic!(), 69 | 1 if node_additional.is_some() => 70 | MerkleNode::Leaf(NibbleVec::new(), node_additional.unwrap()), 71 | 1 /* value in node_nodes */ => { 72 | let (subindex, subvalue) = node_nodes.iter().enumerate() 73 | .filter(|&(_, v)| v != &MerkleValue::Empty).next() 74 | .map(|(i, v)| (i, v.clone())).unwrap(); 75 | let subnibble: Nibble = subindex.into(); 76 | 77 | let (subnode, subchange) = find_and_remove_child(subvalue, database); 78 | change.merge(&subchange); 79 | 80 | match subnode { 81 | MerkleNode::Leaf(mut leaf_nibble, leaf_value) => { 82 | leaf_nibble.insert(0, subnibble); 83 | MerkleNode::Leaf(leaf_nibble, leaf_value) 84 | }, 85 | MerkleNode::Extension(mut ext_nibble, ext_value) => { 86 | debug_assert!(ext_value != MerkleValue::Empty); 87 | 88 | ext_nibble.insert(0, subnibble); 89 | MerkleNode::Extension(ext_nibble, ext_value) 90 | }, 91 | branch => { 92 | let subvalue = change.add_value(&branch); 93 | MerkleNode::Extension(vec![subnibble], subvalue) 94 | }, 95 | } 96 | }, 97 | _ /* value_count > 1 */ => 98 | MerkleNode::Branch(node_nodes, node_additional), 99 | }; 100 | 101 | (node, change) 102 | } 103 | 104 | pub fn delete_by_child<'a, D: DatabaseHandle>( 105 | merkle: MerkleValue<'a>, nibble: NibbleVec, database: &'a D 106 | ) -> (Option>, Change) { 107 | let mut change = Change::default(); 108 | 109 | let new = match merkle { 110 | MerkleValue::Empty => { 111 | None 112 | }, 113 | MerkleValue::Full(ref sub_node) => { 114 | let (new_node, subchange) = delete_by_node( 115 | sub_node.as_ref().clone(), nibble, database); 116 | change.merge(&subchange); 117 | match new_node { 118 | Some(new_node) => Some(new_node), 119 | None => None, 120 | } 121 | }, 122 | MerkleValue::Hash(h) => { 123 | let sub_node = MerkleNode::decode(&Rlp::new(database.get(h))); 124 | change.remove_raw(h); 125 | let (new_node, subchange) = delete_by_node( 126 | sub_node, nibble, database); 127 | change.merge(&subchange); 128 | match new_node { 129 | Some(new_node) => Some(new_node), 130 | None => None, 131 | } 132 | }, 133 | }; 134 | 135 | (new, change) 136 | } 137 | 138 | pub fn delete_by_node<'a, D: DatabaseHandle>( 139 | node: MerkleNode<'a>, nibble: NibbleVec, database: &'a D 140 | ) -> (Option>, Change) { 141 | let mut change = Change::default(); 142 | 143 | let new = match node { 144 | MerkleNode::Leaf(node_nibble, node_value) => { 145 | if node_nibble == nibble { 146 | None 147 | } else { 148 | Some(MerkleNode::Leaf(node_nibble, node_value)) 149 | } 150 | }, 151 | MerkleNode::Extension(node_nibble, node_value) => { 152 | if nibble.starts_with(&node_nibble) { 153 | let (subnode, subchange) = delete_by_child( 154 | node_value, nibble[node_nibble.len()..].into(), 155 | database); 156 | change.merge(&subchange); 157 | 158 | match subnode { 159 | Some(subnode) => { 160 | let (new, subchange) = collapse_extension(node_nibble, subnode); 161 | change.merge(&subchange); 162 | 163 | Some(new) 164 | }, 165 | None => None, 166 | } 167 | } else { 168 | Some(MerkleNode::Extension(node_nibble, node_value)) 169 | } 170 | }, 171 | MerkleNode::Branch(mut node_nodes, mut node_additional) => { 172 | let needs_collapse; 173 | 174 | if nibble.len() == 0 { 175 | node_additional = None; 176 | needs_collapse = true; 177 | } else { 178 | let ni: usize = nibble[0].into(); 179 | let (new_subnode, subchange) = delete_by_child( 180 | node_nodes[ni].clone(), nibble[1..].into(), 181 | database); 182 | change.merge(&subchange); 183 | 184 | match new_subnode { 185 | Some(new_subnode) => { 186 | let new_subvalue = change.add_value(&new_subnode); 187 | 188 | node_nodes[ni] = new_subvalue; 189 | needs_collapse = false; 190 | }, 191 | None => { 192 | node_nodes[ni] = MerkleValue::Empty; 193 | needs_collapse = true; 194 | }, 195 | } 196 | } 197 | 198 | if needs_collapse { 199 | let value_count = nonempty_node_count(&node_nodes, &node_additional); 200 | if value_count > 0 { 201 | let (new, subchange) = collapse_branch(node_nodes, node_additional, database); 202 | change.merge(&subchange); 203 | 204 | Some(new) 205 | } else { 206 | None 207 | } 208 | } else { 209 | Some(MerkleNode::Branch(node_nodes, node_additional)) 210 | } 211 | }, 212 | }; 213 | 214 | (new, change) 215 | } 216 | -------------------------------------------------------------------------------- /trie/src/ops/get.rs: -------------------------------------------------------------------------------- 1 | use merkle::{MerkleValue, MerkleNode}; 2 | use merkle::nibble::{self, NibbleVec, NibbleSlice, Nibble}; 3 | use {Change, DatabaseHandle}; 4 | 5 | use rlp::{self, Rlp}; 6 | 7 | pub fn get_by_value<'a, D: DatabaseHandle>( 8 | merkle: MerkleValue<'a>, nibble: NibbleVec, database: &'a D 9 | ) -> Option<&'a [u8]> { 10 | match merkle { 11 | MerkleValue::Empty => None, 12 | MerkleValue::Full(subnode) => { 13 | get_by_node(subnode.as_ref().clone(), nibble, database) 14 | }, 15 | MerkleValue::Hash(h) => { 16 | let subnode = MerkleNode::decode(&Rlp::new(database.get(h))); 17 | get_by_node(subnode, nibble, database) 18 | }, 19 | } 20 | } 21 | 22 | pub fn get_by_node<'a, D: DatabaseHandle>( 23 | node: MerkleNode<'a>, nibble: NibbleVec, database: &'a D 24 | ) -> Option<&'a [u8]> { 25 | match node { 26 | MerkleNode::Leaf(node_nibble, node_value) => { 27 | if node_nibble == nibble { 28 | Some(node_value) 29 | } else { 30 | None 31 | } 32 | }, 33 | MerkleNode::Extension(node_nibble, node_value) => { 34 | if nibble.starts_with(&node_nibble) { 35 | get_by_value(node_value, nibble[node_nibble.len()..].into(), database) 36 | } else { 37 | None 38 | } 39 | }, 40 | MerkleNode::Branch(node_nodes, node_additional) => { 41 | if nibble.len() == 0 { 42 | node_additional 43 | } else { 44 | let ni: usize = nibble[0].into(); 45 | get_by_value(node_nodes[ni].clone(), nibble[1..].into(), database) 46 | } 47 | }, 48 | } 49 | } 50 | -------------------------------------------------------------------------------- /trie/src/ops/insert.rs: -------------------------------------------------------------------------------- 1 | use merkle::{MerkleValue, MerkleNode}; 2 | use merkle::nibble::{self, NibbleVec, NibbleSlice, Nibble}; 3 | use {Change, DatabaseHandle}; 4 | 5 | use rlp::{self, Rlp}; 6 | 7 | fn value_and_leaf_branch<'a>( 8 | anibble: NibbleVec, avalue: MerkleValue<'a>, bnibble: NibbleVec, bvalue: &'a [u8] 9 | ) -> (MerkleNode<'a>, Change) { 10 | debug_assert!(anibble.len() > 0); 11 | 12 | let mut change = Change::default(); 13 | let mut additional = None; 14 | let mut nodes = empty_nodes!(); 15 | 16 | let ai: usize = anibble[0].into(); 17 | let asub: NibbleVec = anibble[1..].into(); 18 | 19 | if asub.len() > 0 { 20 | let ext_value = change.add_value(&MerkleNode::Extension(asub, avalue)); 21 | nodes[ai] = ext_value; 22 | } else { 23 | nodes[ai] = avalue; 24 | } 25 | 26 | if bnibble.len() == 0 { 27 | additional = Some(bvalue); 28 | } else { 29 | let bi: usize = bnibble[0].into(); 30 | debug_assert!(ai != bi); 31 | 32 | let bsub = bnibble[1..].into(); 33 | let bvalue = change.add_value(&MerkleNode::Leaf(bsub, bvalue)); 34 | 35 | nodes[bi] = bvalue; 36 | } 37 | 38 | (MerkleNode::Branch(nodes, additional), change) 39 | } 40 | 41 | fn two_leaf_branch<'a>( 42 | anibble: NibbleVec, avalue: &'a [u8], bnibble: NibbleVec, bvalue: &'a [u8] 43 | ) -> (MerkleNode<'a>, Change) { 44 | debug_assert!(bnibble.len() == 0 || !anibble.starts_with(&bnibble)); 45 | debug_assert!(anibble.len() == 0 || !bnibble.starts_with(&anibble)); 46 | 47 | let mut change = Change::default(); 48 | let mut additional = None; 49 | let mut nodes = empty_nodes!(); 50 | 51 | if anibble.len() == 0 { 52 | additional = Some(avalue); 53 | } else { 54 | let ai: usize = anibble[0].into(); 55 | let asub: NibbleVec = anibble[1..].into(); 56 | let avalue = change.add_value(&MerkleNode::Leaf(asub, avalue)); 57 | nodes[ai] = avalue; 58 | } 59 | 60 | if bnibble.len() == 0 { 61 | additional = Some(bvalue); 62 | } else { 63 | let bi: usize = bnibble[0].into(); 64 | let bsub: NibbleVec = bnibble[1..].into(); 65 | let bvalue = change.add_value(&MerkleNode::Leaf(bsub, bvalue)); 66 | nodes[bi] = bvalue; 67 | } 68 | 69 | (MerkleNode::Branch(nodes, additional), change) 70 | } 71 | 72 | pub fn insert_by_value<'a, D: DatabaseHandle>( 73 | merkle: MerkleValue<'a>, nibble: NibbleVec, value: &'a [u8], database: &'a D 74 | ) -> (MerkleValue<'a>, Change) { 75 | let mut change = Change::default(); 76 | 77 | let new = match merkle { 78 | MerkleValue::Empty => { 79 | change.add_value(&MerkleNode::Leaf(nibble, value)) 80 | }, 81 | MerkleValue::Full(ref sub_node) => { 82 | let (new_node, subchange) = insert_by_node( 83 | sub_node.as_ref().clone(), nibble, value, database); 84 | change.merge(&subchange); 85 | change.add_value(&new_node) 86 | }, 87 | MerkleValue::Hash(h) => { 88 | let sub_node = MerkleNode::decode(&Rlp::new(database.get(h))); 89 | change.remove_raw(h); 90 | let (new_node, subchange) = insert_by_node( 91 | sub_node, nibble, value, database); 92 | change.merge(&subchange); 93 | change.add_value(&new_node) 94 | }, 95 | }; 96 | 97 | (new, change) 98 | } 99 | 100 | pub fn insert_by_node<'a, D: DatabaseHandle>( 101 | node: MerkleNode<'a>, nibble: NibbleVec, value: &'a [u8], database: &'a D 102 | ) -> (MerkleNode<'a>, Change) { 103 | let mut change = Change::default(); 104 | 105 | let new = match node { 106 | MerkleNode::Leaf(ref node_nibble, ref node_value) => { 107 | if node_nibble == &nibble { 108 | MerkleNode::Leaf(nibble, value) 109 | } else { 110 | let (common, nibble_sub, node_nibble_sub) = 111 | nibble::common_with_sub(&nibble, &node_nibble); 112 | 113 | let (branch, subchange) = two_leaf_branch(node_nibble_sub, node_value, 114 | nibble_sub, value); 115 | change.merge(&subchange); 116 | if common.len() > 0 { 117 | MerkleNode::Extension(common.into(), change.add_value(&branch)) 118 | } else { 119 | branch 120 | } 121 | } 122 | }, 123 | MerkleNode::Extension(ref node_nibble, ref node_value) => { 124 | if nibble.starts_with(node_nibble) { 125 | let (subvalue, subchange) = insert_by_value( 126 | node_value.clone(), 127 | nibble[node_nibble.len()..].into(), 128 | value, database); 129 | change.merge(&subchange); 130 | 131 | MerkleNode::Extension(node_nibble.clone(), subvalue) 132 | } else { 133 | let (common, nibble_sub, node_nibble_sub) = 134 | nibble::common_with_sub(&nibble, &node_nibble); 135 | 136 | let (branch, subchange) = value_and_leaf_branch(node_nibble_sub, node_value.clone(), 137 | nibble_sub, value); 138 | change.merge(&subchange); 139 | if common.len() > 0 { 140 | MerkleNode::Extension(common.into(), change.add_value(&branch)) 141 | } else { 142 | branch 143 | } 144 | } 145 | }, 146 | MerkleNode::Branch(ref node_nodes, ref node_additional) => { 147 | let mut nodes = node_nodes.clone(); 148 | if nibble.len() == 0 { 149 | MerkleNode::Branch(nodes, Some(value)) 150 | } else { 151 | let ni: usize = nibble[0].into(); 152 | let prev = nodes[ni].clone(); 153 | let (new, subchange) = insert_by_value( 154 | prev, 155 | nibble[1..].into(), 156 | value, database); 157 | change.merge(&subchange); 158 | 159 | nodes[ni] = new; 160 | MerkleNode::Branch(nodes, node_additional.clone()) 161 | } 162 | }, 163 | }; 164 | 165 | (new, change) 166 | } 167 | 168 | pub fn insert_by_empty<'a>( 169 | nibble: NibbleVec, value: &'a [u8] 170 | ) -> (MerkleNode<'a>, Change) { 171 | let new = MerkleNode::Leaf(nibble, value); 172 | (new, Change::default()) 173 | } 174 | -------------------------------------------------------------------------------- /trie/src/ops/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod insert; 2 | pub mod delete; 3 | pub mod build; 4 | pub mod get; 5 | --------------------------------------------------------------------------------