1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139
// Copyright 2015-2018 Parity Technologies (UK) Ltd.
// This file is part of Parity.
// Parity is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// Parity is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
// Copyright 2019 Conflux Foundation. All rights reserved.
// Conflux is free software and distributed under GNU General Public License.
// See http://www.gnu.org/licenses/
//! Evm factory.
use super::{interpreter::SharedCache, vmtype::VMType};
use cfx_types::U256;
#[cfg(test)]
use cfx_vm_types::CallType;
use cfx_vm_types::{ActionParams, Exec, Spec};
use std::sync::Arc;
/// Evm factory. Creates appropriate Evm.
#[derive(Clone)]
pub struct Factory {
evm: VMType,
evm_cache: Arc<SharedCache<false>>,
evm_cache_cancun: Arc<SharedCache<true>>,
}
impl Factory {
/// Create fresh instance of VM
/// Might choose implementation depending on supplied gas.
pub fn create(
&self, params: ActionParams, spec: &Spec, depth: usize,
) -> Box<dyn Exec> {
use super::interpreter::Interpreter;
// Assert there is only one type. Parity Ethereum is dead and no more
// types will be added.
match self.evm {
VMType::Interpreter => {}
};
match (Self::can_fit_in_usize(¶ms.gas), spec.cancun_opcodes) {
(true, true) => Box::new(Interpreter::<usize, true>::new(
params,
self.evm_cache_cancun.clone(),
spec,
depth,
)),
(true, false) => Box::new(Interpreter::<usize, false>::new(
params,
self.evm_cache.clone(),
spec,
depth,
)),
(false, true) => Box::new(Interpreter::<U256, true>::new(
params,
self.evm_cache_cancun.clone(),
spec,
depth,
)),
(false, false) => Box::new(Interpreter::<U256, false>::new(
params,
self.evm_cache.clone(),
spec,
depth,
)),
}
}
/// Create new instance of specific `VMType` factory, with a size in bytes
/// for caching jump destinations.
pub fn new(evm: VMType, cache_size: usize) -> Self {
Factory {
evm,
evm_cache: Arc::new(SharedCache::new(cache_size)),
evm_cache_cancun: Arc::new(SharedCache::new(cache_size)),
}
}
fn can_fit_in_usize(gas: &U256) -> bool {
gas == &U256::from(gas.low_u64() as usize)
}
}
impl Default for Factory {
/// Returns native rust evm factory
fn default() -> Factory {
Factory {
evm: VMType::Interpreter,
evm_cache: Arc::new(SharedCache::default()),
evm_cache_cancun: Arc::new(SharedCache::default()),
}
}
}
#[test]
fn test_create_vm() {
use cfx_bytes::Bytes;
use cfx_vm_types::{tests::MockContext, Context};
let mut params = ActionParams::default();
params.call_type = CallType::None;
params.code = Some(Arc::new(Bytes::default()));
let context = MockContext::new();
let _vm =
Factory::default().create(params, context.spec(), context.depth());
}
/// Create tests by injecting different VM factories
#[macro_export]
macro_rules! evm_test(
($name_test: ident: $name_int: ident) => {
#[test]
fn $name_int() {
$name_test(Factory::new(VMType::Interpreter, 1024 * 32));
}
}
);
/// Create ignored tests by injecting different VM factories
#[macro_export]
macro_rules! evm_test_ignore(
($name_test: ident: $name_int: ident) => {
#[test]
#[ignore]
#[cfg(feature = "ignored-tests")]
fn $name_int() {
$name_test(Factory::new(VMType::Interpreter, 1024 * 32));
}
}
);