From edaf24a2ce230a2adf85ae1ab39a0bad80001b0e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 11 Jul 2016 12:15:22 +0200 Subject: [PATCH 1/6] EVM bin benches --- evmbin/Cargo.toml | 8 ++++++ evmbin/benches/mod.rs | 61 +++++++++++++++++++++++++++++++++++++++++++ evmbin/src/main.rs | 29 +++++++++++++++++--- 3 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 evmbin/benches/mod.rs diff --git a/evmbin/Cargo.toml b/evmbin/Cargo.toml index 3e531f5d3..8ec687687 100644 --- a/evmbin/Cargo.toml +++ b/evmbin/Cargo.toml @@ -4,6 +4,14 @@ description = "Parity's EVM implementation" version = "0.1.0" authors = ["Ethcore "] +[lib] +name = "evm" +path = "./src/main.rs" + +[[bin]] +name = "evm" +path = "./src/main.rs" + [dependencies] rustc-serialize = "0.3" docopt = { version = "0.6" } diff --git a/evmbin/benches/mod.rs b/evmbin/benches/mod.rs new file mode 100644 index 000000000..3013a170a --- /dev/null +++ b/evmbin/benches/mod.rs @@ -0,0 +1,61 @@ +// Copyright 2015, 2016 Ethcore (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 . + +//! benchmarking for EVM +//! should be started with: +//! ```bash +//! multirust run nightly cargo bench +//! ``` + +#![feature(test)] + +extern crate test; +extern crate ethcore; +extern crate evm; +extern crate ethcore_util; +extern crate rustc_serialize; + +use self::test::{Bencher, black_box}; + +use evm::run_vm; +use ethcore::action_params::ActionParams; +use ethcore_util::{U256, Uint}; +use rustc_serialize::hex::FromHex; + +#[bench] +fn simple_loop_usize(b: &mut Bencher) { + simple_loop(U256::from(::std::usize::MAX), b) +} + +#[bench] +fn simple_loop_u256(b: &mut Bencher) { + simple_loop(!U256::zero(), b) +} + +fn simple_loop(gas: U256, b: &mut Bencher) { + let code = black_box( + "606060405260005b620f42408112156019575b6001016007565b600081905550600680602b6000396000f3606060405200".from_hex().unwrap() + ); + + b.iter(|| { + let mut params = ActionParams::default(); + params.gas = gas; + params.code = Some(code.clone()); + + run_vm(params) + }); +} + diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index 3fa06d004..240a02ccf 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -25,7 +25,7 @@ extern crate ethcore_util as util; mod ext; -use std::time::Instant; +use std::time::{Instant, Duration}; use std::str::FromStr; use docopt::Docopt; use util::{U256, FromHex, Uint, Bytes}; @@ -58,6 +58,15 @@ fn main() { params.code = Some(args.code()); params.data = args.data(); + let result = run_vm(params); + println!("Gas used: {:?}", result.gas_used); + println!("Output: {:?}", result.output); + println!("Time: {}.{:.9}s", result.time.as_secs(), result.time.subsec_nanos()); +} + +/// Execute VM with given `ActionParams` +pub fn run_vm(params: ActionParams) -> ExecutionResults { + let initial_gas = params.gas; let factory = Factory::new(VMType::Interpreter); let mut vm = factory.create(params.gas); let mut ext = ext::FakeExt::default(); @@ -66,9 +75,21 @@ fn main() { let gas_left = vm.exec(params, &mut ext).finalize(ext).expect("OK"); let duration = start.elapsed(); - println!("Gas used: {:?}", args.gas() - gas_left); - println!("Output: {:?}", ""); - println!("Time: {}.{:.9}s", duration.as_secs(), duration.subsec_nanos()); + ExecutionResults { + gas_used: initial_gas - gas_left, + output: Vec::new(), + time: duration, + } +} + +/// VM execution results +pub struct ExecutionResults { + /// Used gas + pub gas_used: U256, + /// Output as bytes + pub output: Vec, + /// Time Taken + pub time: Duration, } #[derive(Debug, RustcDecodable)] From f1edd3d6834b6fa8c7cd9921b9e567e281db64aa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 11 Jul 2016 12:51:31 +0200 Subject: [PATCH 2/6] Optimizing mem gas cost --- ethcore/src/evm/evm.rs | 70 ++++++++++++++++++++++++ ethcore/src/evm/interpreter/gasometer.rs | 18 +++--- evmbin/src/main.rs | 1 + 3 files changed, 79 insertions(+), 10 deletions(-) diff --git a/ethcore/src/evm/evm.rs b/ethcore/src/evm/evm.rs index 3ec943f18..a300650f3 100644 --- a/ethcore/src/evm/evm.rs +++ b/ethcore/src/evm/evm.rs @@ -107,6 +107,11 @@ pub trait CostType: ops::Mul + ops::Div + ops::Add (Self, bool); /// Multiple with overflow fn overflow_mul(self, other: Self) -> (Self, bool); + /// Divide with overflow + fn overflow_div(self, other: Self) -> (Self, bool); + /// Single-step full multiplication and division: `self*other/div` + /// Should not overflow on intermediate steps + fn overflow_mul_div(self, other: Self, div: Self) -> (Self, bool); } impl CostType for U256 { @@ -129,6 +134,21 @@ impl CostType for U256 { fn overflow_mul(self, other: Self) -> (Self, bool) { Uint::overflowing_mul(self, other) } + + fn overflow_div(self, other: Self) -> (Self, bool) { + Uint::overflowing_div(self, other) + } + + fn overflow_mul_div(self, other: Self, div: Self) -> (Self, bool) { + let x = self.full_mul(other); + let (U512(parts), o) = Uint::overflowing_div(x, U512::from(div)); + let overflow = (parts[4] | parts[5] | parts[6] | parts[7]) > 0; + + ( + U256([parts[0], parts[1], parts[2], parts[3]]), + o | overflow + ) + } } impl CostType for usize { @@ -154,6 +174,18 @@ impl CostType for usize { fn overflow_mul(self, other: Self) -> (Self, bool) { self.overflowing_mul(other) } + + fn overflow_div(self, other: Self) -> (Self, bool) { + self.overflowing_div(other) + } + + fn overflow_mul_div(self, other: Self, div: Self) -> (Self, bool) { + let (c, o) = U128::from(self).overflowing_mul(U128::from(other)); + let (U128(parts), o1) = c.overflowing_div(U128::from(div)); + let result = parts[0] as usize; + let overflow = o | o1 | (parts[1] > 0) | (parts[0] > result as u64); + (result, overflow) + } } /// Evm interface @@ -164,3 +196,41 @@ pub trait Evm { /// to compute the final gas left. fn exec(&mut self, params: ActionParams, ext: &mut Ext) -> Result; } + + +#[test] +fn should_calculate_overflow_mul_div_without_overflow() { + // given + let num = 10_000_000; + + // when + let (res1, o1) = U256::from(num).overflow_mul_div(U256::from(num), U256::from(num)); + let (res2, o2) = num.overflow_mul_div(num, num); + + // then + assert_eq!(res1, U256::from(num)); + assert!(!o1); + assert_eq!(res2, num); + assert!(!o2); +} + +#[test] +fn should_calculate_overflow_mul_div_with_overflow() { + // given + let max = ::std::u64::MAX; + let num1 = U256([max, max, max, max]); + let num2 = ::std::usize::MAX; + + // when + let (res1, o1) = num1.overflow_mul_div(num1, num1 - U256::from(2)); + let (res2, o2) = num2.overflow_mul_div(num2, num2 - 2); + + // then + // (x+2)^2/x = (x^2 + 4x + 4)/x = x + 4 + 4/x ~ (MAX-2) + 4 + 0 = 1 + assert_eq!(res2, 1); + assert!(o2); + + assert_eq!(res1, U256::from(1)); + assert!(o1); +} + diff --git a/ethcore/src/evm/interpreter/gasometer.rs b/ethcore/src/evm/interpreter/gasometer.rs index 069d70e19..0fc349a27 100644 --- a/ethcore/src/evm/interpreter/gasometer.rs +++ b/ethcore/src/evm/interpreter/gasometer.rs @@ -68,6 +68,9 @@ impl Gasometer { let default_gas = Gas::from(schedule.tier_step_gas[tier]); let cost = match instruction { + instructions::JUMPDEST => { + InstructionCost::Gas(Gas::from(1)) + }, instructions::SSTORE => { let address = H256::from(stack.peek(0)); let newval = stack.peek(1); @@ -106,9 +109,6 @@ impl Gasometer { instructions::EXTCODECOPY => { InstructionCost::GasMemCopy(default_gas, try!(self.mem_needed(stack.peek(1), stack.peek(3))), try!(Gas::from_u256(*stack.peek(3)))) }, - instructions::JUMPDEST => { - InstructionCost::Gas(Gas::from(1)) - }, instructions::LOG0...instructions::LOG4 => { let no_of_topics = instructions::get_log_topics(instruction); let log_gas = schedule.log_gas + schedule.log_topic_gas * no_of_topics; @@ -199,14 +199,12 @@ impl Gasometer { let s = mem_size >> 5; // s * memory_gas + s * s / quad_coeff_div let a = overflowing!(s.overflow_mul(Gas::from(schedule.memory_gas))); - // We need to go to U512 to calculate s*s/quad_coeff_div - let b = U512::from(s.as_u256()) * U512::from(s.as_u256()) / U512::from(schedule.quad_coeff_div); - if b > U512::from(!U256::zero()) { - Err(evm::Error::OutOfGas) - } else { - Ok(overflowing!(a.overflow_add(try!(Gas::from_u256(U256::from(b)))))) - } + + // Calculate s*s/quad_coeff_div + let b = overflowing!(s.overflow_mul_div(s, Gas::from(schedule.quad_coeff_div))); + Ok(overflowing!(a.overflow_add(b))) }; + let current_mem_size = Gas::from(current_mem_size); let req_mem_size_rounded = (overflowing!(mem_size.overflow_add(Gas::from(31 as usize))) >> 5) << 5; diff --git a/evmbin/src/main.rs b/evmbin/src/main.rs index 240a02ccf..94684129c 100644 --- a/evmbin/src/main.rs +++ b/evmbin/src/main.rs @@ -17,6 +17,7 @@ //! Parity EVM interpreter binary. #![warn(missing_docs)] +#![allow(dead_code)] extern crate ethcore; extern crate rustc_serialize; extern crate docopt; From cca4efb861002e44b466ad015c56989f547d75b0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 11 Jul 2016 14:52:56 +0200 Subject: [PATCH 3/6] Removing overflow_div since it's not used --- ethcore/src/evm/evm.rs | 10 ---------- 1 file changed, 10 deletions(-) diff --git a/ethcore/src/evm/evm.rs b/ethcore/src/evm/evm.rs index a300650f3..77b57bf69 100644 --- a/ethcore/src/evm/evm.rs +++ b/ethcore/src/evm/evm.rs @@ -107,8 +107,6 @@ pub trait CostType: ops::Mul + ops::Div + ops::Add (Self, bool); /// Multiple with overflow fn overflow_mul(self, other: Self) -> (Self, bool); - /// Divide with overflow - fn overflow_div(self, other: Self) -> (Self, bool); /// Single-step full multiplication and division: `self*other/div` /// Should not overflow on intermediate steps fn overflow_mul_div(self, other: Self, div: Self) -> (Self, bool); @@ -135,10 +133,6 @@ impl CostType for U256 { Uint::overflowing_mul(self, other) } - fn overflow_div(self, other: Self) -> (Self, bool) { - Uint::overflowing_div(self, other) - } - fn overflow_mul_div(self, other: Self, div: Self) -> (Self, bool) { let x = self.full_mul(other); let (U512(parts), o) = Uint::overflowing_div(x, U512::from(div)); @@ -175,10 +169,6 @@ impl CostType for usize { self.overflowing_mul(other) } - fn overflow_div(self, other: Self) -> (Self, bool) { - self.overflowing_div(other) - } - fn overflow_mul_div(self, other: Self, div: Self) -> (Self, bool) { let (c, o) = U128::from(self).overflowing_mul(U128::from(other)); let (U128(parts), o1) = c.overflowing_div(U128::from(div)); From fbdde8f0e67a1a2dc6a9ed9c9bf31fbba4b0b13d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 11 Jul 2016 16:17:30 +0200 Subject: [PATCH 4/6] More benchmarks --- evmbin/bench.sh | 24 ++++++++++++++++++++++++ evmbin/benches/mod.rs | 26 +++++++++++++++++++++++++- 2 files changed, 49 insertions(+), 1 deletion(-) create mode 100755 evmbin/bench.sh diff --git a/evmbin/bench.sh b/evmbin/bench.sh new file mode 100755 index 000000000..a7d5557cb --- /dev/null +++ b/evmbin/bench.sh @@ -0,0 +1,24 @@ +#!/bin/bash + +set -x +set -e + +cargo build --release + +# LOOP TEST +CODE1=606060405260005b620f42408112156019575b6001016007565b600081905550600680602b6000396000f3606060405200 +ethvm --code $CODE1 +echo "^^^^ ethvm" +./target/release/evm stats --code $CODE1 --gas 4402000 +echo "^^^^ usize" +./target/release/evm stats --code $CODE1 +echo "^^^^ U256" + +# RNG TEST +CODE2=6060604052600360056007600b60005b620f4240811215607f5767ffe7649d5eca84179490940267f47ed85c4b9a6379019367f8e5dd9a5c994bba9390930267f91d87e4b8b74e55019267ff97f6f3b29cda529290920267f393ada8dd75c938019167fe8d437c45bb3735830267f47d9a7b5428ffec019150600101600f565b838518831882186000555050505050600680609a6000396000f3606060405200 +ethvm --code $CODE2 +echo "^^^^ ethvm" +./target/release/evm stats --code $CODE2 --gas 143020115 +echo "^^^^ usize" +./target/release/evm stats --code $CODE2 +echo "^^^^ U256" diff --git a/evmbin/benches/mod.rs b/evmbin/benches/mod.rs index 3013a170a..3013dca54 100644 --- a/evmbin/benches/mod.rs +++ b/evmbin/benches/mod.rs @@ -47,7 +47,31 @@ fn simple_loop_u256(b: &mut Bencher) { fn simple_loop(gas: U256, b: &mut Bencher) { let code = black_box( - "606060405260005b620f42408112156019575b6001016007565b600081905550600680602b6000396000f3606060405200".from_hex().unwrap() + "606060405260005b620042408112156019575b6001016007565b600081905550600680602b6000396000f3606060405200".from_hex().unwrap() + ); + + b.iter(|| { + let mut params = ActionParams::default(); + params.gas = gas; + params.code = Some(code.clone()); + + run_vm(params) + }); +} + +#[bench] +fn rng_usize(b: &mut Bencher) { + rng(U256::from(::std::usize::MAX), b) +} + +#[bench] +fn rng_u256(b: &mut Bencher) { + rng(!U256::zero(), b) +} + +fn rng(gas: U256, b: &mut Bencher) { + let code = black_box( + "6060604052600360056007600b60005b62004240811215607f5767ffe7649d5eca84179490940267f47ed85c4b9a6379019367f8e5dd9a5c994bba9390930267f91d87e4b8b74e55019267ff97f6f3b29cda529290920267f393ada8dd75c938019167fe8d437c45bb3735830267f47d9a7b5428ffec019150600101600f565b838518831882186000555050505050600680609a6000396000f3606060405200".from_hex().unwrap() ); b.iter(|| { From 2d5d632d7418871086ab97712654b85415d11908 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Mon, 11 Jul 2016 16:18:27 +0200 Subject: [PATCH 5/6] Optimizing instruction info --- ethcore/src/evm/instructions.rs | 283 +++++++++++++++++--------------- 1 file changed, 147 insertions(+), 136 deletions(-) diff --git a/ethcore/src/evm/instructions.rs b/ethcore/src/evm/instructions.rs index 9a1ea97cc..9e7527fa3 100644 --- a/ethcore/src/evm/instructions.rs +++ b/ethcore/src/evm/instructions.rs @@ -101,6 +101,12 @@ pub enum GasPriceTier { Invalid } +impl Default for GasPriceTier { + fn default() -> Self { + GasPriceTier::Invalid + } +} + /// Returns the index in schedule for specific `GasPriceTier` pub fn get_tier_idx (tier: GasPriceTier) -> usize { match tier { @@ -116,6 +122,7 @@ pub fn get_tier_idx (tier: GasPriceTier) -> usize { } } +#[derive(Copy, Clone, Default)] pub struct InstructionInfo { pub name: &'static str, pub additional: usize, @@ -126,7 +133,7 @@ pub struct InstructionInfo { } impl InstructionInfo { - pub fn new(name: &'static str, additional: usize, args: usize, ret: usize, side_effects: bool, tier: GasPriceTier) -> InstructionInfo { + pub fn new(name: &'static str, additional: usize, args: usize, ret: usize, side_effects: bool, tier: GasPriceTier) -> Self { InstructionInfo { name: name, additional: additional, @@ -138,142 +145,146 @@ impl InstructionInfo { } } -#[cfg_attr(rustfmt, rustfmt_skip)] +lazy_static! { + static ref INSTRUCTIONS: [InstructionInfo; 0x100] = { + let mut arr = [InstructionInfo::default(); 0x100]; + arr[STOP as usize] = InstructionInfo::new("STOP", 0, 0, 0, true, GasPriceTier::Zero); + arr[ADD as usize] = InstructionInfo::new("ADD", 0, 2, 1, false, GasPriceTier::VeryLow); + arr[SUB as usize] = InstructionInfo::new("SUB", 0, 2, 1, false, GasPriceTier::VeryLow); + arr[MUL as usize] = InstructionInfo::new("MUL", 0, 2, 1, false, GasPriceTier::Low); + arr[DIV as usize] = InstructionInfo::new("DIV", 0, 2, 1, false, GasPriceTier::Low); + arr[SDIV as usize] = InstructionInfo::new("SDIV", 0, 2, 1, false, GasPriceTier::Low); + arr[MOD as usize] = InstructionInfo::new("MOD", 0, 2, 1, false, GasPriceTier::Low); + arr[SMOD as usize] = InstructionInfo::new("SMOD", 0, 2, 1, false, GasPriceTier::Low); + arr[EXP as usize] = InstructionInfo::new("EXP", 0, 2, 1, false, GasPriceTier::Special); + arr[NOT as usize] = InstructionInfo::new("NOT", 0, 1, 1, false, GasPriceTier::VeryLow); + arr[LT as usize] = InstructionInfo::new("LT", 0, 2, 1, false, GasPriceTier::VeryLow); + arr[GT as usize] = InstructionInfo::new("GT", 0, 2, 1, false, GasPriceTier::VeryLow); + arr[SLT as usize] = InstructionInfo::new("SLT", 0, 2, 1, false, GasPriceTier::VeryLow); + arr[SGT as usize] = InstructionInfo::new("SGT", 0, 2, 1, false, GasPriceTier::VeryLow); + arr[EQ as usize] = InstructionInfo::new("EQ", 0, 2, 1, false, GasPriceTier::VeryLow); + arr[ISZERO as usize] = InstructionInfo::new("ISZERO", 0, 1, 1, false, GasPriceTier::VeryLow); + arr[AND as usize] = InstructionInfo::new("AND", 0, 2, 1, false, GasPriceTier::VeryLow); + arr[OR as usize] = InstructionInfo::new("OR", 0, 2, 1, false, GasPriceTier::VeryLow); + arr[XOR as usize] = InstructionInfo::new("XOR", 0, 2, 1, false, GasPriceTier::VeryLow); + arr[BYTE as usize] = InstructionInfo::new("BYTE", 0, 2, 1, false, GasPriceTier::VeryLow); + arr[ADDMOD as usize] = InstructionInfo::new("ADDMOD", 0, 3, 1, false, GasPriceTier::Mid); + arr[MULMOD as usize] = InstructionInfo::new("MULMOD", 0, 3, 1, false, GasPriceTier::Mid); + arr[SIGNEXTEND as usize] = InstructionInfo::new("SIGNEXTEND", 0, 2, 1, false, GasPriceTier::Low); + arr[SHA3 as usize] = InstructionInfo::new("SHA3", 0, 2, 1, false, GasPriceTier::Special); + arr[ADDRESS as usize] = InstructionInfo::new("ADDRESS", 0, 0, 1, false, GasPriceTier::Base); + arr[BALANCE as usize] = InstructionInfo::new("BALANCE", 0, 1, 1, false, GasPriceTier::Ext); + arr[ORIGIN as usize] = InstructionInfo::new("ORIGIN", 0, 0, 1, false, GasPriceTier::Base); + arr[CALLER as usize] = InstructionInfo::new("CALLER", 0, 0, 1, false, GasPriceTier::Base); + arr[CALLVALUE as usize] = InstructionInfo::new("CALLVALUE", 0, 0, 1, false, GasPriceTier::Base); + arr[CALLDATALOAD as usize] = InstructionInfo::new("CALLDATALOAD", 0, 1, 1, false, GasPriceTier::VeryLow); + arr[CALLDATASIZE as usize] = InstructionInfo::new("CALLDATASIZE", 0, 0, 1, false, GasPriceTier::Base); + arr[CALLDATACOPY as usize] = InstructionInfo::new("CALLDATACOPY", 0, 3, 0, true, GasPriceTier::VeryLow); + arr[CODESIZE as usize] = InstructionInfo::new("CODESIZE", 0, 0, 1, false, GasPriceTier::Base); + arr[CODECOPY as usize] = InstructionInfo::new("CODECOPY", 0, 3, 0, true, GasPriceTier::VeryLow); + arr[GASPRICE as usize] = InstructionInfo::new("GASPRICE", 0, 0, 1, false, GasPriceTier::Base); + arr[EXTCODESIZE as usize] = InstructionInfo::new("EXTCODESIZE", 0, 1, 1, false, GasPriceTier::Ext); + arr[EXTCODECOPY as usize] = InstructionInfo::new("EXTCODECOPY", 0, 4, 0, true, GasPriceTier::Ext); + arr[BLOCKHASH as usize] = InstructionInfo::new("BLOCKHASH", 0, 1, 1, false, GasPriceTier::Ext); + arr[COINBASE as usize] = InstructionInfo::new("COINBASE", 0, 0, 1, false, GasPriceTier::Base); + arr[TIMESTAMP as usize] = InstructionInfo::new("TIMESTAMP", 0, 0, 1, false, GasPriceTier::Base); + arr[NUMBER as usize] = InstructionInfo::new("NUMBER", 0, 0, 1, false, GasPriceTier::Base); + arr[DIFFICULTY as usize] = InstructionInfo::new("DIFFICULTY", 0, 0, 1, false, GasPriceTier::Base); + arr[GASLIMIT as usize] = InstructionInfo::new("GASLIMIT", 0, 0, 1, false, GasPriceTier::Base); + arr[POP as usize] = InstructionInfo::new("POP", 0, 1, 0, false, GasPriceTier::Base); + arr[MLOAD as usize] = InstructionInfo::new("MLOAD", 0, 1, 1, false, GasPriceTier::VeryLow); + arr[MSTORE as usize] = InstructionInfo::new("MSTORE", 0, 2, 0, true, GasPriceTier::VeryLow); + arr[MSTORE8 as usize] = InstructionInfo::new("MSTORE8", 0, 2, 0, true, GasPriceTier::VeryLow); + arr[SLOAD as usize] = InstructionInfo::new("SLOAD", 0, 1, 1, false, GasPriceTier::Special); + arr[SSTORE as usize] = InstructionInfo::new("SSTORE", 0, 2, 0, true, GasPriceTier::Special); + arr[JUMP as usize] = InstructionInfo::new("JUMP", 0, 1, 0, true, GasPriceTier::Mid); + arr[JUMPI as usize] = InstructionInfo::new("JUMPI", 0, 2, 0, true, GasPriceTier::High); + arr[PC as usize] = InstructionInfo::new("PC", 0, 0, 1, false, GasPriceTier::Base); + arr[MSIZE as usize] = InstructionInfo::new("MSIZE", 0, 0, 1, false, GasPriceTier::Base); + arr[GAS as usize] = InstructionInfo::new("GAS", 0, 0, 1, false, GasPriceTier::Base); + arr[JUMPDEST as usize] = InstructionInfo::new("JUMPDEST", 0, 0, 0, true, GasPriceTier::Special); + arr[PUSH1 as usize] = InstructionInfo::new("PUSH1", 1, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH2 as usize] = InstructionInfo::new("PUSH2", 2, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH3 as usize] = InstructionInfo::new("PUSH3", 3, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH4 as usize] = InstructionInfo::new("PUSH4", 4, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH5 as usize] = InstructionInfo::new("PUSH5", 5, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH6 as usize] = InstructionInfo::new("PUSH6", 6, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH7 as usize] = InstructionInfo::new("PUSH7", 7, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH8 as usize] = InstructionInfo::new("PUSH8", 8, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH9 as usize] = InstructionInfo::new("PUSH9", 9, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH10 as usize] = InstructionInfo::new("PUSH10", 10, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH11 as usize] = InstructionInfo::new("PUSH11", 11, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH12 as usize] = InstructionInfo::new("PUSH12", 12, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH13 as usize] = InstructionInfo::new("PUSH13", 13, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH14 as usize] = InstructionInfo::new("PUSH14", 14, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH15 as usize] = InstructionInfo::new("PUSH15", 15, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH16 as usize] = InstructionInfo::new("PUSH16", 16, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH17 as usize] = InstructionInfo::new("PUSH17", 17, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH18 as usize] = InstructionInfo::new("PUSH18", 18, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH19 as usize] = InstructionInfo::new("PUSH19", 19, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH20 as usize] = InstructionInfo::new("PUSH20", 20, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH21 as usize] = InstructionInfo::new("PUSH21", 21, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH22 as usize] = InstructionInfo::new("PUSH22", 22, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH23 as usize] = InstructionInfo::new("PUSH23", 23, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH24 as usize] = InstructionInfo::new("PUSH24", 24, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH25 as usize] = InstructionInfo::new("PUSH25", 25, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH26 as usize] = InstructionInfo::new("PUSH26", 26, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH27 as usize] = InstructionInfo::new("PUSH27", 27, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH28 as usize] = InstructionInfo::new("PUSH28", 28, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH29 as usize] = InstructionInfo::new("PUSH29", 29, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH30 as usize] = InstructionInfo::new("PUSH30", 30, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH31 as usize] = InstructionInfo::new("PUSH31", 31, 0, 1, false, GasPriceTier::VeryLow); + arr[PUSH32 as usize] = InstructionInfo::new("PUSH32", 32, 0, 1, false, GasPriceTier::VeryLow); + arr[DUP1 as usize] = InstructionInfo::new("DUP1", 0, 1, 2, false, GasPriceTier::VeryLow); + arr[DUP2 as usize] = InstructionInfo::new("DUP2", 0, 2, 3, false, GasPriceTier::VeryLow); + arr[DUP3 as usize] = InstructionInfo::new("DUP3", 0, 3, 4, false, GasPriceTier::VeryLow); + arr[DUP4 as usize] = InstructionInfo::new("DUP4", 0, 4, 5, false, GasPriceTier::VeryLow); + arr[DUP5 as usize] = InstructionInfo::new("DUP5", 0, 5, 6, false, GasPriceTier::VeryLow); + arr[DUP6 as usize] = InstructionInfo::new("DUP6", 0, 6, 7, false, GasPriceTier::VeryLow); + arr[DUP7 as usize] = InstructionInfo::new("DUP7", 0, 7, 8, false, GasPriceTier::VeryLow); + arr[DUP8 as usize] = InstructionInfo::new("DUP8", 0, 8, 9, false, GasPriceTier::VeryLow); + arr[DUP9 as usize] = InstructionInfo::new("DUP9", 0, 9, 10, false, GasPriceTier::VeryLow); + arr[DUP10 as usize] = InstructionInfo::new("DUP10", 0, 10, 11, false, GasPriceTier::VeryLow); + arr[DUP11 as usize] = InstructionInfo::new("DUP11", 0, 11, 12, false, GasPriceTier::VeryLow); + arr[DUP12 as usize] = InstructionInfo::new("DUP12", 0, 12, 13, false, GasPriceTier::VeryLow); + arr[DUP13 as usize] = InstructionInfo::new("DUP13", 0, 13, 14, false, GasPriceTier::VeryLow); + arr[DUP14 as usize] = InstructionInfo::new("DUP14", 0, 14, 15, false, GasPriceTier::VeryLow); + arr[DUP15 as usize] = InstructionInfo::new("DUP15", 0, 15, 16, false, GasPriceTier::VeryLow); + arr[DUP16 as usize] = InstructionInfo::new("DUP16", 0, 16, 17, false, GasPriceTier::VeryLow); + arr[SWAP1 as usize] = InstructionInfo::new("SWAP1", 0, 2, 2, false, GasPriceTier::VeryLow); + arr[SWAP2 as usize] = InstructionInfo::new("SWAP2", 0, 3, 3, false, GasPriceTier::VeryLow); + arr[SWAP3 as usize] = InstructionInfo::new("SWAP3", 0, 4, 4, false, GasPriceTier::VeryLow); + arr[SWAP4 as usize] = InstructionInfo::new("SWAP4", 0, 5, 5, false, GasPriceTier::VeryLow); + arr[SWAP5 as usize] = InstructionInfo::new("SWAP5", 0, 6, 6, false, GasPriceTier::VeryLow); + arr[SWAP6 as usize] = InstructionInfo::new("SWAP6", 0, 7, 7, false, GasPriceTier::VeryLow); + arr[SWAP7 as usize] = InstructionInfo::new("SWAP7", 0, 8, 8, false, GasPriceTier::VeryLow); + arr[SWAP8 as usize] = InstructionInfo::new("SWAP8", 0, 9, 9, false, GasPriceTier::VeryLow); + arr[SWAP9 as usize] = InstructionInfo::new("SWAP9", 0, 10, 10, false, GasPriceTier::VeryLow); + arr[SWAP10 as usize] = InstructionInfo::new("SWAP10", 0, 11, 11, false, GasPriceTier::VeryLow); + arr[SWAP11 as usize] = InstructionInfo::new("SWAP11", 0, 12, 12, false, GasPriceTier::VeryLow); + arr[SWAP12 as usize] = InstructionInfo::new("SWAP12", 0, 13, 13, false, GasPriceTier::VeryLow); + arr[SWAP13 as usize] = InstructionInfo::new("SWAP13", 0, 14, 14, false, GasPriceTier::VeryLow); + arr[SWAP14 as usize] = InstructionInfo::new("SWAP14", 0, 15, 15, false, GasPriceTier::VeryLow); + arr[SWAP15 as usize] = InstructionInfo::new("SWAP15", 0, 16, 16, false, GasPriceTier::VeryLow); + arr[SWAP16 as usize] = InstructionInfo::new("SWAP16", 0, 17, 17, false, GasPriceTier::VeryLow); + arr[LOG0 as usize] = InstructionInfo::new("LOG0", 0, 2, 0, true, GasPriceTier::Special); + arr[LOG1 as usize] = InstructionInfo::new("LOG1", 0, 3, 0, true, GasPriceTier::Special); + arr[LOG2 as usize] = InstructionInfo::new("LOG2", 0, 4, 0, true, GasPriceTier::Special); + arr[LOG3 as usize] = InstructionInfo::new("LOG3", 0, 5, 0, true, GasPriceTier::Special); + arr[LOG4 as usize] = InstructionInfo::new("LOG4", 0, 6, 0, true, GasPriceTier::Special); + arr[CREATE as usize] = InstructionInfo::new("CREATE", 0, 3, 1, true, GasPriceTier::Special); + arr[CALL as usize] = InstructionInfo::new("CALL", 0, 7, 1, true, GasPriceTier::Special); + arr[CALLCODE as usize] = InstructionInfo::new("CALLCODE", 0, 7, 1, true, GasPriceTier::Special); + arr[RETURN as usize] = InstructionInfo::new("RETURN", 0, 2, 0, true, GasPriceTier::Zero); + arr[DELEGATECALL as usize] = InstructionInfo::new("DELEGATECALL", 0, 6, 1, true, GasPriceTier::Special); + arr[SUICIDE as usize] = InstructionInfo::new("SUICIDE", 0, 1, 0, true, GasPriceTier::Zero); + arr + }; +} + /// Return details about specific instruction -pub fn get_info(instruction: Instruction) -> InstructionInfo { - match instruction { - STOP => InstructionInfo::new("STOP", 0, 0, 0, true, GasPriceTier::Zero), - ADD => InstructionInfo::new("ADD", 0, 2, 1, false, GasPriceTier::VeryLow), - SUB => InstructionInfo::new("SUB", 0, 2, 1, false, GasPriceTier::VeryLow), - MUL => InstructionInfo::new("MUL", 0, 2, 1, false, GasPriceTier::Low), - DIV => InstructionInfo::new("DIV", 0, 2, 1, false, GasPriceTier::Low), - SDIV => InstructionInfo::new("SDIV", 0, 2, 1, false, GasPriceTier::Low), - MOD => InstructionInfo::new("MOD", 0, 2, 1, false, GasPriceTier::Low), - SMOD => InstructionInfo::new("SMOD", 0, 2, 1, false, GasPriceTier::Low), - EXP => InstructionInfo::new("EXP", 0, 2, 1, false, GasPriceTier::Special), - NOT => InstructionInfo::new("NOT", 0, 1, 1, false, GasPriceTier::VeryLow), - LT => InstructionInfo::new("LT", 0, 2, 1, false, GasPriceTier::VeryLow), - GT => InstructionInfo::new("GT", 0, 2, 1, false, GasPriceTier::VeryLow), - SLT => InstructionInfo::new("SLT", 0, 2, 1, false, GasPriceTier::VeryLow), - SGT => InstructionInfo::new("SGT", 0, 2, 1, false, GasPriceTier::VeryLow), - EQ => InstructionInfo::new("EQ", 0, 2, 1, false, GasPriceTier::VeryLow), - ISZERO => InstructionInfo::new("ISZERO", 0, 1, 1, false, GasPriceTier::VeryLow), - AND => InstructionInfo::new("AND", 0, 2, 1, false, GasPriceTier::VeryLow), - OR => InstructionInfo::new("OR", 0, 2, 1, false, GasPriceTier::VeryLow), - XOR => InstructionInfo::new("XOR", 0, 2, 1, false, GasPriceTier::VeryLow), - BYTE => InstructionInfo::new("BYTE", 0, 2, 1, false, GasPriceTier::VeryLow), - ADDMOD => InstructionInfo::new("ADDMOD", 0, 3, 1, false, GasPriceTier::Mid), - MULMOD => InstructionInfo::new("MULMOD", 0, 3, 1, false, GasPriceTier::Mid), - SIGNEXTEND => InstructionInfo::new("SIGNEXTEND", 0, 2, 1, false, GasPriceTier::Low), - SHA3 => InstructionInfo::new("SHA3", 0, 2, 1, false, GasPriceTier::Special), - ADDRESS => InstructionInfo::new("ADDRESS", 0, 0, 1, false, GasPriceTier::Base), - BALANCE => InstructionInfo::new("BALANCE", 0, 1, 1, false, GasPriceTier::Ext), - ORIGIN => InstructionInfo::new("ORIGIN", 0, 0, 1, false, GasPriceTier::Base), - CALLER => InstructionInfo::new("CALLER", 0, 0, 1, false, GasPriceTier::Base), - CALLVALUE => InstructionInfo::new("CALLVALUE", 0, 0, 1, false, GasPriceTier::Base), - CALLDATALOAD => InstructionInfo::new("CALLDATALOAD", 0, 1, 1, false, GasPriceTier::VeryLow), - CALLDATASIZE => InstructionInfo::new("CALLDATASIZE", 0, 0, 1, false, GasPriceTier::Base), - CALLDATACOPY => InstructionInfo::new("CALLDATACOPY", 0, 3, 0, true, GasPriceTier::VeryLow), - CODESIZE => InstructionInfo::new("CODESIZE", 0, 0, 1, false, GasPriceTier::Base), - CODECOPY => InstructionInfo::new("CODECOPY", 0, 3, 0, true, GasPriceTier::VeryLow), - GASPRICE => InstructionInfo::new("GASPRICE", 0, 0, 1, false, GasPriceTier::Base), - EXTCODESIZE => InstructionInfo::new("EXTCODESIZE", 0, 1, 1, false, GasPriceTier::Ext), - EXTCODECOPY => InstructionInfo::new("EXTCODECOPY", 0, 4, 0, true, GasPriceTier::Ext), - BLOCKHASH => InstructionInfo::new("BLOCKHASH", 0, 1, 1, false, GasPriceTier::Ext), - COINBASE => InstructionInfo::new("COINBASE", 0, 0, 1, false, GasPriceTier::Base), - TIMESTAMP => InstructionInfo::new("TIMESTAMP", 0, 0, 1, false, GasPriceTier::Base), - NUMBER => InstructionInfo::new("NUMBER", 0, 0, 1, false, GasPriceTier::Base), - DIFFICULTY => InstructionInfo::new("DIFFICULTY", 0, 0, 1, false, GasPriceTier::Base), - GASLIMIT => InstructionInfo::new("GASLIMIT", 0, 0, 1, false, GasPriceTier::Base), - POP => InstructionInfo::new("POP", 0, 1, 0, false, GasPriceTier::Base), - MLOAD => InstructionInfo::new("MLOAD", 0, 1, 1, false, GasPriceTier::VeryLow), - MSTORE => InstructionInfo::new("MSTORE", 0, 2, 0, true, GasPriceTier::VeryLow), - MSTORE8 => InstructionInfo::new("MSTORE8", 0, 2, 0, true, GasPriceTier::VeryLow), - SLOAD => InstructionInfo::new("SLOAD", 0, 1, 1, false, GasPriceTier::Special), - SSTORE => InstructionInfo::new("SSTORE", 0, 2, 0, true, GasPriceTier::Special), - JUMP => InstructionInfo::new("JUMP", 0, 1, 0, true, GasPriceTier::Mid), - JUMPI => InstructionInfo::new("JUMPI", 0, 2, 0, true, GasPriceTier::High), - PC => InstructionInfo::new("PC", 0, 0, 1, false, GasPriceTier::Base), - MSIZE => InstructionInfo::new("MSIZE", 0, 0, 1, false, GasPriceTier::Base), - GAS => InstructionInfo::new("GAS", 0, 0, 1, false, GasPriceTier::Base), - JUMPDEST => InstructionInfo::new("JUMPDEST", 0, 0, 0, true, GasPriceTier::Special), - PUSH1 => InstructionInfo::new("PUSH1", 1, 0, 1, false, GasPriceTier::VeryLow), - PUSH2 => InstructionInfo::new("PUSH2", 2, 0, 1, false, GasPriceTier::VeryLow), - PUSH3 => InstructionInfo::new("PUSH3", 3, 0, 1, false, GasPriceTier::VeryLow), - PUSH4 => InstructionInfo::new("PUSH4", 4, 0, 1, false, GasPriceTier::VeryLow), - PUSH5 => InstructionInfo::new("PUSH5", 5, 0, 1, false, GasPriceTier::VeryLow), - PUSH6 => InstructionInfo::new("PUSH6", 6, 0, 1, false, GasPriceTier::VeryLow), - PUSH7 => InstructionInfo::new("PUSH7", 7, 0, 1, false, GasPriceTier::VeryLow), - PUSH8 => InstructionInfo::new("PUSH8", 8, 0, 1, false, GasPriceTier::VeryLow), - PUSH9 => InstructionInfo::new("PUSH9", 9, 0, 1, false, GasPriceTier::VeryLow), - PUSH10 => InstructionInfo::new("PUSH10", 10, 0, 1, false, GasPriceTier::VeryLow), - PUSH11 => InstructionInfo::new("PUSH11", 11, 0, 1, false, GasPriceTier::VeryLow), - PUSH12 => InstructionInfo::new("PUSH12", 12, 0, 1, false, GasPriceTier::VeryLow), - PUSH13 => InstructionInfo::new("PUSH13", 13, 0, 1, false, GasPriceTier::VeryLow), - PUSH14 => InstructionInfo::new("PUSH14", 14, 0, 1, false, GasPriceTier::VeryLow), - PUSH15 => InstructionInfo::new("PUSH15", 15, 0, 1, false, GasPriceTier::VeryLow), - PUSH16 => InstructionInfo::new("PUSH16", 16, 0, 1, false, GasPriceTier::VeryLow), - PUSH17 => InstructionInfo::new("PUSH17", 17, 0, 1, false, GasPriceTier::VeryLow), - PUSH18 => InstructionInfo::new("PUSH18", 18, 0, 1, false, GasPriceTier::VeryLow), - PUSH19 => InstructionInfo::new("PUSH19", 19, 0, 1, false, GasPriceTier::VeryLow), - PUSH20 => InstructionInfo::new("PUSH20", 20, 0, 1, false, GasPriceTier::VeryLow), - PUSH21 => InstructionInfo::new("PUSH21", 21, 0, 1, false, GasPriceTier::VeryLow), - PUSH22 => InstructionInfo::new("PUSH22", 22, 0, 1, false, GasPriceTier::VeryLow), - PUSH23 => InstructionInfo::new("PUSH23", 23, 0, 1, false, GasPriceTier::VeryLow), - PUSH24 => InstructionInfo::new("PUSH24", 24, 0, 1, false, GasPriceTier::VeryLow), - PUSH25 => InstructionInfo::new("PUSH25", 25, 0, 1, false, GasPriceTier::VeryLow), - PUSH26 => InstructionInfo::new("PUSH26", 26, 0, 1, false, GasPriceTier::VeryLow), - PUSH27 => InstructionInfo::new("PUSH27", 27, 0, 1, false, GasPriceTier::VeryLow), - PUSH28 => InstructionInfo::new("PUSH28", 28, 0, 1, false, GasPriceTier::VeryLow), - PUSH29 => InstructionInfo::new("PUSH29", 29, 0, 1, false, GasPriceTier::VeryLow), - PUSH30 => InstructionInfo::new("PUSH30", 30, 0, 1, false, GasPriceTier::VeryLow), - PUSH31 => InstructionInfo::new("PUSH31", 31, 0, 1, false, GasPriceTier::VeryLow), - PUSH32 => InstructionInfo::new("PUSH32", 32, 0, 1, false, GasPriceTier::VeryLow), - DUP1 => InstructionInfo::new("DUP1", 0, 1, 2, false, GasPriceTier::VeryLow), - DUP2 => InstructionInfo::new("DUP2", 0, 2, 3, false, GasPriceTier::VeryLow), - DUP3 => InstructionInfo::new("DUP3", 0, 3, 4, false, GasPriceTier::VeryLow), - DUP4 => InstructionInfo::new("DUP4", 0, 4, 5, false, GasPriceTier::VeryLow), - DUP5 => InstructionInfo::new("DUP5", 0, 5, 6, false, GasPriceTier::VeryLow), - DUP6 => InstructionInfo::new("DUP6", 0, 6, 7, false, GasPriceTier::VeryLow), - DUP7 => InstructionInfo::new("DUP7", 0, 7, 8, false, GasPriceTier::VeryLow), - DUP8 => InstructionInfo::new("DUP8", 0, 8, 9, false, GasPriceTier::VeryLow), - DUP9 => InstructionInfo::new("DUP9", 0, 9, 10, false, GasPriceTier::VeryLow), - DUP10 => InstructionInfo::new("DUP10", 0, 10, 11, false, GasPriceTier::VeryLow), - DUP11 => InstructionInfo::new("DUP11", 0, 11, 12, false, GasPriceTier::VeryLow), - DUP12 => InstructionInfo::new("DUP12", 0, 12, 13, false, GasPriceTier::VeryLow), - DUP13 => InstructionInfo::new("DUP13", 0, 13, 14, false, GasPriceTier::VeryLow), - DUP14 => InstructionInfo::new("DUP14", 0, 14, 15, false, GasPriceTier::VeryLow), - DUP15 => InstructionInfo::new("DUP15", 0, 15, 16, false, GasPriceTier::VeryLow), - DUP16 => InstructionInfo::new("DUP16", 0, 16, 17, false, GasPriceTier::VeryLow), - SWAP1 => InstructionInfo::new("SWAP1", 0, 2, 2, false, GasPriceTier::VeryLow), - SWAP2 => InstructionInfo::new("SWAP2", 0, 3, 3, false, GasPriceTier::VeryLow), - SWAP3 => InstructionInfo::new("SWAP3", 0, 4, 4, false, GasPriceTier::VeryLow), - SWAP4 => InstructionInfo::new("SWAP4", 0, 5, 5, false, GasPriceTier::VeryLow), - SWAP5 => InstructionInfo::new("SWAP5", 0, 6, 6, false, GasPriceTier::VeryLow), - SWAP6 => InstructionInfo::new("SWAP6", 0, 7, 7, false, GasPriceTier::VeryLow), - SWAP7 => InstructionInfo::new("SWAP7", 0, 8, 8, false, GasPriceTier::VeryLow), - SWAP8 => InstructionInfo::new("SWAP8", 0, 9, 9, false, GasPriceTier::VeryLow), - SWAP9 => InstructionInfo::new("SWAP9", 0, 10, 10, false, GasPriceTier::VeryLow), - SWAP10 => InstructionInfo::new("SWAP10", 0, 11, 11, false, GasPriceTier::VeryLow), - SWAP11 => InstructionInfo::new("SWAP11", 0, 12, 12, false, GasPriceTier::VeryLow), - SWAP12 => InstructionInfo::new("SWAP12", 0, 13, 13, false, GasPriceTier::VeryLow), - SWAP13 => InstructionInfo::new("SWAP13", 0, 14, 14, false, GasPriceTier::VeryLow), - SWAP14 => InstructionInfo::new("SWAP14", 0, 15, 15, false, GasPriceTier::VeryLow), - SWAP15 => InstructionInfo::new("SWAP15", 0, 16, 16, false, GasPriceTier::VeryLow), - SWAP16 => InstructionInfo::new("SWAP16", 0, 17, 17, false, GasPriceTier::VeryLow), - LOG0 => InstructionInfo::new("LOG0", 0, 2, 0, true, GasPriceTier::Special), - LOG1 => InstructionInfo::new("LOG1", 0, 3, 0, true, GasPriceTier::Special), - LOG2 => InstructionInfo::new("LOG2", 0, 4, 0, true, GasPriceTier::Special), - LOG3 => InstructionInfo::new("LOG3", 0, 5, 0, true, GasPriceTier::Special), - LOG4 => InstructionInfo::new("LOG4", 0, 6, 0, true, GasPriceTier::Special), - CREATE => InstructionInfo::new("CREATE", 0, 3, 1, true, GasPriceTier::Special), - CALL => InstructionInfo::new("CALL", 0, 7, 1, true, GasPriceTier::Special), - CALLCODE => InstructionInfo::new("CALLCODE", 0, 7, 1, true, GasPriceTier::Special), - RETURN => InstructionInfo::new("RETURN", 0, 2, 0, true, GasPriceTier::Zero), - DELEGATECALL => InstructionInfo::new("DELEGATECALL", 0, 6, 1, true, GasPriceTier::Special), - SUICIDE => InstructionInfo::new("SUICIDE", 0, 1, 0, true, GasPriceTier::Zero), - _ => InstructionInfo::new("INVALID_INSTRUCTION", 0, 0, 0, false, GasPriceTier::Invalid) - } +pub fn get_info(instruction: Instruction) -> &'static InstructionInfo { + &INSTRUCTIONS[instruction as usize] } /// Virtual machine bytecode instruction. From c7a11418bbb55e217f416cd35e9e4de7c3777781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20Drwi=C4=99ga?= Date: Tue, 12 Jul 2016 10:28:42 +0200 Subject: [PATCH 6/6] Getting rid of get_info --- ethcore/src/evm/instructions.rs | 7 +------ ethcore/src/evm/interpreter/mod.rs | 3 ++- ethcore/src/evm/mod.rs | 1 - ethcore/src/lib.rs | 1 - 4 files changed, 3 insertions(+), 9 deletions(-) diff --git a/ethcore/src/evm/instructions.rs b/ethcore/src/evm/instructions.rs index 9e7527fa3..62cfe77d6 100644 --- a/ethcore/src/evm/instructions.rs +++ b/ethcore/src/evm/instructions.rs @@ -146,7 +146,7 @@ impl InstructionInfo { } lazy_static! { - static ref INSTRUCTIONS: [InstructionInfo; 0x100] = { + pub static ref INSTRUCTIONS: [InstructionInfo; 0x100] = { let mut arr = [InstructionInfo::default(); 0x100]; arr[STOP as usize] = InstructionInfo::new("STOP", 0, 0, 0, true, GasPriceTier::Zero); arr[ADD as usize] = InstructionInfo::new("ADD", 0, 2, 1, false, GasPriceTier::VeryLow); @@ -282,11 +282,6 @@ lazy_static! { }; } -/// Return details about specific instruction -pub fn get_info(instruction: Instruction) -> &'static InstructionInfo { - &INSTRUCTIONS[instruction as usize] -} - /// Virtual machine bytecode instruction. /// halts execution pub const STOP: Instruction = 0x00; diff --git a/ethcore/src/evm/interpreter/mod.rs b/ethcore/src/evm/interpreter/mod.rs index f79d18b36..a43592c6d 100644 --- a/ethcore/src/evm/interpreter/mod.rs +++ b/ethcore/src/evm/interpreter/mod.rs @@ -104,12 +104,13 @@ impl evm::Evm for Interpreter { position: 0, code: &code }; + let infos = &*instructions::INSTRUCTIONS; while reader.position < code.len() { let instruction = code[reader.position]; reader.position += 1; - let info = instructions::get_info(instruction); + let info = infos[instruction as usize]; try!(self.verify_instruction(ext, instruction, &info, &stack)); // Calculate gas cost diff --git a/ethcore/src/evm/mod.rs b/ethcore/src/evm/mod.rs index de208c6a4..d0f379f24 100644 --- a/ethcore/src/evm/mod.rs +++ b/ethcore/src/evm/mod.rs @@ -35,4 +35,3 @@ pub use self::evm::{Evm, Error, Finalize, GasLeft, Result, CostType}; pub use self::ext::{Ext, ContractCreateResult, MessageCallResult}; pub use self::factory::{Factory, VMType}; pub use self::schedule::Schedule; -pub use self::instructions::get_info; diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 4f644db03..9f4f02491 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -146,5 +146,4 @@ mod tests; mod json_tests; pub use types::*; -pub use evm::get_info; pub use executive::contract_address;