├── .editorconfig ├── .gitignore ├── .gitmodules ├── Cargo.lock ├── Cargo.toml ├── EIP-152 ├── Cargo.toml ├── LICENSE ├── benches │ └── bench.rs └── src │ ├── avx2.rs │ ├── lib.rs │ └── portable.rs ├── ethcore-builtin ├── Cargo.toml └── src │ └── lib.rs ├── ethjson ├── Cargo.toml └── src │ ├── bytes.rs │ ├── hash.rs │ ├── lib.rs │ ├── maybe.rs │ ├── spec │ ├── account.rs │ ├── authority_round.rs │ ├── basic_authority.rs │ ├── builtin.rs │ ├── clique.rs │ ├── engine.rs │ ├── ethash.rs │ ├── genesis.rs │ ├── hardcoded_sync.rs │ ├── instant_seal.rs │ ├── mod.rs │ ├── null_engine.rs │ ├── params.rs │ ├── seal.rs │ ├── spec.rs │ ├── state.rs │ ├── step_duration.rs │ └── validator_set.rs │ ├── state.rs │ ├── test_helpers │ ├── blockchain │ │ ├── block.rs │ │ ├── header.rs │ │ └── mod.rs │ ├── difficulty.rs │ ├── mod.rs │ ├── skip.rs │ ├── state.rs │ ├── tester.rs │ ├── transaction.rs │ └── trie │ │ ├── input.rs │ │ └── mod.rs │ ├── transaction.rs │ ├── uint.rs │ └── vm.rs ├── jsontests ├── Cargo.toml ├── res │ ├── berlin_builtins.json │ └── istanbul_builtins.json ├── src │ ├── lib.rs │ ├── main.rs │ ├── state.rs │ ├── utils.rs │ └── vm.rs └── tests │ ├── state.rs │ └── vm.rs └── rustfmt.toml /.editorconfig: -------------------------------------------------------------------------------- 1 | root = true 2 | [*] 3 | indent_style=tab 4 | indent_size=tab 5 | tab_width=4 6 | end_of_line=lf 7 | charset=utf-8 8 | trim_trailing_whitespace=true 9 | max_line_length=80 10 | insert_final_newline=true 11 | 12 | [*.yml] 13 | indent_style=space 14 | indent_size=2 15 | tab_width=8 16 | end_of_line=lf 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | **/*.rs.bk 3 | .idea 4 | -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "evm"] 2 | path = evm 3 | url = https://github.com/rust-blockchain/evm 4 | [submodule "jsontests/res/ethtests"] 5 | path = jsontests/res/ethtests 6 | url = https://github.com/ethereum/tests 7 | tag = 9.0.5 8 | -------------------------------------------------------------------------------- /Cargo.toml: -------------------------------------------------------------------------------- 1 | [workspace] 2 | members = [ 3 | "jsontests", 4 | ] 5 | exclude = [ 6 | "evm" 7 | ] 8 | -------------------------------------------------------------------------------- /EIP-152/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "eip-152" 3 | version = "0.1.0" 4 | authors = ["Parity Technologies "] 5 | repository = "https://github.com/openethereum/openethereum" 6 | documentation = "https://docs.rs/eip-152" 7 | readme = "README.md" 8 | description = "eip-512 blake2 F compression function" 9 | keywords = ["eip-152", "eip152", "eip"] 10 | license = "GPL-3.0" 11 | edition = "2018" 12 | 13 | [dependencies] 14 | arrayref = "0.3.5" 15 | 16 | [dev-dependencies] 17 | criterion = "0.3" 18 | rustc-hex = "2.1.0" 19 | 20 | [[bench]] 21 | name = "bench" 22 | harness = false 23 | -------------------------------------------------------------------------------- /EIP-152/LICENSE: -------------------------------------------------------------------------------- 1 | This program is copyright 2020 Parity Technologies Limited and its licensors. 2 | 3 | GNU GENERAL PUBLIC LICENSE 4 | Version 3, 29 June 2007 5 | 6 | Some portions of the program (“the Software”) are Copyright (c) 2018 Jack O'Connor 7 | and the following relates solely to such portions: 8 | 9 | Permission is hereby granted, free of charge, to any person obtaining a copy 10 | of this software and associated documentation files (the "Software"), to deal 11 | in the Software without restriction, including without limitation the rights 12 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 13 | copies of the Software, and to permit persons to whom the Software is 14 | furnished to do so, subject to the following conditions: 15 | 16 | The above copyright notice and this permission notice shall be included in all 17 | copies or substantial portions of the Software. 18 | 19 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 20 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 21 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 22 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 23 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 24 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 25 | SOFTWARE. 26 | -------------------------------------------------------------------------------- /EIP-152/benches/bench.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | use criterion::{black_box, criterion_group, criterion_main, BenchmarkId, Criterion, Throughput}; 18 | use eip_152::portable; 19 | use std::mem; 20 | use std::sync::atomic::{AtomicPtr, Ordering}; 21 | 22 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 23 | use eip_152::avx2; 24 | 25 | type FnRaw = *mut (); 26 | type Blake2bF = fn(&mut [u64; 8], [u64; 16], [u64; 2], bool, usize); 27 | 28 | static FN: AtomicPtr<()> = AtomicPtr::new(detect as FnRaw); 29 | 30 | fn detect(state: &mut [u64; 8], message: [u64; 16], count: [u64; 2], f: bool, rounds: usize) { 31 | let fun = if is_x86_feature_detected!("avx2") { 32 | avx2::compress as FnRaw 33 | } else { 34 | portable::compress as FnRaw 35 | }; 36 | FN.store(fun as FnRaw, Ordering::Relaxed); 37 | unsafe { mem::transmute::(fun)(state, message, count, f, rounds) } 38 | } 39 | 40 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 41 | pub fn avx_ifunc_benchmark(c: &mut Criterion) { 42 | let mut group = c.benchmark_group("avx2_ifunc"); 43 | 44 | for rounds in [12, 50, 100].iter() { 45 | group.throughput(Throughput::Elements(*rounds as u64)); 46 | group.bench_with_input(BenchmarkId::new("rounds", rounds), &rounds, |b, rounds| { 47 | let mut state = [ 48 | 0x6a09e667f2bdc948_u64, 49 | 0xbb67ae8584caa73b_u64, 50 | 0x3c6ef372fe94f82b_u64, 51 | 0xa54ff53a5f1d36f1_u64, 52 | 0x510e527fade682d1_u64, 53 | 0x9b05688c2b3e6c1f_u64, 54 | 0x1f83d9abfb41bd6b_u64, 55 | 0x5be0cd19137e2179_u64, 56 | ]; 57 | 58 | let message = [ 59 | 0x0000000000636261_u64, 60 | 0x0000000000000000_u64, 61 | 0x0000000000000000_u64, 62 | 0x0000000000000000_u64, 63 | 0x0000000000000000_u64, 64 | 0x0000000000000000_u64, 65 | 0x0000000000000000_u64, 66 | 0x0000000000000000_u64, 67 | 0x0000000000000000_u64, 68 | 0x0000000000000000_u64, 69 | 0x0000000000000000_u64, 70 | 0x0000000000000000_u64, 71 | 0x0000000000000000_u64, 72 | 0x0000000000000000_u64, 73 | 0x0000000000000000_u64, 74 | 0x0000000000000000_u64, 75 | ]; 76 | let count = [3, 0]; 77 | let f = true; 78 | 79 | b.iter(|| unsafe { 80 | let fun = FN.load(Ordering::Relaxed); 81 | mem::transmute::(fun)( 82 | black_box(&mut state), 83 | black_box(message), 84 | black_box(count), 85 | black_box(f), 86 | black_box(**rounds as usize), 87 | ); 88 | }); 89 | }); 90 | } 91 | 92 | group.finish(); 93 | } 94 | 95 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 96 | pub fn avx_benchmark(c: &mut Criterion) { 97 | let mut group = c.benchmark_group("avx2"); 98 | 99 | for rounds in [12, 50, 100].iter() { 100 | group.throughput(Throughput::Elements(*rounds as u64)); 101 | group.bench_with_input(BenchmarkId::new("rounds", rounds), &rounds, |b, rounds| { 102 | let mut state = [ 103 | 0x6a09e667f2bdc948_u64, 104 | 0xbb67ae8584caa73b_u64, 105 | 0x3c6ef372fe94f82b_u64, 106 | 0xa54ff53a5f1d36f1_u64, 107 | 0x510e527fade682d1_u64, 108 | 0x9b05688c2b3e6c1f_u64, 109 | 0x1f83d9abfb41bd6b_u64, 110 | 0x5be0cd19137e2179_u64, 111 | ]; 112 | 113 | let message = [ 114 | 0x0000000000636261_u64, 115 | 0x0000000000000000_u64, 116 | 0x0000000000000000_u64, 117 | 0x0000000000000000_u64, 118 | 0x0000000000000000_u64, 119 | 0x0000000000000000_u64, 120 | 0x0000000000000000_u64, 121 | 0x0000000000000000_u64, 122 | 0x0000000000000000_u64, 123 | 0x0000000000000000_u64, 124 | 0x0000000000000000_u64, 125 | 0x0000000000000000_u64, 126 | 0x0000000000000000_u64, 127 | 0x0000000000000000_u64, 128 | 0x0000000000000000_u64, 129 | 0x0000000000000000_u64, 130 | ]; 131 | let count = [3, 0]; 132 | let f = true; 133 | 134 | b.iter(|| unsafe { 135 | avx2::compress( 136 | black_box(&mut state), 137 | black_box(message), 138 | black_box(count), 139 | black_box(f), 140 | black_box(**rounds as usize), 141 | ); 142 | }); 143 | }); 144 | } 145 | 146 | group.finish(); 147 | } 148 | 149 | pub fn portable_benchmark(c: &mut Criterion) { 150 | let mut group = c.benchmark_group("portable_impl"); 151 | 152 | for rounds in [12, 50, 100].iter() { 153 | group.throughput(Throughput::Elements(*rounds as u64)); 154 | group.bench_with_input(BenchmarkId::new("rounds", rounds), &rounds, |b, rounds| { 155 | let mut state = [ 156 | 0x6a09e667f2bdc948_u64, 157 | 0xbb67ae8584caa73b_u64, 158 | 0x3c6ef372fe94f82b_u64, 159 | 0xa54ff53a5f1d36f1_u64, 160 | 0x510e527fade682d1_u64, 161 | 0x9b05688c2b3e6c1f_u64, 162 | 0x1f83d9abfb41bd6b_u64, 163 | 0x5be0cd19137e2179_u64, 164 | ]; 165 | 166 | let message = [ 167 | 0x0000000000636261_u64, 168 | 0x0000000000000000_u64, 169 | 0x0000000000000000_u64, 170 | 0x0000000000000000_u64, 171 | 0x0000000000000000_u64, 172 | 0x0000000000000000_u64, 173 | 0x0000000000000000_u64, 174 | 0x0000000000000000_u64, 175 | 0x0000000000000000_u64, 176 | 0x0000000000000000_u64, 177 | 0x0000000000000000_u64, 178 | 0x0000000000000000_u64, 179 | 0x0000000000000000_u64, 180 | 0x0000000000000000_u64, 181 | 0x0000000000000000_u64, 182 | 0x0000000000000000_u64, 183 | ]; 184 | let count = [3, 0]; 185 | let f = true; 186 | 187 | b.iter(|| { 188 | portable::compress( 189 | black_box(&mut state), 190 | black_box(message), 191 | black_box(count), 192 | black_box(f), 193 | black_box(**rounds as usize), 194 | ); 195 | }); 196 | }); 197 | } 198 | 199 | group.finish(); 200 | } 201 | 202 | criterion_group!( 203 | benches, 204 | avx_benchmark, 205 | avx_ifunc_benchmark, 206 | portable_benchmark 207 | ); 208 | criterion_main!(benches); 209 | -------------------------------------------------------------------------------- /EIP-152/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 18 | pub mod avx2; 19 | pub mod portable; 20 | 21 | /// The precomputed values for BLAKE2b [from the spec](https://tools.ietf.org/html/rfc7693#section-2.7) 22 | /// There are 10 16-byte arrays - one for each round 23 | /// the entries are calculated from the sigma constants. 24 | const SIGMA: [[usize; 16]; 10] = [ 25 | [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15], 26 | [14, 10, 4, 8, 9, 15, 13, 6, 1, 12, 0, 2, 11, 7, 5, 3], 27 | [11, 8, 12, 0, 5, 2, 15, 13, 10, 14, 3, 6, 7, 1, 9, 4], 28 | [7, 9, 3, 1, 13, 12, 11, 14, 2, 6, 5, 10, 4, 0, 15, 8], 29 | [9, 0, 5, 7, 2, 4, 10, 15, 14, 1, 11, 12, 6, 8, 3, 13], 30 | [2, 12, 6, 10, 0, 11, 8, 3, 4, 13, 7, 5, 15, 14, 1, 9], 31 | [12, 5, 1, 15, 14, 13, 4, 10, 0, 7, 6, 3, 9, 2, 8, 11], 32 | [13, 11, 7, 14, 12, 1, 3, 9, 5, 0, 15, 4, 8, 6, 2, 10], 33 | [6, 15, 14, 9, 11, 3, 0, 8, 12, 2, 13, 7, 1, 4, 10, 5], 34 | [10, 2, 8, 4, 7, 6, 1, 5, 15, 11, 9, 14, 3, 12, 13, 0], 35 | ]; 36 | 37 | /// IV is the initialization vector for BLAKE2b. See https://tools.ietf.org/html/rfc7693#section-2.6 38 | /// for details. 39 | const IV: [u64; 8] = [ 40 | 0x6a09e667f3bcc908, 41 | 0xbb67ae8584caa73b, 42 | 0x3c6ef372fe94f82b, 43 | 0xa54ff53a5f1d36f1, 44 | 0x510e527fade682d1, 45 | 0x9b05688c2b3e6c1f, 46 | 0x1f83d9abfb41bd6b, 47 | 0x5be0cd19137e2179, 48 | ]; 49 | 50 | /// blake2b compression function 51 | pub fn compress(state: &mut [u64; 8], message: [u64; 16], count: [u64; 2], f: bool, rounds: usize) { 52 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 53 | { 54 | if is_x86_feature_detected!("avx2") { 55 | unsafe { return avx2::compress(state, message, count, f, rounds) } 56 | } else { 57 | return portable::compress(state, message, count, f, rounds); 58 | }; 59 | } 60 | 61 | #[cfg(not(any(target_arch = "x86", target_arch = "x86_64")))] 62 | portable::compress(state, message, count, f, rounds); 63 | } 64 | 65 | #[cfg(test)] 66 | mod tests { 67 | use crate::portable; 68 | 69 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 70 | use crate::avx2; 71 | use rustc_hex::FromHex; 72 | 73 | #[test] 74 | fn test_blake2_f() { 75 | // test from https://github.com/ethereum/EIPs/blob/master/EIPS/eip-152.md#example-usage-in-solidity 76 | let mut h_in = [ 77 | 0x6a09e667f2bdc948_u64, 78 | 0xbb67ae8584caa73b_u64, 79 | 0x3c6ef372fe94f82b_u64, 80 | 0xa54ff53a5f1d36f1_u64, 81 | 0x510e527fade682d1_u64, 82 | 0x9b05688c2b3e6c1f_u64, 83 | 0x1f83d9abfb41bd6b_u64, 84 | 0x5be0cd19137e2179_u64, 85 | ]; 86 | 87 | let m = [ 88 | 0x0000000000636261_u64, 89 | 0x0000000000000000_u64, 90 | 0x0000000000000000_u64, 91 | 0x0000000000000000_u64, 92 | 0x0000000000000000_u64, 93 | 0x0000000000000000_u64, 94 | 0x0000000000000000_u64, 95 | 0x0000000000000000_u64, 96 | 0x0000000000000000_u64, 97 | 0x0000000000000000_u64, 98 | 0x0000000000000000_u64, 99 | 0x0000000000000000_u64, 100 | 0x0000000000000000_u64, 101 | 0x0000000000000000_u64, 102 | 0x0000000000000000_u64, 103 | 0x0000000000000000_u64, 104 | ]; 105 | let c = [3, 0]; 106 | let f = true; 107 | let rounds = 12; 108 | let h_out: [u64; 8] = [ 109 | 0x0D4D1C983FA580BA_u64, 110 | 0xE9F6129FB697276A_u64, 111 | 0xB7C45A68142F214C_u64, 112 | 0xD1A2FFDB6FBB124B_u64, 113 | 0x2D79AB2A39C5877D_u64, 114 | 0x95CC3345DED552C2_u64, 115 | 0x5A92F1DBA88AD318_u64, 116 | 0x239900D4ED8623B9_u64, 117 | ]; 118 | 119 | // portable 120 | portable::compress(&mut h_in, m, c, f, rounds); 121 | assert_eq!(h_in, h_out); 122 | 123 | let mut h_in = [ 124 | 0x6a09e667f2bdc948_u64, 125 | 0xbb67ae8584caa73b_u64, 126 | 0x3c6ef372fe94f82b_u64, 127 | 0xa54ff53a5f1d36f1_u64, 128 | 0x510e527fade682d1_u64, 129 | 0x9b05688c2b3e6c1f_u64, 130 | 0x1f83d9abfb41bd6b_u64, 131 | 0x5be0cd19137e2179_u64, 132 | ]; 133 | 134 | // avx 135 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 136 | { 137 | if is_x86_feature_detected!("avx2") { 138 | unsafe { 139 | avx2::compress(&mut h_in, m, c, f, rounds); 140 | assert_eq!(h_in, h_out); 141 | } 142 | } 143 | } 144 | } 145 | 146 | fn to_u64_slice(vec: &[u8], slice: &mut [u64]) { 147 | vec.chunks(8).enumerate().for_each(|(index, val)| { 148 | slice[index] = u64::from_le_bytes([ 149 | val[0], val[1], val[2], val[3], val[4], val[5], val[6], val[7], 150 | ]) 151 | }) 152 | } 153 | 154 | #[test] 155 | fn test_vectors_from_eip() { 156 | let vec = vec![ 157 | ( 158 | // Test vector 4 159 | "0000000048c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", 160 | "08c9bcf367e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d282e6ad7f520e511f6c3e2b8c68059b9442be0454267ce079217e1319cde05b", 161 | ), 162 | ( // test vector 5 163 | "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", 164 | "ba80a53f981c4d0d6a2797b69f12f6e94c212f14685ac4b74b12bb6fdbffa2d17d87c5392aab792dc252d5de4533cc9518d38aa8dbf1925ab92386edd4009923", 165 | ), 166 | ( 167 | // Test vector 6 168 | "0000000c48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000000", 169 | "75ab69d3190a562c51aef8d88f1c2775876944407270c42c9844252c26d2875298743e7f6d5ea2f2d3e8d226039cd31b4e426ac4f2d3d666a610c2116fde4735", 170 | ), 171 | ( 172 | // Test vector 7 173 | "0000000148c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", 174 | "b63a380cb2897d521994a85234ee2c181b5f844d2c624c002677e9703449d2fba551b3a8333bcdf5f2f7e08993d53923de3d64fcc68c034e717b9293fed7a421", 175 | ), 176 | // Test vector 8 – u32::MAX rounds – too slow to run 177 | // ( 178 | // "ffffffff48c9bdf267e6096a3ba7ca8485ae67bb2bf894fe72f36e3cf1361d5f3af54fa5d182e6ad7f520e511f6c3e2b8c68059b6bbd41fbabd9831f79217e1319cde05b61626300000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000000000000000000000000000001", 179 | // "fc59093aafa9ab43daae0e914c57635c5402d8e3d2130eb9b3cc181de7f0ecf9b22bf99a7815ce16419e200e01846e6b5df8cc7703041bbceb571de6631d2615", 180 | // ), 181 | ]; 182 | for (hex, output) in vec { 183 | let hex = hex; 184 | let bytes: Vec = hex.from_hex().unwrap(); 185 | 186 | assert_eq!(bytes.len(), 213); 187 | 188 | let mut h = [0u64; 8]; 189 | let mut m = [0u64; 16]; 190 | let mut t = [0u64; 2]; 191 | 192 | let rounds = u32::from_be_bytes([bytes[0], bytes[1], bytes[2], bytes[3]]); 193 | let f = match bytes[212] { 194 | 1 => true, 195 | 0 => false, 196 | _ => unreachable!(), 197 | }; 198 | 199 | to_u64_slice(&bytes[4..68], &mut h); 200 | to_u64_slice(&bytes[68..196], &mut m); 201 | to_u64_slice(&bytes[196..212], &mut t); 202 | let output: Vec = output.from_hex().unwrap(); 203 | let mut out = [0u64; 8]; 204 | to_u64_slice(&output[..], &mut out); 205 | 206 | #[cfg(any(target_arch = "x86", target_arch = "x86_64"))] 207 | { 208 | // avx 209 | if is_x86_feature_detected!("avx2") { 210 | unsafe { 211 | avx2::compress(&mut h, m, t, f, rounds as usize); 212 | assert_eq!(out, h); 213 | } 214 | } 215 | } 216 | 217 | { 218 | // portable 219 | to_u64_slice(&bytes[4..68], &mut h); 220 | portable::compress(&mut h, m, t, f, rounds as usize); 221 | assert_eq!(out, h); 222 | } 223 | } 224 | } 225 | } 226 | -------------------------------------------------------------------------------- /EIP-152/src/portable.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Portable implementation of the blake2b compress function 18 | 19 | use crate::{IV, SIGMA}; 20 | 21 | /// The G mixing function. See https://tools.ietf.org/html/rfc7693#section-3.1 22 | #[inline(always)] 23 | fn g(v: &mut [u64], a: usize, b: usize, c: usize, d: usize, x: u64, y: u64) { 24 | v[a] = v[a].wrapping_add(v[b]).wrapping_add(x); 25 | v[d] = (v[d] ^ v[a]).rotate_right(32); 26 | v[c] = v[c].wrapping_add(v[d]); 27 | v[b] = (v[b] ^ v[c]).rotate_right(24); 28 | 29 | v[a] = v[a].wrapping_add(v[b]).wrapping_add(y); 30 | v[d] = (v[d] ^ v[a]).rotate_right(16); 31 | v[c] = v[c].wrapping_add(v[d]); 32 | v[b] = (v[b] ^ v[c]).rotate_right(63); 33 | } 34 | 35 | /// The Blake2b compression function F. See https://tools.ietf.org/html/rfc7693#section-3.2 36 | /// Takes as an argument the state vector `h`, message block vector `m`, offset counter `t`, final 37 | /// block indicator flag `f`, and number of rounds `rounds`. The state vector provided as the first 38 | /// parameter is modified by the function. 39 | pub fn compress(h: &mut [u64; 8], m: [u64; 16], t: [u64; 2], f: bool, rounds: usize) { 40 | let mut v = [0u64; 16]; 41 | v[..8].copy_from_slice(h); // First half from state. 42 | v[8..].copy_from_slice(&IV); // Second half from IV. 43 | 44 | v[12] ^= t[0]; 45 | v[13] ^= t[1]; 46 | 47 | if f { 48 | v[14] = !v[14]; // Invert all bits if the last-block-flag is set. 49 | } 50 | 51 | for i in 0..rounds { 52 | // Message word selection permutation for this round. 53 | let s = &SIGMA[i % 10]; 54 | g(&mut v, 0, 4, 8, 12, m[s[0]], m[s[1]]); 55 | g(&mut v, 1, 5, 9, 13, m[s[2]], m[s[3]]); 56 | g(&mut v, 2, 6, 10, 14, m[s[4]], m[s[5]]); 57 | g(&mut v, 3, 7, 11, 15, m[s[6]], m[s[7]]); 58 | 59 | g(&mut v, 0, 5, 10, 15, m[s[8]], m[s[9]]); 60 | g(&mut v, 1, 6, 11, 12, m[s[10]], m[s[11]]); 61 | g(&mut v, 2, 7, 8, 13, m[s[12]], m[s[13]]); 62 | g(&mut v, 3, 4, 9, 14, m[s[14]], m[s[15]]); 63 | } 64 | 65 | for i in 0..8 { 66 | h[i] ^= v[i] ^ v[i + 8]; 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /ethcore-builtin/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | description = "ethereum vm builtin" 3 | name = "ethcore-builtin" 4 | version = "0.1.0" 5 | authors = ["Parity Technologies "] 6 | edition = "2018" 7 | 8 | [dependencies] 9 | bn = { git = "https://github.com/paritytech/bn", default-features = false } 10 | byteorder = "1.3.2" 11 | eip-152 = { path = "../EIP-152" } 12 | ethereum-types = "0.14" 13 | ethjson = { path = "../ethjson" } 14 | keccak-hash = "0.10" 15 | log = "0.4" 16 | num = "0.2" 17 | parity-bytes = "0.1" 18 | libsecp256k1 = "0.7" 19 | ripemd = { version = "0.1", default-features = false } 20 | sha2 = { version = "0.10.0", default-features = false } 21 | eth_pairings = { git = "https://github.com/matter-labs/eip1962.git", default-features = false, features = ["eip_2537"], rev = "ece6cbabc41948db4200e41f0bfdab7ab94c7af8" } 22 | 23 | [dev-dependencies] 24 | hex-literal = "0.2.1" 25 | maplit = "1.0.2" 26 | -------------------------------------------------------------------------------- /ethjson/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | description = "OpenEthereum JSON Deserialization" 3 | name = "ethjson" 4 | version = "0.1.0" 5 | authors = ["Parity Technologies "] 6 | edition = "2018" 7 | 8 | [dependencies] 9 | ethereum-types = "0.14" 10 | rustc-hex = "2.1.0" 11 | serde = { version = "1.0", features = ["derive"] } 12 | serde_json = "1.0" 13 | 14 | [dev-dependencies] 15 | maplit = "1.0.2" 16 | 17 | [features] 18 | test-helpers = [] 19 | -------------------------------------------------------------------------------- /ethjson/src/bytes.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Lenient bytes json deserialization for test json files. 18 | 19 | use rustc_hex::FromHex; 20 | use serde::de::{Error, Visitor}; 21 | use serde::{Deserialize, Deserializer}; 22 | use std::fmt; 23 | use std::ops::Deref; 24 | use std::str::FromStr; 25 | 26 | /// Lenient bytes json deserialization for test json files. 27 | #[derive(Default, Debug, PartialEq, Eq, Clone, PartialOrd, Ord)] 28 | pub struct Bytes(Vec); 29 | 30 | impl Bytes { 31 | /// Creates bytes struct. 32 | pub fn new(v: Vec) -> Self { 33 | Bytes(v) 34 | } 35 | } 36 | 37 | impl From for Vec { 38 | fn from(bytes: Bytes) -> Self { 39 | bytes.0 40 | } 41 | } 42 | 43 | impl From> for Bytes { 44 | fn from(bytes: Vec) -> Self { 45 | Bytes(bytes) 46 | } 47 | } 48 | 49 | impl Deref for Bytes { 50 | type Target = [u8]; 51 | 52 | fn deref(&self) -> &[u8] { 53 | &self.0 54 | } 55 | } 56 | 57 | impl FromStr for Bytes { 58 | type Err = String; 59 | 60 | fn from_str(value: &str) -> Result { 61 | let v = match value.len() { 62 | 0 => vec![], 63 | 2 if value.starts_with("0x") => vec![], 64 | _ if value.starts_with("0x") && value.len() % 2 == 1 => { 65 | let v = "0".to_owned() + &value[2..]; 66 | FromHex::from_hex(v.as_str()).unwrap_or_default() 67 | } 68 | _ if value.starts_with("0x") => FromHex::from_hex(&value[2..]).unwrap_or_default(), 69 | _ => FromHex::from_hex(value).unwrap_or_default(), 70 | }; 71 | 72 | Ok(Bytes(v)) 73 | } 74 | } 75 | 76 | impl<'a> Deserialize<'a> for Bytes { 77 | fn deserialize(deserializer: D) -> Result 78 | where 79 | D: Deserializer<'a>, 80 | { 81 | deserializer.deserialize_any(BytesVisitor) 82 | } 83 | } 84 | 85 | struct BytesVisitor; 86 | 87 | impl<'a> Visitor<'a> for BytesVisitor { 88 | type Value = Bytes; 89 | 90 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 91 | write!(formatter, "a hex encoded string of bytes") 92 | } 93 | 94 | fn visit_str(self, value: &str) -> Result 95 | where 96 | E: Error, 97 | { 98 | Bytes::from_str(value).map_err(Error::custom) 99 | } 100 | 101 | fn visit_string(self, value: String) -> Result 102 | where 103 | E: Error, 104 | { 105 | self.visit_str(value.as_ref()) 106 | } 107 | } 108 | 109 | #[cfg(test)] 110 | mod test { 111 | use super::Bytes; 112 | 113 | #[test] 114 | fn bytes_deserialization() { 115 | let s = r#"["", "0x", "0x12", "1234", "0x001"]"#; 116 | let deserialized: Vec = serde_json::from_str(s).unwrap(); 117 | assert_eq!( 118 | deserialized, 119 | vec![ 120 | Bytes(vec![]), 121 | Bytes(vec![]), 122 | Bytes(vec![0x12]), 123 | Bytes(vec![0x12, 0x34]), 124 | Bytes(vec![0, 1]) 125 | ] 126 | ); 127 | } 128 | 129 | #[test] 130 | fn bytes_into() { 131 | let v: Vec = Bytes(vec![0xff, 0x11]).into(); 132 | assert_eq!(vec![0xff, 0x11], v); 133 | } 134 | } 135 | -------------------------------------------------------------------------------- /ethjson/src/hash.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Lenient hash json deserialization for test json files. 18 | 19 | use ethereum_types::{ 20 | Bloom as Hash2048, H160 as Hash160, H256 as Hash256, H520 as Hash520, H64 as Hash64, 21 | }; 22 | use serde::de::{Error, Visitor}; 23 | use serde::{Deserialize, Deserializer, Serialize, Serializer}; 24 | use std::fmt; 25 | use std::str::FromStr; 26 | 27 | macro_rules! impl_hash { 28 | ($name: ident, $inner: ident) => { 29 | /// Lenient hash json deserialization for test json files. 30 | #[derive(Default, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, Clone, Copy)] 31 | pub struct $name(pub $inner); 32 | 33 | impl From<$name> for $inner { 34 | fn from(other: $name) -> $inner { 35 | other.0 36 | } 37 | } 38 | 39 | impl From<$inner> for $name { 40 | fn from(i: $inner) -> Self { 41 | $name(i) 42 | } 43 | } 44 | 45 | impl<'a> Deserialize<'a> for $name { 46 | fn deserialize(deserializer: D) -> Result 47 | where 48 | D: Deserializer<'a>, 49 | { 50 | struct HashVisitor; 51 | 52 | impl<'b> Visitor<'b> for HashVisitor { 53 | type Value = $name; 54 | 55 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 56 | write!(formatter, "a 0x-prefixed hex-encoded hash") 57 | } 58 | 59 | fn visit_str(self, value: &str) -> Result 60 | where 61 | E: Error, 62 | { 63 | let value = match value.len() { 64 | 0 => $inner::from_low_u64_be(0), 65 | 2 if value == "0x" => $inner::from_low_u64_be(0), 66 | _ if value.starts_with("0x") => { 67 | $inner::from_str(&value[2..]).map_err(|e| { 68 | Error::custom( 69 | format!("Invalid hex value {}: {}", value, e).as_str(), 70 | ) 71 | })? 72 | } 73 | _ => $inner::from_str(value).map_err(|e| { 74 | Error::custom( 75 | format!("Invalid hex value {}: {}", value, e).as_str(), 76 | ) 77 | })?, 78 | }; 79 | 80 | Ok($name(value)) 81 | } 82 | 83 | fn visit_string(self, value: String) -> Result 84 | where 85 | E: Error, 86 | { 87 | self.visit_str(value.as_ref()) 88 | } 89 | } 90 | 91 | deserializer.deserialize_any(HashVisitor) 92 | } 93 | } 94 | 95 | impl Serialize for $name { 96 | fn serialize(&self, serializer: S) -> Result 97 | where 98 | S: Serializer, 99 | { 100 | serializer.serialize_str(&format!("{:#x}", self.0)) 101 | } 102 | } 103 | }; 104 | } 105 | 106 | impl_hash!(H64, Hash64); 107 | impl_hash!(Address, Hash160); 108 | impl_hash!(H256, Hash256); 109 | impl_hash!(H520, Hash520); 110 | impl_hash!(Bloom, Hash2048); 111 | 112 | #[cfg(test)] 113 | mod test { 114 | use super::H256; 115 | use std::str::FromStr; 116 | 117 | #[test] 118 | fn hash_deserialization() { 119 | let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#; 120 | let deserialized: Vec = serde_json::from_str(s).unwrap(); 121 | assert_eq!( 122 | deserialized, 123 | vec![ 124 | H256(ethereum_types::H256::zero()), 125 | H256( 126 | ethereum_types::H256::from_str( 127 | "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae" 128 | ) 129 | .unwrap() 130 | ) 131 | ] 132 | ); 133 | } 134 | 135 | #[test] 136 | fn hash_into() { 137 | assert_eq!( 138 | ethereum_types::H256::zero(), 139 | H256(ethereum_types::H256::zero()).into() 140 | ); 141 | } 142 | } 143 | -------------------------------------------------------------------------------- /ethjson/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! JSON deserialization library 18 | 19 | #![warn(missing_docs)] 20 | 21 | pub mod bytes; 22 | pub mod hash; 23 | pub mod maybe; 24 | pub mod spec; 25 | pub mod state; 26 | pub mod transaction; 27 | pub mod uint; 28 | pub mod vm; 29 | 30 | #[cfg(any(test, feature = "test-helpers"))] 31 | pub mod test_helpers; 32 | -------------------------------------------------------------------------------- /ethjson/src/maybe.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Deserializer of empty string values into optionals. 18 | 19 | use std::fmt; 20 | use std::marker::PhantomData; 21 | 22 | use ethereum_types::U256; 23 | use serde::de::{Error, IntoDeserializer, Visitor}; 24 | use serde::{Deserialize, Deserializer}; 25 | 26 | use crate::uint::Uint; 27 | 28 | /// Deserializer of empty string values into optionals. 29 | #[derive(Debug, PartialEq, Clone)] 30 | pub enum MaybeEmpty { 31 | /// Some. 32 | Some(T), 33 | /// None. 34 | None, 35 | } 36 | 37 | impl<'a, T> Deserialize<'a> for MaybeEmpty 38 | where 39 | T: Deserialize<'a>, 40 | { 41 | fn deserialize(deserializer: D) -> Result 42 | where 43 | D: Deserializer<'a>, 44 | { 45 | deserializer.deserialize_any(MaybeEmptyVisitor::new()) 46 | } 47 | } 48 | 49 | struct MaybeEmptyVisitor { 50 | _phantom: PhantomData, 51 | } 52 | 53 | impl MaybeEmptyVisitor { 54 | fn new() -> Self { 55 | MaybeEmptyVisitor { 56 | _phantom: PhantomData, 57 | } 58 | } 59 | } 60 | 61 | impl<'a, T> Visitor<'a> for MaybeEmptyVisitor 62 | where 63 | T: Deserialize<'a>, 64 | { 65 | type Value = MaybeEmpty; 66 | 67 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 68 | write!(formatter, "an empty string or string-encoded type") 69 | } 70 | 71 | fn visit_str(self, value: &str) -> Result 72 | where 73 | E: Error, 74 | { 75 | self.visit_string(value.to_owned()) 76 | } 77 | 78 | fn visit_string(self, value: String) -> Result 79 | where 80 | E: Error, 81 | { 82 | if value.is_empty() { 83 | Ok(MaybeEmpty::None) 84 | } else { 85 | T::deserialize(value.into_deserializer()).map(MaybeEmpty::Some) 86 | } 87 | } 88 | } 89 | 90 | impl Into> for MaybeEmpty { 91 | fn into(self) -> Option { 92 | match self { 93 | MaybeEmpty::Some(s) => Some(s), 94 | MaybeEmpty::None => None, 95 | } 96 | } 97 | } 98 | 99 | #[cfg(test)] 100 | impl From for MaybeEmpty { 101 | fn from(uint: Uint) -> Self { 102 | MaybeEmpty::Some(uint) 103 | } 104 | } 105 | 106 | impl From> for U256 { 107 | fn from(maybe: MaybeEmpty) -> U256 { 108 | match maybe { 109 | MaybeEmpty::Some(v) => v.0, 110 | MaybeEmpty::None => U256::zero(), 111 | } 112 | } 113 | } 114 | 115 | impl From> for u64 { 116 | fn from(maybe: MaybeEmpty) -> u64 { 117 | match maybe { 118 | MaybeEmpty::Some(v) => v.0.low_u64(), 119 | MaybeEmpty::None => 0u64, 120 | } 121 | } 122 | } 123 | 124 | impl Default for MaybeEmpty { 125 | fn default() -> Self { 126 | MaybeEmpty::Some(Uint::default()) 127 | } 128 | } 129 | 130 | #[cfg(test)] 131 | mod tests { 132 | use super::MaybeEmpty; 133 | use crate::hash::H256; 134 | use std::str::FromStr; 135 | 136 | #[test] 137 | fn maybe_deserialization() { 138 | let s = r#"["", "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae"]"#; 139 | let deserialized: Vec> = serde_json::from_str(s).unwrap(); 140 | assert_eq!( 141 | deserialized, 142 | vec![ 143 | MaybeEmpty::None, 144 | MaybeEmpty::Some(H256( 145 | ethereum_types::H256::from_str( 146 | "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae" 147 | ) 148 | .unwrap() 149 | )) 150 | ] 151 | ); 152 | } 153 | } 154 | -------------------------------------------------------------------------------- /ethjson/src/spec/account.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Spec account deserialization. 18 | 19 | use std::collections::BTreeMap; 20 | 21 | use crate::{bytes::Bytes, spec::builtin::BuiltinCompat, uint::Uint}; 22 | use serde::Deserialize; 23 | 24 | /// Spec account. 25 | #[cfg_attr(any(test, feature = "test-helpers"), derive(Clone))] 26 | #[derive(Debug, PartialEq, Deserialize)] 27 | #[serde(deny_unknown_fields)] 28 | #[serde(rename_all = "camelCase")] 29 | pub struct Account { 30 | /// Builtin contract. 31 | pub builtin: Option, 32 | /// Balance. 33 | pub balance: Option, 34 | /// Nonce. 35 | pub nonce: Option, 36 | /// Code. 37 | pub code: Option, 38 | /// Version. 39 | pub version: Option, 40 | /// Storage. 41 | pub storage: Option>, 42 | /// Constructor. 43 | pub constructor: Option, 44 | } 45 | 46 | impl Account { 47 | /// Returns true if account does not have nonce, balance, code and storage. 48 | pub fn is_empty(&self) -> bool { 49 | self.balance.is_none() 50 | && self.nonce.is_none() 51 | && self.code.is_none() 52 | && self.storage.is_none() 53 | } 54 | } 55 | 56 | #[cfg(test)] 57 | mod tests { 58 | use super::{Account, BTreeMap, Bytes, Uint}; 59 | use ethereum_types::U256; 60 | 61 | #[test] 62 | fn account_balance_missing_not_empty() { 63 | let s = r#"{ 64 | "nonce": "0", 65 | "code": "1234", 66 | "storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" } 67 | }"#; 68 | let deserialized: Account = serde_json::from_str(s).unwrap(); 69 | assert!(!deserialized.is_empty()); 70 | } 71 | 72 | #[test] 73 | fn account_nonce_missing_not_empty() { 74 | let s = r#"{ 75 | "balance": "1", 76 | "code": "1234", 77 | "storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" } 78 | }"#; 79 | let deserialized: Account = serde_json::from_str(s).unwrap(); 80 | assert!(!deserialized.is_empty()); 81 | } 82 | 83 | #[test] 84 | fn account_code_missing_not_empty() { 85 | let s = r#"{ 86 | "balance": "1", 87 | "nonce": "0", 88 | "storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" } 89 | }"#; 90 | let deserialized: Account = serde_json::from_str(s).unwrap(); 91 | assert!(!deserialized.is_empty()); 92 | } 93 | 94 | #[test] 95 | fn account_storage_missing_not_empty() { 96 | let s = r#"{ 97 | "balance": "1", 98 | "nonce": "0", 99 | "code": "1234" 100 | }"#; 101 | let deserialized: Account = serde_json::from_str(s).unwrap(); 102 | assert!(!deserialized.is_empty()); 103 | } 104 | 105 | #[test] 106 | fn account_empty() { 107 | let s = r#"{ 108 | "builtin": { 109 | "name": "ecrecover", 110 | "pricing": { 111 | "linear": { 112 | "base": 3000, 113 | "word": 0 114 | } 115 | } 116 | } 117 | }"#; 118 | let deserialized: Account = serde_json::from_str(s).unwrap(); 119 | assert!(deserialized.is_empty()); 120 | } 121 | 122 | #[test] 123 | fn account_deserialization() { 124 | let s = r#"{ 125 | "balance": "1", 126 | "nonce": "0", 127 | "code": "1234", 128 | "builtin": { 129 | "name": "ecrecover", 130 | "pricing": { 131 | "linear": { 132 | "base": 3000, 133 | "word": 0 134 | } 135 | } 136 | } 137 | }"#; 138 | let deserialized: Account = serde_json::from_str(s).unwrap(); 139 | assert!(!deserialized.is_empty()); 140 | assert_eq!(deserialized.balance.unwrap(), Uint(U256::from(1))); 141 | assert_eq!(deserialized.nonce.unwrap(), Uint(U256::from(0))); 142 | assert_eq!(deserialized.code.unwrap(), Bytes::new(vec![0x12, 0x34])); 143 | assert!(deserialized.builtin.is_some()); // Further tested in builtin.rs 144 | } 145 | 146 | #[test] 147 | fn account_storage_deserialization() { 148 | let s = r#"{ 149 | "balance": "1", 150 | "nonce": "0", 151 | "code": "1234", 152 | "storage": { "0x7fffffffffffffff7fffffffffffffff": "0x1" } 153 | }"#; 154 | let deserialized: Account = serde_json::from_str(s).unwrap(); 155 | assert!(!deserialized.is_empty()); 156 | assert_eq!(deserialized.balance.unwrap(), Uint(U256::from(1))); 157 | assert_eq!(deserialized.nonce.unwrap(), Uint(U256::from(0))); 158 | assert_eq!(deserialized.code.unwrap(), Bytes::new(vec![0x12, 0x34])); 159 | let mut storage = BTreeMap::new(); 160 | storage.insert( 161 | Uint(U256::from("7fffffffffffffff7fffffffffffffff")), 162 | Uint(U256::from(1)), 163 | ); 164 | assert_eq!(deserialized.storage.unwrap(), storage); 165 | } 166 | } 167 | -------------------------------------------------------------------------------- /ethjson/src/spec/authority_round.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Authority Round parameter deserialization. 18 | //! 19 | //! Here is an example of input parameters where the step duration is constant at 5 seconds, the set 20 | //! of validators is decided by the contract at address `0x10..01` starting from block 0, and where 21 | //! the address of the contract that computes block rewards is set to `0x20..02` for blocks 0 22 | //! through 41 and to `0x30.03` for all blocks starting from block 42. 23 | //! 24 | //! ```ignore 25 | //! "params": { 26 | //! "stepDuration": "5", 27 | //! "validators": { 28 | //! "multi": { 29 | //! "0": { 30 | //! "contract": "0x1000000000000000000000000000000000000001" 31 | //! } 32 | //! } 33 | //! }, 34 | //! "blockRewardContractTransitions": { 35 | //! "0": "0x2000000000000000000000000000000000000002", 36 | //! "42": "0x3000000000000000000000000000000000000003" 37 | //! } 38 | //! } 39 | //! ``` 40 | 41 | use super::{StepDuration, ValidatorSet}; 42 | use crate::{bytes::Bytes, hash::Address, uint::Uint}; 43 | use serde::Deserialize; 44 | use std::collections::BTreeMap; 45 | 46 | /// Authority params deserialization. 47 | #[derive(Debug, PartialEq, Deserialize)] 48 | #[serde(deny_unknown_fields)] 49 | #[serde(rename_all = "camelCase")] 50 | pub struct AuthorityRoundParams { 51 | /// Block duration, in seconds. 52 | pub step_duration: StepDuration, 53 | /// Valid authorities 54 | pub validators: ValidatorSet, 55 | /// Starting step. Determined automatically if not specified. 56 | /// To be used for testing only. 57 | pub start_step: Option, 58 | /// Block at which score validation should start. 59 | pub validate_score_transition: Option, 60 | /// Block from which monotonic steps start. 61 | pub validate_step_transition: Option, 62 | /// Whether transitions should be immediate. 63 | pub immediate_transitions: Option, 64 | /// Reward per block in wei. 65 | pub block_reward: Option, 66 | /// Block at which the block reward contract should start being used. This option allows one to 67 | /// add a single block reward contract transition and is compatible with the multiple address 68 | /// option `block_reward_contract_transitions` below. 69 | pub block_reward_contract_transition: Option, 70 | /// Block reward contract address which overrides the `block_reward` setting. This option allows 71 | /// one to add a single block reward contract address and is compatible with the multiple 72 | /// address option `block_reward_contract_transitions` below. 73 | pub block_reward_contract_address: Option
, 74 | /// Block reward contract addresses with their associated starting block numbers. 75 | /// 76 | /// Setting the block reward contract overrides `block_reward`. If the single block reward 77 | /// contract address is also present then it is added into the map at the block number stored in 78 | /// `block_reward_contract_transition` or 0 if that block number is not provided. Therefore both 79 | /// a single block reward contract transition and a map of reward contract transitions can be 80 | /// used simulataneously in the same configuration. In such a case the code requires that the 81 | /// block number of the single transition is strictly less than any of the block numbers in the 82 | /// map. 83 | pub block_reward_contract_transitions: Option>, 84 | /// Block reward code. This overrides the block reward contract address. 85 | pub block_reward_contract_code: Option, 86 | /// Block at which maximum uncle count should be considered. 87 | pub maximum_uncle_count_transition: Option, 88 | /// Maximum number of accepted uncles. 89 | pub maximum_uncle_count: Option, 90 | /// Block at which empty step messages should start. 91 | pub empty_steps_transition: Option, 92 | /// Maximum number of accepted empty steps. 93 | pub maximum_empty_steps: Option, 94 | /// Strict validation of empty steps transition block. 95 | pub strict_empty_steps_transition: Option, 96 | /// First block for which a 2/3 quorum (instead of 1/2) is required. 97 | pub two_thirds_majority_transition: Option, 98 | /// The random number contract's address, or a map of contract transitions. 99 | pub randomness_contract_address: Option>, 100 | /// The addresses of contracts that determine the block gas limit starting from the block number 101 | /// associated with each of those contracts. 102 | pub block_gas_limit_contract_transitions: Option>, 103 | /// The block number at which the consensus engine switches from AuRa to AuRa with POSDAO 104 | /// modifications. 105 | pub posdao_transition: Option, 106 | } 107 | 108 | /// Authority engine deserialization. 109 | #[derive(Debug, PartialEq, Deserialize)] 110 | #[serde(deny_unknown_fields)] 111 | pub struct AuthorityRound { 112 | /// Authority Round parameters. 113 | pub params: AuthorityRoundParams, 114 | } 115 | 116 | #[cfg(test)] 117 | mod tests { 118 | use std::str::FromStr; 119 | 120 | use ethereum_types::{H160, U256}; 121 | use serde_json; 122 | 123 | use super::{Address, StepDuration, Uint}; 124 | use crate::spec::{authority_round::AuthorityRound, validator_set::ValidatorSet}; 125 | 126 | #[test] 127 | fn authority_round_deserialization() { 128 | let s = r#"{ 129 | "params": { 130 | "stepDuration": "0x02", 131 | "validators": { 132 | "list" : ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"] 133 | }, 134 | "startStep" : 24, 135 | "validateStepTransition": 150, 136 | "blockReward": 5000000, 137 | "maximumUncleCountTransition": 10000000, 138 | "maximumUncleCount": 5, 139 | "randomnessContractAddress": { 140 | "10": "0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa", 141 | "20": "0xbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb" 142 | }, 143 | "blockGasLimitContractTransitions": { 144 | "10": "0x1000000000000000000000000000000000000001", 145 | "20": "0x2000000000000000000000000000000000000002" 146 | } 147 | } 148 | }"#; 149 | 150 | let deserialized: AuthorityRound = serde_json::from_str(s).unwrap(); 151 | assert_eq!( 152 | deserialized.params.step_duration, 153 | StepDuration::Single(Uint(U256::from(2))) 154 | ); 155 | assert_eq!( 156 | deserialized.params.validators, 157 | ValidatorSet::List(vec![Address( 158 | H160::from_str("c6d9d2cd449a754c494264e1809c50e34d64562b").unwrap() 159 | )]), 160 | ); 161 | assert_eq!(deserialized.params.start_step, Some(Uint(U256::from(24)))); 162 | assert_eq!(deserialized.params.immediate_transitions, None); 163 | assert_eq!( 164 | deserialized.params.maximum_uncle_count_transition, 165 | Some(Uint(10_000_000.into())) 166 | ); 167 | assert_eq!( 168 | deserialized.params.maximum_uncle_count, 169 | Some(Uint(5.into())) 170 | ); 171 | assert_eq!( 172 | deserialized.params.randomness_contract_address.unwrap(), 173 | vec![ 174 | ( 175 | Uint(10.into()), 176 | Address(H160::from_str("aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa").unwrap()) 177 | ), 178 | ( 179 | Uint(20.into()), 180 | Address(H160::from_str("bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb").unwrap()) 181 | ), 182 | ] 183 | .into_iter() 184 | .collect() 185 | ); 186 | let expected_bglc = [ 187 | ( 188 | Uint(10.into()), 189 | Address(H160::from_str("1000000000000000000000000000000000000001").unwrap()), 190 | ), 191 | ( 192 | Uint(20.into()), 193 | Address(H160::from_str("2000000000000000000000000000000000000002").unwrap()), 194 | ), 195 | ]; 196 | assert_eq!( 197 | deserialized.params.block_gas_limit_contract_transitions, 198 | Some(expected_bglc.to_vec().into_iter().collect()) 199 | ); 200 | } 201 | } 202 | -------------------------------------------------------------------------------- /ethjson/src/spec/basic_authority.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Authority params deserialization. 18 | 19 | use super::ValidatorSet; 20 | use crate::uint::Uint; 21 | use serde::Deserialize; 22 | 23 | /// Authority params deserialization. 24 | #[derive(Debug, PartialEq, Deserialize)] 25 | #[serde(deny_unknown_fields)] 26 | #[serde(rename_all = "camelCase")] 27 | pub struct BasicAuthorityParams { 28 | /// Block duration. 29 | pub duration_limit: Uint, 30 | /// Valid authorities 31 | pub validators: ValidatorSet, 32 | } 33 | 34 | /// Authority engine deserialization. 35 | #[derive(Debug, PartialEq, Deserialize)] 36 | #[serde(deny_unknown_fields)] 37 | pub struct BasicAuthority { 38 | /// Ethash params. 39 | pub params: BasicAuthorityParams, 40 | } 41 | 42 | #[cfg(test)] 43 | mod tests { 44 | use super::{BasicAuthority, Uint}; 45 | use crate::{hash::Address, spec::validator_set::ValidatorSet}; 46 | use ethereum_types::{H160, U256}; 47 | use std::str::FromStr; 48 | 49 | #[test] 50 | fn basic_authority_deserialization() { 51 | let s = r#"{ 52 | "params": { 53 | "durationLimit": "0x0d", 54 | "validators" : { 55 | "list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"] 56 | } 57 | } 58 | }"#; 59 | 60 | let deserialized: BasicAuthority = serde_json::from_str(s).unwrap(); 61 | 62 | assert_eq!(deserialized.params.duration_limit, Uint(U256::from(0x0d))); 63 | let vs = ValidatorSet::List(vec![Address( 64 | H160::from_str("c6d9d2cd449a754c494264e1809c50e34d64562b").unwrap(), 65 | )]); 66 | assert_eq!(deserialized.params.validators, vs); 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /ethjson/src/spec/builtin.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Spec builtin deserialization. 18 | 19 | use std::collections::BTreeMap; 20 | 21 | use crate::uint::Uint; 22 | use serde::Deserialize; 23 | 24 | /// Linear pricing. 25 | #[derive(Debug, PartialEq, Deserialize, Clone)] 26 | #[serde(deny_unknown_fields)] 27 | pub struct Linear { 28 | /// Base price. 29 | pub base: u64, 30 | /// Price for word. 31 | pub word: u64, 32 | } 33 | 34 | /// Pricing for modular exponentiation. 35 | #[derive(Debug, PartialEq, Deserialize, Clone)] 36 | #[serde(deny_unknown_fields)] 37 | pub struct Modexp { 38 | /// Price divisor. 39 | pub divisor: u64, 40 | /// Use price scheme from EIP-2565 41 | pub is_eip_2565: bool, 42 | } 43 | 44 | /// Pricing for constant alt_bn128 operations (ECADD and ECMUL) 45 | #[derive(Debug, PartialEq, Deserialize, Clone)] 46 | #[serde(deny_unknown_fields)] 47 | pub struct AltBn128ConstOperations { 48 | /// price 49 | pub price: u64, 50 | } 51 | 52 | /// Pricing for alt_bn128_pairing. 53 | #[derive(Debug, PartialEq, Deserialize, Clone)] 54 | #[serde(deny_unknown_fields)] 55 | pub struct AltBn128Pairing { 56 | /// Base price. 57 | pub base: u64, 58 | /// Price per point pair. 59 | pub pair: u64, 60 | } 61 | 62 | /// Bls12 pairing price 63 | #[derive(Debug, PartialEq, Deserialize, Clone)] 64 | #[serde(deny_unknown_fields)] 65 | pub struct Bls12Pairing { 66 | /// Price per final exp 67 | pub base: u64, 68 | /// Price per pair (Miller loop) 69 | pub pair: u64, 70 | } 71 | 72 | /// Pricing for constant Bls12 operations (ADD and MUL in G1 and G2, as well as mappings) 73 | #[derive(Debug, PartialEq, Deserialize, Clone)] 74 | #[serde(deny_unknown_fields)] 75 | pub struct Bls12ConstOperations { 76 | /// Fixed price. 77 | pub price: u64, 78 | } 79 | 80 | /// Pricing for constant Bls12 operations (ADD and MUL in G1, as well as mappings) 81 | #[derive(Debug, PartialEq, Deserialize, Clone)] 82 | #[serde(deny_unknown_fields)] 83 | pub struct Bls12G1Multiexp { 84 | /// Base const of the operation (G1 or G2 multiplication) 85 | pub base: u64, 86 | } 87 | 88 | /// Pricing for constant Bls12 operations (ADD and MUL in G2, as well as mappings) 89 | #[derive(Debug, PartialEq, Deserialize, Clone)] 90 | #[serde(deny_unknown_fields)] 91 | pub struct Bls12G2Multiexp { 92 | /// Base const of the operation (G1 or G2 multiplication) 93 | pub base: u64, 94 | } 95 | 96 | /// Pricing variants. 97 | #[derive(Debug, PartialEq, Deserialize, Clone)] 98 | #[serde(deny_unknown_fields)] 99 | #[serde(rename_all = "snake_case")] 100 | pub enum Pricing { 101 | /// Pricing for Blake2 compression function: each call costs the same amount per round. 102 | Blake2F { 103 | /// Price per round of Blake2 compression function. 104 | gas_per_round: u64, 105 | }, 106 | /// Linear pricing. 107 | Linear(Linear), 108 | /// Pricing for modular exponentiation. 109 | Modexp(Modexp), 110 | /// Pricing for alt_bn128_pairing exponentiation. 111 | AltBn128Pairing(AltBn128Pairing), 112 | /// Pricing for constant alt_bn128 operations 113 | AltBn128ConstOperations(AltBn128ConstOperations), 114 | /// Pricing of constant price bls12_381 operations 115 | Bls12ConstOperations(Bls12ConstOperations), 116 | /// Pricing of pairing bls12_381 operation 117 | Bls12Pairing(Bls12Pairing), 118 | /// Pricing of bls12_381 multiexp operations in G1 119 | Bls12G1Multiexp(Bls12G1Multiexp), 120 | /// Pricing of bls12_381 multiexp operations in G2 121 | Bls12G2Multiexp(Bls12G2Multiexp), 122 | } 123 | 124 | /// Builtin compability layer 125 | #[derive(Debug, PartialEq, Deserialize, Clone)] 126 | #[serde(deny_unknown_fields)] 127 | pub struct BuiltinCompat { 128 | /// Builtin name. 129 | name: String, 130 | /// Builtin pricing. 131 | pricing: PricingCompat, 132 | /// Activation block. 133 | activate_at: Option, 134 | } 135 | 136 | /// Spec builtin. 137 | #[derive(Debug, PartialEq, Clone)] 138 | pub struct Builtin { 139 | /// Builtin name. 140 | pub name: String, 141 | /// Builtin pricing. 142 | pub pricing: BTreeMap, 143 | } 144 | 145 | impl From for Builtin { 146 | fn from(legacy: BuiltinCompat) -> Self { 147 | let pricing = match legacy.pricing { 148 | PricingCompat::Single(pricing) => { 149 | let mut map = BTreeMap::new(); 150 | let activate_at: u64 = legacy.activate_at.map_or(0, Into::into); 151 | map.insert( 152 | activate_at, 153 | PricingAt { 154 | info: None, 155 | price: pricing, 156 | }, 157 | ); 158 | map 159 | } 160 | PricingCompat::Multi(pricings) => { 161 | pricings.into_iter().map(|(a, p)| (a.into(), p)).collect() 162 | } 163 | }; 164 | Self { 165 | name: legacy.name, 166 | pricing, 167 | } 168 | } 169 | } 170 | 171 | /// Compability layer for different pricings 172 | #[derive(Debug, PartialEq, Deserialize, Clone)] 173 | #[serde(rename_all = "snake_case")] 174 | #[serde(deny_unknown_fields)] 175 | #[serde(untagged)] 176 | enum PricingCompat { 177 | /// Single builtin 178 | Single(Pricing), 179 | /// Multiple builtins 180 | Multi(BTreeMap), 181 | } 182 | 183 | /// Price for a builtin, with the block number to activate it on 184 | #[derive(Debug, PartialEq, Deserialize, Clone)] 185 | #[serde(deny_unknown_fields)] 186 | pub struct PricingAt { 187 | /// Description of the activation, e.g. "PunyPony HF, March 12, 2025". 188 | pub info: Option, 189 | /// Builtin pricing. 190 | pub price: Pricing, 191 | } 192 | 193 | #[cfg(test)] 194 | mod tests { 195 | use super::{ 196 | AltBn128ConstOperations, Bls12G1Multiexp, Bls12G2Multiexp, Builtin, BuiltinCompat, Linear, 197 | Modexp, Pricing, PricingAt, 198 | }; 199 | use maplit::btreemap; 200 | 201 | #[test] 202 | fn builtin_deserialization() { 203 | let s = r#"{ 204 | "name": "ecrecover", 205 | "pricing": { "linear": { "base": 3000, "word": 0 } } 206 | }"#; 207 | let builtin: Builtin = serde_json::from_str::(s).unwrap().into(); 208 | assert_eq!(builtin.name, "ecrecover"); 209 | assert_eq!( 210 | builtin.pricing, 211 | btreemap![ 212 | 0 => PricingAt { 213 | info: None, 214 | price: Pricing::Linear(Linear { base: 3000, word: 0 }) 215 | } 216 | ] 217 | ); 218 | } 219 | 220 | #[test] 221 | fn deserialize_multiple_pricings() { 222 | let s = r#"{ 223 | "name": "ecrecover", 224 | "pricing": { 225 | "0": { 226 | "price": {"linear": { "base": 3000, "word": 0 }} 227 | }, 228 | "500": { 229 | "info": "enable fake EIP at block 500", 230 | "price": {"linear": { "base": 10, "word": 0 }} 231 | } 232 | } 233 | }"#; 234 | let builtin: Builtin = serde_json::from_str::(s).unwrap().into(); 235 | assert_eq!(builtin.name, "ecrecover"); 236 | assert_eq!( 237 | builtin.pricing, 238 | btreemap![ 239 | 0 => PricingAt { 240 | info: None, 241 | price: Pricing::Linear(Linear { base: 3000, word: 0 }) 242 | }, 243 | 500 => PricingAt { 244 | info: Some(String::from("enable fake EIP at block 500")), 245 | price: Pricing::Linear(Linear { base: 10, word: 0 }) 246 | } 247 | ] 248 | ); 249 | } 250 | 251 | #[test] 252 | fn deserialization_blake2_f_builtin() { 253 | let s = r#"{ 254 | "name": "blake2_f", 255 | "activate_at": "0xffffff", 256 | "pricing": { "blake2_f": { "gas_per_round": 123 } } 257 | }"#; 258 | let builtin: Builtin = serde_json::from_str::(s).unwrap().into(); 259 | assert_eq!(builtin.name, "blake2_f"); 260 | assert_eq!( 261 | builtin.pricing, 262 | btreemap![ 263 | 0xffffff => PricingAt { 264 | info: None, 265 | price: Pricing::Blake2F { gas_per_round: 123 } 266 | } 267 | ] 268 | ); 269 | } 270 | 271 | #[test] 272 | fn deserialization_alt_bn128_const_operations() { 273 | let s = r#"{ 274 | "name": "alt_bn128_mul", 275 | "pricing": { 276 | "100500": { 277 | "price": { "alt_bn128_const_operations": { "price": 123 }} 278 | } 279 | } 280 | }"#; 281 | let builtin: Builtin = serde_json::from_str::(s).unwrap().into(); 282 | assert_eq!(builtin.name, "alt_bn128_mul"); 283 | assert_eq!( 284 | builtin.pricing, 285 | btreemap![ 286 | 100500 => PricingAt { 287 | info: None, 288 | price: Pricing::AltBn128ConstOperations(AltBn128ConstOperations { 289 | price: 123, 290 | }), 291 | } 292 | ] 293 | ); 294 | } 295 | 296 | #[test] 297 | fn activate_at() { 298 | let s = r#"{ 299 | "name": "late_start", 300 | "activate_at": 100000, 301 | "pricing": { "modexp": { "divisor": 5, "is_eip_2565": false } } 302 | }"#; 303 | 304 | let builtin: Builtin = serde_json::from_str::(s).unwrap().into(); 305 | assert_eq!(builtin.name, "late_start"); 306 | assert_eq!( 307 | builtin.pricing, 308 | btreemap![ 309 | 100_000 => PricingAt { 310 | info: None, 311 | price: Pricing::Modexp(Modexp { divisor: 5, is_eip_2565: false }) 312 | } 313 | ] 314 | ); 315 | } 316 | 317 | #[test] 318 | fn deserialization_bls12_381_multiexp_operation() { 319 | let s = r#"{ 320 | "name": "bls12_381_g1_multiexp", 321 | "pricing": { 322 | "10000000": { 323 | "price": { "bls12_g1_multiexp": { "base": 12000}} 324 | } 325 | } 326 | }"#; 327 | let builtin: Builtin = serde_json::from_str::(s).unwrap().into(); 328 | assert_eq!(builtin.name, "bls12_381_g1_multiexp"); 329 | assert_eq!( 330 | builtin.pricing, 331 | btreemap![ 332 | 10000000 => PricingAt { 333 | info: None, 334 | price: Pricing::Bls12G1Multiexp(Bls12G1Multiexp{ 335 | base: 12000 336 | }), 337 | } 338 | ] 339 | ); 340 | } 341 | 342 | #[test] 343 | fn deserialization_bls12_381_multiexp_operation_in_g2() { 344 | let s = r#"{ 345 | "name": "bls12_381_g2_multiexp", 346 | "pricing": { 347 | "10000000": { 348 | "price": { "bls12_g2_multiexp": { "base": 55000}} 349 | } 350 | } 351 | }"#; 352 | let builtin: Builtin = serde_json::from_str::(s).unwrap().into(); 353 | assert_eq!(builtin.name, "bls12_381_g2_multiexp"); 354 | assert_eq!( 355 | builtin.pricing, 356 | btreemap![ 357 | 10000000 => PricingAt { 358 | info: None, 359 | price: Pricing::Bls12G2Multiexp(Bls12G2Multiexp{ 360 | base: 55000 361 | }), 362 | } 363 | ] 364 | ); 365 | } 366 | } 367 | -------------------------------------------------------------------------------- /ethjson/src/spec/clique.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Clique params deserialization. 18 | 19 | use serde::Deserialize; 20 | use std::num::NonZeroU64; 21 | 22 | /// Clique params deserialization. 23 | #[derive(Debug, PartialEq, Deserialize)] 24 | pub struct CliqueParams { 25 | /// period as defined in EIP 225 26 | pub period: Option, 27 | /// epoch length as defined in EIP 225 28 | pub epoch: Option, 29 | } 30 | 31 | /// Clique engine deserialization. 32 | #[derive(Debug, PartialEq, Deserialize)] 33 | pub struct Clique { 34 | /// CliqueEngine params 35 | pub params: CliqueParams, 36 | } 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use super::{Clique, NonZeroU64}; 41 | 42 | #[test] 43 | fn clique_deserialization() { 44 | let s = r#"{ 45 | "params": { 46 | "period": 5, 47 | "epoch": 30000 48 | } 49 | }"#; 50 | 51 | let deserialized: Clique = serde_json::from_str(s).unwrap(); 52 | assert_eq!(deserialized.params.period, Some(5u64)); 53 | assert_eq!(deserialized.params.epoch, NonZeroU64::new(30000)); 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ethjson/src/spec/engine.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Engine deserialization. 18 | 19 | use super::{AuthorityRound, BasicAuthority, Clique, Ethash, InstantSeal, NullEngine}; 20 | use serde::Deserialize; 21 | 22 | /// Engine deserialization. 23 | #[derive(Debug, PartialEq, Deserialize)] 24 | #[serde(deny_unknown_fields)] 25 | #[serde(rename_all = "camelCase")] 26 | pub enum Engine { 27 | /// Null engine. 28 | Null(NullEngine), 29 | /// Instantly sealing engine. 30 | InstantSeal(Option), 31 | /// Ethash engine. 32 | #[serde(rename = "Ethash")] 33 | Ethash(Ethash), 34 | /// BasicAuthority engine. 35 | BasicAuthority(BasicAuthority), 36 | /// AuthorityRound engine. 37 | AuthorityRound(AuthorityRound), 38 | /// Clique engine. 39 | Clique(Clique), 40 | } 41 | 42 | #[cfg(test)] 43 | mod tests { 44 | use super::Engine; 45 | 46 | #[test] 47 | fn engine_deserialization() { 48 | let s = r#"{ 49 | "null": { 50 | "params": { 51 | "blockReward": "0x0d" 52 | } 53 | } 54 | }"#; 55 | 56 | let deserialized: Engine = serde_json::from_str(s).unwrap(); 57 | match deserialized { 58 | Engine::Null(_) => {} // unit test in its own file. 59 | _ => panic!(), 60 | } 61 | 62 | let s = r#"{ 63 | "instantSeal": {"params": {}} 64 | }"#; 65 | 66 | let deserialized: Engine = serde_json::from_str(s).unwrap(); 67 | match deserialized { 68 | Engine::InstantSeal(_) => {} // instant seal is unit tested in its own file. 69 | _ => panic!(), 70 | }; 71 | 72 | let s = r#"{ 73 | "instantSeal": null 74 | }"#; 75 | 76 | let deserialized: Engine = serde_json::from_str(s).unwrap(); 77 | match deserialized { 78 | Engine::InstantSeal(_) => {} // instant seal is unit tested in its own file. 79 | _ => panic!(), 80 | }; 81 | 82 | let s = r#"{ 83 | "Ethash": { 84 | "params": { 85 | "minimumDifficulty": "0x020000", 86 | "difficultyBoundDivisor": "0x0800", 87 | "durationLimit": "0x0d", 88 | "homesteadTransition" : "0x", 89 | "daoHardforkTransition": "0xffffffffffffffff", 90 | "daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000", 91 | "daoHardforkAccounts": [] 92 | } 93 | } 94 | }"#; 95 | 96 | let deserialized: Engine = serde_json::from_str(s).unwrap(); 97 | match deserialized { 98 | Engine::Ethash(_) => {} // ethash is unit tested in its own file. 99 | _ => panic!(), 100 | }; 101 | 102 | let s = r#"{ 103 | "basicAuthority": { 104 | "params": { 105 | "durationLimit": "0x0d", 106 | "validators" : { 107 | "list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"] 108 | } 109 | } 110 | } 111 | }"#; 112 | let deserialized: Engine = serde_json::from_str(s).unwrap(); 113 | match deserialized { 114 | Engine::BasicAuthority(_) => {} // basicAuthority is unit tested in its own file. 115 | _ => panic!(), 116 | }; 117 | 118 | let s = r#"{ 119 | "authorityRound": { 120 | "params": { 121 | "stepDuration": "0x02", 122 | "validators": { 123 | "list" : ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"] 124 | }, 125 | "startStep" : 24, 126 | "validateStepTransition": 150 127 | } 128 | } 129 | }"#; 130 | let deserialized: Engine = serde_json::from_str(s).unwrap(); 131 | match deserialized { 132 | Engine::AuthorityRound(_) => {} // AuthorityRound is unit tested in its own file. 133 | _ => panic!(), 134 | }; 135 | 136 | let s = r#"{ 137 | "clique": { 138 | "params": { 139 | "period": 15, 140 | "epoch": 30000 141 | } 142 | } 143 | }"#; 144 | let deserialized: Engine = serde_json::from_str(s).unwrap(); 145 | match deserialized { 146 | Engine::Clique(_) => {} // Clique is unit tested in its own file. 147 | _ => panic!(), 148 | }; 149 | } 150 | } 151 | -------------------------------------------------------------------------------- /ethjson/src/spec/ethash.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Ethash params deserialization. 18 | 19 | use crate::{ 20 | bytes::Bytes, 21 | hash::Address, 22 | uint::{self, Uint}, 23 | }; 24 | use serde::Deserialize; 25 | use std::collections::BTreeMap; 26 | 27 | /// Deserializable doppelganger of block rewards for EthashParams 28 | #[derive(Clone, Debug, PartialEq, Deserialize)] 29 | #[serde(deny_unknown_fields)] 30 | #[serde(untagged)] 31 | pub enum BlockReward { 32 | /// Single block reward 33 | Single(Uint), 34 | /// Several block rewards 35 | Multi(BTreeMap), 36 | } 37 | 38 | /// Deserializable doppelganger of EthashParams. 39 | #[derive(Clone, Debug, PartialEq, Deserialize)] 40 | #[serde(deny_unknown_fields)] 41 | #[serde(rename_all = "camelCase")] 42 | pub struct EthashParams { 43 | /// See main EthashParams docs. 44 | #[serde(deserialize_with = "uint::validate_non_zero")] 45 | pub minimum_difficulty: Uint, 46 | /// See main EthashParams docs. 47 | #[serde(deserialize_with = "uint::validate_non_zero")] 48 | pub difficulty_bound_divisor: Uint, 49 | /// See main EthashParams docs. 50 | #[serde(default, deserialize_with = "uint::validate_optional_non_zero")] 51 | pub difficulty_increment_divisor: Option, 52 | /// See main EthashParams docs. 53 | #[serde(default, deserialize_with = "uint::validate_optional_non_zero")] 54 | pub metropolis_difficulty_increment_divisor: Option, 55 | /// See main EthashParams docs. 56 | pub duration_limit: Option, 57 | 58 | /// See main EthashParams docs. 59 | pub homestead_transition: Option, 60 | /// Reward per block in wei. 61 | pub block_reward: Option, 62 | /// Block at which the block reward contract should start being used. 63 | pub block_reward_contract_transition: Option, 64 | /// Block reward contract address (setting the block reward contract 65 | /// overrides all other block reward parameters). 66 | pub block_reward_contract_address: Option
, 67 | /// Block reward code. This overrides the block reward contract address. 68 | pub block_reward_contract_code: Option, 69 | 70 | /// See main EthashParams docs. 71 | pub dao_hardfork_transition: Option, 72 | /// See main EthashParams docs. 73 | pub dao_hardfork_beneficiary: Option
, 74 | /// See main EthashParams docs. 75 | pub dao_hardfork_accounts: Option>, 76 | 77 | /// See main EthashParams docs. 78 | pub difficulty_hardfork_transition: Option, 79 | /// See main EthashParams docs. 80 | #[serde(default, deserialize_with = "uint::validate_optional_non_zero")] 81 | pub difficulty_hardfork_bound_divisor: Option, 82 | /// See main EthashParams docs. 83 | pub bomb_defuse_transition: Option, 84 | 85 | /// See main EthashParams docs. 86 | pub eip100b_transition: Option, 87 | 88 | /// See main EthashParams docs. 89 | #[serde(default, deserialize_with = "uint::validate_optional_non_zero")] 90 | pub ecip1017_era_rounds: Option, 91 | 92 | /// Delays of difficulty bombs. 93 | pub difficulty_bomb_delays: Option>, 94 | 95 | /// EXPIP-2 block height 96 | pub expip2_transition: Option, 97 | /// EXPIP-2 duration limit 98 | pub expip2_duration_limit: Option, 99 | /// Block to transition to progpow 100 | pub progpow_transition: Option, 101 | } 102 | 103 | /// Ethash engine deserialization. 104 | #[derive(Debug, PartialEq, Deserialize)] 105 | #[serde(deny_unknown_fields)] 106 | pub struct Ethash { 107 | /// Ethash params. 108 | pub params: EthashParams, 109 | } 110 | 111 | #[cfg(test)] 112 | mod tests { 113 | use super::{Address, BlockReward, Ethash, EthashParams, Uint}; 114 | use ethereum_types::{H160, U256}; 115 | use std::str::FromStr; 116 | 117 | #[test] 118 | fn ethash_deserialization() { 119 | let s = r#"{ 120 | "params": { 121 | "minimumDifficulty": "0x020000", 122 | "difficultyBoundDivisor": "0x0800", 123 | "durationLimit": "0x0d", 124 | "homesteadTransition": "0x42", 125 | "blockReward": "0x100", 126 | "daoHardforkTransition": "0x08", 127 | "daoHardforkBeneficiary": "0xabcabcabcabcabcabcabcabcabcabcabcabcabca", 128 | "daoHardforkAccounts": [ 129 | "0x304a554a310c7e546dfe434669c62820b7d83490", 130 | "0x914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79", 131 | "0xfe24cdd8648121a43a7c86d289be4dd2951ed49f", 132 | "0x17802f43a0137c506ba92291391a8a8f207f487d", 133 | "0xb136707642a4ea12fb4bae820f03d2562ebff487", 134 | "0xdbe9b615a3ae8709af8b93336ce9b477e4ac0940", 135 | "0xf14c14075d6c4ed84b86798af0956deef67365b5", 136 | "0xca544e5c4687d109611d0f8f928b53a25af72448", 137 | "0xaeeb8ff27288bdabc0fa5ebb731b6f409507516c", 138 | "0xcbb9d3703e651b0d496cdefb8b92c25aeb2171f7", 139 | "0xaccc230e8a6e5be9160b8cdf2864dd2a001c28b6", 140 | "0x2b3455ec7fedf16e646268bf88846bd7a2319bb2", 141 | "0x4613f3bca5c44ea06337a9e439fbc6d42e501d0a", 142 | "0xd343b217de44030afaa275f54d31a9317c7f441e", 143 | "0x84ef4b2357079cd7a7c69fd7a37cd0609a679106", 144 | "0xda2fef9e4a3230988ff17df2165440f37e8b1708", 145 | "0xf4c64518ea10f995918a454158c6b61407ea345c", 146 | "0x7602b46df5390e432ef1c307d4f2c9ff6d65cc97", 147 | "0xbb9bc244d798123fde783fcc1c72d3bb8c189413", 148 | "0x807640a13483f8ac783c557fcdf27be11ea4ac7a" 149 | ], 150 | "difficultyHardforkTransition": "0x59d9", 151 | "difficultyHardforkBoundDivisor": "0x0200", 152 | "bombDefuseTransition": "0x41", 153 | "eip100bTransition": "0x42" 154 | } 155 | }"#; 156 | 157 | let deserialized: Ethash = serde_json::from_str(s).unwrap(); 158 | 159 | assert_eq!( 160 | deserialized, 161 | Ethash { 162 | params: EthashParams { 163 | minimum_difficulty: Uint(U256::from(0x020000)), 164 | difficulty_bound_divisor: Uint(U256::from(0x0800)), 165 | difficulty_increment_divisor: None, 166 | metropolis_difficulty_increment_divisor: None, 167 | duration_limit: Some(Uint(U256::from(0x0d))), 168 | homestead_transition: Some(Uint(U256::from(0x42))), 169 | block_reward: Some(BlockReward::Single(Uint(U256::from(0x100)))), 170 | block_reward_contract_address: None, 171 | block_reward_contract_code: None, 172 | block_reward_contract_transition: None, 173 | dao_hardfork_transition: Some(Uint(U256::from(0x08))), 174 | dao_hardfork_beneficiary: Some(Address( 175 | H160::from_str("abcabcabcabcabcabcabcabcabcabcabcabcabca").unwrap() 176 | )), 177 | dao_hardfork_accounts: Some(vec![ 178 | Address( 179 | H160::from_str("304a554a310c7e546dfe434669c62820b7d83490").unwrap() 180 | ), 181 | Address( 182 | H160::from_str("914d1b8b43e92723e64fd0a06f5bdb8dd9b10c79").unwrap() 183 | ), 184 | Address( 185 | H160::from_str("fe24cdd8648121a43a7c86d289be4dd2951ed49f").unwrap() 186 | ), 187 | Address( 188 | H160::from_str("17802f43a0137c506ba92291391a8a8f207f487d").unwrap() 189 | ), 190 | Address( 191 | H160::from_str("b136707642a4ea12fb4bae820f03d2562ebff487").unwrap() 192 | ), 193 | Address( 194 | H160::from_str("dbe9b615a3ae8709af8b93336ce9b477e4ac0940").unwrap() 195 | ), 196 | Address( 197 | H160::from_str("f14c14075d6c4ed84b86798af0956deef67365b5").unwrap() 198 | ), 199 | Address( 200 | H160::from_str("ca544e5c4687d109611d0f8f928b53a25af72448").unwrap() 201 | ), 202 | Address( 203 | H160::from_str("aeeb8ff27288bdabc0fa5ebb731b6f409507516c").unwrap() 204 | ), 205 | Address( 206 | H160::from_str("cbb9d3703e651b0d496cdefb8b92c25aeb2171f7").unwrap() 207 | ), 208 | Address( 209 | H160::from_str("accc230e8a6e5be9160b8cdf2864dd2a001c28b6").unwrap() 210 | ), 211 | Address( 212 | H160::from_str("2b3455ec7fedf16e646268bf88846bd7a2319bb2").unwrap() 213 | ), 214 | Address( 215 | H160::from_str("4613f3bca5c44ea06337a9e439fbc6d42e501d0a").unwrap() 216 | ), 217 | Address( 218 | H160::from_str("d343b217de44030afaa275f54d31a9317c7f441e").unwrap() 219 | ), 220 | Address( 221 | H160::from_str("84ef4b2357079cd7a7c69fd7a37cd0609a679106").unwrap() 222 | ), 223 | Address( 224 | H160::from_str("da2fef9e4a3230988ff17df2165440f37e8b1708").unwrap() 225 | ), 226 | Address( 227 | H160::from_str("f4c64518ea10f995918a454158c6b61407ea345c").unwrap() 228 | ), 229 | Address( 230 | H160::from_str("7602b46df5390e432ef1c307d4f2c9ff6d65cc97").unwrap() 231 | ), 232 | Address( 233 | H160::from_str("bb9bc244d798123fde783fcc1c72d3bb8c189413").unwrap() 234 | ), 235 | Address( 236 | H160::from_str("807640a13483f8ac783c557fcdf27be11ea4ac7a").unwrap() 237 | ), 238 | ]), 239 | difficulty_hardfork_transition: Some(Uint(U256::from(0x59d9))), 240 | difficulty_hardfork_bound_divisor: Some(Uint(U256::from(0x0200))), 241 | bomb_defuse_transition: Some(Uint(U256::from(0x41))), 242 | eip100b_transition: Some(Uint(U256::from(0x42))), 243 | ecip1017_era_rounds: None, 244 | expip2_transition: None, 245 | expip2_duration_limit: None, 246 | progpow_transition: None, 247 | difficulty_bomb_delays: None, 248 | } 249 | } 250 | ); 251 | } 252 | 253 | #[test] 254 | fn ethash_deserialization_missing_optionals() { 255 | let s = r#"{ 256 | "params": { 257 | "difficultyBoundDivisor": "0x0800", 258 | "minimumDifficulty": "0x020000" 259 | } 260 | }"#; 261 | 262 | let deserialized: Ethash = serde_json::from_str(s).unwrap(); 263 | assert_eq!( 264 | deserialized, 265 | Ethash { 266 | params: EthashParams { 267 | minimum_difficulty: Uint(U256::from(0x020000)), 268 | difficulty_bound_divisor: Uint(U256::from(0x0800)), 269 | difficulty_increment_divisor: None, 270 | metropolis_difficulty_increment_divisor: None, 271 | duration_limit: None, 272 | homestead_transition: None, 273 | block_reward: None, 274 | block_reward_contract_address: None, 275 | block_reward_contract_code: None, 276 | block_reward_contract_transition: None, 277 | dao_hardfork_transition: None, 278 | dao_hardfork_beneficiary: None, 279 | dao_hardfork_accounts: None, 280 | difficulty_hardfork_transition: None, 281 | difficulty_hardfork_bound_divisor: None, 282 | bomb_defuse_transition: None, 283 | eip100b_transition: None, 284 | ecip1017_era_rounds: None, 285 | expip2_transition: None, 286 | expip2_duration_limit: None, 287 | progpow_transition: None, 288 | difficulty_bomb_delays: None, 289 | } 290 | } 291 | ); 292 | } 293 | 294 | #[test] 295 | #[should_panic(expected = "a non-zero value")] 296 | fn test_zero_value_divisor() { 297 | let s = r#"{ 298 | "params": { 299 | "difficultyBoundDivisor": "0x0", 300 | "minimumDifficulty": "0x020000" 301 | } 302 | }"#; 303 | 304 | let _deserialized: Ethash = serde_json::from_str(s).unwrap(); 305 | } 306 | } 307 | -------------------------------------------------------------------------------- /ethjson/src/spec/genesis.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Spec genesis deserialization. 18 | 19 | use crate::{ 20 | bytes::Bytes, 21 | hash::{Address, H256}, 22 | spec::Seal, 23 | uint::{self, Uint}, 24 | }; 25 | use serde::Deserialize; 26 | 27 | /// Spec genesis. 28 | #[derive(Debug, PartialEq, Deserialize)] 29 | #[serde(deny_unknown_fields)] 30 | #[serde(rename_all = "camelCase")] 31 | pub struct Genesis { 32 | /// Seal. 33 | pub seal: Seal, 34 | /// Difficulty. 35 | pub difficulty: Uint, 36 | /// Block author, defaults to 0. 37 | pub author: Option
, 38 | /// Block timestamp, defaults to 0. 39 | pub timestamp: Option, 40 | /// Parent hash, defaults to 0. 41 | pub parent_hash: Option, 42 | /// Gas limit. 43 | #[serde(deserialize_with = "uint::validate_non_zero")] 44 | pub gas_limit: Uint, 45 | /// Transactions root. 46 | pub transactions_root: Option, 47 | /// Receipts root. 48 | pub receipts_root: Option, 49 | /// State root. 50 | pub state_root: Option, 51 | /// Gas used. 52 | pub gas_used: Option, 53 | /// Extra data. 54 | pub extra_data: Option, 55 | } 56 | 57 | #[cfg(test)] 58 | mod tests { 59 | use super::{Address, Bytes, Genesis, Uint, H256}; 60 | use crate::{ 61 | hash::H64, 62 | spec::{Ethereum, Seal}, 63 | }; 64 | use ethereum_types::{H160, H256 as Eth256, H64 as Eth64, U256}; 65 | use std::str::FromStr; 66 | 67 | #[test] 68 | fn genesis_deserialization() { 69 | let s = r#"{ 70 | "difficulty": "0x400000000", 71 | "seal": { 72 | "ethereum": { 73 | "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 74 | "nonce": "0x00006d6f7264656e" 75 | } 76 | }, 77 | "author": "0x1000000000000000000000000000000000000001", 78 | "timestamp": "0x07", 79 | "parentHash": "0x9000000000000000000000000000000000000000000000000000000000000000", 80 | "extraData": "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", 81 | "gasLimit": "0x1388", 82 | "stateRoot": "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" 83 | }"#; 84 | let deserialized: Genesis = serde_json::from_str(s).unwrap(); 85 | assert_eq!( 86 | deserialized, 87 | Genesis { 88 | seal: Seal::Ethereum(Ethereum { 89 | nonce: H64(Eth64::from_str("00006d6f7264656e").unwrap()), 90 | mix_hash: H256( 91 | Eth256::from_str( 92 | "0000000000000000000000000000000000000000000000000000000000000000" 93 | ) 94 | .unwrap() 95 | ) 96 | }), 97 | difficulty: Uint(U256::from(0x400000000u64)), 98 | author: Some(Address( 99 | H160::from_str("1000000000000000000000000000000000000001").unwrap() 100 | )), 101 | timestamp: Some(Uint(U256::from(0x07))), 102 | parent_hash: Some(H256( 103 | Eth256::from_str( 104 | "9000000000000000000000000000000000000000000000000000000000000000" 105 | ) 106 | .unwrap() 107 | )), 108 | gas_limit: Uint(U256::from(0x1388)), 109 | transactions_root: None, 110 | receipts_root: None, 111 | state_root: Some(H256( 112 | Eth256::from_str( 113 | "d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" 114 | ) 115 | .unwrap() 116 | )), 117 | gas_used: None, 118 | extra_data: Some( 119 | Bytes::from_str( 120 | "11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa" 121 | ) 122 | .unwrap() 123 | ), 124 | } 125 | ); 126 | } 127 | } 128 | -------------------------------------------------------------------------------- /ethjson/src/spec/hardcoded_sync.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Spec hardcoded synchronization deserialization for the light client. 18 | 19 | use crate::{bytes::Bytes, hash::H256, uint::Uint}; 20 | use serde::Deserialize; 21 | 22 | /// Spec hardcoded sync. 23 | #[derive(Debug, PartialEq, Deserialize)] 24 | #[serde(deny_unknown_fields)] 25 | #[serde(rename_all = "camelCase")] 26 | pub struct HardcodedSync { 27 | /// Hexadecimal of the RLP encoding of the header of the block to start synchronization from. 28 | pub header: Bytes, 29 | /// Total difficulty including the block of `header`. 30 | pub total_difficulty: Uint, 31 | /// Ordered trie roots of blocks before and including `header`. 32 | #[serde(rename = "CHTs")] 33 | pub chts: Vec, 34 | } 35 | 36 | #[cfg(test)] 37 | mod tests { 38 | use super::{HardcodedSync, Uint, H256}; 39 | use ethereum_types::{H256 as Eth256, U256}; 40 | use std::str::FromStr; 41 | 42 | #[test] 43 | fn hardcoded_sync_deserialization() { 44 | let s = r#"{ 45 | "header": "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23", 46 | "totalDifficulty": "0x400000000", 47 | "CHTs": [ 48 | "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", 49 | "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" 50 | ] 51 | }"#; 52 | let deserialized: HardcodedSync = serde_json::from_str(s).unwrap(); 53 | assert_eq!(deserialized, HardcodedSync { 54 | header: "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23".parse().unwrap(), 55 | total_difficulty: Uint(U256::from(0x400000000u64)), 56 | chts: vec![ 57 | H256(Eth256::from_str("11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa").unwrap()), 58 | H256(Eth256::from_str("d7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544").unwrap()), 59 | ] 60 | }); 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /ethjson/src/spec/instant_seal.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Instant seal engine params deserialization. 18 | 19 | use serde::Deserialize; 20 | 21 | /// Instant seal engine params deserialization. 22 | #[derive(Debug, PartialEq, Deserialize)] 23 | #[serde(deny_unknown_fields)] 24 | #[serde(rename_all = "camelCase")] 25 | pub struct InstantSealParams { 26 | /// Whether to enable millisecond timestamp. 27 | #[serde(default)] 28 | pub millisecond_timestamp: bool, 29 | } 30 | 31 | /// Instant seal engine descriptor. 32 | #[derive(Debug, PartialEq, Deserialize)] 33 | #[serde(deny_unknown_fields)] 34 | pub struct InstantSeal { 35 | /// Instant seal parameters. 36 | pub params: InstantSealParams, 37 | } 38 | -------------------------------------------------------------------------------- /ethjson/src/spec/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Spec deserialization. 18 | 19 | pub mod account; 20 | pub mod authority_round; 21 | pub mod basic_authority; 22 | pub mod builtin; 23 | pub mod clique; 24 | pub mod engine; 25 | pub mod ethash; 26 | pub mod genesis; 27 | pub mod hardcoded_sync; 28 | pub mod instant_seal; 29 | pub mod null_engine; 30 | pub mod params; 31 | pub mod seal; 32 | pub mod spec; 33 | pub mod state; 34 | pub mod step_duration; 35 | pub mod validator_set; 36 | 37 | pub use self::account::Account; 38 | pub use self::authority_round::{AuthorityRound, AuthorityRoundParams}; 39 | pub use self::basic_authority::{BasicAuthority, BasicAuthorityParams}; 40 | pub use self::builtin::{Builtin, Linear, Pricing}; 41 | pub use self::clique::{Clique, CliqueParams}; 42 | pub use self::engine::Engine; 43 | pub use self::ethash::{BlockReward, Ethash, EthashParams}; 44 | pub use self::genesis::Genesis; 45 | pub use self::hardcoded_sync::HardcodedSync; 46 | pub use self::instant_seal::{InstantSeal, InstantSealParams}; 47 | pub use self::null_engine::{NullEngine, NullEngineParams}; 48 | pub use self::params::Params; 49 | pub use self::seal::{AuthorityRoundSeal, Ethereum, Seal, TendermintSeal}; 50 | pub use self::spec::{ForkSpec, Spec}; 51 | pub use self::state::{HashOrMap, State}; 52 | pub use self::step_duration::StepDuration; 53 | pub use self::validator_set::ValidatorSet; 54 | -------------------------------------------------------------------------------- /ethjson/src/spec/null_engine.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Null engine params deserialization. 18 | 19 | use crate::uint::Uint; 20 | use serde::Deserialize; 21 | 22 | /// Authority params deserialization. 23 | #[derive(Debug, PartialEq, Deserialize)] 24 | #[serde(deny_unknown_fields)] 25 | #[serde(rename_all = "camelCase")] 26 | pub struct NullEngineParams { 27 | /// Block reward. 28 | pub block_reward: Option, 29 | /// Immediate finalization. 30 | pub immediate_finalization: Option, 31 | } 32 | 33 | /// Null engine descriptor 34 | #[derive(Debug, PartialEq, Deserialize)] 35 | #[serde(deny_unknown_fields)] 36 | pub struct NullEngine { 37 | /// Ethash params. 38 | pub params: NullEngineParams, 39 | } 40 | 41 | #[cfg(test)] 42 | mod tests { 43 | use super::{NullEngine, Uint}; 44 | use ethereum_types::U256; 45 | 46 | #[test] 47 | fn null_engine_deserialization() { 48 | let s = r#"{ 49 | "params": { 50 | "blockReward": "0x0d" 51 | } 52 | }"#; 53 | 54 | let deserialized: NullEngine = serde_json::from_str(s).unwrap(); 55 | assert_eq!( 56 | deserialized.params.block_reward, 57 | Some(Uint(U256::from(0x0d))) 58 | ); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /ethjson/src/spec/params.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Spec params deserialization. 18 | 19 | use crate::{ 20 | bytes::Bytes, 21 | hash::{Address, H256}, 22 | uint::{self, Uint}, 23 | }; 24 | use serde::Deserialize; 25 | 26 | /// Spec params. 27 | #[derive(Debug, PartialEq, Deserialize)] 28 | #[serde(deny_unknown_fields)] 29 | #[serde(rename_all = "camelCase")] 30 | pub struct Params { 31 | /// Account start nonce, defaults to 0. 32 | pub account_start_nonce: Option, 33 | /// Maximum size of extra data. 34 | pub maximum_extra_data_size: Uint, 35 | /// Minimum gas limit. 36 | pub min_gas_limit: Uint, 37 | 38 | /// Network id. 39 | #[serde(rename = "networkID")] 40 | pub network_id: Uint, 41 | /// Chain id. 42 | #[serde(rename = "chainID")] 43 | pub chain_id: Option, 44 | 45 | /// Name of the main ("eth") subprotocol. 46 | pub subprotocol_name: Option, 47 | 48 | /// Option fork block number to check. 49 | pub fork_block: Option, 50 | /// Expected fork block hash. 51 | #[serde(rename = "forkCanonHash")] 52 | pub fork_hash: Option, 53 | 54 | /// See main EthashParams docs. 55 | pub eip150_transition: Option, 56 | 57 | /// See main EthashParams docs. 58 | pub eip160_transition: Option, 59 | 60 | /// See main EthashParams docs. 61 | pub eip161abc_transition: Option, 62 | /// See main EthashParams docs. 63 | pub eip161d_transition: Option, 64 | 65 | /// See `CommonParams` docs. 66 | pub eip98_transition: Option, 67 | /// See `CommonParams` docs. 68 | pub eip155_transition: Option, 69 | /// See `CommonParams` docs. 70 | pub validate_chain_id_transition: Option, 71 | /// See `CommonParams` docs. 72 | pub validate_receipts_transition: Option, 73 | /// See `CommonParams` docs. 74 | pub eip140_transition: Option, 75 | /// See `CommonParams` docs. 76 | pub eip210_transition: Option, 77 | /// See `CommonParams` docs. 78 | pub eip210_contract_address: Option
, 79 | /// See `CommonParams` docs. 80 | pub eip210_contract_code: Option, 81 | /// See `CommonParams` docs. 82 | pub eip210_contract_gas: Option, 83 | /// See `CommonParams` docs. 84 | pub eip211_transition: Option, 85 | /// See `CommonParams` docs. 86 | pub eip145_transition: Option, 87 | /// See `CommonParams` docs. 88 | pub eip214_transition: Option, 89 | /// See `CommonParams` docs. 90 | pub eip658_transition: Option, 91 | /// See `CommonParams` docs. 92 | pub eip1052_transition: Option, 93 | /// See `CommonParams` docs. 94 | pub eip1283_transition: Option, 95 | /// See `CommonParams` docs. 96 | pub eip1283_disable_transition: Option, 97 | /// See `CommonParams` docs. 98 | pub eip1283_reenable_transition: Option, 99 | /// See `CommonParams` docs. 100 | pub eip1014_transition: Option, 101 | /// See `CommonParams` docs. 102 | pub eip1706_transition: Option, 103 | /// See `CommonParams` docs. 104 | pub eip1344_transition: Option, 105 | /// See `CommonParams` docs. 106 | pub eip1884_transition: Option, 107 | /// See `CommonParams` docs. 108 | pub eip2028_transition: Option, 109 | /// See `CommonParams` docs. 110 | pub eip2046_transition: Option, 111 | /// See `CommonParams` docs. 112 | pub eip2200_advance_transition: Option, 113 | /// See `CommonParams` docs. 114 | pub eip2315_transition: Option, 115 | /// See `CommonParams` docs. 116 | pub dust_protection_transition: Option, 117 | /// See `CommonParams` docs. 118 | pub nonce_cap_increment: Option, 119 | /// See `CommonParams` docs. 120 | pub remove_dust_contracts: Option, 121 | /// See `CommonParams` docs. 122 | #[serde(deserialize_with = "uint::validate_non_zero")] 123 | pub gas_limit_bound_divisor: Uint, 124 | /// See `CommonParams` docs. 125 | pub registrar: Option
, 126 | /// Apply reward flag 127 | pub apply_reward: Option, 128 | /// Node permission contract address. 129 | pub node_permission_contract: Option
, 130 | /// See main EthashParams docs. 131 | pub max_code_size: Option, 132 | /// Maximum size of transaction RLP payload. 133 | pub max_transaction_size: Option, 134 | /// See main EthashParams docs. 135 | pub max_code_size_transition: Option, 136 | /// Transaction permission contract address. 137 | pub transaction_permission_contract: Option
, 138 | /// Block at which the transaction permission contract should start being used. 139 | pub transaction_permission_contract_transition: Option, 140 | /// Wasm activation block height, if not activated from start. 141 | pub wasm_activation_transition: Option, 142 | /// Define a separate wasm version instead of using the prefix. 143 | pub wasm_version: Option, 144 | /// KIP4 activiation block height. 145 | pub kip4_transition: Option, 146 | /// KIP6 activiation block height. 147 | pub kip6_transition: Option, 148 | } 149 | 150 | #[cfg(test)] 151 | mod tests { 152 | use super::{Params, Uint}; 153 | use ethereum_types::U256; 154 | 155 | #[test] 156 | fn params_deserialization() { 157 | let s = r#"{ 158 | "maximumExtraDataSize": "0x20", 159 | "networkID": "0x1", 160 | "chainID": "0x15", 161 | "subprotocolName": "exp", 162 | "minGasLimit": "0x1388", 163 | "accountStartNonce": "0x01", 164 | "gasLimitBoundDivisor": "0x20", 165 | "maxCodeSize": "0x1000", 166 | "wasmActivationTransition": "0x1010" 167 | }"#; 168 | 169 | let deserialized: Params = serde_json::from_str(s).unwrap(); 170 | assert_eq!(deserialized.maximum_extra_data_size, Uint(U256::from(0x20))); 171 | assert_eq!(deserialized.network_id, Uint(U256::from(0x1))); 172 | assert_eq!(deserialized.chain_id, Some(Uint(U256::from(0x15)))); 173 | assert_eq!(deserialized.subprotocol_name, Some("exp".to_owned())); 174 | assert_eq!(deserialized.min_gas_limit, Uint(U256::from(0x1388))); 175 | assert_eq!( 176 | deserialized.account_start_nonce, 177 | Some(Uint(U256::from(0x01))) 178 | ); 179 | assert_eq!(deserialized.gas_limit_bound_divisor, Uint(U256::from(0x20))); 180 | assert_eq!(deserialized.max_code_size, Some(Uint(U256::from(0x1000)))); 181 | assert_eq!( 182 | deserialized.wasm_activation_transition, 183 | Some(Uint(U256::from(0x1010))) 184 | ); 185 | } 186 | 187 | #[test] 188 | #[should_panic(expected = "a non-zero value")] 189 | fn test_zero_value_divisor() { 190 | let s = r#"{ 191 | "maximumExtraDataSize": "0x20", 192 | "networkID" : "0x1", 193 | "chainID" : "0x15", 194 | "subprotocolName" : "exp", 195 | "minGasLimit": "0x1388", 196 | "accountStartNonce": "0x01", 197 | "gasLimitBoundDivisor": "0x0", 198 | "maxCodeSize": "0x1000" 199 | }"#; 200 | 201 | let _deserialized: Params = serde_json::from_str(s).unwrap(); 202 | } 203 | } 204 | -------------------------------------------------------------------------------- /ethjson/src/spec/seal.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Spec seal deserialization. 18 | 19 | use crate::{ 20 | bytes::Bytes, 21 | hash::{H256, H520, H64}, 22 | uint::Uint, 23 | }; 24 | use serde::Deserialize; 25 | 26 | /// Ethereum seal. 27 | #[derive(Debug, PartialEq, Deserialize)] 28 | #[serde(deny_unknown_fields)] 29 | #[serde(rename_all = "camelCase")] 30 | pub struct Ethereum { 31 | /// Seal nonce. 32 | pub nonce: H64, 33 | /// Seal mix hash. 34 | pub mix_hash: H256, 35 | } 36 | 37 | /// AuthorityRound seal. 38 | #[derive(Debug, PartialEq, Deserialize)] 39 | #[serde(deny_unknown_fields)] 40 | pub struct AuthorityRoundSeal { 41 | /// Seal step. 42 | pub step: Uint, 43 | /// Seal signature. 44 | pub signature: H520, 45 | } 46 | 47 | /// Tendermint seal. 48 | #[derive(Debug, PartialEq, Deserialize)] 49 | #[serde(deny_unknown_fields)] 50 | pub struct TendermintSeal { 51 | /// Seal round. 52 | pub round: Uint, 53 | /// Proposal seal signature. 54 | pub proposal: H520, 55 | /// Proposal seal signature. 56 | pub precommits: Vec, 57 | } 58 | 59 | /// Seal variants. 60 | #[derive(Debug, PartialEq, Deserialize)] 61 | #[serde(deny_unknown_fields)] 62 | #[serde(rename_all = "camelCase")] 63 | pub enum Seal { 64 | /// Ethereum seal. 65 | Ethereum(Ethereum), 66 | /// AuthorityRound seal. 67 | AuthorityRound(AuthorityRoundSeal), 68 | /// Tendermint seal. 69 | Tendermint(TendermintSeal), 70 | /// Generic seal. 71 | Generic(Bytes), 72 | } 73 | 74 | #[cfg(test)] 75 | mod tests { 76 | use super::{AuthorityRoundSeal, Bytes, Ethereum, Seal, TendermintSeal, Uint, H256, H520, H64}; 77 | use ethereum_types::{H256 as Eth256, H520 as Eth520, H64 as Eth64, U256}; 78 | use std::str::FromStr; 79 | 80 | #[test] 81 | fn seal_deserialization() { 82 | let s = r#"[{ 83 | "ethereum": { 84 | "nonce": "0x0000000000000042", 85 | "mixHash": "0x1000000000000000000000000000000000000000000000000000000000000001" 86 | } 87 | },{ 88 | "generic": "0xe011bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa" 89 | },{ 90 | "authorityRound": { 91 | "step": "0x0", 92 | "signature": "0x2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002" 93 | } 94 | },{ 95 | "tendermint": { 96 | "round": "0x3", 97 | "proposal": "0x3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003", 98 | "precommits": [ 99 | "0x4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004" 100 | ] 101 | } 102 | }]"#; 103 | 104 | let deserialized: Vec = serde_json::from_str(s).unwrap(); 105 | assert_eq!(deserialized.len(), 4); 106 | 107 | // [0] 108 | assert_eq!( 109 | deserialized[0], 110 | Seal::Ethereum(Ethereum { 111 | nonce: H64(Eth64::from_str("0000000000000042").unwrap()), 112 | mix_hash: H256( 113 | Eth256::from_str( 114 | "1000000000000000000000000000000000000000000000000000000000000001" 115 | ) 116 | .unwrap() 117 | ) 118 | }) 119 | ); 120 | 121 | // [1] 122 | assert_eq!( 123 | deserialized[1], 124 | Seal::Generic(Bytes::new(vec![ 125 | 0xe0, 0x11, 0xbb, 0xe8, 0xdb, 0x4e, 0x34, 0x7b, 0x4e, 0x8c, 0x93, 0x7c, 0x1c, 0x83, 126 | 0x70, 0xe4, 0xb5, 0xed, 0x33, 0xad, 0xb3, 0xdb, 0x69, 0xcb, 0xdb, 0x7a, 0x38, 0xe1, 127 | 0xe5, 0x0b, 0x1b, 0x82, 0xfa 128 | ])) 129 | ); 130 | 131 | // [2] 132 | assert_eq!(deserialized[2], Seal::AuthorityRound(AuthorityRoundSeal { 133 | step: Uint(U256::from(0x0)), 134 | signature: H520(Eth520::from_str("2000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000002").unwrap()) 135 | })); 136 | 137 | // [3] 138 | assert_eq!(deserialized[3], Seal::Tendermint(TendermintSeal { 139 | round: Uint(U256::from(0x3)), 140 | proposal: H520(Eth520::from_str("3000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000003").unwrap()), 141 | precommits: vec![H520(Eth520::from_str("4000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004").unwrap())] 142 | })); 143 | } 144 | } 145 | -------------------------------------------------------------------------------- /ethjson/src/spec/spec.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Spec deserialization. 18 | 19 | use crate::spec::{Engine, Genesis, HardcodedSync, Params, State}; 20 | use serde::Deserialize; 21 | use serde_json::Error; 22 | use std::io::Read; 23 | 24 | /// Fork spec definition 25 | #[derive(Debug, PartialEq, Eq, PartialOrd, Ord, Deserialize)] 26 | pub enum ForkSpec { 27 | /// EIP 150 Tangerine Whistle: Gas cost changes for IO-heavy operations (#2,463,000, 2016-10-18) 28 | EIP150, 29 | /// EIP 158/EIP 161 Spurious Dragon: State trie clearing (#2,675,000, 2016-11-22) 30 | EIP158, 31 | /// Frontier (#1, 2015-07-30) 32 | Frontier, 33 | /// Homestead (#1,150,000, 2016-03-14) 34 | Homestead, 35 | /// Byzantium Metropolis phase 1 (#4,370,000, 2017-10-16) 36 | Byzantium, 37 | /// Constantinople Metropolis phase 2 (#7,280,000, 2019-02-28) 38 | Constantinople, 39 | /// Constantinople transition test-net 40 | ConstantinopleFix, 41 | /// Istanbul (#9,069,000, 2019-12-08) 42 | Istanbul, 43 | /// Berlin (#12,244,000, 2021-04-15) 44 | Berlin, 45 | /// London (#12,965,000, 2021-08-05) 46 | London, 47 | /// Paris - The Merge (#15,537,394, 2022-09-15) 48 | Merge, 49 | /// Shanghai (#17,034,870, 2023-04-12) 50 | Shanghai, 51 | 52 | /// Byzantium transition test-net 53 | EIP158ToByzantiumAt5, 54 | /// Homestead transition test-net 55 | FrontierToHomesteadAt5, 56 | /// Homestead transition test-net 57 | HomesteadToDaoAt5, 58 | /// EIP158/EIP161 transition test-net 59 | HomesteadToEIP150At5, 60 | /// ConstantinopleFix transition test-net 61 | ByzantiumToConstantinopleFixAt5, 62 | /// Istanbul transition test-net 63 | ConstantinopleFixToIstanbulAt5, 64 | } 65 | 66 | impl ForkSpec { 67 | /// Returns true if the fork is at or after the merge. 68 | pub fn is_eth2(&self) -> bool { 69 | // NOTE: Include new forks in this match arm. 70 | matches!( 71 | *self, 72 | ForkSpec::London | ForkSpec::Merge | ForkSpec::Shanghai 73 | ) 74 | } 75 | } 76 | 77 | /// Spec deserialization. 78 | #[derive(Debug, PartialEq, Deserialize)] 79 | #[serde(deny_unknown_fields)] 80 | #[serde(rename_all = "camelCase")] 81 | pub struct Spec { 82 | /// Spec name. 83 | pub name: String, 84 | /// Special fork name. 85 | pub data_dir: Option, 86 | /// Engine. 87 | pub engine: Engine, 88 | /// Spec params. 89 | pub params: Params, 90 | /// Genesis header. 91 | pub genesis: Genesis, 92 | /// Genesis state. 93 | pub accounts: State, 94 | /// Boot nodes. 95 | pub nodes: Option>, 96 | /// Hardcoded synchronization for the light client. 97 | pub hardcoded_sync: Option, 98 | } 99 | 100 | impl Spec { 101 | /// Loads test from json. 102 | pub fn load(reader: R) -> Result 103 | where 104 | R: Read, 105 | { 106 | serde_json::from_reader(reader) 107 | } 108 | } 109 | 110 | #[cfg(test)] 111 | mod tests { 112 | use super::Spec; 113 | 114 | #[test] 115 | fn should_error_on_unknown_fields() { 116 | let s = r#"{ 117 | "name": "Null Morden", 118 | "dataDir": "morden", 119 | "engine": { 120 | "Ethash": { 121 | "params": { 122 | "minimumDifficulty": "0x020000", 123 | "difficultyBoundDivisor": "0x0800", 124 | "durationLimit": "0x0d", 125 | "homesteadTransition" : "0x", 126 | "daoHardforkTransition": "0xffffffffffffffff", 127 | "daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000", 128 | "daoHardforkAccounts": [] 129 | } 130 | } 131 | }, 132 | "params": { 133 | "accountStartNonce": "0x0100000", 134 | "maximumExtraDataSize": "0x20", 135 | "minGasLimit": "0x1388", 136 | "networkID" : "0x2", 137 | "forkBlock": "0xffffffffffffffff", 138 | "forkCanonHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 139 | "gasLimitBoundDivisor": "0x20", 140 | "unknownField": "0x0" 141 | }, 142 | "genesis": { 143 | "seal": { 144 | "ethereum": { 145 | "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 146 | "nonce": "0x00006d6f7264656e" 147 | } 148 | }, 149 | "difficulty": "0x20000", 150 | "author": "0x0000000000000000000000000000000000000000", 151 | "timestamp": "0x00", 152 | "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 153 | "extraData": "0x", 154 | "gasLimit": "0x2fefd8" 155 | }, 156 | "nodes": [ 157 | "enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303" 158 | ], 159 | "accounts": { 160 | "0000000000000000000000000000000000000001": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } } }, 161 | "0000000000000000000000000000000000000002": { "balance": "1", "nonce": "1048576", "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } }, 162 | "0000000000000000000000000000000000000003": { "balance": "1", "nonce": "1048576", "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } }, 163 | "0000000000000000000000000000000000000004": { "balance": "1", "nonce": "1048576", "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } }, 164 | "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } 165 | }, 166 | "hardcodedSync": { 167 | "header": "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23", 168 | "totalDifficulty": "0x400000000", 169 | "CHTs": [ 170 | "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", 171 | "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" 172 | ] 173 | } 174 | }"#; 175 | let result: Result = serde_json::from_str(s); 176 | assert!(result.is_err()); 177 | } 178 | 179 | #[test] 180 | fn spec_deserialization() { 181 | let s = r#"{ 182 | "name": "Null Morden", 183 | "dataDir": "morden", 184 | "engine": { 185 | "Ethash": { 186 | "params": { 187 | "minimumDifficulty": "0x020000", 188 | "difficultyBoundDivisor": "0x0800", 189 | "durationLimit": "0x0d", 190 | "homesteadTransition" : "0x", 191 | "daoHardforkTransition": "0xffffffffffffffff", 192 | "daoHardforkBeneficiary": "0x0000000000000000000000000000000000000000", 193 | "daoHardforkAccounts": [] 194 | } 195 | } 196 | }, 197 | "params": { 198 | "accountStartNonce": "0x0100000", 199 | "maximumExtraDataSize": "0x20", 200 | "minGasLimit": "0x1388", 201 | "networkID" : "0x2", 202 | "forkBlock": "0xffffffffffffffff", 203 | "forkCanonHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 204 | "gasLimitBoundDivisor": "0x20" 205 | }, 206 | "genesis": { 207 | "seal": { 208 | "ethereum": { 209 | "mixHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 210 | "nonce": "0x00006d6f7264656e" 211 | } 212 | }, 213 | "difficulty": "0x20000", 214 | "author": "0x0000000000000000000000000000000000000000", 215 | "timestamp": "0x00", 216 | "parentHash": "0x0000000000000000000000000000000000000000000000000000000000000000", 217 | "extraData": "0x", 218 | "gasLimit": "0x2fefd8" 219 | }, 220 | "nodes": [ 221 | "enode://b1217cbaa440e35ed471157123fe468e19e8b5ad5bedb4b1fdbcbdab6fb2f5ed3e95dd9c24a22a79fdb2352204cea207df27d92bfd21bfd41545e8b16f637499@104.44.138.37:30303" 222 | ], 223 | "accounts": { 224 | "0000000000000000000000000000000000000001": { 225 | "balance": "1", 226 | "nonce": "1048576", 227 | "builtin": { 228 | "name": "ecrecover", 229 | "pricing": { 230 | "linear": { 231 | "base": 3000, 232 | "word": 0 233 | } 234 | } 235 | } 236 | }, 237 | "0000000000000000000000000000000000000002": { 238 | "balance": "1", 239 | "nonce": "1048576", 240 | "builtin": { 241 | "name": "sha256", 242 | "pricing": { 243 | "linear": { 244 | "base": 60, 245 | "word": 12 246 | } 247 | } 248 | } 249 | }, 250 | "0000000000000000000000000000000000000003": { 251 | "balance": "1", 252 | "nonce": "1048576", 253 | "builtin": { 254 | "name": "ripemd160", 255 | "pricing": { 256 | "linear": { 257 | "base": 600, 258 | "word": 120 259 | } 260 | } 261 | } 262 | }, 263 | "0000000000000000000000000000000000000004": { 264 | "balance": "1", 265 | "nonce": "1048576", 266 | "builtin": { 267 | "name": "identity", 268 | "pricing": { 269 | "linear": { 270 | "base": 15, 271 | "word": 3 272 | } 273 | } 274 | } 275 | }, 276 | "102e61f5d8f9bc71d0ad4a084df4e65e05ce0e1c": { "balance": "1606938044258990275541962092341162602522202993782792835301376", "nonce": "1048576" } 277 | }, 278 | "hardcodedSync": { 279 | "header": "f901f9a0d405da4e66f1445d455195229624e133f5baafe72b5cf7b3c36c12c8146e98b7a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a05fb2b4bfdef7b314451cb138a534d225c922fc0e5fbe25e451142732c3e25c25a088d2ec6b9860aae1a2c3b299f72b6a5d70d7f7ba4722c78f2c49ba96273c2158a007c6fdfa8eea7e86b81f5b0fc0f78f90cc19f4aa60d323151e0cac660199e9a1b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302008003832fefba82524d84568e932a80a0a0349d8c3df71f1a48a9df7d03fd5f14aeee7d91332c009ecaff0a71ead405bd88ab4e252a7e8c2a23", 280 | "totalDifficulty": "0x400000000", 281 | "CHTs": [ 282 | "0x11bbe8db4e347b4e8c937c1c8370e4b5ed33adb3db69cbdb7a38e1e50b1b82fa", 283 | "0xd7f8974fb5ac78d9ac099b9ad5018bedc2ce0a72dad1827a1709da30580f0544" 284 | ] 285 | } 286 | }"#; 287 | let _deserialized: Spec = serde_json::from_str(s).unwrap(); 288 | // TODO: validate all fields 289 | } 290 | } 291 | -------------------------------------------------------------------------------- /ethjson/src/spec/state.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Blockchain state deserializer. 18 | 19 | use crate::{ 20 | bytes::Bytes, 21 | hash::{Address, H256}, 22 | spec::{Account, Builtin}, 23 | }; 24 | use serde::Deserialize; 25 | use std::collections::BTreeMap; 26 | 27 | /// Recent JSON tests can be either a map or a hash (represented by a string). 28 | /// See https://github.com/ethereum/tests/issues/637 29 | #[cfg_attr(any(test, feature = "test-helpers"), derive(Clone))] 30 | #[derive(Debug, PartialEq, Deserialize)] 31 | #[serde(untagged)] 32 | pub enum HashOrMap { 33 | /// When the `postState` is large, tests sometimes just include the state root of the last 34 | /// successful block here. 35 | Hash(H256), 36 | /// The expected `postState` of a test 37 | Map(BTreeMap), 38 | } 39 | 40 | /// Blockchain state deserializer. 41 | #[cfg_attr(any(test, feature = "test-helpers"), derive(Clone))] 42 | #[derive(Debug, PartialEq, Deserialize)] 43 | #[serde(deny_unknown_fields)] 44 | pub struct State(pub HashOrMap); 45 | 46 | impl State { 47 | /// Returns all builtins. 48 | pub fn builtins(&self) -> BTreeMap { 49 | match &self.0 { 50 | HashOrMap::Hash(_) => BTreeMap::default(), 51 | HashOrMap::Map(map) => map 52 | .iter() 53 | .filter_map(|(add, ref acc)| acc.builtin.clone().map(|b| (add.clone(), b.into()))) 54 | .collect(), 55 | } 56 | } 57 | 58 | /// Returns all constructors. 59 | pub fn constructors(&self) -> BTreeMap { 60 | match &self.0 { 61 | HashOrMap::Hash(_) => BTreeMap::default(), 62 | HashOrMap::Map(map) => map 63 | .iter() 64 | .filter_map(|(add, ref acc)| acc.constructor.clone().map(|b| (add.clone(), b))) 65 | .collect(), 66 | } 67 | } 68 | } 69 | 70 | impl IntoIterator for State { 71 | type Item = as IntoIterator>::Item; 72 | type IntoIter = as IntoIterator>::IntoIter; 73 | 74 | fn into_iter(self) -> Self::IntoIter { 75 | if let HashOrMap::Map(m) = self.0 { 76 | m.into_iter() 77 | } else { 78 | BTreeMap::default().into_iter() 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /ethjson/src/spec/step_duration.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Step duration configuration parameter 18 | 19 | use std::collections::BTreeMap; 20 | 21 | use serde::Deserialize; 22 | 23 | use crate::uint::Uint; 24 | 25 | /// Step duration can be specified either as a `Uint` (in seconds), in which case it will be 26 | /// constant, or as a list of pairs consisting of a timestamp of type `Uint` and a duration, in 27 | /// which case the duration of a step will be determined by a mapping arising from that list. 28 | #[derive(Debug, PartialEq, Deserialize)] 29 | #[serde(deny_unknown_fields)] 30 | #[serde(untagged)] 31 | pub enum StepDuration { 32 | /// Duration of all steps. 33 | Single(Uint), 34 | /// Step duration transitions: a mapping of timestamp to step durations. 35 | Transitions(BTreeMap), 36 | } 37 | -------------------------------------------------------------------------------- /ethjson/src/spec/validator_set.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Validator set deserialization. 18 | 19 | use crate::{hash::Address, uint::Uint}; 20 | use serde::Deserialize; 21 | use std::collections::BTreeMap; 22 | 23 | /// Different ways of specifying validators. 24 | #[derive(Debug, PartialEq, Deserialize)] 25 | #[serde(deny_unknown_fields)] 26 | #[serde(rename_all = "camelCase")] 27 | pub enum ValidatorSet { 28 | /// A simple list of authorities. 29 | List(Vec
), 30 | /// Address of a contract that indicates the list of authorities. 31 | SafeContract(Address), 32 | /// Address of a contract that indicates the list of authorities and enables reporting of theor misbehaviour using transactions. 33 | Contract(Address), 34 | /// A map of starting blocks for each validator set. 35 | Multi(BTreeMap), 36 | } 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use super::{Address, Uint, ValidatorSet}; 41 | use ethereum_types::{H160, U256}; 42 | use std::str::FromStr; 43 | 44 | #[test] 45 | fn validator_set_deserialization() { 46 | let s = r#"[{ 47 | "list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"] 48 | }, { 49 | "safeContract": "0xc6d9d2cd449a754c494264e1809c50e34d64562b" 50 | }, { 51 | "contract": "0xc6d9d2cd449a754c494264e1809c50e34d64562b" 52 | }, { 53 | "multi": { 54 | "0": { "list": ["0xc6d9d2cd449a754c494264e1809c50e34d64562b"] }, 55 | "10": { "list": ["0xd6d9d2cd449a754c494264e1809c50e34d64562b"] }, 56 | "20": { "contract": "0xc6d9d2cd449a754c494264e1809c50e34d64562b" } 57 | } 58 | }]"#; 59 | 60 | let deserialized: Vec = serde_json::from_str(s).unwrap(); 61 | assert_eq!(deserialized.len(), 4); 62 | 63 | assert_eq!( 64 | deserialized[0], 65 | ValidatorSet::List(vec![Address( 66 | H160::from_str("c6d9d2cd449a754c494264e1809c50e34d64562b").unwrap() 67 | )]) 68 | ); 69 | assert_eq!( 70 | deserialized[1], 71 | ValidatorSet::SafeContract(Address( 72 | H160::from_str("c6d9d2cd449a754c494264e1809c50e34d64562b").unwrap() 73 | )) 74 | ); 75 | assert_eq!( 76 | deserialized[2], 77 | ValidatorSet::Contract(Address( 78 | H160::from_str("c6d9d2cd449a754c494264e1809c50e34d64562b").unwrap() 79 | )) 80 | ); 81 | match deserialized[3] { 82 | ValidatorSet::Multi(ref map) => { 83 | assert_eq!(map.len(), 3); 84 | assert!(map.contains_key(&Uint(U256::from(0)))); 85 | assert!(map.contains_key(&Uint(U256::from(10)))); 86 | assert!(map.contains_key(&Uint(U256::from(20)))); 87 | } 88 | _ => assert!(false), 89 | } 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /ethjson/src/state.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! State deserialization types 18 | 19 | use crate::{ 20 | bytes::Bytes, 21 | hash::{Address, Bloom, H256}, 22 | }; 23 | use serde::Deserialize; 24 | 25 | /// State log deserialization. 26 | #[derive(Debug, PartialEq, Deserialize)] 27 | pub struct Log { 28 | /// Address. 29 | pub address: Address, 30 | /// Topics. 31 | pub topics: Vec, 32 | /// Data. 33 | pub data: Bytes, 34 | /// Bloom. 35 | pub bloom: Bloom, 36 | } 37 | 38 | #[cfg(test)] 39 | mod tests { 40 | use super::Log; 41 | 42 | #[test] 43 | fn log_deserialization() { 44 | let s = r#"{ 45 | "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", 46 | "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008800000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000800000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000000000", 47 | "data" : "0xffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff", 48 | "topics" : [ 49 | "0000000000000000000000000000000000000000000000000000000000000000" 50 | ] 51 | }"#; 52 | let _deserialized: Log = serde_json::from_str(s).unwrap(); 53 | // TODO: validate all fields 54 | } 55 | } 56 | -------------------------------------------------------------------------------- /ethjson/src/test_helpers/blockchain/block.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Blockchain test block deserializer. 18 | 19 | use super::header::Header; 20 | use crate::{bytes::Bytes, transaction::Transaction}; 21 | use serde::Deserialize; 22 | 23 | /// Blockchain test block deserializer. 24 | #[derive(Debug, PartialEq, Deserialize)] 25 | pub struct Block { 26 | #[serde(rename = "blockHeader")] 27 | header: Option
, 28 | rlp: Bytes, 29 | transactions: Option>, 30 | #[serde(rename = "uncleHeaders")] 31 | uncles: Option>, 32 | } 33 | 34 | impl Block { 35 | /// Returns block rlp. 36 | pub fn rlp(&self) -> Vec { 37 | self.rlp.clone().into() 38 | } 39 | } 40 | 41 | #[cfg(test)] 42 | mod tests { 43 | use super::Block; 44 | 45 | #[test] 46 | fn block_deserialization() { 47 | let s = r#"{ 48 | "blockHeader" : { 49 | "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 50 | "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", 51 | "difficulty" : "0x020000", 52 | "extraData" : "0x", 53 | "gasLimit" : "0x2fefba", 54 | "gasUsed" : "0x00", 55 | "hash" : "65ebf1b97fb89b14680267e0723d69267ec4bf9a96d4a60ffcb356ae0e81c18f", 56 | "mixHash" : "13735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd06", 57 | "nonce" : "931dcc53e5edc514", 58 | "number" : "0x01", 59 | "parentHash" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae", 60 | "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 61 | "stateRoot" : "c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3", 62 | "timestamp" : "0x56850b7b", 63 | "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 64 | "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" 65 | }, 66 | "blocknumber" : "1", 67 | "rlp" : "0xf901fcf901f7a05a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5aea01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000001832fefba808456850b7b80a013735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd0688931dcc53e5edc514c0c0", 68 | "transaction" : [], 69 | "uncleHeaders" : [] 70 | }"#; 71 | let _deserialized: Block = serde_json::from_str(s).unwrap(); 72 | // TODO: validate all fields 73 | } 74 | } 75 | -------------------------------------------------------------------------------- /ethjson/src/test_helpers/blockchain/header.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Blockchain test header deserializer. 18 | 19 | use crate::{ 20 | bytes::Bytes, 21 | hash::{Address, Bloom, H256, H64}, 22 | uint::Uint, 23 | }; 24 | use serde::Deserialize; 25 | 26 | /// Blockchain test header deserializer. 27 | #[derive(Debug, PartialEq, Deserialize)] 28 | #[serde(rename_all = "camelCase")] 29 | pub struct Header { 30 | /// Blocks bloom. 31 | pub bloom: Bloom, 32 | /// Blocks author. 33 | #[serde(rename = "coinbase")] 34 | pub author: Address, 35 | /// Difficulty. 36 | pub difficulty: Uint, 37 | /// Extra data. 38 | pub extra_data: Bytes, 39 | /// Gas limit. 40 | pub gas_limit: Uint, 41 | /// Gas used. 42 | pub gas_used: Uint, 43 | /// Hash. 44 | pub hash: H256, 45 | /// Mix hash. 46 | pub mix_hash: H256, 47 | /// Seal nonce. 48 | pub nonce: H64, 49 | /// Block number. 50 | pub number: Uint, 51 | /// Parent hash. 52 | pub parent_hash: H256, 53 | /// Receipt root. 54 | #[serde(rename = "receiptTrie")] 55 | pub receipts_root: H256, 56 | /// State root. 57 | pub state_root: H256, 58 | /// Timestamp. 59 | pub timestamp: Uint, 60 | /// Transactions root. 61 | #[serde(rename = "transactionsTrie")] 62 | pub transactions_root: H256, 63 | /// Uncles hash. 64 | #[serde(rename = "uncleHash")] 65 | pub uncles_hash: H256, 66 | } 67 | 68 | #[cfg(test)] 69 | mod tests { 70 | use super::Header; 71 | 72 | #[test] 73 | fn header_deserialization() { 74 | let s = r#"{ 75 | "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 76 | "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", 77 | "difficulty" : "0x020000", 78 | "extraData" : "0x", 79 | "gasLimit" : "0x2fefba", 80 | "gasUsed" : "0x00", 81 | "hash" : "65ebf1b97fb89b14680267e0723d69267ec4bf9a96d4a60ffcb356ae0e81c18f", 82 | "mixHash" : "13735ab4156c9b36327224d92e1692fab8fc362f8e0f868c94d421848ef7cd06", 83 | "nonce" : "931dcc53e5edc514", 84 | "number" : "0x01", 85 | "parentHash" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c2965db8bc3468093a31bc5ae", 86 | "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 87 | "stateRoot" : "c5c83ff43741f573a0c9b31d0e56fdd745f4e37d193c4e78544f302777aafcf3", 88 | "timestamp" : "0x56850b7b", 89 | "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 90 | "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" 91 | }"#; 92 | let _deserialized: Header = serde_json::from_str(s).unwrap(); 93 | // TODO: validate all fields 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /ethjson/src/test_helpers/blockchain/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Blockchain test deserialization. 18 | 19 | use crate::{ 20 | bytes::Bytes, 21 | hash::H256, 22 | spec::{Ethereum, ForkSpec, Genesis, Seal, State}, 23 | }; 24 | use serde::Deserialize; 25 | 26 | pub mod block; 27 | pub mod header; 28 | 29 | pub use self::block::Block; 30 | pub use self::header::Header; 31 | 32 | /// Type for running `Blockchain` tests 33 | pub type Test = super::tester::GenericTester; 34 | 35 | /// Json Block test possible engine kind. 36 | #[derive(Debug, PartialEq, Deserialize)] 37 | pub enum Engine { 38 | /// Default (old) behaviour. 39 | Ethash, 40 | /// No check of block's difficulty and nonce for tests. 41 | NoProof, 42 | } 43 | 44 | impl Default for Engine { 45 | fn default() -> Self { 46 | Engine::Ethash 47 | } 48 | } 49 | 50 | /// Blockchain deserialization. 51 | #[derive(Debug, PartialEq, Deserialize)] 52 | #[serde(rename_all = "camelCase")] 53 | pub struct BlockChain { 54 | /// Genesis block header. 55 | #[serde(rename = "genesisBlockHeader")] 56 | pub genesis_block: Header, 57 | /// Genesis block rlp. 58 | #[serde(rename = "genesisRLP")] 59 | pub genesis_rlp: Option, 60 | /// Blocks. 61 | pub blocks: Vec, 62 | /// Post state. 63 | pub post_state: Option, 64 | /// Pre state. 65 | #[serde(rename = "pre")] 66 | pub pre_state: State, 67 | /// Hash of best block. 68 | #[serde(rename = "lastblockhash")] 69 | pub best_block: H256, 70 | /// Network. 71 | pub network: ForkSpec, 72 | #[serde(default)] 73 | #[serde(rename = "sealEngine")] 74 | /// Engine 75 | pub engine: Engine, 76 | } 77 | 78 | impl BlockChain { 79 | /// Returns blocks rlp. 80 | pub fn blocks_rlp(&self) -> Vec> { 81 | self.blocks.iter().map(|block| block.rlp()).collect() 82 | } 83 | 84 | /// Returns spec compatible genesis struct. 85 | pub fn genesis(&self) -> Genesis { 86 | Genesis { 87 | seal: Seal::Ethereum(Ethereum { 88 | nonce: self.genesis_block.nonce.clone(), 89 | mix_hash: self.genesis_block.mix_hash.clone(), 90 | }), 91 | difficulty: self.genesis_block.difficulty, 92 | author: Some(self.genesis_block.author.clone()), 93 | timestamp: Some(self.genesis_block.timestamp), 94 | parent_hash: Some(self.genesis_block.parent_hash.clone()), 95 | gas_limit: self.genesis_block.gas_limit, 96 | transactions_root: Some(self.genesis_block.transactions_root.clone()), 97 | receipts_root: Some(self.genesis_block.receipts_root.clone()), 98 | state_root: Some(self.genesis_block.state_root.clone()), 99 | gas_used: Some(self.genesis_block.gas_used), 100 | extra_data: Some(self.genesis_block.extra_data.clone()), 101 | } 102 | } 103 | } 104 | 105 | #[cfg(test)] 106 | mod tests { 107 | use super::BlockChain; 108 | 109 | #[test] 110 | fn blockchain_deserialization() { 111 | let s = r#"{ 112 | "blocks" : [{ 113 | "blockHeader" : { 114 | "bloom" : "00000000000000001000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000000000000800000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000020000000000040000000000000000000000000000000000000000000000000000000", 115 | "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", 116 | "difficulty" : "0x020000", 117 | "extraData" : "0x0102030405060708091011121314151617181920212223242526272829303132", 118 | "gasLimit" : "0x2fefba", 119 | "gasUsed" : "0x560b", 120 | "hash" : "06b5b1742bde29468510c92641f36b719c61b3fc3e9a21c92a23978f4f7faa2a", 121 | "mixHash" : "5266ca43e81d25925a9ba573c3e4f9180bc076d316d90e63c6f8708b272f5ce2", 122 | "nonce" : "59ba4daed1898e21", 123 | "number" : "0x01", 124 | "parentHash" : "f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524d", 125 | "receiptTrie" : "c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296", 126 | "stateRoot" : "bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bf", 127 | "timestamp" : "0x56850c2c", 128 | "transactionsTrie" : "498785da562aa0c5dd5937cf15f22139b0b1bcf3b4fc48986e1bb1dae9292796", 129 | "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" 130 | }, 131 | "rlp" : "0xf90285f90219a0f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524da01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0bac6177a79e910c98d86ec31a09ae37ac2de15b754fd7bed1ba52362c49416bfa0498785da562aa0c5dd5937cf15f22139b0b1bcf3b4fc48986e1bb1dae9292796a0c7778a7376099ee2e5c455791c1885b5c361b95713fddcbe32d97fd01334d296b90100000000000000000010000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000000000008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000200000000000400000000000000000000000000000000000000000000000000000008302000001832fefba82560b8456850c2ca00102030405060708091011121314151617181920212223242526272829303132a05266ca43e81d25925a9ba573c3e4f9180bc076d316d90e63c6f8708b272f5ce28859ba4daed1898e21f866f864800a82c35094095e7baea6a6c7c4c2dfeb977efac326af552d8785012a05f200801ca0ee0b9ec878fbd4258a9473199d8ecc32996a20c323c004e79e0cda20e0418ce3a04e6bc63927d1510bab54f37e46fa036faf4b2c465d271920d9afea1fadf7bd21c0", 132 | "transactions" : [ 133 | { 134 | "data" : "0x00", 135 | "gasLimit" : "0xc350", 136 | "gasPrice" : "0x0a", 137 | "nonce" : "0x00", 138 | "r" : "0xee0b9ec878fbd4258a9473199d8ecc32996a20c323c004e79e0cda20e0418ce3", 139 | "s" : "0x4e6bc63927d1510bab54f37e46fa036faf4b2c465d271920d9afea1fadf7bd21", 140 | "to" : "095e7baea6a6c7c4c2dfeb977efac326af552d87", 141 | "v" : "0x1c", 142 | "value" : "0x012a05f200" 143 | } 144 | ], 145 | "uncleHeaders" : [ 146 | ] 147 | }], 148 | "network" : "Frontier", 149 | "genesisBlockHeader" : { 150 | "bloom" : "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000", 151 | "coinbase" : "8888f1f195afa192cfee860698584c030f4c9db1", 152 | "difficulty" : "0x020000", 153 | "extraData" : "0x42", 154 | "gasLimit" : "0x2fefd8", 155 | "gasUsed" : "0x00", 156 | "hash" : "f052d217bd5275a5177a3c3b7debdfe2670f1c8394b2965ccd5c1883cc1a524d", 157 | "mixHash" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 158 | "nonce" : "0102030405060708", 159 | "number" : "0x00", 160 | "parentHash" : "0000000000000000000000000000000000000000000000000000000000000000", 161 | "receiptTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 162 | "stateRoot" : "925002c3260b44e44c3edebad1cc442142b03020209df1ab8bb86752edbd2cd7", 163 | "timestamp" : "0x54c98c81", 164 | "transactionsTrie" : "56e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421", 165 | "uncleHash" : "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" 166 | }, 167 | "genesisRLP" : "0xf901fcf901f7a00000000000000000000000000000000000000000000000000000000000000000a01dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347948888f1f195afa192cfee860698584c030f4c9db1a0925002c3260b44e44c3edebad1cc442142b03020209df1ab8bb86752edbd2cd7a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421b90100000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000008302000080832fefd8808454c98c8142a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421880102030405060708c0c0", 168 | "lastblockhash" : "06b5b1742bde29468510c92641f36b719c61b3fc3e9a21c92a23978f4f7faa2a", 169 | "postState" : { 170 | "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { 171 | "balance" : "0x012a05f264", 172 | "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600052600060206000a1", 173 | "nonce" : "0x00", 174 | "storage" : { 175 | } 176 | }, 177 | "8888f1f195afa192cfee860698584c030f4c9db1" : { 178 | "balance" : "0x4563918244f75c6e", 179 | "code" : "0x", 180 | "nonce" : "0x00", 181 | "storage" : { 182 | } 183 | }, 184 | "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { 185 | "balance" : "0x012a029592", 186 | "code" : "0x", 187 | "nonce" : "0x01", 188 | "storage" : { 189 | } 190 | } 191 | }, 192 | "pre" : { 193 | "095e7baea6a6c7c4c2dfeb977efac326af552d87" : { 194 | "balance" : "0x64", 195 | "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600052600060206000a1", 196 | "nonce" : "0x00", 197 | "storage" : { 198 | } 199 | }, 200 | "a94f5374fce5edbc8e2a8697c15331677e6ebf0b" : { 201 | "balance" : "0x02540be400", 202 | "code" : "0x", 203 | "nonce" : "0x00", 204 | "storage" : { 205 | } 206 | } 207 | } 208 | }"#; 209 | let _deserialized: BlockChain = serde_json::from_str(s).unwrap(); 210 | // TODO: validate all fields 211 | } 212 | } 213 | -------------------------------------------------------------------------------- /ethjson/src/test_helpers/difficulty.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | use crate::{hash::H256, uint::Uint}; 18 | use serde::Deserialize; 19 | 20 | /// Blockchain test header deserializer. 21 | #[derive(Debug, PartialEq, Deserialize)] 22 | #[serde(rename_all = "camelCase")] 23 | pub struct DifficultyTestCase { 24 | /// Parent timestamp. 25 | pub parent_timestamp: Uint, 26 | /// Parent difficulty. 27 | pub parent_difficulty: Uint, 28 | /// Parent uncle hash. 29 | pub parent_uncles: H256, 30 | /// Current timestamp. 31 | pub current_timestamp: Uint, 32 | /// Current difficulty. 33 | pub current_difficulty: Uint, 34 | /// Current block number. 35 | pub current_block_number: Uint, 36 | } 37 | 38 | /// Type for running `Difficulty` tests 39 | pub type DifficultyTest = super::tester::GenericTester; 40 | -------------------------------------------------------------------------------- /ethjson/src/test_helpers/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Test structures for JSON deserialization. 18 | 19 | /// Blockchain test helpers 20 | pub mod blockchain; 21 | /// Difficulty test helpers 22 | pub mod difficulty; 23 | /// Tests to skip helpers 24 | pub mod skip; 25 | /// State test helpers 26 | pub mod state; 27 | /// Test primitives 28 | pub mod tester; 29 | /// Transaction test helpers 30 | pub mod transaction; 31 | /// Trie test helpers 32 | pub mod trie; 33 | /// Vm test helpers 34 | pub mod vm { 35 | /// Type for running `vm` tests 36 | pub type Test = super::tester::GenericTester; 37 | } 38 | -------------------------------------------------------------------------------- /ethjson/src/test_helpers/skip.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | use serde::Deserialize; 18 | use std::collections::BTreeMap; 19 | 20 | /// Test to skip (only if issue ongoing) 21 | #[derive(Debug, PartialEq, Deserialize)] 22 | pub struct SkipTests { 23 | /// Block tests 24 | pub block: Vec, 25 | /// State tests 26 | pub state: Vec, 27 | /// Legacy block tests 28 | pub legacy_block: Vec, 29 | /// Legacy state tests 30 | pub legacy_state: Vec, 31 | } 32 | 33 | /// Block test to skip. 34 | #[derive(Debug, PartialEq, Deserialize)] 35 | pub struct SkipBlockchainTest { 36 | /// Issue reference. 37 | pub reference: String, 38 | /// Test failing name. 39 | pub failing: String, 40 | /// Items failing for the test. 41 | pub subtests: Vec, 42 | } 43 | 44 | /// State test to skip. 45 | #[derive(Debug, PartialEq, Deserialize)] 46 | pub struct SkipStateTest { 47 | /// Issue reference. 48 | pub reference: String, 49 | /// Test failing name. 50 | pub failing: String, 51 | /// Items failing for the test. 52 | pub subtests: BTreeMap, 53 | } 54 | 55 | /// State subtest to skip. 56 | #[derive(Debug, PartialEq, Deserialize)] 57 | pub struct StateSkipSubStates { 58 | /// State test number of this item. Or '*' for all state. 59 | pub subnumbers: Vec, 60 | /// Chain for this items. 61 | pub chain: String, 62 | } 63 | 64 | impl SkipTests { 65 | /// Empty skip states. 66 | pub fn empty() -> Self { 67 | SkipTests { 68 | block: Vec::new(), 69 | state: Vec::new(), 70 | legacy_block: Vec::new(), 71 | legacy_state: Vec::new(), 72 | } 73 | } 74 | 75 | /// Loads test from json. 76 | pub fn load(reader: R) -> Result 77 | where 78 | R: std::io::Read, 79 | { 80 | serde_json::from_reader(reader) 81 | } 82 | } 83 | -------------------------------------------------------------------------------- /ethjson/src/test_helpers/state.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! State test deserialization. 18 | 19 | /// Type for running `State` tests 20 | pub type Test = super::tester::GenericTester; 21 | 22 | use crate::{ 23 | bytes::Bytes, 24 | hash::{Address, H256}, 25 | maybe::MaybeEmpty, 26 | spec::{ForkSpec, State as AccountState}, 27 | transaction::Transaction, 28 | uint::Uint, 29 | vm::Env, 30 | }; 31 | use ethereum_types::U256; 32 | use serde::Deserialize; 33 | use std::collections::BTreeMap; 34 | 35 | /// State test deserialization. 36 | #[derive(Debug, PartialEq, Deserialize)] 37 | pub struct State { 38 | /// Environment. 39 | pub env: Env, 40 | /// Pre state. 41 | #[serde(rename = "pre")] 42 | pub pre_state: AccountState, 43 | /// Post state. 44 | #[serde(rename = "post")] 45 | pub post_states: BTreeMap>, 46 | /// Transaction. 47 | pub transaction: MultiTransaction, 48 | } 49 | 50 | /// State test transaction deserialization. 51 | #[derive(Debug, PartialEq, Deserialize)] 52 | #[serde(rename_all = "camelCase")] 53 | pub struct MultiTransaction { 54 | /// Transaction data set. 55 | pub data: Vec, 56 | /// Access lists (see EIP-2930) 57 | #[serde(default)] 58 | pub access_lists: Vec>, 59 | /// Gas limit set. 60 | pub gas_limit: Vec, 61 | /// Gas price. 62 | #[serde(default)] 63 | pub gas_price: Uint, 64 | /// for details on `maxFeePerGas` see EIP-1559 65 | #[serde(default)] 66 | pub max_fee_per_gas: Uint, 67 | /// for details on `maxPriorityFeePerGas` see EIP-1559 68 | #[serde(default)] 69 | pub max_priority_fee_per_gas: Uint, 70 | /// Nonce. 71 | pub nonce: Uint, 72 | /// Secret key. 73 | #[serde(rename = "secretKey")] 74 | pub secret: Option, 75 | /// To. 76 | pub to: MaybeEmpty
, 77 | /// Value set. 78 | pub value: Vec, 79 | } 80 | 81 | impl MultiTransaction { 82 | /// max_priority_fee_per_gas (see EIP-1559) 83 | pub fn max_priority_fee_per_gas(&self) -> U256 { 84 | if self.max_priority_fee_per_gas.0.is_zero() { 85 | self.gas_price.0 86 | } else { 87 | self.max_priority_fee_per_gas.0 88 | } 89 | } 90 | 91 | /// max_fee_per_gas (see EIP-1559) 92 | pub fn max_fee_per_gas(&self) -> U256 { 93 | if self.max_fee_per_gas.0.is_zero() { 94 | self.gas_price.0 95 | } else { 96 | self.max_fee_per_gas.0 97 | } 98 | } 99 | 100 | /// Build transaction with given indexes. 101 | pub fn select(&self, indexes: &PostStateIndexes) -> Transaction { 102 | let data_index = indexes.data as usize; 103 | let access_list = if data_index < self.access_lists.len() { 104 | self.access_lists 105 | .get(data_index) 106 | .unwrap() 107 | .as_ref() 108 | .cloned() 109 | .unwrap_or_default() 110 | .into_iter() 111 | .map(|a| (a.address, a.storage_keys)) 112 | .collect() 113 | } else { 114 | Vec::new() 115 | }; 116 | 117 | let gas_price = if self.gas_price.0.is_zero() { 118 | self.max_fee_per_gas.0 + self.max_priority_fee_per_gas.0 119 | } else { 120 | self.gas_price.0 121 | }; 122 | 123 | Transaction { 124 | data: self.data[data_index].clone(), 125 | gas_limit: self.gas_limit[indexes.gas as usize], 126 | gas_price: Uint(gas_price), 127 | nonce: self.nonce, 128 | to: self.to.clone(), 129 | value: self.value[indexes.value as usize], 130 | r: Default::default(), 131 | s: Default::default(), 132 | v: Default::default(), 133 | secret: self.secret, 134 | access_list, 135 | } 136 | } 137 | } 138 | 139 | /// Type alias for access lists (see EIP-2930) 140 | pub type AccessList = Vec; 141 | 142 | /// Access list tuple (see https://eips.ethereum.org/EIPS/eip-2930). 143 | /// Example test spec: https://github.com/ethereum/tests/blob/5490db3ff58d371c0c74826280256ba016b0bd5c/GeneralStateTests/stExample/accessListExample.json 144 | #[derive(Debug, Clone, PartialEq, Deserialize)] 145 | #[serde(rename_all = "camelCase")] 146 | pub struct AccessListTuple { 147 | /// Address to access 148 | pub address: Address, 149 | /// Keys (slots) to access at that address 150 | pub storage_keys: Vec, 151 | } 152 | 153 | /// State test indexes deserialization. 154 | #[derive(Debug, PartialEq, Deserialize)] 155 | pub struct PostStateIndexes { 156 | /// Index into transaction data set. 157 | pub data: u64, 158 | /// Index into transaction gas limit set. 159 | pub gas: u64, 160 | /// Index into transaction value set. 161 | pub value: u64, 162 | } 163 | 164 | /// State test indexed state result deserialization. 165 | #[derive(Debug, PartialEq, Deserialize)] 166 | #[serde(rename_all = "camelCase")] 167 | pub struct PostStateResult { 168 | /// Post state hash 169 | pub hash: H256, 170 | /// Indexes 171 | pub indexes: PostStateIndexes, 172 | /// Expected error if the test is meant to fail 173 | pub expect_exception: Option, 174 | /// Transaction bytes 175 | pub txbytes: Bytes, 176 | } 177 | 178 | #[cfg(test)] 179 | mod tests { 180 | use super::{MultiTransaction, State}; 181 | use serde_json; 182 | 183 | #[test] 184 | fn multi_transaction_deserialization() { 185 | let s = r#"{ 186 | "data": [ "" ], 187 | "gasLimit": [ "0x2dc6c0", "0x222222" ], 188 | "gasPrice": "0x01", 189 | "nonce": "0x00", 190 | "secretKey": "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", 191 | "to": "1000000000000000000000000000000000000000", 192 | "value": [ "0x00", "0x01", "0x02" ] 193 | }"#; 194 | let _deserialized: MultiTransaction = serde_json::from_str(s).unwrap(); 195 | } 196 | 197 | #[test] 198 | fn state_deserialization() { 199 | let s = r#"{ 200 | "env": { 201 | "currentCoinbase": "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", 202 | "currentDifficulty": "0x0100", 203 | "currentGasLimit": "0x01c9c380", 204 | "currentNumber": "0x00", 205 | "currentTimestamp": "0x01", 206 | "previousHash": "5e20a0453cecd065ea59c37ac63e079ee08998b6045136a8ce6635c7912ec0b6" 207 | }, 208 | "post": { 209 | "EIP150": [ 210 | { 211 | "hash": "3e6dacc1575c6a8c76422255eca03529bbf4c0dda75dfc110b22d6dc4152396f", 212 | "txbytes" : "0xf861800a84042c1d8094b94f5374fce5edbc8e2a8697c15331677e6ebf0b80801ca0f141d67812db948c9a4ea43c27d695248205c121ae8d924d23517ab09e38f369a03fe3cfedb4c9a7e61340b6fec87917690e92082f752ad820ad5006c7d49185ed", 213 | "indexes": { "data": 0, "gas": 0, "value": 0 } 214 | }, 215 | { 216 | "hash": "99a450d8ce5b987a71346d8a0a1203711f770745c7ef326912e46761f14cd764", 217 | "txbytes" : "0xf861800a84042c1d8094b94f5374fce5edbc8e2a8697c15331677e6ebf0b80801ca0f141d67812db948c9a4ea43c27d695248205c121ae8d924d23517ab09e38f369a03fe3cfedb4c9a7e61340b6fec87917690e92082f752ad820ad5006c7d49185ed", 218 | "indexes": { "data": 0, "gas": 0, "value": 1 } 219 | } 220 | ], 221 | "EIP158": [ 222 | { 223 | "hash": "3e6dacc1575c6a8c76422255eca03529bbf4c0dda75dfc110b22d6dc4152396f", 224 | "txbytes" : "0xf861800a84042c1d8094b94f5374fce5edbc8e2a8697c15331677e6ebf0b80801ca0f141d67812db948c9a4ea43c27d695248205c121ae8d924d23517ab09e38f369a03fe3cfedb4c9a7e61340b6fec87917690e92082f752ad820ad5006c7d49185ed", 225 | "indexes": { "data": 0, "gas": 0, "value": 0 } 226 | }, 227 | { 228 | "hash": "99a450d8ce5b987a71346d8a0a1203711f770745c7ef326912e46761f14cd764", 229 | "txbytes" : "0xf861800a84042c1d8094b94f5374fce5edbc8e2a8697c15331677e6ebf0b80801ca0f141d67812db948c9a4ea43c27d695248205c121ae8d924d23517ab09e38f369a03fe3cfedb4c9a7e61340b6fec87917690e92082f752ad820ad5006c7d49185ed", 230 | "indexes": { "data": 0, "gas": 0, "value": 1 } 231 | } 232 | ] 233 | }, 234 | "pre": { 235 | "1000000000000000000000000000000000000000": { 236 | "balance": "0x0de0b6b3a7640000", 237 | "code": "0x6040600060406000600173100000000000000000000000000000000000000162055730f1600055", 238 | "nonce": "0x00", 239 | "storage": { 240 | } 241 | }, 242 | "1000000000000000000000000000000000000001": { 243 | "balance": "0x0de0b6b3a7640000", 244 | "code": "0x604060006040600060027310000000000000000000000000000000000000026203d090f1600155", 245 | "nonce": "0x00", 246 | "storage": { 247 | } 248 | }, 249 | "1000000000000000000000000000000000000002": { 250 | "balance": "0x00", 251 | "code": "0x600160025533600455346007553060e6553260e8553660ec553860ee553a60f055", 252 | "nonce": "0x00", 253 | "storage": { 254 | } 255 | }, 256 | "a94f5374fce5edbc8e2a8697c15331677e6ebf0b": { 257 | "balance": "0x0de0b6b3a7640000", 258 | "code": "0x", 259 | "nonce": "0x00", 260 | "storage": { 261 | } 262 | } 263 | }, 264 | "transaction": { 265 | "data": [ "" ], 266 | "gasLimit": [ "285000", "100000", "6000" ], 267 | "gasPrice": "0x01", 268 | "nonce": "0x00", 269 | "secretKey": "45a915e4d060149eb4365960e6a7a45f334393093061116b197e3240065ff2d8", 270 | "to": "095e7baea6a6c7c4c2dfeb977efac326af552d87", 271 | "value": [ "10", "0" ] 272 | } 273 | }"#; 274 | let _deserialized: State = serde_json::from_str(s).unwrap(); 275 | // TODO: validate all fields 276 | } 277 | } 278 | -------------------------------------------------------------------------------- /ethjson/src/test_helpers/tester.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | use serde::de::DeserializeOwned; 18 | use serde::Deserialize; 19 | use std::collections::BTreeMap; 20 | 21 | /// A genric wrapper over a `BTreeMap` for tests 22 | #[derive(Deserialize)] 23 | pub struct GenericTester(BTreeMap); 24 | 25 | impl IntoIterator for GenericTester { 26 | type Item = as IntoIterator>::Item; 27 | type IntoIter = as IntoIterator>::IntoIter; 28 | 29 | fn into_iter(self) -> Self::IntoIter { 30 | self.0.into_iter() 31 | } 32 | } 33 | 34 | impl GenericTester 35 | where 36 | T: DeserializeOwned + Ord, 37 | U: DeserializeOwned, 38 | { 39 | /// Loads test from json. 40 | pub fn load(reader: R) -> Result 41 | where 42 | R: std::io::Read, 43 | { 44 | serde_json::from_reader(reader) 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /ethjson/src/test_helpers/transaction.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Transaction test deserialization. 18 | 19 | use crate::{ 20 | bytes::Bytes, 21 | hash::{Address, H256}, 22 | spec::ForkSpec, 23 | }; 24 | use serde::Deserialize; 25 | use std::collections::BTreeMap; 26 | 27 | /// Type for running `Transaction` tests 28 | pub type Test = super::tester::GenericTester; 29 | 30 | /// Transaction test deserialization. 31 | #[derive(Debug, Deserialize)] 32 | pub struct TransactionTest { 33 | /// RLP of the transaction 34 | pub rlp: Bytes, 35 | #[allow(missing_docs)] 36 | pub _info: serde::de::IgnoredAny, 37 | /// State of the transaction after the test runs 38 | #[serde(flatten)] 39 | pub post_state: BTreeMap, 40 | } 41 | 42 | /// TransactionTest post state. 43 | #[derive(Debug, PartialEq, Deserialize)] 44 | #[serde(deny_unknown_fields)] 45 | pub struct PostState { 46 | /// Transaction sender. 47 | pub sender: Option
, 48 | /// Transaction hash. 49 | pub hash: Option, 50 | } 51 | 52 | #[cfg(test)] 53 | mod tests { 54 | use super::TransactionTest; 55 | 56 | #[test] 57 | fn transaction_deserialization() { 58 | let s = r#"{ 59 | "Byzantium" : { 60 | "hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5", 61 | "sender" : "2ea991808ba979ba103147edfd72304ebd95c028" 62 | }, 63 | "Constantinople" : { 64 | "hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5", 65 | "sender" : "2ea991808ba979ba103147edfd72304ebd95c028" 66 | }, 67 | "EIP150" : { 68 | }, 69 | "EIP158" : { 70 | "hash" : "4782cb5edcaeda1f0aef204b161214f124cefade9e146245183abbb9ca01bca5", 71 | "sender" : "2ea991808ba979ba103147edfd72304ebd95c028" 72 | }, 73 | "Frontier" : { 74 | }, 75 | "Homestead" : { 76 | }, 77 | "_info" : { 78 | "comment" : "", 79 | "filledwith" : "cpp-1.3.0+commit.1829957d.Linux.g++", 80 | "lllcversion" : "Version: 0.4.18-develop.2017.10.11+commit.81f9f86c.Linux.g++", 81 | "source" : "src/TransactionTestsFiller/ttVValue/V_equals37Filler.json", 82 | "sourceHash" : "89ef69312d4c0b4e3742da501263d23d2a64f180258ac93940997ac6a17b9b19" 83 | }, 84 | "rlp" : "0xf865808698852840a46f82d6d894095e7baea6a6c7c4c2dfeb977efac326af552d87808025a098ff921201554726367d2be8c804a7ff89ccf285ebc57dff8ae4c44b9c19ac4aa01887321be575c8095f789dd4c743dfe42c1820f9231f98a962b210e3ac2452a3" 85 | }"#; 86 | 87 | let _deserialized: TransactionTest = serde_json::from_str(s).unwrap(); 88 | // TODO: validate all fields 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /ethjson/src/test_helpers/trie/input.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Trie test input deserialization. 18 | 19 | use crate::bytes::Bytes; 20 | use serde::de::{Error as ErrorTrait, MapAccess, SeqAccess, Visitor}; 21 | use serde::{Deserialize, Deserializer}; 22 | use std::collections::BTreeMap; 23 | use std::fmt; 24 | use std::str::FromStr; 25 | 26 | /// Trie test input. 27 | #[derive(Debug, PartialEq)] 28 | pub struct Input { 29 | /// Input params. 30 | pub data: BTreeMap>, 31 | } 32 | 33 | impl<'a> Deserialize<'a> for Input { 34 | fn deserialize(deserializer: D) -> Result 35 | where 36 | D: Deserializer<'a>, 37 | { 38 | deserializer.deserialize_any(InputVisitor) 39 | } 40 | } 41 | 42 | struct InputVisitor; 43 | 44 | impl<'a> Visitor<'a> for InputVisitor { 45 | type Value = Input; 46 | 47 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 48 | write!(formatter, "a map of bytes into bytes") 49 | } 50 | 51 | fn visit_map(self, mut visitor: V) -> Result 52 | where 53 | V: MapAccess<'a>, 54 | { 55 | let mut result = BTreeMap::new(); 56 | 57 | loop { 58 | let key_str: Option = visitor.next_key()?; 59 | let key = match key_str { 60 | Some(ref k) if k.starts_with("0x") => { 61 | Bytes::from_str(k).map_err(V::Error::custom)? 62 | } 63 | Some(k) => Bytes::new(k.into_bytes()), 64 | None => { 65 | break; 66 | } 67 | }; 68 | 69 | let val_str: Option = visitor.next_value()?; 70 | let val = match val_str { 71 | Some(ref v) if v.starts_with("0x") => { 72 | Some(Bytes::from_str(v).map_err(V::Error::custom)?) 73 | } 74 | Some(v) => Some(Bytes::new(v.into_bytes())), 75 | None => None, 76 | }; 77 | 78 | result.insert(key, val); 79 | } 80 | 81 | let input = Input { data: result }; 82 | 83 | Ok(input) 84 | } 85 | 86 | fn visit_seq(self, mut visitor: V) -> Result 87 | where 88 | V: SeqAccess<'a>, 89 | { 90 | let mut result = BTreeMap::new(); 91 | 92 | loop { 93 | let keyval: Option>> = visitor.next_element()?; 94 | let keyval = match keyval { 95 | Some(k) => k, 96 | _ => { 97 | break; 98 | } 99 | }; 100 | 101 | if keyval.len() != 2 { 102 | return Err(V::Error::custom("Invalid key value pair.")); 103 | } 104 | 105 | let key_str = &keyval[0]; 106 | let val_str = &keyval[1]; 107 | 108 | let key = match *key_str { 109 | Some(ref k) if k.starts_with("0x") => { 110 | Bytes::from_str(k).map_err(V::Error::custom)? 111 | } 112 | Some(ref k) => Bytes::new(k.clone().into_bytes()), 113 | None => { 114 | break; 115 | } 116 | }; 117 | 118 | let val = match *val_str { 119 | Some(ref v) if v.starts_with("0x") => { 120 | Some(Bytes::from_str(v).map_err(V::Error::custom)?) 121 | } 122 | Some(ref v) => Some(Bytes::new(v.clone().into_bytes())), 123 | None => None, 124 | }; 125 | 126 | result.insert(key, val); 127 | } 128 | 129 | let input = Input { data: result }; 130 | 131 | Ok(input) 132 | } 133 | } 134 | 135 | #[cfg(test)] 136 | mod tests { 137 | use super::{BTreeMap, Bytes, Input}; 138 | 139 | #[test] 140 | fn input_deserialization_from_map() { 141 | let s = r#"{ 142 | "0x0045" : "0x0123456789", 143 | "be" : "e", 144 | "0x0a" : null 145 | }"#; 146 | 147 | let input: Input = serde_json::from_str(s).unwrap(); 148 | let mut map = BTreeMap::new(); 149 | map.insert( 150 | Bytes::new(vec![0, 0x45]), 151 | Some(Bytes::new(vec![0x01, 0x23, 0x45, 0x67, 0x89])), 152 | ); 153 | map.insert(Bytes::new(vec![0x62, 0x65]), Some(Bytes::new(vec![0x65]))); 154 | map.insert(Bytes::new(vec![0x0a]), None); 155 | assert_eq!(input.data, map); 156 | } 157 | 158 | #[test] 159 | fn input_deserialization_from_array() { 160 | let s = r#"[ 161 | ["0x0045", "0x0123456789"], 162 | ["be", "e"], 163 | ["0x0a", null] 164 | ]"#; 165 | 166 | let input: Input = serde_json::from_str(s).unwrap(); 167 | let mut map = BTreeMap::new(); 168 | map.insert( 169 | Bytes::new(vec![0, 0x45]), 170 | Some(Bytes::new(vec![0x01, 0x23, 0x45, 0x67, 0x89])), 171 | ); 172 | map.insert(Bytes::new(vec![0x62, 0x65]), Some(Bytes::new(vec![0x65]))); 173 | map.insert(Bytes::new(vec![0x0a]), None); 174 | assert_eq!(input.data, map); 175 | } 176 | } 177 | -------------------------------------------------------------------------------- /ethjson/src/test_helpers/trie/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Trie test deserialization. 18 | 19 | mod input; 20 | 21 | pub use self::input::Input; 22 | 23 | /// Type used by `trie` tests 24 | pub type Test = super::tester::GenericTester; 25 | 26 | use crate::hash::H256; 27 | use serde::Deserialize; 28 | 29 | /// Trie test deserialization. 30 | #[derive(Debug, Deserialize, PartialEq)] 31 | pub struct Trie { 32 | /// Trie test input. 33 | #[serde(rename = "in")] 34 | pub input: Input, 35 | /// Trie root hash. 36 | pub root: H256, 37 | } 38 | -------------------------------------------------------------------------------- /ethjson/src/transaction.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Transaction deserialization. 18 | 19 | use crate::{ 20 | bytes::Bytes, 21 | hash::{Address, H256}, 22 | maybe::MaybeEmpty, 23 | uint::Uint, 24 | }; 25 | use serde::Deserialize; 26 | 27 | /// Unsigned transaction with signing information deserialization. 28 | #[derive(Debug, PartialEq, Deserialize)] 29 | #[serde(rename_all = "camelCase")] 30 | pub struct Transaction { 31 | /// Transaction data. 32 | pub data: Bytes, 33 | /// Transaction access list (see EIP-2930). 34 | #[serde(default)] 35 | pub access_list: Vec<(Address, Vec)>, 36 | /// Gas limit. 37 | pub gas_limit: Uint, 38 | /// Gas price. 39 | pub gas_price: Uint, 40 | /// Nonce. 41 | pub nonce: Uint, 42 | /// To. 43 | pub to: MaybeEmpty
, 44 | /// Value. 45 | pub value: Uint, 46 | /// R. 47 | #[serde(default)] 48 | pub r: MaybeEmpty, 49 | /// S. 50 | #[serde(default)] 51 | pub s: MaybeEmpty, 52 | /// V. 53 | #[serde(default)] 54 | pub v: MaybeEmpty, 55 | /// Secret 56 | #[serde(rename = "secretKey")] 57 | pub secret: Option, 58 | } 59 | 60 | #[cfg(test)] 61 | mod tests { 62 | use super::{Bytes, MaybeEmpty, Transaction, Uint, H256}; 63 | use ethereum_types::{H256 as Eth256, U256}; 64 | 65 | #[test] 66 | fn transaction_deserialization() { 67 | let s = r#"{ 68 | "data" : "0x", 69 | "gasLimit" : "0xf388", 70 | "gasPrice" : "0x09184e72a000", 71 | "nonce" : "0x00", 72 | "to" : "", 73 | "value" : "0x00", 74 | "r": "0", 75 | "s": "1", 76 | "v": "2", 77 | "secretKey": "0x0000000000000000000000000000000000000000000000000000000000000000" 78 | }"#; 79 | let tx: Transaction = serde_json::from_str(s).expect("JSON string is valid"); 80 | assert_eq!(tx.data, Bytes::new(Vec::new())); 81 | assert_eq!(tx.gas_limit, Uint(U256::from(0xf388))); 82 | assert_eq!(tx.gas_price, Uint(U256::from(0x09184e72a000_u64))); 83 | assert_eq!(tx.nonce, Uint(U256::zero())); 84 | assert_eq!(tx.to, MaybeEmpty::None); 85 | assert_eq!(tx.value, Uint(U256::zero())); 86 | assert_eq!(tx.r, Uint(U256::zero()).into()); 87 | assert_eq!(tx.s, Uint(U256::one()).into()); 88 | assert_eq!(tx.v, Uint(U256::from(2)).into()); 89 | assert_eq!(tx.secret, Some(H256(Eth256::zero()))); 90 | } 91 | } 92 | -------------------------------------------------------------------------------- /ethjson/src/uint.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Lenient uint json deserialization for test json files. 18 | 19 | use ethereum_types::U256; 20 | use serde::de::{Error, Unexpected, Visitor}; 21 | use serde::{Deserialize, Deserializer, Serialize, Serializer}; 22 | use std::fmt; 23 | use std::str::FromStr; 24 | 25 | /// Lenient uint json deserialization for test json files. 26 | #[derive(Default, Debug, PartialEq, Eq, PartialOrd, Ord, Hash, Clone, Copy)] 27 | pub struct Uint(pub U256); 28 | 29 | impl Into for Uint { 30 | fn into(self) -> U256 { 31 | self.0 32 | } 33 | } 34 | 35 | impl Into for Uint { 36 | fn into(self) -> u64 { 37 | self.0.low_u64() 38 | } 39 | } 40 | 41 | impl Into for Uint { 42 | fn into(self) -> usize { 43 | self.0.low_u64() as usize 44 | } 45 | } 46 | 47 | impl Serialize for Uint { 48 | fn serialize(&self, serializer: S) -> Result 49 | where 50 | S: Serializer, 51 | { 52 | self.0.to_string().serialize(serializer) 53 | } 54 | } 55 | 56 | impl<'a> Deserialize<'a> for Uint { 57 | fn deserialize(deserializer: D) -> Result 58 | where 59 | D: Deserializer<'a>, 60 | { 61 | deserializer.deserialize_any(UintVisitor) 62 | } 63 | } 64 | 65 | struct UintVisitor; 66 | 67 | impl<'a> Visitor<'a> for UintVisitor { 68 | type Value = Uint; 69 | 70 | fn expecting(&self, formatter: &mut fmt::Formatter) -> fmt::Result { 71 | write!(formatter, "a hex encoded or decimal uint") 72 | } 73 | 74 | fn visit_u64(self, value: u64) -> Result 75 | where 76 | E: Error, 77 | { 78 | Ok(Uint(U256::from(value))) 79 | } 80 | 81 | fn visit_str(self, value: &str) -> Result 82 | where 83 | E: Error, 84 | { 85 | let parse = |value: &str| { 86 | if value.len() > 64 { 87 | return Err(Error::custom( 88 | format!( 89 | "Invalid hex value 0x{value}: value too big (length={})", 90 | value.len() 91 | ) 92 | .as_str(), 93 | )); 94 | } 95 | U256::from_str(value) 96 | .map_err(|e| Error::custom(format!("Invalid hex value 0x{value}: {e}").as_str())) 97 | }; 98 | 99 | let value = match value.len() { 100 | 0 => U256::from(0), 101 | 2 if value.starts_with("0x") => U256::from(0), 102 | _ if value.starts_with("0x:bigint 0x") => parse(&value[12..])?, 103 | _ if value.starts_with("0x") => parse(&value[2..])?, 104 | _ => U256::from_dec_str(value).map_err(|e| { 105 | Error::custom(format!("Invalid decimal value {}: {:?}", value, e).as_str()) 106 | })?, 107 | }; 108 | 109 | Ok(Uint(value)) 110 | } 111 | 112 | fn visit_string(self, value: String) -> Result 113 | where 114 | E: Error, 115 | { 116 | self.visit_str(value.as_ref()) 117 | } 118 | } 119 | 120 | /// Deserialize and validate that the value is non-zero 121 | pub fn validate_non_zero<'de, D>(d: D) -> Result 122 | where 123 | D: Deserializer<'de>, 124 | { 125 | let value = Uint::deserialize(d)?; 126 | 127 | if value == Uint(U256::from(0)) { 128 | return Err(Error::invalid_value( 129 | Unexpected::Unsigned(0), 130 | &"a non-zero value", 131 | )); 132 | } 133 | 134 | Ok(value) 135 | } 136 | 137 | /// Deserialize and validate that the value is non-zero 138 | pub fn validate_optional_non_zero<'de, D>(d: D) -> Result, D::Error> 139 | where 140 | D: Deserializer<'de>, 141 | { 142 | let value: Option = Option::deserialize(d)?; 143 | 144 | if let Some(value) = value { 145 | if value == Uint(U256::from(0)) { 146 | return Err(Error::invalid_value( 147 | Unexpected::Unsigned(0), 148 | &"a non-zero value", 149 | )); 150 | } 151 | } 152 | 153 | Ok(value) 154 | } 155 | 156 | #[cfg(test)] 157 | mod test { 158 | use super::Uint; 159 | use ethereum_types::U256; 160 | 161 | #[test] 162 | fn uint_deserialization() { 163 | let s = r#"["0xa", "10", "", "0x", 0]"#; 164 | let deserialized: Vec = serde_json::from_str(s).unwrap(); 165 | assert_eq!( 166 | deserialized, 167 | vec![ 168 | Uint(U256::from(10)), 169 | Uint(U256::from(10)), 170 | Uint(U256::from(0)), 171 | Uint(U256::from(0)), 172 | Uint(U256::from(0)) 173 | ] 174 | ); 175 | } 176 | 177 | #[test] 178 | fn uint_deserialization_error_for_hex_too_large() { 179 | let hex = format!("0x{}", "1".repeat(65)); 180 | let result: Result = serde_json::from_str(&format!(r#""{}""#, hex)); 181 | let err = result.unwrap_err(); 182 | assert!(err.is_data()); 183 | assert_eq!( 184 | err.to_string(), 185 | format!( 186 | "Invalid hex value {}: value too big (length=65) at line 1 column 69", 187 | hex 188 | ) 189 | ); 190 | } 191 | 192 | #[test] 193 | fn uint_into() { 194 | assert_eq!(U256::from(10), Uint(U256::from(10)).into()); 195 | } 196 | } 197 | -------------------------------------------------------------------------------- /ethjson/src/vm.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2015-2020 Parity Technologies (UK) Ltd. 2 | // This file is part of Open Ethereum. 3 | 4 | // Open Ethereum is free software: you can redistribute it and/or modify 5 | // it under the terms of the GNU General Public License as published by 6 | // the Free Software Foundation, either version 3 of the License, or 7 | // (at your option) any later version. 8 | 9 | // Open Ethereum is distributed in the hope that it will be useful, 10 | // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 | // GNU General Public License for more details. 13 | 14 | // You should have received a copy of the GNU General Public License 15 | // along with Open Ethereum. If not, see . 16 | 17 | //! Vm json deserialization 18 | 19 | use crate::{ 20 | bytes::Bytes, 21 | hash::{Address, H256}, 22 | maybe::MaybeEmpty, 23 | spec::State, 24 | uint::Uint, 25 | }; 26 | use serde::Deserialize; 27 | 28 | /// Represents vm execution environment before and after execution of transaction. 29 | #[derive(Debug, PartialEq, Deserialize)] 30 | pub struct Vm { 31 | /// Contract calls made internaly by executed transaction. 32 | #[serde(rename = "callcreates")] 33 | pub calls: Option>, 34 | /// Env info. 35 | pub env: Env, 36 | /// Executed transaction 37 | #[serde(rename = "exec")] 38 | pub transaction: Transaction, 39 | /// Gas left after transaction execution. 40 | #[serde(rename = "gas")] 41 | pub gas_left: Option, 42 | /// Hash of logs created during execution of transaction. 43 | pub logs: Option, 44 | /// Transaction output. 45 | #[serde(rename = "out")] 46 | pub output: Option, 47 | /// Post execution vm state. 48 | #[serde(rename = "post")] 49 | pub post_state: Option, 50 | /// Pre execution vm state. 51 | #[serde(rename = "pre")] 52 | pub pre_state: State, 53 | } 54 | 55 | impl Vm { 56 | /// Returns true if transaction execution run out of gas. 57 | pub fn out_of_gas(&self) -> bool { 58 | self.calls.is_none() 59 | } 60 | } 61 | 62 | /// Call deserialization. 63 | #[derive(Debug, PartialEq, Deserialize)] 64 | #[serde(rename_all = "camelCase")] 65 | pub struct Call { 66 | /// Call data. 67 | pub data: Bytes, 68 | /// Call destination. 69 | pub destination: MaybeEmpty
, 70 | /// Gas limit. 71 | pub gas_limit: Uint, 72 | /// Call value. 73 | pub value: Uint, 74 | } 75 | 76 | /// Executed transaction. 77 | #[derive(Debug, PartialEq, Deserialize)] 78 | #[serde(rename_all = "camelCase")] 79 | pub struct Transaction { 80 | /// Contract address. 81 | pub address: Address, 82 | /// Transaction sender. 83 | #[serde(rename = "caller")] 84 | pub sender: Address, 85 | /// Contract code. 86 | pub code: Bytes, 87 | /// Input data. 88 | pub data: Bytes, 89 | /// Gas. 90 | pub gas: Uint, 91 | /// Gas price. 92 | pub gas_price: Uint, 93 | /// Transaction origin. 94 | pub origin: Address, 95 | /// Sent value. 96 | pub value: Uint, 97 | /// Contract code version. 98 | #[serde(default)] 99 | pub code_version: Uint, 100 | } 101 | 102 | /// Environment. 103 | #[derive(Debug, PartialEq, Deserialize)] 104 | pub struct Env { 105 | /// Address. 106 | #[serde(rename = "currentCoinbase")] 107 | pub author: Address, 108 | /// Difficulty 109 | #[serde(rename = "currentDifficulty")] 110 | pub difficulty: Uint, 111 | /// Gas limit. 112 | #[serde(rename = "currentGasLimit")] 113 | pub gas_limit: Uint, 114 | /// Number. 115 | #[serde(rename = "currentNumber")] 116 | pub number: Uint, 117 | /// Timestamp. 118 | #[serde(rename = "currentTimestamp")] 119 | pub timestamp: Uint, 120 | /// Block base fee (see EIP-1559) 121 | #[serde(rename = "currentBaseFee")] 122 | #[serde(default)] 123 | pub block_base_fee_per_gas: Uint, 124 | /// Pre-seeded random value for testing 125 | #[serde(rename = "currentRandom")] 126 | #[serde(default)] 127 | pub random: Option, 128 | } 129 | 130 | #[cfg(test)] 131 | mod tests { 132 | use super::{Address, Bytes, Call, Env, MaybeEmpty, State, Transaction, Uint, Vm, H256}; 133 | use std::str::FromStr; 134 | 135 | use crate::spec::{Account, HashOrMap}; 136 | use ethereum_types::{H160 as Hash160, H256 as Hash256, U256}; 137 | use maplit::btreemap; 138 | use rustc_hex::FromHex; 139 | 140 | const TEST_CODE: &str = "7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055"; 141 | 142 | #[test] 143 | fn vm_deserialization() { 144 | let s = r#"{ 145 | "callcreates" : [ 146 | ], 147 | "env" : { 148 | "currentCoinbase" : "2adc25665018aa1fe0e6bc666dac8fc2697ff9ba", 149 | "currentDifficulty" : "0x0100", 150 | "currentGasLimit" : "0x0f4240", 151 | "currentNumber" : "0x00", 152 | "currentTimestamp" : "0x01", 153 | "currentRandom" : "0x01" 154 | }, 155 | "exec" : { 156 | "address" : "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6", 157 | "caller" : "cd1722f2947def4cf144679da39c4c32bdc35681", 158 | "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055", 159 | "data" : "0x", 160 | "gas" : "0x0186a0", 161 | "gasPrice" : "0x5af3107a4000", 162 | "origin" : "cd1722f2947def4cf144679da39c4c32bdc35681", 163 | "value" : "0x0de0b6b3a7640000" 164 | }, 165 | "gas" : "0x013874", 166 | "logs" : "0x1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347", 167 | "out" : "0x", 168 | "post" : { 169 | "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { 170 | "balance" : "0x0de0b6b3a7640000", 171 | "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055", 172 | "nonce" : "0x00", 173 | "storage" : { 174 | "0x00" : "0xfffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe" 175 | } 176 | } 177 | }, 178 | "pre" : { 179 | "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6" : { 180 | "balance" : "0x0de0b6b3a7640000", 181 | "code" : "0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff01600055", 182 | "nonce" : "0x00", 183 | "storage" : { 184 | } 185 | } 186 | } 187 | }"#; 188 | let vm: Vm = serde_json::from_str(s).expect("JSON is valid"); 189 | assert_eq!(vm.calls, Some(Vec::new())); 190 | assert_eq!( 191 | vm.env, 192 | Env { 193 | author: Address( 194 | Hash160::from_str("2adc25665018aa1fe0e6bc666dac8fc2697ff9ba").unwrap() 195 | ), 196 | difficulty: Uint(0x0100.into()), 197 | gas_limit: Uint(0x0f4240.into()), 198 | number: Uint(0.into()), 199 | timestamp: Uint(1.into()), 200 | block_base_fee_per_gas: Uint(0.into()), 201 | random: Some(Uint(1.into())), 202 | } 203 | ); 204 | assert_eq!( 205 | vm.transaction, 206 | Transaction { 207 | address: Address( 208 | Hash160::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap() 209 | ), 210 | sender: Address( 211 | Hash160::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap() 212 | ), 213 | code: Bytes::new(TEST_CODE.from_hex().unwrap()), 214 | code_version: Uint(0.into()), 215 | data: Bytes::new(Vec::new()), 216 | gas: Uint(0x0186a0.into()), 217 | gas_price: Uint(0x5af3107a4000_u64.into()), 218 | origin: Address( 219 | Hash160::from_str("cd1722f2947def4cf144679da39c4c32bdc35681").unwrap() 220 | ), 221 | value: Uint(0x0de0b6b3a7640000_u64.into()) 222 | } 223 | ); 224 | assert_eq!(vm.gas_left, Some(Uint(0x013874.into()))); 225 | assert_eq!( 226 | vm.logs, 227 | Some(H256( 228 | Hash256::from_str( 229 | "1dcc4de8dec75d7aab85b567b6ccd41ad312451b948a7413f0a142fd40d49347" 230 | ) 231 | .unwrap() 232 | )) 233 | ); 234 | assert_eq!(vm.output, Some(Bytes::new(Vec::new()))); 235 | assert_eq!( 236 | vm.pre_state, 237 | State(HashOrMap::Map(btreemap![ 238 | Address(Hash160::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap()) => Account { 239 | builtin: None, 240 | balance: Some(Uint(0x0de0b6b3a7640000_u64.into())), 241 | code: Some(Bytes::new(TEST_CODE.from_hex().unwrap())), 242 | constructor: None, 243 | nonce: Some(Uint(0.into())), 244 | storage: Some(btreemap![]), 245 | version: None, 246 | } 247 | ])) 248 | ); 249 | assert_eq!( 250 | vm.post_state, 251 | Some(State(HashOrMap::Map(btreemap![ 252 | Address(Hash160::from_str("0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6").unwrap()) => Account { 253 | builtin: None, 254 | balance: Some(Uint(0x0de0b6b3a7640000_u64.into())), 255 | code: Some(Bytes::new(TEST_CODE.from_hex().unwrap())), 256 | constructor: None, 257 | nonce: Some(Uint(0.into())), 258 | storage: Some(btreemap![ 259 | Uint(0.into()) => Uint(U256::from_str("fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe").unwrap()) 260 | ]), 261 | version: None, 262 | }]))) 263 | ); 264 | } 265 | 266 | #[test] 267 | fn call_deserialization_empty_dest() { 268 | let s = r#"{ 269 | "data" : "0x1111222233334444555566667777888899990000aaaabbbbccccddddeeeeffff", 270 | "destination" : "", 271 | "gasLimit" : "0x1748766aa5", 272 | "value" : "0x00" 273 | }"#; 274 | let call: Call = serde_json::from_str(s).unwrap(); 275 | 276 | assert_eq!( 277 | &call.data[..], 278 | &[ 279 | 0x11, 0x11, 0x22, 0x22, 0x33, 0x33, 0x44, 0x44, 0x55, 0x55, 0x66, 0x66, 0x77, 0x77, 280 | 0x88, 0x88, 0x99, 0x99, 0x00, 0x00, 0xaa, 0xaa, 0xbb, 0xbb, 0xcc, 0xcc, 0xdd, 0xdd, 281 | 0xee, 0xee, 0xff, 0xff 282 | ] 283 | ); 284 | 285 | assert_eq!(call.destination, MaybeEmpty::None); 286 | assert_eq!(call.gas_limit, Uint(U256::from(0x1748766aa5u64))); 287 | assert_eq!(call.value, Uint(U256::from(0))); 288 | } 289 | 290 | #[test] 291 | fn call_deserialization_full_dest() { 292 | let s = r#"{ 293 | "data" : "0x1234", 294 | "destination" : "5a39ed1020c04d4d84539975b893a4e7c53eab6c", 295 | "gasLimit" : "0x1748766aa5", 296 | "value" : "0x00" 297 | }"#; 298 | 299 | let call: Call = serde_json::from_str(s).unwrap(); 300 | 301 | assert_eq!(&call.data[..], &[0x12, 0x34]); 302 | assert_eq!( 303 | call.destination, 304 | MaybeEmpty::Some(Address( 305 | Hash160::from_str("5a39ed1020c04d4d84539975b893a4e7c53eab6c").unwrap() 306 | )) 307 | ); 308 | assert_eq!(call.gas_limit, Uint(U256::from(0x1748766aa5u64))); 309 | assert_eq!(call.value, Uint(U256::from(0))); 310 | } 311 | } 312 | -------------------------------------------------------------------------------- /jsontests/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "evm-jsontests" 3 | version = "0.13.1" 4 | license = "GPL-3.0" 5 | authors = ["Wei Tang ", "Parity Technologies "] 6 | description = "SputnikVM - a Portable Blockchain Virtual Machine" 7 | repository = "https://github.com/sorpaas/rust-evm" 8 | keywords = ["no_std", "ethereum"] 9 | edition = "2018" 10 | 11 | [dependencies] 12 | evm = { path = "../evm" } 13 | ethereum = "0.15.0" 14 | primitive-types = "0.12" 15 | serde = { version = "1.0", features = ["derive"] } 16 | serde_json = "1.0" 17 | hex = "0.4" 18 | clap = "2.32" 19 | ethjson = { path = "../ethjson", features = ["test-helpers"] } 20 | libsecp256k1 = "0.7" 21 | ethcore-builtin = { path = "../ethcore-builtin" } 22 | rlp = "0.5" 23 | sha3 = "0.10" 24 | parity-bytes = "0.1" 25 | env_logger = "0.9" 26 | lazy_static = "1.4.0" 27 | -------------------------------------------------------------------------------- /jsontests/res/berlin_builtins.json: -------------------------------------------------------------------------------- 1 | { 2 | "0000000000000000000000000000000000000001": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } }, 3 | "0000000000000000000000000000000000000002": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } }, 4 | "0000000000000000000000000000000000000003": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } }, 5 | "0000000000000000000000000000000000000004": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } }, 6 | "0000000000000000000000000000000000000005": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 3, "is_eip_2565": true } } }, 7 | "0000000000000000000000000000000000000006": { 8 | "name": "alt_bn128_add", 9 | "pricing": { 10 | "0": { 11 | "price": { "alt_bn128_const_operations": { "price": 500 }} 12 | }, 13 | "0": { 14 | "info": "EIP 1108 transition", 15 | "price": { "alt_bn128_const_operations": { "price": 150 }} 16 | } 17 | } 18 | }, 19 | "0000000000000000000000000000000000000007": { 20 | "name": "alt_bn128_mul", 21 | "pricing": { 22 | "0": { 23 | "price": { "alt_bn128_const_operations": { "price": 40000 }} 24 | }, 25 | "0": { 26 | "info": "EIP 1108 transition", 27 | "price": { "alt_bn128_const_operations": { "price": 6000 }} 28 | } 29 | } 30 | }, 31 | "0000000000000000000000000000000000000008": { 32 | "name": "alt_bn128_pairing", 33 | "pricing": { 34 | "0": { 35 | "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} 36 | }, 37 | "0": { 38 | "info": "EIP 1108 transition", 39 | "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} 40 | } 41 | } 42 | }, 43 | "0000000000000000000000000000000000000009": { 44 | "name": "blake2_f", 45 | "activate_at": "0x00", 46 | "pricing": { 47 | "blake2_f": { 48 | "gas_per_round": 1 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /jsontests/res/istanbul_builtins.json: -------------------------------------------------------------------------------- 1 | { 2 | "0000000000000000000000000000000000000001": { "name": "ecrecover", "pricing": { "linear": { "base": 3000, "word": 0 } } }, 3 | "0000000000000000000000000000000000000002": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } }, 4 | "0000000000000000000000000000000000000003": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } }, 5 | "0000000000000000000000000000000000000004": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } }, 6 | "0000000000000000000000000000000000000005": { "name": "modexp", "activate_at": "0x00", "pricing": { "modexp": { "divisor": 20, "is_eip_2565": false } } }, 7 | "0000000000000000000000000000000000000006": { 8 | "name": "alt_bn128_add", 9 | "pricing": { 10 | "0": { 11 | "price": { "alt_bn128_const_operations": { "price": 500 }} 12 | }, 13 | "0": { 14 | "info": "EIP 1108 transition", 15 | "price": { "alt_bn128_const_operations": { "price": 150 }} 16 | } 17 | } 18 | }, 19 | "0000000000000000000000000000000000000007": { 20 | "name": "alt_bn128_mul", 21 | "pricing": { 22 | "0": { 23 | "price": { "alt_bn128_const_operations": { "price": 40000 }} 24 | }, 25 | "0": { 26 | "info": "EIP 1108 transition", 27 | "price": { "alt_bn128_const_operations": { "price": 6000 }} 28 | } 29 | } 30 | }, 31 | "0000000000000000000000000000000000000008": { 32 | "name": "alt_bn128_pairing", 33 | "pricing": { 34 | "0": { 35 | "price": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 }} 36 | }, 37 | "0": { 38 | "info": "EIP 1108 transition", 39 | "price": { "alt_bn128_pairing": { "base": 45000, "pair": 34000 }} 40 | } 41 | } 42 | }, 43 | "0000000000000000000000000000000000000009": { 44 | "name": "blake2_f", 45 | "activate_at": "0x00", 46 | "pricing": { 47 | "blake2_f": { 48 | "gas_per_round": 1 49 | } 50 | } 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /jsontests/src/lib.rs: -------------------------------------------------------------------------------- 1 | mod utils; 2 | 3 | pub mod state; 4 | pub mod vm; 5 | -------------------------------------------------------------------------------- /jsontests/src/main.rs: -------------------------------------------------------------------------------- 1 | use clap::{App, Arg, SubCommand}; 2 | use evm_jsontests::state as statetests; 3 | use evm_jsontests::vm as vmtests; 4 | use std::collections::HashMap; 5 | use std::fs::File; 6 | use std::io::BufReader; 7 | 8 | fn main() { 9 | let matches = App::new("jsontests") 10 | .version("0.1.0") 11 | .author("Wei Tang ") 12 | .about("EVM json test utilities") 13 | .subcommand( 14 | SubCommand::with_name("vm").arg( 15 | Arg::with_name("FILE") 16 | .help("Target yaml file to import") 17 | .required(true) 18 | .min_values(1), 19 | ), 20 | ) 21 | .subcommand( 22 | SubCommand::with_name("state").arg( 23 | Arg::with_name("FILE") 24 | .help("Target yaml file to import") 25 | .required(true) 26 | .min_values(1), 27 | ), 28 | ) 29 | .get_matches(); 30 | 31 | if let Some(matches) = matches.subcommand_matches("vm") { 32 | for file_name in matches.values_of("FILE").unwrap() { 33 | let file = File::open(file_name).expect("Open file failed"); 34 | 35 | let reader = BufReader::new(file); 36 | let coll = serde_json::from_reader::<_, HashMap>(reader) 37 | .expect("Parse test cases failed"); 38 | 39 | for (name, test) in coll { 40 | vmtests::test(&name, test); 41 | } 42 | } 43 | } 44 | 45 | if let Some(matches) = matches.subcommand_matches("state") { 46 | for file_name in matches.values_of("FILE").unwrap() { 47 | let file = File::open(file_name).expect("Open file failed"); 48 | 49 | let reader = BufReader::new(file); 50 | let coll = serde_json::from_reader::<_, HashMap>(reader) 51 | .expect("Parse test cases failed"); 52 | 53 | for (name, test) in coll { 54 | statetests::test(&name, test); 55 | } 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /jsontests/src/utils.rs: -------------------------------------------------------------------------------- 1 | use evm::backend::MemoryAccount; 2 | use primitive_types::{H160, H256, U256}; 3 | use sha3::{Digest, Keccak256}; 4 | use std::collections::BTreeMap; 5 | 6 | pub fn u256_to_h256(u: U256) -> H256 { 7 | let mut h = H256::default(); 8 | u.to_big_endian(&mut h[..]); 9 | h 10 | } 11 | 12 | pub fn unwrap_to_account(s: ðjson::spec::Account) -> MemoryAccount { 13 | MemoryAccount { 14 | balance: s.balance.clone().unwrap().into(), 15 | nonce: s.nonce.unwrap().0, 16 | code: s.code.clone().unwrap().into(), 17 | storage: s 18 | .storage 19 | .as_ref() 20 | .unwrap() 21 | .iter() 22 | .filter_map(|(k, v)| { 23 | if v.0.is_zero() { 24 | // If value is zero then the key is not really there 25 | None 26 | } else { 27 | Some(( 28 | u256_to_h256(k.clone().into()), 29 | u256_to_h256(v.clone().into()), 30 | )) 31 | } 32 | }) 33 | .collect(), 34 | } 35 | } 36 | 37 | pub fn unwrap_to_state(a: ðjson::spec::State) -> BTreeMap { 38 | match &a.0 { 39 | ethjson::spec::HashOrMap::Map(m) => m 40 | .iter() 41 | .map(|(k, v)| (k.clone().into(), unwrap_to_account(v))) 42 | .collect(), 43 | ethjson::spec::HashOrMap::Hash(_) => panic!("Hash can not be converted."), 44 | } 45 | } 46 | 47 | /// Basic account type. 48 | #[derive(Debug, Clone, PartialEq, Eq)] 49 | pub struct TrieAccount { 50 | /// Nonce of the account. 51 | pub nonce: U256, 52 | /// Balance of the account. 53 | pub balance: U256, 54 | /// Storage root of the account. 55 | pub storage_root: H256, 56 | /// Code hash of the account. 57 | pub code_hash: H256, 58 | /// Code version of the account. 59 | pub code_version: U256, 60 | } 61 | 62 | impl rlp::Encodable for TrieAccount { 63 | fn rlp_append(&self, stream: &mut rlp::RlpStream) { 64 | let use_short_version = self.code_version == U256::zero(); 65 | 66 | match use_short_version { 67 | true => { 68 | stream.begin_list(4); 69 | } 70 | false => { 71 | stream.begin_list(5); 72 | } 73 | } 74 | 75 | stream.append(&self.nonce); 76 | stream.append(&self.balance); 77 | stream.append(&self.storage_root); 78 | stream.append(&self.code_hash); 79 | 80 | if !use_short_version { 81 | stream.append(&self.code_version); 82 | } 83 | } 84 | } 85 | 86 | impl rlp::Decodable for TrieAccount { 87 | fn decode(rlp: &rlp::Rlp) -> Result { 88 | let use_short_version = match rlp.item_count()? { 89 | 4 => true, 90 | 5 => false, 91 | _ => return Err(rlp::DecoderError::RlpIncorrectListLen), 92 | }; 93 | 94 | Ok(TrieAccount { 95 | nonce: rlp.val_at(0)?, 96 | balance: rlp.val_at(1)?, 97 | storage_root: rlp.val_at(2)?, 98 | code_hash: rlp.val_at(3)?, 99 | code_version: if use_short_version { 100 | U256::zero() 101 | } else { 102 | rlp.val_at(4)? 103 | }, 104 | }) 105 | } 106 | } 107 | 108 | pub fn assert_valid_state(a: ðjson::spec::State, b: &BTreeMap) { 109 | match &a.0 { 110 | ethjson::spec::HashOrMap::Map(m) => { 111 | assert_eq!( 112 | &m.iter() 113 | .map(|(k, v)| { (k.clone().into(), unwrap_to_account(v)) }) 114 | .collect::>(), 115 | b 116 | ); 117 | } 118 | ethjson::spec::HashOrMap::Hash(h) => assert_valid_hash(&h.clone().into(), b), 119 | } 120 | } 121 | 122 | pub fn assert_valid_hash(h: &H256, b: &BTreeMap) { 123 | let tree = b 124 | .iter() 125 | .map(|(address, account)| { 126 | let storage_root = ethereum::util::sec_trie_root( 127 | account 128 | .storage 129 | .iter() 130 | .map(|(k, v)| (k, rlp::encode(&U256::from_big_endian(&v[..])))), 131 | ); 132 | let code_hash = H256::from_slice(Keccak256::digest(&account.code).as_slice()); 133 | 134 | let account = TrieAccount { 135 | nonce: account.nonce, 136 | balance: account.balance, 137 | storage_root, 138 | code_hash, 139 | code_version: U256::zero(), 140 | }; 141 | 142 | (address, rlp::encode(&account)) 143 | }) 144 | .collect::>(); 145 | 146 | let root = ethereum::util::sec_trie_root(tree); 147 | let expect = h; 148 | 149 | if root != *expect { 150 | panic!( 151 | "Hash not equal; calculated: {:?}, expect: {:?}\nState: {:#x?}", 152 | root, expect, b 153 | ); 154 | } 155 | } 156 | 157 | pub fn flush() { 158 | use std::io::{self, Write}; 159 | 160 | io::stdout().flush().expect("Could not flush stdout"); 161 | } 162 | 163 | pub mod transaction { 164 | use ethjson::maybe::MaybeEmpty; 165 | use ethjson::transaction::Transaction; 166 | use ethjson::uint::Uint; 167 | use evm::gasometer::{self, Gasometer}; 168 | use primitive_types::{H160, H256, U256}; 169 | 170 | pub fn validate( 171 | tx: Transaction, 172 | block_gas_limit: U256, 173 | caller_balance: U256, 174 | config: &evm::Config, 175 | ) -> Result { 176 | match intrinsic_gas(&tx, config) { 177 | None => return Err(InvalidTxReason::IntrinsicGas), 178 | Some(required_gas) => { 179 | if tx.gas_limit < Uint(U256::from(required_gas)) { 180 | return Err(InvalidTxReason::IntrinsicGas); 181 | } 182 | } 183 | } 184 | 185 | if block_gas_limit < tx.gas_limit.0 { 186 | return Err(InvalidTxReason::GasLimitReached); 187 | } 188 | 189 | let required_funds = tx.gas_limit.0 * tx.gas_price.0 + tx.value.0; 190 | if caller_balance < required_funds { 191 | return Err(InvalidTxReason::OutOfFund); 192 | } 193 | 194 | Ok(tx) 195 | } 196 | 197 | fn intrinsic_gas(tx: &Transaction, config: &evm::Config) -> Option { 198 | let is_contract_creation = match tx.to { 199 | MaybeEmpty::None => true, 200 | MaybeEmpty::Some(_) => false, 201 | }; 202 | let data = &tx.data; 203 | let access_list: Vec<(H160, Vec)> = tx 204 | .access_list 205 | .iter() 206 | .map(|(a, s)| (a.0, s.into_iter().map(|h| h.0).collect())) 207 | .collect(); 208 | 209 | let cost = if is_contract_creation { 210 | gasometer::create_transaction_cost(data, &access_list) 211 | } else { 212 | gasometer::call_transaction_cost(data, &access_list) 213 | }; 214 | 215 | let mut g = Gasometer::new(u64::MAX, config); 216 | g.record_transaction(cost).ok()?; 217 | 218 | Some(g.total_used_gas()) 219 | } 220 | 221 | pub enum InvalidTxReason { 222 | IntrinsicGas, 223 | OutOfFund, 224 | GasLimitReached, 225 | } 226 | } 227 | -------------------------------------------------------------------------------- /jsontests/src/vm.rs: -------------------------------------------------------------------------------- 1 | use crate::utils::*; 2 | use evm::backend::{ApplyBackend, MemoryAccount, MemoryBackend, MemoryVicinity}; 3 | use evm::executor::stack::{MemoryStackState, StackExecutor, StackSubstateMetadata}; 4 | use evm::Config; 5 | use primitive_types::{H160, H256, U256}; 6 | use serde::Deserialize; 7 | use std::collections::BTreeMap; 8 | use std::rc::Rc; 9 | 10 | #[derive(Deserialize, Debug)] 11 | pub struct Test(ethjson::vm::Vm); 12 | 13 | impl Test { 14 | pub fn unwrap_to_pre_state(&self) -> BTreeMap { 15 | unwrap_to_state(&self.0.pre_state) 16 | } 17 | 18 | pub fn unwrap_to_vicinity(&self) -> MemoryVicinity { 19 | let block_randomness = self.0.env.random.map(|r| { 20 | // Convert between U256 and H256. U256 is in little-endian but since H256 is just 21 | // a string-like byte array, it's big endian (MSB is the first element of the array). 22 | // 23 | // Byte order here is important because this opcode has the same value as DIFFICULTY 24 | // (0x44), and so for older forks of Ethereum, the threshold value of 2^64 is used to 25 | // distinguish between the two: if it's below, the value corresponds to the DIFFICULTY 26 | // opcode, otherwise to the PREVRANDAO opcode. 27 | let mut buf = [0u8; 32]; 28 | r.0.to_big_endian(&mut buf); 29 | H256(buf) 30 | }); 31 | 32 | MemoryVicinity { 33 | gas_price: self.0.transaction.gas_price.clone().into(), 34 | origin: self.0.transaction.origin.clone().into(), 35 | block_hashes: Vec::new(), 36 | block_number: self.0.env.number.clone().into(), 37 | block_coinbase: self.0.env.author.clone().into(), 38 | block_timestamp: self.0.env.timestamp.clone().into(), 39 | block_difficulty: self.0.env.difficulty.clone().into(), 40 | block_gas_limit: self.0.env.gas_limit.clone().into(), 41 | chain_id: U256::zero(), 42 | block_base_fee_per_gas: self.0.transaction.gas_price.clone().into(), 43 | block_randomness, 44 | } 45 | } 46 | 47 | pub fn unwrap_to_code(&self) -> Rc> { 48 | Rc::new(self.0.transaction.code.clone().into()) 49 | } 50 | 51 | pub fn unwrap_to_data(&self) -> Rc> { 52 | Rc::new(self.0.transaction.data.clone().into()) 53 | } 54 | 55 | pub fn unwrap_to_context(&self) -> evm::Context { 56 | evm::Context { 57 | address: self.0.transaction.address.clone().into(), 58 | caller: self.0.transaction.sender.clone().into(), 59 | apparent_value: self.0.transaction.value.clone().into(), 60 | } 61 | } 62 | 63 | pub fn unwrap_to_return_value(&self) -> Vec { 64 | self.0.output.clone().unwrap().into() 65 | } 66 | 67 | pub fn unwrap_to_gas_limit(&self) -> u64 { 68 | self.0.transaction.gas.clone().into() 69 | } 70 | 71 | pub fn unwrap_to_post_gas(&self) -> u64 { 72 | self.0.gas_left.clone().unwrap().into() 73 | } 74 | } 75 | 76 | pub fn test(name: &str, test: Test) { 77 | print!("Running test {} ... ", name); 78 | flush(); 79 | 80 | let original_state = test.unwrap_to_pre_state(); 81 | let vicinity = test.unwrap_to_vicinity(); 82 | let config = Config::frontier(); 83 | let mut backend = MemoryBackend::new(&vicinity, original_state); 84 | let metadata = StackSubstateMetadata::new(test.unwrap_to_gas_limit(), &config); 85 | let state = MemoryStackState::new(metadata, &mut backend); 86 | let precompile = BTreeMap::new(); 87 | let mut executor = StackExecutor::new_with_precompiles(state, &config, &precompile); 88 | 89 | let code = test.unwrap_to_code(); 90 | let data = test.unwrap_to_data(); 91 | let context = test.unwrap_to_context(); 92 | let mut runtime = 93 | evm::Runtime::new(code, data, context, config.stack_limit, config.memory_limit); 94 | 95 | let reason = executor.execute(&mut runtime); 96 | let gas = executor.gas(); 97 | let (values, logs) = executor.into_state().deconstruct(); 98 | backend.apply(values, logs, false); 99 | 100 | if test.0.output.is_none() { 101 | print!("{:?} ", reason); 102 | 103 | assert!(!reason.is_succeed()); 104 | assert!(test.0.post_state.is_none() && test.0.gas_left.is_none()); 105 | 106 | println!("succeed"); 107 | } else { 108 | let expected_post_gas = test.unwrap_to_post_gas(); 109 | print!("{:?} ", reason); 110 | 111 | assert_eq!( 112 | runtime.machine().return_value(), 113 | test.unwrap_to_return_value() 114 | ); 115 | assert_valid_state(test.0.post_state.as_ref().unwrap(), &backend.state()); 116 | assert_eq!(gas, expected_post_gas); 117 | println!("succeed"); 118 | } 119 | } 120 | -------------------------------------------------------------------------------- /jsontests/tests/state.rs: -------------------------------------------------------------------------------- 1 | use evm_jsontests::state as statetests; 2 | use std::fs::{self, File}; 3 | use std::io::BufReader; 4 | use std::path::PathBuf; 5 | use std::{collections::HashMap, path::Path}; 6 | 7 | pub fn run(dir: &str) { 8 | let _ = env_logger::try_init(); 9 | 10 | let mut dest = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 11 | dest.push(dir); 12 | 13 | for entry in fs::read_dir(dest).unwrap() { 14 | let entry = entry.unwrap(); 15 | if let Some(s) = entry.file_name().to_str() { 16 | if s.starts_with('.') { 17 | continue; 18 | } 19 | } 20 | 21 | let path = entry.path(); 22 | 23 | if should_skip(&path) { 24 | println!("Skipping test case {path:?}"); 25 | continue; 26 | } 27 | 28 | let file = File::open(&path).expect("Open file failed"); 29 | 30 | let reader = BufReader::new(file); 31 | let coll: HashMap = serde_json::from_reader(reader) 32 | .unwrap_or_else(|e| { 33 | panic!("Parsing test case {:?} failed: {:?}", path, e); 34 | }); 35 | 36 | for (name, test) in coll { 37 | statetests::test(&name, test); 38 | } 39 | } 40 | } 41 | 42 | // NOTE: Add a comment here explaining why you're skipping a test case. 43 | const SKIPPED_CASES: &[&str] = &[ 44 | // This is an expected failure case for testing that the VM rejects 45 | // transactions with values that are too large, but it's geth 46 | // specific because geth parses the hex string later in the test 47 | // run, whereas this test runner parses everything up-front before 48 | // running the test. 49 | "stTransactionTest/ValueOverflow", 50 | // The below test cases are failing in geth too and as such are 51 | // skipped here until they are fixed there (otherwise we don't know 52 | // what the expected value should be for each test output). 53 | "stTransactionTest/HighGasPrice", 54 | "stCreateTest/CreateTransactionHighNonce", 55 | ]; 56 | 57 | fn should_skip(path: &Path) -> bool { 58 | let matches = |case: &str| { 59 | let file_stem = path.file_stem().unwrap(); 60 | let dir_path = path.parent().unwrap(); 61 | let dir_name = dir_path.file_name().unwrap(); 62 | Path::new(dir_name).join(file_stem) == Path::new(case) 63 | }; 64 | 65 | for case in SKIPPED_CASES { 66 | if matches(case) { 67 | return true; 68 | } 69 | } 70 | 71 | false 72 | } 73 | 74 | #[test] 75 | fn st_args_zero_one_balance() { 76 | run("res/ethtests/GeneralStateTests/stArgsZeroOneBalance") 77 | } 78 | #[test] 79 | fn st_attack() { 80 | run("res/ethtests/GeneralStateTests/stAttackTest") 81 | } 82 | #[test] 83 | fn st_bad_opcode() { 84 | run("res/ethtests/GeneralStateTests/stBadOpcode") 85 | } 86 | #[test] 87 | fn st_bugs() { 88 | run("res/ethtests/GeneralStateTests/stBugs") 89 | } 90 | #[test] 91 | fn st_call_code() { 92 | run("res/ethtests/GeneralStateTests/stCallCodes") 93 | } 94 | #[test] 95 | fn st_call_create_call_code() { 96 | run("res/ethtests/GeneralStateTests/stCallCreateCallCodeTest") 97 | } 98 | #[test] 99 | fn st_call_delegate_codes_call_code_homestead() { 100 | run("res/ethtests/GeneralStateTests/stCallDelegateCodesCallCodeHomestead") 101 | } 102 | #[test] 103 | fn st_call_delegate_codes_homestead() { 104 | run("res/ethtests/GeneralStateTests/stCallDelegateCodesHomestead") 105 | } 106 | #[test] 107 | fn st_chain_id() { 108 | run("res/ethtests/GeneralStateTests/stChainId") 109 | } 110 | #[test] 111 | fn st_code_copy() { 112 | run("res/ethtests/GeneralStateTests/stCodeCopyTest") 113 | } 114 | #[test] 115 | fn st_code_size_limit() { 116 | run("res/ethtests/GeneralStateTests/stCodeSizeLimit") 117 | } 118 | #[test] 119 | #[ignore] 120 | fn st_create2() { 121 | run("res/ethtests/GeneralStateTests/stCreate2") 122 | } 123 | #[test] 124 | fn st_create() { 125 | run("res/ethtests/GeneralStateTests/stCreateTest") 126 | } 127 | #[test] 128 | fn st_delegate_call_homestead() { 129 | run("res/ethtests/GeneralStateTests/stDelegatecallTestHomestead") 130 | } 131 | #[test] 132 | fn st_eip150_single_code_gas_prices() { 133 | run("res/ethtests/GeneralStateTests/stEIP150singleCodeGasPrices") 134 | } 135 | #[test] 136 | fn st_eip150_specific() { 137 | run("res/ethtests/GeneralStateTests/stEIP150Specific") 138 | } 139 | #[test] 140 | fn st_eip1559() { 141 | run("res/ethtests/GeneralStateTests/stEIP1559") 142 | } 143 | #[test] 144 | fn st_eip158_specific() { 145 | run("res/ethtests/GeneralStateTests/stEIP158Specific") 146 | } 147 | #[test] 148 | fn st_eip2930() { 149 | run("res/ethtests/GeneralStateTests/stEIP2930") 150 | } 151 | #[test] 152 | fn st_example() { 153 | run("res/ethtests/GeneralStateTests/stExample") 154 | } 155 | #[test] 156 | fn st_ext_code_hash() { 157 | run("res/ethtests/GeneralStateTests/stExtCodeHash") 158 | } 159 | #[test] 160 | fn st_homestead_specific() { 161 | run("res/ethtests/GeneralStateTests/stHomesteadSpecific") 162 | } 163 | #[test] 164 | fn st_init_code() { 165 | run("res/ethtests/GeneralStateTests/stInitCodeTest") 166 | } 167 | #[test] 168 | fn st_log() { 169 | run("res/ethtests/GeneralStateTests/stLogTests") 170 | } 171 | #[test] 172 | fn st_mem_expanding_eip_150_calls() { 173 | run("res/ethtests/GeneralStateTests/stMemExpandingEIP150Calls") 174 | } 175 | #[test] 176 | fn st_memory_stress() { 177 | run("res/ethtests/GeneralStateTests/stMemoryStressTest") 178 | } 179 | #[test] 180 | fn st_memory() { 181 | run("res/ethtests/GeneralStateTests/stMemoryTest") 182 | } 183 | #[test] 184 | fn st_non_zero_calls() { 185 | run("res/ethtests/GeneralStateTests/stNonZeroCallsTest") 186 | } 187 | #[test] 188 | fn st_precompiled_contracts() { 189 | run("res/ethtests/GeneralStateTests/stPreCompiledContracts") 190 | } 191 | #[test] 192 | #[ignore] 193 | fn st_precompiled_contracts2() { 194 | run("res/ethtests/GeneralStateTests/stPreCompiledContracts2") 195 | } 196 | #[test] 197 | #[ignore] 198 | fn st_quadratic_complexity() { 199 | run("res/ethtests/GeneralStateTests/stQuadraticComplexityTest") 200 | } 201 | #[test] 202 | fn st_random() { 203 | run("res/ethtests/GeneralStateTests/stRandom") 204 | } 205 | #[test] 206 | fn st_random2() { 207 | run("res/ethtests/GeneralStateTests/stRandom2") 208 | } 209 | #[test] 210 | fn st_recursive_create() { 211 | run("res/ethtests/GeneralStateTests/stRecursiveCreate") 212 | } 213 | #[test] 214 | fn st_refund() { 215 | run("res/ethtests/GeneralStateTests/stRefundTest") 216 | } 217 | #[test] 218 | fn st_return_data() { 219 | run("res/ethtests/GeneralStateTests/stReturnDataTest") 220 | } 221 | #[test] 222 | #[ignore] 223 | fn st_revert() { 224 | run("res/ethtests/GeneralStateTests/stRevertTest") 225 | } 226 | #[test] 227 | fn st_self_balance() { 228 | run("res/ethtests/GeneralStateTests/stSelfBalance") 229 | } 230 | #[test] 231 | fn st_shift() { 232 | run("res/ethtests/GeneralStateTests/stShift") 233 | } 234 | #[test] 235 | fn st_sload() { 236 | run("res/ethtests/GeneralStateTests/stSLoadTest") 237 | } 238 | #[test] 239 | fn st_solidity() { 240 | run("res/ethtests/GeneralStateTests/stSolidityTest") 241 | } 242 | #[test] 243 | #[ignore] 244 | fn st_special() { 245 | run("res/ethtests/GeneralStateTests/stSpecialTest") 246 | } 247 | // Some of the collison test in sstore conflicts with evm's internal 248 | // handlings. Those situations will never happen on a production chain (an empty 249 | // account with storage values), so we can safely ignore them. 250 | #[test] 251 | #[ignore] 252 | fn st_sstore() { 253 | run("res/ethtests/GeneralStateTests/stSStoreTest") 254 | } 255 | #[test] 256 | fn st_stack() { 257 | run("res/ethtests/GeneralStateTests/stStackTests") 258 | } 259 | #[test] 260 | #[ignore] 261 | fn st_static_call() { 262 | run("res/ethtests/GeneralStateTests/stStaticCall") 263 | } 264 | #[test] 265 | fn st_system_operations() { 266 | run("res/ethtests/GeneralStateTests/stSystemOperationsTest") 267 | } 268 | #[test] 269 | fn st_transaction() { 270 | run("res/ethtests/GeneralStateTests/stTransactionTest") 271 | } 272 | #[test] 273 | fn st_transition() { 274 | run("res/ethtests/GeneralStateTests/stTransitionTest") 275 | } 276 | #[test] 277 | fn st_wallet() { 278 | run("res/ethtests/GeneralStateTests/stWalletTest") 279 | } 280 | #[test] 281 | fn st_zero_calls_revert() { 282 | run("res/ethtests/GeneralStateTests/stZeroCallsRevert"); 283 | } 284 | #[test] 285 | fn st_zero_calls() { 286 | run("res/ethtests/GeneralStateTests/stZeroCallsTest") 287 | } 288 | #[test] 289 | fn st_zero_knowledge() { 290 | run("res/ethtests/GeneralStateTests/stZeroKnowledge") 291 | } 292 | #[test] 293 | fn st_zero_knowledge2() { 294 | run("res/ethtests/GeneralStateTests/stZeroKnowledge2") 295 | } 296 | -------------------------------------------------------------------------------- /jsontests/tests/vm.rs: -------------------------------------------------------------------------------- 1 | use evm_jsontests::vm as vmtests; 2 | use std::collections::HashMap; 3 | use std::fs::{self, File}; 4 | use std::io::BufReader; 5 | use std::path::PathBuf; 6 | 7 | pub fn run(dir: &str) { 8 | let _ = env_logger::try_init(); 9 | 10 | let mut dest = PathBuf::from(env!("CARGO_MANIFEST_DIR")); 11 | dest.push(dir); 12 | 13 | for entry in fs::read_dir(dest).unwrap() { 14 | let entry = entry.unwrap(); 15 | let path = entry.path(); 16 | 17 | let file = File::open(path).expect("Open file failed"); 18 | 19 | let reader = BufReader::new(file); 20 | let coll = serde_json::from_reader::<_, HashMap>(reader) 21 | .expect("Parse test cases failed"); 22 | 23 | for (name, test) in coll { 24 | vmtests::test(&name, test); 25 | } 26 | } 27 | } 28 | 29 | // TODO: upgrade to GeneralStateTests/VMTests instead of using LegacyTests version 30 | #[test] 31 | fn vm_arithmetic() { 32 | run("res/ethtests/LegacyTests/Constantinople/VMTests/vmArithmeticTest"); 33 | } 34 | #[test] 35 | fn vm_bitwise_logic() { 36 | run("res/ethtests/LegacyTests/Constantinople/VMTests/vmBitwiseLogicOperation"); 37 | } 38 | #[test] 39 | fn vm_block_info() { 40 | run("res/ethtests/LegacyTests/Constantinople/VMTests/vmBlockInfoTest"); 41 | } 42 | #[test] 43 | fn vm_environmental_info() { 44 | run("res/ethtests/LegacyTests/Constantinople/VMTests/vmEnvironmentalInfo"); 45 | } 46 | #[test] 47 | fn vm_io_and_flow() { 48 | run("res/ethtests/LegacyTests/Constantinople/VMTests/vmIOandFlowOperations"); 49 | } 50 | #[test] 51 | fn vm_log() { 52 | run("res/ethtests/LegacyTests/Constantinople/VMTests/vmLogTest"); 53 | } 54 | #[test] 55 | #[ignore] 56 | fn vm_performance() { 57 | run("res/ethtests/LegacyTests/Constantinople/VMTests/vmPerformance"); 58 | } 59 | #[test] 60 | fn vm_push_dup_swap() { 61 | run("res/ethtests/LegacyTests/Constantinople/VMTests/vmPushDupSwapTest"); 62 | } 63 | #[test] 64 | fn vm_random() { 65 | run("res/ethtests/LegacyTests/Constantinople/VMTests/vmRandomTest"); 66 | } 67 | #[test] 68 | fn vm_sha3() { 69 | run("res/ethtests/LegacyTests/Constantinople/VMTests/vmSha3Test"); 70 | } 71 | #[test] 72 | fn vm_system() { 73 | run("res/ethtests/LegacyTests/Constantinople/VMTests/vmSystemOperations"); 74 | } 75 | #[test] 76 | fn vm_other() { 77 | run("res/ethtests/LegacyTests/Constantinople/VMTests/vmTests"); 78 | } 79 | -------------------------------------------------------------------------------- /rustfmt.toml: -------------------------------------------------------------------------------- 1 | hard_tabs = true 2 | --------------------------------------------------------------------------------