diff --git a/Cargo.lock b/Cargo.lock index 80c31ce3378..494f9c084a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -443,6 +443,14 @@ dependencies = [ "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "error-chain" +version = "0.12.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "backtrace 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "eth-secp256k1" version = "0.5.7" @@ -519,7 +527,7 @@ dependencies = [ "byteorder 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", "common-types 0.1.0", "crossbeam 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -537,6 +545,7 @@ dependencies = [ "ethkey 0.3.0", "ethstore 0.2.0", "evm 0.1.0", + "fake-hardware-wallet 0.0.1", "fetch 0.1.0", "hardware-wallet 1.12.0", "hashdb 0.1.1", @@ -594,7 +603,7 @@ name = "ethcore-crypto" version = "0.1.0" dependencies = [ "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "ring 0.12.1 (git+https://github.com/paritytech/ring)", "rust-crypto 0.2.36 (registry+https://github.com/rust-lang/crates.io-index)", "tiny-keccak 1.4.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -624,7 +633,7 @@ name = "ethcore-light" version = "1.12.0" dependencies = [ "bincode 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-bytes 0.1.0", "ethcore-io 1.12.0", @@ -677,7 +686,7 @@ version = "1.12.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethash 1.12.0", "ethcore-transaction 0.1.0", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -705,7 +714,7 @@ name = "ethcore-network" version = "1.12.0" dependencies = [ "assert_matches 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-crypto 0.1.0", "ethcore-io 1.12.0", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -723,7 +732,7 @@ dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", "assert_matches 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", "bytes 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bytes 0.1.0", "ethcore-crypto 0.1.0", "ethcore-io 1.12.0", @@ -756,7 +765,7 @@ dependencies = [ name = "ethcore-private-tx" version = "1.0.0" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethabi-derive 5.1.2 (registry+https://github.com/rust-lang/crates.io-index)", @@ -831,7 +840,7 @@ name = "ethcore-service" version = "0.1.0" dependencies = [ "ansi_term 0.10.2 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore 1.12.0", "ethcore-io 1.12.0", "ethcore-private-tx 1.0.0", @@ -955,7 +964,7 @@ dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mem 0.1.0", "parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)", + "quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)", "rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", "serde 1.0.37 (registry+https://github.com/rust-lang/crates.io-index)", @@ -1064,6 +1073,14 @@ dependencies = [ "hyper 0.11.24 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "fake-hardware-wallet" +version = "0.0.1" +dependencies = [ + "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", + "ethkey 0.3.0", +] + [[package]] name = "fdlimit" version = "0.1.1" @@ -1495,7 +1512,7 @@ name = "kvdb" version = "0.1.0" dependencies = [ "elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)", - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethcore-bytes 0.1.0", ] @@ -1677,7 +1694,7 @@ dependencies = [ name = "migration-rocksdb" version = "0.1.0" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0", "kvdb-rocksdb 0.1.0", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2091,7 +2108,7 @@ dependencies = [ "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", "node-health 0.1.0", - "parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-dapps-glue 1.9.1", "parity-hash-fetch 1.12.0", "parity-reactor 0.1.0", "parity-version 1.12.0", @@ -2120,20 +2137,6 @@ dependencies = [ "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "parity-dapps-glue" -version = "1.9.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "aster 0.41.0 (registry+https://github.com/rust-lang/crates.io-index)", - "glob 0.2.11 (registry+https://github.com/rust-lang/crates.io-index)", - "mime_guess 2.0.0-alpha.2 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", - "syntex_syntax 0.58.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "parity-hash-fetch" version = "1.12.0" @@ -2230,6 +2233,7 @@ dependencies = [ "ethkey 0.3.0", "ethstore 0.2.0", "fake-fetch 0.0.1", + "fake-hardware-wallet 0.0.1", "fetch 0.1.0", "futures 0.1.21 (registry+https://github.com/rust-lang/crates.io-index)", "futures-cpupool 0.1.8 (registry+https://github.com/rust-lang/crates.io-index)", @@ -2642,7 +2646,7 @@ dependencies = [ [[package]] name = "quick-error" -version = "1.2.1" +version = "1.2.2" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -3459,7 +3463,7 @@ dependencies = [ name = "transaction-pool" version = "1.12.1" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.9 (registry+https://github.com/rust-lang/crates.io-index)", "smallvec 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)", @@ -3611,7 +3615,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" name = "util-error" version = "0.1.0" dependencies = [ - "error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)", "ethereum-types 0.3.2 (registry+https://github.com/rust-lang/crates.io-index)", "kvdb 0.1.0", "rlp 0.2.1", @@ -3858,6 +3862,7 @@ dependencies = [ "checksum elastic-array 0.10.0 (registry+https://github.com/rust-lang/crates.io-index)" = "88d4851b005ef16de812ea9acdb7bece2f0a40dd86c07b85631d7dafa54537bb" "checksum env_logger 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3ddf21e73e016298f5cb37d6ef8e8da8e39f91f9ec8b0df44b7deb16a9f8cd5b" "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3" +"checksum error-chain 0.12.0 (registry+https://github.com/rust-lang/crates.io-index)" = "07e791d3be96241c77c43846b665ef1384606da2cd2a48730abe606a12906e02" "checksum eth-secp256k1 0.5.7 (git+https://github.com/paritytech/rust-secp256k1)" = "" "checksum ethabi 5.1.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05e33a914b94b763f0a92333e4e5c95c095563f06ef7d6b295b3d3c2cf31e21f" "checksum ethabi-contract 5.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "210c9e21d164c15b6ef64fe601e0e12a3c84a031d5ef558e38463e53edbd22ed" @@ -3952,7 +3957,6 @@ dependencies = [ "checksum ordered-float 0.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "58d25b6c0e47b20d05226d288ff434940296e7e2f8b877975da32f862152241f" "checksum ordermap 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a86ed3f5f244b372d6b1a00b72ef7f8876d0bc6a78a4c9985c53614041512063" "checksum owning_ref 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "cdf84f41639e037b484f93433aa3897863b561ed65c6e59c7073d7c561710f37" -"checksum parity-dapps-glue 1.9.1 (registry+https://github.com/rust-lang/crates.io-index)" = "261c025c67ba416e9fe63aa9b3236520ce3c74cfbe43590c9cdcec4ccc8180e4" "checksum parity-tokio-ipc 0.1.5 (git+https://github.com/nikvolf/parity-tokio-ipc)" = "" "checksum parity-wasm 0.27.5 (registry+https://github.com/rust-lang/crates.io-index)" = "a93ad771f67ce8a6af64c6444a99c07b15f4674203657496fc31244ffb1de2c3" "checksum parity-wordlist 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1d0dec124478845b142f68b446cbee953d14d4b41f1bc0425024417720dce693" @@ -3978,7 +3982,7 @@ dependencies = [ "checksum quasi 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "18c45c4854d6d1cf5d531db97c75880feb91c958b0720f4ec1057135fec358b3" "checksum quasi_codegen 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "51b9e25fa23c044c1803f43ca59c98dac608976dd04ce799411edd58ece776d4" "checksum quasi_macros 0.32.0 (registry+https://github.com/rust-lang/crates.io-index)" = "29cec87bc2816766d7e4168302d505dd06b0a825aed41b00633d296e922e02dd" -"checksum quick-error 1.2.1 (registry+https://github.com/rust-lang/crates.io-index)" = "eda5fe9b71976e62bc81b781206aaa076401769b2143379d3eb2118388babac4" +"checksum quick-error 1.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "9274b940887ce9addde99c4eee6b5c44cc494b182b97e73dc8ffdcb3397fd3f0" "checksum quote 0.5.1 (registry+https://github.com/rust-lang/crates.io-index)" = "7b0ff51282f28dc1b53fd154298feaa2e77c5ea0dba68e1fd8b03b72fbe13d2a" "checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" "checksum rand 0.4.2 (registry+https://github.com/rust-lang/crates.io-index)" = "eba5f8cb59cc50ed56be8880a5c7b496bfd9bd26394e176bc67884094145c2c5" diff --git a/Cargo.toml b/Cargo.toml index ddbc2e69447..7424ba38bfa 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -115,12 +115,9 @@ path = "parity/main.rs" name = "parity" [profile.dev] -panic = "abort" [profile.release] debug = false -lto = false -panic = "abort" [workspace] members = [ diff --git a/dapps/Cargo.toml b/dapps/Cargo.toml index c3fd75ddc10..f16233b607c 100644 --- a/dapps/Cargo.toml +++ b/dapps/Cargo.toml @@ -13,7 +13,6 @@ futures = "0.1" futures-cpupool = "0.1" linked-hash-map = "0.5" log = "0.3" -parity-dapps-glue = "1.9" parking_lot = "0.5" mime_guess = "2.0.0-alpha.2" rand = "0.4" @@ -32,6 +31,7 @@ ethcore-bytes = { path = "../util/bytes" } ethereum-types = "0.3" fetch = { path = "../util/fetch" } node-health = { path = "./node-health" } +parity-dapps-glue = { path = "./js-glue" } parity-hash-fetch = { path = "../hash-fetch" } parity-reactor = { path = "../util/reactor" } keccak-hash = { path = "../util/hash" } diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index fdf66b90150..4d930926013 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -21,7 +21,7 @@ hashdb = { path = "../util/hashdb" } memorydb = { path = "../util/memorydb" } patricia-trie = { path = "../util/patricia_trie" } ethcore-crypto = { path = "crypto" } -error-chain = { version = "0.11", default-features = false } +error-chain = { version = "0.12", default-features = false } ethcore-io = { path = "../util/io" } ethcore-logger = { path = "../logger" } ethcore-miner = { path = "../miner" } @@ -36,7 +36,6 @@ ethjson = { path = "../json" } ethkey = { path = "../ethkey" } ethstore = { path = "../ethstore" } evm = { path = "evm" } -hardware-wallet = { path = "../hw" } heapsize = "0.4" itertools = "0.5" lazy_static = "1.0" @@ -70,6 +69,12 @@ journaldb = { path = "../util/journaldb" } tempdir = { version = "0.3", optional = true } kvdb-rocksdb = { path = "../util/kvdb-rocksdb" } +[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))'.dependencies] +hardware-wallet = { path = "../hw" } + +[target.'cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))'.dependencies] +fake-hardware-wallet = { path = "../util/fake-hardware-wallet" } + [dev-dependencies] trie-standardmap = { path = "../util/trie-standardmap" } tempdir = "0.3" diff --git a/ethcore/crypto/Cargo.toml b/ethcore/crypto/Cargo.toml index b57b8497c0e..c882d0d093f 100644 --- a/ethcore/crypto/Cargo.toml +++ b/ethcore/crypto/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] [dependencies] ethereum-types = "0.3" -quick-error = "1.2" +quick-error = "1.2.2" ring = "0.12" rust-crypto = "0.2.36" tiny-keccak = "1.4" diff --git a/ethcore/evm/src/instructions.rs b/ethcore/evm/src/instructions.rs index 76f99a93338..7a41ed33c75 100644 --- a/ethcore/evm/src/instructions.rs +++ b/ethcore/evm/src/instructions.rs @@ -16,83 +16,378 @@ //! VM Instructions list and utility functions -pub type Instruction = u8; +pub use self::Instruction::*; -/// Returns true if given instruction is `PUSHN` instruction. -pub fn is_push(i: Instruction) -> bool { - i >= PUSH1 && i <= PUSH32 -} +macro_rules! enum_with_from_u8 { + ( + $( #[$enum_attr:meta] )* + pub enum $name:ident { + $( $( #[$variant_attr:meta] )* $variant:ident = $discriminator:expr ),+, + } + ) => { + $( #[$enum_attr] )* + pub enum $name { + $( $( #[$variant_attr] )* $variant = $discriminator ),+, + } -#[test] -fn test_is_push() { - assert!(is_push(PUSH1)); - assert!(is_push(PUSH32)); - assert!(!is_push(DUP1)); + impl $name { + #[doc = "Convert from u8 to the given enum"] + pub fn from_u8(value: u8) -> Option { + match value { + $( $discriminator => Some($variant) ),+, + _ => None, + } + } + } + }; } -/// Returns number of bytes to read for `PUSHN` instruction -/// PUSH1 -> 1 -pub fn get_push_bytes(i: Instruction) -> usize { - assert!(is_push(i), "Only for PUSH instructions."); - (i - PUSH1 + 1) as usize +enum_with_from_u8! { + #[doc = "Virtual machine bytecode instruction."] + #[repr(u8)] + #[derive(Eq, PartialEq, Ord, PartialOrd, Clone, Copy, Debug)] + pub enum Instruction { + #[doc = "halts execution"] + STOP = 0x00, + #[doc = "addition operation"] + ADD = 0x01, + #[doc = "mulitplication operation"] + MUL = 0x02, + #[doc = "subtraction operation"] + SUB = 0x03, + #[doc = "integer division operation"] + DIV = 0x04, + #[doc = "signed integer division operation"] + SDIV = 0x05, + #[doc = "modulo remainder operation"] + MOD = 0x06, + #[doc = "signed modulo remainder operation"] + SMOD = 0x07, + #[doc = "unsigned modular addition"] + ADDMOD = 0x08, + #[doc = "unsigned modular multiplication"] + MULMOD = 0x09, + #[doc = "exponential operation"] + EXP = 0x0a, + #[doc = "extend length of signed integer"] + SIGNEXTEND = 0x0b, + + #[doc = "less-than comparision"] + LT = 0x10, + #[doc = "greater-than comparision"] + GT = 0x11, + #[doc = "signed less-than comparision"] + SLT = 0x12, + #[doc = "signed greater-than comparision"] + SGT = 0x13, + #[doc = "equality comparision"] + EQ = 0x14, + #[doc = "simple not operator"] + ISZERO = 0x15, + #[doc = "bitwise AND operation"] + AND = 0x16, + #[doc = "bitwise OR operation"] + OR = 0x17, + #[doc = "bitwise XOR operation"] + XOR = 0x18, + #[doc = "bitwise NOT opertation"] + NOT = 0x19, + #[doc = "retrieve single byte from word"] + BYTE = 0x1a, + #[doc = "shift left operation"] + SHL = 0x1b, + #[doc = "logical shift right operation"] + SHR = 0x1c, + #[doc = "arithmetic shift right operation"] + SAR = 0x1d, + + #[doc = "compute SHA3-256 hash"] + SHA3 = 0x20, + + #[doc = "get address of currently executing account"] + ADDRESS = 0x30, + #[doc = "get balance of the given account"] + BALANCE = 0x31, + #[doc = "get execution origination address"] + ORIGIN = 0x32, + #[doc = "get caller address"] + CALLER = 0x33, + #[doc = "get deposited value by the instruction/transaction responsible for this execution"] + CALLVALUE = 0x34, + #[doc = "get input data of current environment"] + CALLDATALOAD = 0x35, + #[doc = "get size of input data in current environment"] + CALLDATASIZE = 0x36, + #[doc = "copy input data in current environment to memory"] + CALLDATACOPY = 0x37, + #[doc = "get size of code running in current environment"] + CODESIZE = 0x38, + #[doc = "copy code running in current environment to memory"] + CODECOPY = 0x39, + #[doc = "get price of gas in current environment"] + GASPRICE = 0x3a, + #[doc = "get external code size (from another contract)"] + EXTCODESIZE = 0x3b, + #[doc = "copy external code (from another contract)"] + EXTCODECOPY = 0x3c, + #[doc = "get the size of the return data buffer for the last call"] + RETURNDATASIZE = 0x3d, + #[doc = "copy return data buffer to memory"] + RETURNDATACOPY = 0x3e, + + #[doc = "get hash of most recent complete block"] + BLOCKHASH = 0x40, + #[doc = "get the block's coinbase address"] + COINBASE = 0x41, + #[doc = "get the block's timestamp"] + TIMESTAMP = 0x42, + #[doc = "get the block's number"] + NUMBER = 0x43, + #[doc = "get the block's difficulty"] + DIFFICULTY = 0x44, + #[doc = "get the block's gas limit"] + GASLIMIT = 0x45, + + #[doc = "remove item from stack"] + POP = 0x50, + #[doc = "load word from memory"] + MLOAD = 0x51, + #[doc = "save word to memory"] + MSTORE = 0x52, + #[doc = "save byte to memory"] + MSTORE8 = 0x53, + #[doc = "load word from storage"] + SLOAD = 0x54, + #[doc = "save word to storage"] + SSTORE = 0x55, + #[doc = "alter the program counter"] + JUMP = 0x56, + #[doc = "conditionally alter the program counter"] + JUMPI = 0x57, + #[doc = "get the program counter"] + PC = 0x58, + #[doc = "get the size of active memory"] + MSIZE = 0x59, + #[doc = "get the amount of available gas"] + GAS = 0x5a, + #[doc = "set a potential jump destination"] + JUMPDEST = 0x5b, + + #[doc = "place 1 byte item on stack"] + PUSH1 = 0x60, + #[doc = "place 2 byte item on stack"] + PUSH2 = 0x61, + #[doc = "place 3 byte item on stack"] + PUSH3 = 0x62, + #[doc = "place 4 byte item on stack"] + PUSH4 = 0x63, + #[doc = "place 5 byte item on stack"] + PUSH5 = 0x64, + #[doc = "place 6 byte item on stack"] + PUSH6 = 0x65, + #[doc = "place 7 byte item on stack"] + PUSH7 = 0x66, + #[doc = "place 8 byte item on stack"] + PUSH8 = 0x67, + #[doc = "place 9 byte item on stack"] + PUSH9 = 0x68, + #[doc = "place 10 byte item on stack"] + PUSH10 = 0x69, + #[doc = "place 11 byte item on stack"] + PUSH11 = 0x6a, + #[doc = "place 12 byte item on stack"] + PUSH12 = 0x6b, + #[doc = "place 13 byte item on stack"] + PUSH13 = 0x6c, + #[doc = "place 14 byte item on stack"] + PUSH14 = 0x6d, + #[doc = "place 15 byte item on stack"] + PUSH15 = 0x6e, + #[doc = "place 16 byte item on stack"] + PUSH16 = 0x6f, + #[doc = "place 17 byte item on stack"] + PUSH17 = 0x70, + #[doc = "place 18 byte item on stack"] + PUSH18 = 0x71, + #[doc = "place 19 byte item on stack"] + PUSH19 = 0x72, + #[doc = "place 20 byte item on stack"] + PUSH20 = 0x73, + #[doc = "place 21 byte item on stack"] + PUSH21 = 0x74, + #[doc = "place 22 byte item on stack"] + PUSH22 = 0x75, + #[doc = "place 23 byte item on stack"] + PUSH23 = 0x76, + #[doc = "place 24 byte item on stack"] + PUSH24 = 0x77, + #[doc = "place 25 byte item on stack"] + PUSH25 = 0x78, + #[doc = "place 26 byte item on stack"] + PUSH26 = 0x79, + #[doc = "place 27 byte item on stack"] + PUSH27 = 0x7a, + #[doc = "place 28 byte item on stack"] + PUSH28 = 0x7b, + #[doc = "place 29 byte item on stack"] + PUSH29 = 0x7c, + #[doc = "place 30 byte item on stack"] + PUSH30 = 0x7d, + #[doc = "place 31 byte item on stack"] + PUSH31 = 0x7e, + #[doc = "place 32 byte item on stack"] + PUSH32 = 0x7f, + + #[doc = "copies the highest item in the stack to the top of the stack"] + DUP1 = 0x80, + #[doc = "copies the second highest item in the stack to the top of the stack"] + DUP2 = 0x81, + #[doc = "copies the third highest item in the stack to the top of the stack"] + DUP3 = 0x82, + #[doc = "copies the 4th highest item in the stack to the top of the stack"] + DUP4 = 0x83, + #[doc = "copies the 5th highest item in the stack to the top of the stack"] + DUP5 = 0x84, + #[doc = "copies the 6th highest item in the stack to the top of the stack"] + DUP6 = 0x85, + #[doc = "copies the 7th highest item in the stack to the top of the stack"] + DUP7 = 0x86, + #[doc = "copies the 8th highest item in the stack to the top of the stack"] + DUP8 = 0x87, + #[doc = "copies the 9th highest item in the stack to the top of the stack"] + DUP9 = 0x88, + #[doc = "copies the 10th highest item in the stack to the top of the stack"] + DUP10 = 0x89, + #[doc = "copies the 11th highest item in the stack to the top of the stack"] + DUP11 = 0x8a, + #[doc = "copies the 12th highest item in the stack to the top of the stack"] + DUP12 = 0x8b, + #[doc = "copies the 13th highest item in the stack to the top of the stack"] + DUP13 = 0x8c, + #[doc = "copies the 14th highest item in the stack to the top of the stack"] + DUP14 = 0x8d, + #[doc = "copies the 15th highest item in the stack to the top of the stack"] + DUP15 = 0x8e, + #[doc = "copies the 16th highest item in the stack to the top of the stack"] + DUP16 = 0x8f, + + #[doc = "swaps the highest and second highest value on the stack"] + SWAP1 = 0x90, + #[doc = "swaps the highest and third highest value on the stack"] + SWAP2 = 0x91, + #[doc = "swaps the highest and 4th highest value on the stack"] + SWAP3 = 0x92, + #[doc = "swaps the highest and 5th highest value on the stack"] + SWAP4 = 0x93, + #[doc = "swaps the highest and 6th highest value on the stack"] + SWAP5 = 0x94, + #[doc = "swaps the highest and 7th highest value on the stack"] + SWAP6 = 0x95, + #[doc = "swaps the highest and 8th highest value on the stack"] + SWAP7 = 0x96, + #[doc = "swaps the highest and 9th highest value on the stack"] + SWAP8 = 0x97, + #[doc = "swaps the highest and 10th highest value on the stack"] + SWAP9 = 0x98, + #[doc = "swaps the highest and 11th highest value on the stack"] + SWAP10 = 0x99, + #[doc = "swaps the highest and 12th highest value on the stack"] + SWAP11 = 0x9a, + #[doc = "swaps the highest and 13th highest value on the stack"] + SWAP12 = 0x9b, + #[doc = "swaps the highest and 14th highest value on the stack"] + SWAP13 = 0x9c, + #[doc = "swaps the highest and 15th highest value on the stack"] + SWAP14 = 0x9d, + #[doc = "swaps the highest and 16th highest value on the stack"] + SWAP15 = 0x9e, + #[doc = "swaps the highest and 17th highest value on the stack"] + SWAP16 = 0x9f, + + #[doc = "Makes a log entry, no topics."] + LOG0 = 0xa0, + #[doc = "Makes a log entry, 1 topic."] + LOG1 = 0xa1, + #[doc = "Makes a log entry, 2 topics."] + LOG2 = 0xa2, + #[doc = "Makes a log entry, 3 topics."] + LOG3 = 0xa3, + #[doc = "Makes a log entry, 4 topics."] + LOG4 = 0xa4, + + #[doc = "create a new account with associated code"] + CREATE = 0xf0, + #[doc = "message-call into an account"] + CALL = 0xf1, + #[doc = "message-call with another account's code only"] + CALLCODE = 0xf2, + #[doc = "halt execution returning output data"] + RETURN = 0xf3, + #[doc = "like CALLCODE but keeps caller's value and sender"] + DELEGATECALL = 0xf4, + #[doc = "create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160"] + CREATE2 = 0xfb, + #[doc = "stop execution and revert state changes. Return output data."] + REVERT = 0xfd, + #[doc = "like CALL but it does not take value, nor modify the state"] + STATICCALL = 0xfa, + #[doc = "halt execution and register account for later deletion"] + SUICIDE = 0xff, + } } -/// Returns number of bytes to read for `PUSHN` instruction or 0. -pub fn push_bytes(i: Instruction) -> usize { - if is_push(i) { - get_push_bytes(i) - } else { - 0 +impl Instruction { + /// Returns true if given instruction is `PUSHN` instruction. + pub fn is_push(&self) -> bool { + *self >= PUSH1 && *self <= PUSH32 } -} -#[test] -fn test_get_push_bytes() { - assert_eq!(get_push_bytes(PUSH1), 1); - assert_eq!(get_push_bytes(PUSH3), 3); - assert_eq!(get_push_bytes(PUSH32), 32); -} + /// Returns number of bytes to read for `PUSHN` instruction + /// PUSH1 -> 1 + pub fn push_bytes(&self) -> Option { + if self.is_push() { + Some(((*self as u8) - (PUSH1 as u8) + 1) as usize) + } else { + None + } + } -/// Returns stack position of item to duplicate -/// DUP1 -> 0 -pub fn get_dup_position(i: Instruction) -> usize { - assert!(i >= DUP1 && i <= DUP16); - (i - DUP1) as usize -} -#[test] -fn test_get_dup_position() { - assert_eq!(get_dup_position(DUP1), 0); - assert_eq!(get_dup_position(DUP5), 4); - assert_eq!(get_dup_position(DUP10), 9); -} + /// Returns stack position of item to duplicate + /// DUP1 -> 0 + pub fn dup_position(&self) -> Option { + if *self >= DUP1 && *self <= DUP16 { + Some(((*self as u8) - (DUP1 as u8)) as usize) + } else { + None + } + } -/// Returns stack position of item to SWAP top with -/// SWAP1 -> 1 -pub fn get_swap_position(i: Instruction) -> usize { - assert!(i >= SWAP1 && i <= SWAP16); - (i - SWAP1 + 1) as usize -} -#[test] -fn test_get_swap_position() { - assert_eq!(get_swap_position(SWAP1), 1); - assert_eq!(get_swap_position(SWAP5), 5); - assert_eq!(get_swap_position(SWAP10), 10); -} + /// Returns stack position of item to SWAP top with + /// SWAP1 -> 1 + pub fn swap_position(&self) -> Option { + if *self >= SWAP1 && *self <= SWAP16 { + Some(((*self as u8) - (SWAP1 as u8) + 1) as usize) + } else { + None + } + } -/// Returns number of topics to take from stack -/// LOG0 -> 0 -pub fn get_log_topics (i: Instruction) -> usize { - assert!(i >= LOG0 && i <= LOG4); - (i - LOG0) as usize -} + /// Returns number of topics to take from stack + /// LOG0 -> 0 + pub fn log_topics(&self) -> Option { + if *self >= LOG0 && *self <= LOG4 { + Some(((*self as u8) - (LOG0 as u8)) as usize) + } else { + None + } + } -#[test] -fn test_get_log_topics() { - assert_eq!(get_log_topics(LOG0), 0); - assert_eq!(get_log_topics(LOG2), 2); - assert_eq!(get_log_topics(LOG4), 4); + /// Returns the instruction info. + pub fn info(&self) -> &'static InstructionInfo { + INSTRUCTIONS[*self as usize].as_ref().expect("A instruction is defined in Instruction enum, but it is not found in InstructionInfo struct; this indicates a logic failure in the code.") + } } #[derive(PartialEq, Clone, Copy)] @@ -113,33 +408,26 @@ pub enum GasPriceTier { Ext, /// Multiparam or otherwise special Special, - /// Invalid - 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 { - GasPriceTier::Zero => 0, - GasPriceTier::Base => 1, - GasPriceTier::VeryLow => 2, - GasPriceTier::Low => 3, - GasPriceTier::Mid => 4, - GasPriceTier::High => 5, - GasPriceTier::Ext => 6, - GasPriceTier::Special => 7, - GasPriceTier::Invalid => 8 +impl GasPriceTier { + /// Returns the index in schedule for specific `GasPriceTier` + pub fn idx(&self) -> usize { + match self { + &GasPriceTier::Zero => 0, + &GasPriceTier::Base => 1, + &GasPriceTier::VeryLow => 2, + &GasPriceTier::Low => 3, + &GasPriceTier::Mid => 4, + &GasPriceTier::High => 5, + &GasPriceTier::Ext => 6, + &GasPriceTier::Special => 7, + } } } /// EVM instruction information. -#[derive(Copy, Clone, Default)] +#[derive(Copy, Clone)] pub struct InstructionInfo { /// Mnemonic name. pub name: &'static str, @@ -165,436 +453,189 @@ impl InstructionInfo { lazy_static! { /// Static instruction table. - pub static ref INSTRUCTIONS: [InstructionInfo; 0x100] = { - let mut arr = [InstructionInfo::default(); 0x100]; - arr[STOP as usize] = InstructionInfo::new("STOP", 0, 0, GasPriceTier::Zero); - arr[ADD as usize] = InstructionInfo::new("ADD", 2, 1, GasPriceTier::VeryLow); - arr[SUB as usize] = InstructionInfo::new("SUB", 2, 1, GasPriceTier::VeryLow); - arr[MUL as usize] = InstructionInfo::new("MUL", 2, 1, GasPriceTier::Low); - arr[DIV as usize] = InstructionInfo::new("DIV", 2, 1, GasPriceTier::Low); - arr[SDIV as usize] = InstructionInfo::new("SDIV", 2, 1, GasPriceTier::Low); - arr[MOD as usize] = InstructionInfo::new("MOD", 2, 1, GasPriceTier::Low); - arr[SMOD as usize] = InstructionInfo::new("SMOD", 2, 1, GasPriceTier::Low); - arr[EXP as usize] = InstructionInfo::new("EXP", 2, 1, GasPriceTier::Special); - arr[NOT as usize] = InstructionInfo::new("NOT", 1, 1, GasPriceTier::VeryLow); - arr[LT as usize] = InstructionInfo::new("LT", 2, 1, GasPriceTier::VeryLow); - arr[GT as usize] = InstructionInfo::new("GT", 2, 1, GasPriceTier::VeryLow); - arr[SLT as usize] = InstructionInfo::new("SLT", 2, 1, GasPriceTier::VeryLow); - arr[SGT as usize] = InstructionInfo::new("SGT", 2, 1, GasPriceTier::VeryLow); - arr[EQ as usize] = InstructionInfo::new("EQ", 2, 1, GasPriceTier::VeryLow); - arr[ISZERO as usize] = InstructionInfo::new("ISZERO", 1, 1, GasPriceTier::VeryLow); - arr[AND as usize] = InstructionInfo::new("AND", 2, 1, GasPriceTier::VeryLow); - arr[OR as usize] = InstructionInfo::new("OR", 2, 1, GasPriceTier::VeryLow); - arr[XOR as usize] = InstructionInfo::new("XOR", 2, 1, GasPriceTier::VeryLow); - arr[BYTE as usize] = InstructionInfo::new("BYTE", 2, 1, GasPriceTier::VeryLow); - arr[SHL as usize] = InstructionInfo::new("SHL", 2, 1, GasPriceTier::VeryLow); - arr[SHR as usize] = InstructionInfo::new("SHR", 2, 1, GasPriceTier::VeryLow); - arr[SAR as usize] = InstructionInfo::new("SAR", 2, 1, GasPriceTier::VeryLow); - arr[ADDMOD as usize] = InstructionInfo::new("ADDMOD", 3, 1, GasPriceTier::Mid); - arr[MULMOD as usize] = InstructionInfo::new("MULMOD", 3, 1, GasPriceTier::Mid); - arr[SIGNEXTEND as usize] = InstructionInfo::new("SIGNEXTEND", 2, 1, GasPriceTier::Low); - arr[RETURNDATASIZE as usize] = InstructionInfo::new("RETURNDATASIZE", 0, 1, GasPriceTier::Base); - arr[RETURNDATACOPY as usize] = InstructionInfo::new("RETURNDATACOPY", 3, 0, GasPriceTier::VeryLow); - arr[SHA3 as usize] = InstructionInfo::new("SHA3", 2, 1, GasPriceTier::Special); - arr[ADDRESS as usize] = InstructionInfo::new("ADDRESS", 0, 1, GasPriceTier::Base); - arr[BALANCE as usize] = InstructionInfo::new("BALANCE", 1, 1, GasPriceTier::Special); - arr[ORIGIN as usize] = InstructionInfo::new("ORIGIN", 0, 1, GasPriceTier::Base); - arr[CALLER as usize] = InstructionInfo::new("CALLER", 0, 1, GasPriceTier::Base); - arr[CALLVALUE as usize] = InstructionInfo::new("CALLVALUE", 0, 1, GasPriceTier::Base); - arr[CALLDATALOAD as usize] = InstructionInfo::new("CALLDATALOAD", 1, 1, GasPriceTier::VeryLow); - arr[CALLDATASIZE as usize] = InstructionInfo::new("CALLDATASIZE", 0, 1, GasPriceTier::Base); - arr[CALLDATACOPY as usize] = InstructionInfo::new("CALLDATACOPY", 3, 0, GasPriceTier::VeryLow); - arr[CODESIZE as usize] = InstructionInfo::new("CODESIZE", 0, 1, GasPriceTier::Base); - arr[CODECOPY as usize] = InstructionInfo::new("CODECOPY", 3, 0, GasPriceTier::VeryLow); - arr[GASPRICE as usize] = InstructionInfo::new("GASPRICE", 0, 1, GasPriceTier::Base); - arr[EXTCODESIZE as usize] = InstructionInfo::new("EXTCODESIZE", 1, 1, GasPriceTier::Special); - arr[EXTCODECOPY as usize] = InstructionInfo::new("EXTCODECOPY", 4, 0, GasPriceTier::Special); - arr[BLOCKHASH as usize] = InstructionInfo::new("BLOCKHASH", 1, 1, GasPriceTier::Ext); - arr[COINBASE as usize] = InstructionInfo::new("COINBASE", 0, 1, GasPriceTier::Base); - arr[TIMESTAMP as usize] = InstructionInfo::new("TIMESTAMP", 0, 1, GasPriceTier::Base); - arr[NUMBER as usize] = InstructionInfo::new("NUMBER", 0, 1, GasPriceTier::Base); - arr[DIFFICULTY as usize] = InstructionInfo::new("DIFFICULTY", 0, 1, GasPriceTier::Base); - arr[GASLIMIT as usize] = InstructionInfo::new("GASLIMIT", 0, 1, GasPriceTier::Base); - arr[POP as usize] = InstructionInfo::new("POP", 1, 0, GasPriceTier::Base); - arr[MLOAD as usize] = InstructionInfo::new("MLOAD", 1, 1, GasPriceTier::VeryLow); - arr[MSTORE as usize] = InstructionInfo::new("MSTORE", 2, 0, GasPriceTier::VeryLow); - arr[MSTORE8 as usize] = InstructionInfo::new("MSTORE8", 2, 0, GasPriceTier::VeryLow); - arr[SLOAD as usize] = InstructionInfo::new("SLOAD", 1, 1, GasPriceTier::Special); - arr[SSTORE as usize] = InstructionInfo::new("SSTORE", 2, 0, GasPriceTier::Special); - arr[JUMP as usize] = InstructionInfo::new("JUMP", 1, 0, GasPriceTier::Mid); - arr[JUMPI as usize] = InstructionInfo::new("JUMPI", 2, 0, GasPriceTier::High); - arr[PC as usize] = InstructionInfo::new("PC", 0, 1, GasPriceTier::Base); - arr[MSIZE as usize] = InstructionInfo::new("MSIZE", 0, 1, GasPriceTier::Base); - arr[GAS as usize] = InstructionInfo::new("GAS", 0, 1, GasPriceTier::Base); - arr[JUMPDEST as usize] = InstructionInfo::new("JUMPDEST", 0, 0, GasPriceTier::Special); - arr[PUSH1 as usize] = InstructionInfo::new("PUSH1", 0, 1, GasPriceTier::VeryLow); - arr[PUSH2 as usize] = InstructionInfo::new("PUSH2", 0, 1, GasPriceTier::VeryLow); - arr[PUSH3 as usize] = InstructionInfo::new("PUSH3", 0, 1, GasPriceTier::VeryLow); - arr[PUSH4 as usize] = InstructionInfo::new("PUSH4", 0, 1, GasPriceTier::VeryLow); - arr[PUSH5 as usize] = InstructionInfo::new("PUSH5", 0, 1, GasPriceTier::VeryLow); - arr[PUSH6 as usize] = InstructionInfo::new("PUSH6", 0, 1, GasPriceTier::VeryLow); - arr[PUSH7 as usize] = InstructionInfo::new("PUSH7", 0, 1, GasPriceTier::VeryLow); - arr[PUSH8 as usize] = InstructionInfo::new("PUSH8", 0, 1, GasPriceTier::VeryLow); - arr[PUSH9 as usize] = InstructionInfo::new("PUSH9", 0, 1, GasPriceTier::VeryLow); - arr[PUSH10 as usize] = InstructionInfo::new("PUSH10", 0, 1, GasPriceTier::VeryLow); - arr[PUSH11 as usize] = InstructionInfo::new("PUSH11", 0, 1, GasPriceTier::VeryLow); - arr[PUSH12 as usize] = InstructionInfo::new("PUSH12", 0, 1, GasPriceTier::VeryLow); - arr[PUSH13 as usize] = InstructionInfo::new("PUSH13", 0, 1, GasPriceTier::VeryLow); - arr[PUSH14 as usize] = InstructionInfo::new("PUSH14", 0, 1, GasPriceTier::VeryLow); - arr[PUSH15 as usize] = InstructionInfo::new("PUSH15", 0, 1, GasPriceTier::VeryLow); - arr[PUSH16 as usize] = InstructionInfo::new("PUSH16", 0, 1, GasPriceTier::VeryLow); - arr[PUSH17 as usize] = InstructionInfo::new("PUSH17", 0, 1, GasPriceTier::VeryLow); - arr[PUSH18 as usize] = InstructionInfo::new("PUSH18", 0, 1, GasPriceTier::VeryLow); - arr[PUSH19 as usize] = InstructionInfo::new("PUSH19", 0, 1, GasPriceTier::VeryLow); - arr[PUSH20 as usize] = InstructionInfo::new("PUSH20", 0, 1, GasPriceTier::VeryLow); - arr[PUSH21 as usize] = InstructionInfo::new("PUSH21", 0, 1, GasPriceTier::VeryLow); - arr[PUSH22 as usize] = InstructionInfo::new("PUSH22", 0, 1, GasPriceTier::VeryLow); - arr[PUSH23 as usize] = InstructionInfo::new("PUSH23", 0, 1, GasPriceTier::VeryLow); - arr[PUSH24 as usize] = InstructionInfo::new("PUSH24", 0, 1, GasPriceTier::VeryLow); - arr[PUSH25 as usize] = InstructionInfo::new("PUSH25", 0, 1, GasPriceTier::VeryLow); - arr[PUSH26 as usize] = InstructionInfo::new("PUSH26", 0, 1, GasPriceTier::VeryLow); - arr[PUSH27 as usize] = InstructionInfo::new("PUSH27", 0, 1, GasPriceTier::VeryLow); - arr[PUSH28 as usize] = InstructionInfo::new("PUSH28", 0, 1, GasPriceTier::VeryLow); - arr[PUSH29 as usize] = InstructionInfo::new("PUSH29", 0, 1, GasPriceTier::VeryLow); - arr[PUSH30 as usize] = InstructionInfo::new("PUSH30", 0, 1, GasPriceTier::VeryLow); - arr[PUSH31 as usize] = InstructionInfo::new("PUSH31", 0, 1, GasPriceTier::VeryLow); - arr[PUSH32 as usize] = InstructionInfo::new("PUSH32", 0, 1, GasPriceTier::VeryLow); - arr[DUP1 as usize] = InstructionInfo::new("DUP1", 1, 2, GasPriceTier::VeryLow); - arr[DUP2 as usize] = InstructionInfo::new("DUP2", 2, 3, GasPriceTier::VeryLow); - arr[DUP3 as usize] = InstructionInfo::new("DUP3", 3, 4, GasPriceTier::VeryLow); - arr[DUP4 as usize] = InstructionInfo::new("DUP4", 4, 5, GasPriceTier::VeryLow); - arr[DUP5 as usize] = InstructionInfo::new("DUP5", 5, 6, GasPriceTier::VeryLow); - arr[DUP6 as usize] = InstructionInfo::new("DUP6", 6, 7, GasPriceTier::VeryLow); - arr[DUP7 as usize] = InstructionInfo::new("DUP7", 7, 8, GasPriceTier::VeryLow); - arr[DUP8 as usize] = InstructionInfo::new("DUP8", 8, 9, GasPriceTier::VeryLow); - arr[DUP9 as usize] = InstructionInfo::new("DUP9", 9, 10, GasPriceTier::VeryLow); - arr[DUP10 as usize] = InstructionInfo::new("DUP10", 10, 11, GasPriceTier::VeryLow); - arr[DUP11 as usize] = InstructionInfo::new("DUP11", 11, 12, GasPriceTier::VeryLow); - arr[DUP12 as usize] = InstructionInfo::new("DUP12", 12, 13, GasPriceTier::VeryLow); - arr[DUP13 as usize] = InstructionInfo::new("DUP13", 13, 14, GasPriceTier::VeryLow); - arr[DUP14 as usize] = InstructionInfo::new("DUP14", 14, 15, GasPriceTier::VeryLow); - arr[DUP15 as usize] = InstructionInfo::new("DUP15", 15, 16, GasPriceTier::VeryLow); - arr[DUP16 as usize] = InstructionInfo::new("DUP16", 16, 17, GasPriceTier::VeryLow); - arr[SWAP1 as usize] = InstructionInfo::new("SWAP1", 2, 2, GasPriceTier::VeryLow); - arr[SWAP2 as usize] = InstructionInfo::new("SWAP2", 3, 3, GasPriceTier::VeryLow); - arr[SWAP3 as usize] = InstructionInfo::new("SWAP3", 4, 4, GasPriceTier::VeryLow); - arr[SWAP4 as usize] = InstructionInfo::new("SWAP4", 5, 5, GasPriceTier::VeryLow); - arr[SWAP5 as usize] = InstructionInfo::new("SWAP5", 6, 6, GasPriceTier::VeryLow); - arr[SWAP6 as usize] = InstructionInfo::new("SWAP6", 7, 7, GasPriceTier::VeryLow); - arr[SWAP7 as usize] = InstructionInfo::new("SWAP7", 8, 8, GasPriceTier::VeryLow); - arr[SWAP8 as usize] = InstructionInfo::new("SWAP8", 9, 9, GasPriceTier::VeryLow); - arr[SWAP9 as usize] = InstructionInfo::new("SWAP9", 10, 10, GasPriceTier::VeryLow); - arr[SWAP10 as usize] = InstructionInfo::new("SWAP10", 11, 11, GasPriceTier::VeryLow); - arr[SWAP11 as usize] = InstructionInfo::new("SWAP11", 12, 12, GasPriceTier::VeryLow); - arr[SWAP12 as usize] = InstructionInfo::new("SWAP12", 13, 13, GasPriceTier::VeryLow); - arr[SWAP13 as usize] = InstructionInfo::new("SWAP13", 14, 14, GasPriceTier::VeryLow); - arr[SWAP14 as usize] = InstructionInfo::new("SWAP14", 15, 15, GasPriceTier::VeryLow); - arr[SWAP15 as usize] = InstructionInfo::new("SWAP15", 16, 16, GasPriceTier::VeryLow); - arr[SWAP16 as usize] = InstructionInfo::new("SWAP16", 17, 17, GasPriceTier::VeryLow); - arr[LOG0 as usize] = InstructionInfo::new("LOG0", 2, 0, GasPriceTier::Special); - arr[LOG1 as usize] = InstructionInfo::new("LOG1", 3, 0, GasPriceTier::Special); - arr[LOG2 as usize] = InstructionInfo::new("LOG2", 4, 0, GasPriceTier::Special); - arr[LOG3 as usize] = InstructionInfo::new("LOG3", 5, 0, GasPriceTier::Special); - arr[LOG4 as usize] = InstructionInfo::new("LOG4", 6, 0, GasPriceTier::Special); - arr[CREATE as usize] = InstructionInfo::new("CREATE", 3, 1, GasPriceTier::Special); - arr[CALL as usize] = InstructionInfo::new("CALL", 7, 1, GasPriceTier::Special); - arr[CALLCODE as usize] = InstructionInfo::new("CALLCODE", 7, 1, GasPriceTier::Special); - arr[RETURN as usize] = InstructionInfo::new("RETURN", 2, 0, GasPriceTier::Zero); - arr[DELEGATECALL as usize] = InstructionInfo::new("DELEGATECALL", 6, 1, GasPriceTier::Special); - arr[STATICCALL as usize] = InstructionInfo::new("STATICCALL", 6, 1, GasPriceTier::Special); - arr[SUICIDE as usize] = InstructionInfo::new("SUICIDE", 1, 0, GasPriceTier::Special); - arr[CREATE2 as usize] = InstructionInfo::new("CREATE2", 3, 1, GasPriceTier::Special); - arr[REVERT as usize] = InstructionInfo::new("REVERT", 2, 0, GasPriceTier::Zero); + static ref INSTRUCTIONS: [Option; 0x100] = { + let mut arr = [None; 0x100]; + arr[STOP as usize] = Some(InstructionInfo::new("STOP", 0, 0, GasPriceTier::Zero)); + arr[ADD as usize] = Some(InstructionInfo::new("ADD", 2, 1, GasPriceTier::VeryLow)); + arr[SUB as usize] = Some(InstructionInfo::new("SUB", 2, 1, GasPriceTier::VeryLow)); + arr[MUL as usize] = Some(InstructionInfo::new("MUL", 2, 1, GasPriceTier::Low)); + arr[DIV as usize] = Some(InstructionInfo::new("DIV", 2, 1, GasPriceTier::Low)); + arr[SDIV as usize] = Some(InstructionInfo::new("SDIV", 2, 1, GasPriceTier::Low)); + arr[MOD as usize] = Some(InstructionInfo::new("MOD", 2, 1, GasPriceTier::Low)); + arr[SMOD as usize] = Some(InstructionInfo::new("SMOD", 2, 1, GasPriceTier::Low)); + arr[EXP as usize] = Some(InstructionInfo::new("EXP", 2, 1, GasPriceTier::Special)); + arr[NOT as usize] = Some(InstructionInfo::new("NOT", 1, 1, GasPriceTier::VeryLow)); + arr[LT as usize] = Some(InstructionInfo::new("LT", 2, 1, GasPriceTier::VeryLow)); + arr[GT as usize] = Some(InstructionInfo::new("GT", 2, 1, GasPriceTier::VeryLow)); + arr[SLT as usize] = Some(InstructionInfo::new("SLT", 2, 1, GasPriceTier::VeryLow)); + arr[SGT as usize] = Some(InstructionInfo::new("SGT", 2, 1, GasPriceTier::VeryLow)); + arr[EQ as usize] = Some(InstructionInfo::new("EQ", 2, 1, GasPriceTier::VeryLow)); + arr[ISZERO as usize] = Some(InstructionInfo::new("ISZERO", 1, 1, GasPriceTier::VeryLow)); + arr[AND as usize] = Some(InstructionInfo::new("AND", 2, 1, GasPriceTier::VeryLow)); + arr[OR as usize] = Some(InstructionInfo::new("OR", 2, 1, GasPriceTier::VeryLow)); + arr[XOR as usize] = Some(InstructionInfo::new("XOR", 2, 1, GasPriceTier::VeryLow)); + arr[BYTE as usize] = Some(InstructionInfo::new("BYTE", 2, 1, GasPriceTier::VeryLow)); + arr[SHL as usize] = Some(InstructionInfo::new("SHL", 2, 1, GasPriceTier::VeryLow)); + arr[SHR as usize] = Some(InstructionInfo::new("SHR", 2, 1, GasPriceTier::VeryLow)); + arr[SAR as usize] = Some(InstructionInfo::new("SAR", 2, 1, GasPriceTier::VeryLow)); + arr[ADDMOD as usize] = Some(InstructionInfo::new("ADDMOD", 3, 1, GasPriceTier::Mid)); + arr[MULMOD as usize] = Some(InstructionInfo::new("MULMOD", 3, 1, GasPriceTier::Mid)); + arr[SIGNEXTEND as usize] = Some(InstructionInfo::new("SIGNEXTEND", 2, 1, GasPriceTier::Low)); + arr[RETURNDATASIZE as usize] = Some(InstructionInfo::new("RETURNDATASIZE", 0, 1, GasPriceTier::Base)); + arr[RETURNDATACOPY as usize] = Some(InstructionInfo::new("RETURNDATACOPY", 3, 0, GasPriceTier::VeryLow)); + arr[SHA3 as usize] = Some(InstructionInfo::new("SHA3", 2, 1, GasPriceTier::Special)); + arr[ADDRESS as usize] = Some(InstructionInfo::new("ADDRESS", 0, 1, GasPriceTier::Base)); + arr[BALANCE as usize] = Some(InstructionInfo::new("BALANCE", 1, 1, GasPriceTier::Special)); + arr[ORIGIN as usize] = Some(InstructionInfo::new("ORIGIN", 0, 1, GasPriceTier::Base)); + arr[CALLER as usize] = Some(InstructionInfo::new("CALLER", 0, 1, GasPriceTier::Base)); + arr[CALLVALUE as usize] = Some(InstructionInfo::new("CALLVALUE", 0, 1, GasPriceTier::Base)); + arr[CALLDATALOAD as usize] = Some(InstructionInfo::new("CALLDATALOAD", 1, 1, GasPriceTier::VeryLow)); + arr[CALLDATASIZE as usize] = Some(InstructionInfo::new("CALLDATASIZE", 0, 1, GasPriceTier::Base)); + arr[CALLDATACOPY as usize] = Some(InstructionInfo::new("CALLDATACOPY", 3, 0, GasPriceTier::VeryLow)); + arr[CODESIZE as usize] = Some(InstructionInfo::new("CODESIZE", 0, 1, GasPriceTier::Base)); + arr[CODECOPY as usize] = Some(InstructionInfo::new("CODECOPY", 3, 0, GasPriceTier::VeryLow)); + arr[GASPRICE as usize] = Some(InstructionInfo::new("GASPRICE", 0, 1, GasPriceTier::Base)); + arr[EXTCODESIZE as usize] = Some(InstructionInfo::new("EXTCODESIZE", 1, 1, GasPriceTier::Special)); + arr[EXTCODECOPY as usize] = Some(InstructionInfo::new("EXTCODECOPY", 4, 0, GasPriceTier::Special)); + arr[BLOCKHASH as usize] = Some(InstructionInfo::new("BLOCKHASH", 1, 1, GasPriceTier::Ext)); + arr[COINBASE as usize] = Some(InstructionInfo::new("COINBASE", 0, 1, GasPriceTier::Base)); + arr[TIMESTAMP as usize] = Some(InstructionInfo::new("TIMESTAMP", 0, 1, GasPriceTier::Base)); + arr[NUMBER as usize] = Some(InstructionInfo::new("NUMBER", 0, 1, GasPriceTier::Base)); + arr[DIFFICULTY as usize] = Some(InstructionInfo::new("DIFFICULTY", 0, 1, GasPriceTier::Base)); + arr[GASLIMIT as usize] = Some(InstructionInfo::new("GASLIMIT", 0, 1, GasPriceTier::Base)); + arr[POP as usize] = Some(InstructionInfo::new("POP", 1, 0, GasPriceTier::Base)); + arr[MLOAD as usize] = Some(InstructionInfo::new("MLOAD", 1, 1, GasPriceTier::VeryLow)); + arr[MSTORE as usize] = Some(InstructionInfo::new("MSTORE", 2, 0, GasPriceTier::VeryLow)); + arr[MSTORE8 as usize] = Some(InstructionInfo::new("MSTORE8", 2, 0, GasPriceTier::VeryLow)); + arr[SLOAD as usize] = Some(InstructionInfo::new("SLOAD", 1, 1, GasPriceTier::Special)); + arr[SSTORE as usize] = Some(InstructionInfo::new("SSTORE", 2, 0, GasPriceTier::Special)); + arr[JUMP as usize] = Some(InstructionInfo::new("JUMP", 1, 0, GasPriceTier::Mid)); + arr[JUMPI as usize] = Some(InstructionInfo::new("JUMPI", 2, 0, GasPriceTier::High)); + arr[PC as usize] = Some(InstructionInfo::new("PC", 0, 1, GasPriceTier::Base)); + arr[MSIZE as usize] = Some(InstructionInfo::new("MSIZE", 0, 1, GasPriceTier::Base)); + arr[GAS as usize] = Some(InstructionInfo::new("GAS", 0, 1, GasPriceTier::Base)); + arr[JUMPDEST as usize] = Some(InstructionInfo::new("JUMPDEST", 0, 0, GasPriceTier::Special)); + arr[PUSH1 as usize] = Some(InstructionInfo::new("PUSH1", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH2 as usize] = Some(InstructionInfo::new("PUSH2", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH3 as usize] = Some(InstructionInfo::new("PUSH3", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH4 as usize] = Some(InstructionInfo::new("PUSH4", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH5 as usize] = Some(InstructionInfo::new("PUSH5", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH6 as usize] = Some(InstructionInfo::new("PUSH6", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH7 as usize] = Some(InstructionInfo::new("PUSH7", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH8 as usize] = Some(InstructionInfo::new("PUSH8", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH9 as usize] = Some(InstructionInfo::new("PUSH9", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH10 as usize] = Some(InstructionInfo::new("PUSH10", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH11 as usize] = Some(InstructionInfo::new("PUSH11", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH12 as usize] = Some(InstructionInfo::new("PUSH12", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH13 as usize] = Some(InstructionInfo::new("PUSH13", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH14 as usize] = Some(InstructionInfo::new("PUSH14", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH15 as usize] = Some(InstructionInfo::new("PUSH15", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH16 as usize] = Some(InstructionInfo::new("PUSH16", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH17 as usize] = Some(InstructionInfo::new("PUSH17", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH18 as usize] = Some(InstructionInfo::new("PUSH18", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH19 as usize] = Some(InstructionInfo::new("PUSH19", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH20 as usize] = Some(InstructionInfo::new("PUSH20", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH21 as usize] = Some(InstructionInfo::new("PUSH21", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH22 as usize] = Some(InstructionInfo::new("PUSH22", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH23 as usize] = Some(InstructionInfo::new("PUSH23", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH24 as usize] = Some(InstructionInfo::new("PUSH24", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH25 as usize] = Some(InstructionInfo::new("PUSH25", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH26 as usize] = Some(InstructionInfo::new("PUSH26", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH27 as usize] = Some(InstructionInfo::new("PUSH27", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH28 as usize] = Some(InstructionInfo::new("PUSH28", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH29 as usize] = Some(InstructionInfo::new("PUSH29", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH30 as usize] = Some(InstructionInfo::new("PUSH30", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH31 as usize] = Some(InstructionInfo::new("PUSH31", 0, 1, GasPriceTier::VeryLow)); + arr[PUSH32 as usize] = Some(InstructionInfo::new("PUSH32", 0, 1, GasPriceTier::VeryLow)); + arr[DUP1 as usize] = Some(InstructionInfo::new("DUP1", 1, 2, GasPriceTier::VeryLow)); + arr[DUP2 as usize] = Some(InstructionInfo::new("DUP2", 2, 3, GasPriceTier::VeryLow)); + arr[DUP3 as usize] = Some(InstructionInfo::new("DUP3", 3, 4, GasPriceTier::VeryLow)); + arr[DUP4 as usize] = Some(InstructionInfo::new("DUP4", 4, 5, GasPriceTier::VeryLow)); + arr[DUP5 as usize] = Some(InstructionInfo::new("DUP5", 5, 6, GasPriceTier::VeryLow)); + arr[DUP6 as usize] = Some(InstructionInfo::new("DUP6", 6, 7, GasPriceTier::VeryLow)); + arr[DUP7 as usize] = Some(InstructionInfo::new("DUP7", 7, 8, GasPriceTier::VeryLow)); + arr[DUP8 as usize] = Some(InstructionInfo::new("DUP8", 8, 9, GasPriceTier::VeryLow)); + arr[DUP9 as usize] = Some(InstructionInfo::new("DUP9", 9, 10, GasPriceTier::VeryLow)); + arr[DUP10 as usize] = Some(InstructionInfo::new("DUP10", 10, 11, GasPriceTier::VeryLow)); + arr[DUP11 as usize] = Some(InstructionInfo::new("DUP11", 11, 12, GasPriceTier::VeryLow)); + arr[DUP12 as usize] = Some(InstructionInfo::new("DUP12", 12, 13, GasPriceTier::VeryLow)); + arr[DUP13 as usize] = Some(InstructionInfo::new("DUP13", 13, 14, GasPriceTier::VeryLow)); + arr[DUP14 as usize] = Some(InstructionInfo::new("DUP14", 14, 15, GasPriceTier::VeryLow)); + arr[DUP15 as usize] = Some(InstructionInfo::new("DUP15", 15, 16, GasPriceTier::VeryLow)); + arr[DUP16 as usize] = Some(InstructionInfo::new("DUP16", 16, 17, GasPriceTier::VeryLow)); + arr[SWAP1 as usize] = Some(InstructionInfo::new("SWAP1", 2, 2, GasPriceTier::VeryLow)); + arr[SWAP2 as usize] = Some(InstructionInfo::new("SWAP2", 3, 3, GasPriceTier::VeryLow)); + arr[SWAP3 as usize] = Some(InstructionInfo::new("SWAP3", 4, 4, GasPriceTier::VeryLow)); + arr[SWAP4 as usize] = Some(InstructionInfo::new("SWAP4", 5, 5, GasPriceTier::VeryLow)); + arr[SWAP5 as usize] = Some(InstructionInfo::new("SWAP5", 6, 6, GasPriceTier::VeryLow)); + arr[SWAP6 as usize] = Some(InstructionInfo::new("SWAP6", 7, 7, GasPriceTier::VeryLow)); + arr[SWAP7 as usize] = Some(InstructionInfo::new("SWAP7", 8, 8, GasPriceTier::VeryLow)); + arr[SWAP8 as usize] = Some(InstructionInfo::new("SWAP8", 9, 9, GasPriceTier::VeryLow)); + arr[SWAP9 as usize] = Some(InstructionInfo::new("SWAP9", 10, 10, GasPriceTier::VeryLow)); + arr[SWAP10 as usize] = Some(InstructionInfo::new("SWAP10", 11, 11, GasPriceTier::VeryLow)); + arr[SWAP11 as usize] = Some(InstructionInfo::new("SWAP11", 12, 12, GasPriceTier::VeryLow)); + arr[SWAP12 as usize] = Some(InstructionInfo::new("SWAP12", 13, 13, GasPriceTier::VeryLow)); + arr[SWAP13 as usize] = Some(InstructionInfo::new("SWAP13", 14, 14, GasPriceTier::VeryLow)); + arr[SWAP14 as usize] = Some(InstructionInfo::new("SWAP14", 15, 15, GasPriceTier::VeryLow)); + arr[SWAP15 as usize] = Some(InstructionInfo::new("SWAP15", 16, 16, GasPriceTier::VeryLow)); + arr[SWAP16 as usize] = Some(InstructionInfo::new("SWAP16", 17, 17, GasPriceTier::VeryLow)); + arr[LOG0 as usize] = Some(InstructionInfo::new("LOG0", 2, 0, GasPriceTier::Special)); + arr[LOG1 as usize] = Some(InstructionInfo::new("LOG1", 3, 0, GasPriceTier::Special)); + arr[LOG2 as usize] = Some(InstructionInfo::new("LOG2", 4, 0, GasPriceTier::Special)); + arr[LOG3 as usize] = Some(InstructionInfo::new("LOG3", 5, 0, GasPriceTier::Special)); + arr[LOG4 as usize] = Some(InstructionInfo::new("LOG4", 6, 0, GasPriceTier::Special)); + arr[CREATE as usize] = Some(InstructionInfo::new("CREATE", 3, 1, GasPriceTier::Special)); + arr[CALL as usize] = Some(InstructionInfo::new("CALL", 7, 1, GasPriceTier::Special)); + arr[CALLCODE as usize] = Some(InstructionInfo::new("CALLCODE", 7, 1, GasPriceTier::Special)); + arr[RETURN as usize] = Some(InstructionInfo::new("RETURN", 2, 0, GasPriceTier::Zero)); + arr[DELEGATECALL as usize] = Some(InstructionInfo::new("DELEGATECALL", 6, 1, GasPriceTier::Special)); + arr[STATICCALL as usize] = Some(InstructionInfo::new("STATICCALL", 6, 1, GasPriceTier::Special)); + arr[SUICIDE as usize] = Some(InstructionInfo::new("SUICIDE", 1, 0, GasPriceTier::Special)); + arr[CREATE2 as usize] = Some(InstructionInfo::new("CREATE2", 3, 1, GasPriceTier::Special)); + arr[REVERT as usize] = Some(InstructionInfo::new("REVERT", 2, 0, GasPriceTier::Zero)); arr }; } -/// Virtual machine bytecode instruction. -/// halts execution -pub const STOP: Instruction = 0x00; -/// addition operation -pub const ADD: Instruction = 0x01; -/// mulitplication operation -pub const MUL: Instruction = 0x02; -/// subtraction operation -pub const SUB: Instruction = 0x03; -/// integer division operation -pub const DIV: Instruction = 0x04; -/// signed integer division operation -pub const SDIV: Instruction = 0x05; -/// modulo remainder operation -pub const MOD: Instruction = 0x06; -/// signed modulo remainder operation -pub const SMOD: Instruction = 0x07; -/// unsigned modular addition -pub const ADDMOD: Instruction = 0x08; -/// unsigned modular multiplication -pub const MULMOD: Instruction = 0x09; -/// exponential operation -pub const EXP: Instruction = 0x0a; -/// extend length of signed integer -pub const SIGNEXTEND: Instruction = 0x0b; - -/// less-than comparision -pub const LT: Instruction = 0x10; -/// greater-than comparision -pub const GT: Instruction = 0x11; -/// signed less-than comparision -pub const SLT: Instruction = 0x12; -/// signed greater-than comparision -pub const SGT: Instruction = 0x13; -/// equality comparision -pub const EQ: Instruction = 0x14; -/// simple not operator -pub const ISZERO: Instruction = 0x15; -/// bitwise AND operation -pub const AND: Instruction = 0x16; -/// bitwise OR operation -pub const OR: Instruction = 0x17; -/// bitwise XOR operation -pub const XOR: Instruction = 0x18; -/// bitwise NOT opertation -pub const NOT: Instruction = 0x19; -/// retrieve single byte from word -pub const BYTE: Instruction = 0x1a; -/// shift left operation -pub const SHL: Instruction = 0x1b; -/// logical shift right operation -pub const SHR: Instruction = 0x1c; -/// arithmetic shift right operation -pub const SAR: Instruction = 0x1d; - -/// compute SHA3-256 hash -pub const SHA3: Instruction = 0x20; - -/// get address of currently executing account -pub const ADDRESS: Instruction = 0x30; -/// get balance of the given account -pub const BALANCE: Instruction = 0x31; -/// get execution origination address -pub const ORIGIN: Instruction = 0x32; -/// get caller address -pub const CALLER: Instruction = 0x33; -/// get deposited value by the instruction/transaction responsible for this execution -pub const CALLVALUE: Instruction = 0x34; -/// get input data of current environment -pub const CALLDATALOAD: Instruction = 0x35; -/// get size of input data in current environment -pub const CALLDATASIZE: Instruction = 0x36; -/// copy input data in current environment to memory -pub const CALLDATACOPY: Instruction = 0x37; -/// get size of code running in current environment -pub const CODESIZE: Instruction = 0x38; -/// copy code running in current environment to memory -pub const CODECOPY: Instruction = 0x39; -/// get price of gas in current environment -pub const GASPRICE: Instruction = 0x3a; -/// get external code size (from another contract) -pub const EXTCODESIZE: Instruction = 0x3b; -/// copy external code (from another contract) -pub const EXTCODECOPY: Instruction = 0x3c; -/// get the size of the return data buffer for the last call -pub const RETURNDATASIZE: Instruction = 0x3d; -/// copy return data buffer to memory -pub const RETURNDATACOPY: Instruction = 0x3e; - -/// get hash of most recent complete block -pub const BLOCKHASH: Instruction = 0x40; -/// get the block's coinbase address -pub const COINBASE: Instruction = 0x41; -/// get the block's timestamp -pub const TIMESTAMP: Instruction = 0x42; -/// get the block's number -pub const NUMBER: Instruction = 0x43; -/// get the block's difficulty -pub const DIFFICULTY: Instruction = 0x44; -/// get the block's gas limit -pub const GASLIMIT: Instruction = 0x45; - -/// remove item from stack -pub const POP: Instruction = 0x50; -/// load word from memory -pub const MLOAD: Instruction = 0x51; -/// save word to memory -pub const MSTORE: Instruction = 0x52; -/// save byte to memory -pub const MSTORE8: Instruction = 0x53; -/// load word from storage -pub const SLOAD: Instruction = 0x54; -/// save word to storage -pub const SSTORE: Instruction = 0x55; -/// alter the program counter -pub const JUMP: Instruction = 0x56; -/// conditionally alter the program counter -pub const JUMPI: Instruction = 0x57; -/// get the program counter -pub const PC: Instruction = 0x58; -/// get the size of active memory -pub const MSIZE: Instruction = 0x59; -/// get the amount of available gas -pub const GAS: Instruction = 0x5a; -/// set a potential jump destination -pub const JUMPDEST: Instruction = 0x5b; - -/// place 1 byte item on stack -pub const PUSH1: Instruction = 0x60; -/// place 2 byte item on stack -pub const PUSH2: Instruction = 0x61; -/// place 3 byte item on stack -pub const PUSH3: Instruction = 0x62; -/// place 4 byte item on stack -pub const PUSH4: Instruction = 0x63; -/// place 5 byte item on stack -pub const PUSH5: Instruction = 0x64; -/// place 6 byte item on stack -pub const PUSH6: Instruction = 0x65; -/// place 7 byte item on stack -pub const PUSH7: Instruction = 0x66; -/// place 8 byte item on stack -pub const PUSH8: Instruction = 0x67; -/// place 9 byte item on stack -pub const PUSH9: Instruction = 0x68; -/// place 10 byte item on stack -pub const PUSH10: Instruction = 0x69; -/// place 11 byte item on stack -pub const PUSH11: Instruction = 0x6a; -/// place 12 byte item on stack -pub const PUSH12: Instruction = 0x6b; -/// place 13 byte item on stack -pub const PUSH13: Instruction = 0x6c; -/// place 14 byte item on stack -pub const PUSH14: Instruction = 0x6d; -/// place 15 byte item on stack -pub const PUSH15: Instruction = 0x6e; -/// place 16 byte item on stack -pub const PUSH16: Instruction = 0x6f; -/// place 17 byte item on stack -pub const PUSH17: Instruction = 0x70; -/// place 18 byte item on stack -pub const PUSH18: Instruction = 0x71; -/// place 19 byte item on stack -pub const PUSH19: Instruction = 0x72; -/// place 20 byte item on stack -pub const PUSH20: Instruction = 0x73; -/// place 21 byte item on stack -pub const PUSH21: Instruction = 0x74; -/// place 22 byte item on stack -pub const PUSH22: Instruction = 0x75; -/// place 23 byte item on stack -pub const PUSH23: Instruction = 0x76; -/// place 24 byte item on stack -pub const PUSH24: Instruction = 0x77; -/// place 25 byte item on stack -pub const PUSH25: Instruction = 0x78; -/// place 26 byte item on stack -pub const PUSH26: Instruction = 0x79; -/// place 27 byte item on stack -pub const PUSH27: Instruction = 0x7a; -/// place 28 byte item on stack -pub const PUSH28: Instruction = 0x7b; -/// place 29 byte item on stack -pub const PUSH29: Instruction = 0x7c; -/// place 30 byte item on stack -pub const PUSH30: Instruction = 0x7d; -/// place 31 byte item on stack -pub const PUSH31: Instruction = 0x7e; -/// place 32 byte item on stack -pub const PUSH32: Instruction = 0x7f; - -/// copies the highest item in the stack to the top of the stack -pub const DUP1: Instruction = 0x80; -/// copies the second highest item in the stack to the top of the stack -pub const DUP2: Instruction = 0x81; -/// copies the third highest item in the stack to the top of the stack -pub const DUP3: Instruction = 0x82; -/// copies the 4th highest item in the stack to the top of the stack -pub const DUP4: Instruction = 0x83; -/// copies the 5th highest item in the stack to the top of the stack -pub const DUP5: Instruction = 0x84; -/// copies the 6th highest item in the stack to the top of the stack -pub const DUP6: Instruction = 0x85; -/// copies the 7th highest item in the stack to the top of the stack -pub const DUP7: Instruction = 0x86; -/// copies the 8th highest item in the stack to the top of the stack -pub const DUP8: Instruction = 0x87; -/// copies the 9th highest item in the stack to the top of the stack -pub const DUP9: Instruction = 0x88; -/// copies the 10th highest item in the stack to the top of the stack -pub const DUP10: Instruction = 0x89; -/// copies the 11th highest item in the stack to the top of the stack -pub const DUP11: Instruction = 0x8a; -/// copies the 12th highest item in the stack to the top of the stack -pub const DUP12: Instruction = 0x8b; -/// copies the 13th highest item in the stack to the top of the stack -pub const DUP13: Instruction = 0x8c; -/// copies the 14th highest item in the stack to the top of the stack -pub const DUP14: Instruction = 0x8d; -/// copies the 15th highest item in the stack to the top of the stack -pub const DUP15: Instruction = 0x8e; -/// copies the 16th highest item in the stack to the top of the stack -pub const DUP16: Instruction = 0x8f; - -/// swaps the highest and second highest value on the stack -pub const SWAP1: Instruction = 0x90; -/// swaps the highest and third highest value on the stack -pub const SWAP2: Instruction = 0x91; -/// swaps the highest and 4th highest value on the stack -pub const SWAP3: Instruction = 0x92; -/// swaps the highest and 5th highest value on the stack -pub const SWAP4: Instruction = 0x93; -/// swaps the highest and 6th highest value on the stack -pub const SWAP5: Instruction = 0x94; -/// swaps the highest and 7th highest value on the stack -pub const SWAP6: Instruction = 0x95; -/// swaps the highest and 8th highest value on the stack -pub const SWAP7: Instruction = 0x96; -/// swaps the highest and 9th highest value on the stack -pub const SWAP8: Instruction = 0x97; -/// swaps the highest and 10th highest value on the stack -pub const SWAP9: Instruction = 0x98; -/// swaps the highest and 11th highest value on the stack -pub const SWAP10: Instruction = 0x99; -/// swaps the highest and 12th highest value on the stack -pub const SWAP11: Instruction = 0x9a; -/// swaps the highest and 13th highest value on the stack -pub const SWAP12: Instruction = 0x9b; -/// swaps the highest and 14th highest value on the stack -pub const SWAP13: Instruction = 0x9c; -/// swaps the highest and 15th highest value on the stack -pub const SWAP14: Instruction = 0x9d; -/// swaps the highest and 16th highest value on the stack -pub const SWAP15: Instruction = 0x9e; -/// swaps the highest and 17th highest value on the stack -pub const SWAP16: Instruction = 0x9f; - -/// Makes a log entry; no topics. -pub const LOG0: Instruction = 0xa0; -/// Makes a log entry; 1 topic. -pub const LOG1: Instruction = 0xa1; -/// Makes a log entry; 2 topics. -pub const LOG2: Instruction = 0xa2; -/// Makes a log entry; 3 topics. -pub const LOG3: Instruction = 0xa3; -/// Makes a log entry; 4 topics. -pub const LOG4: Instruction = 0xa4; /// Maximal number of topics for log instructions -pub const MAX_NO_OF_TOPICS : usize = 4; - -/// create a new account with associated code -pub const CREATE: Instruction = 0xf0; -/// message-call into an account -pub const CALL: Instruction = 0xf1; -/// message-call with another account's code only -pub const CALLCODE: Instruction = 0xf2; -/// halt execution returning output data -pub const RETURN: Instruction = 0xf3; -/// like CALLCODE but keeps caller's value and sender -pub const DELEGATECALL: Instruction = 0xf4; -/// create a new account and set creation address to sha3(sender + sha3(init code)) % 2**160 -pub const CREATE2: Instruction = 0xfb; -/// stop execution and revert state changes. Return output data. -pub const REVERT: Instruction = 0xfd; -/// like CALL but it does not take value, nor modify the state -pub const STATICCALL: Instruction = 0xfa; -/// halt execution and register account for later deletion -pub const SUICIDE: Instruction = 0xff; +pub const MAX_NO_OF_TOPICS: usize = 4; + +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_is_push() { + assert!(PUSH1.is_push()); + assert!(PUSH32.is_push()); + assert!(!DUP1.is_push()); + } + + #[test] + fn test_get_push_bytes() { + assert_eq!(PUSH1.push_bytes(), Some(1)); + assert_eq!(PUSH3.push_bytes(), Some(3)); + assert_eq!(PUSH32.push_bytes(), Some(32)); + } + + #[test] + fn test_get_dup_position() { + assert_eq!(DUP1.dup_position(), Some(0)); + assert_eq!(DUP5.dup_position(), Some(4)); + assert_eq!(DUP10.dup_position(), Some(9)); + } + + #[test] + fn test_get_swap_position() { + assert_eq!(SWAP1.swap_position(), Some(1)); + assert_eq!(SWAP5.swap_position(), Some(5)); + assert_eq!(SWAP10.swap_position(), Some(10)); + } + + #[test] + fn test_get_log_topics() { + assert_eq!(LOG0.log_topics(), Some(0)); + assert_eq!(LOG2.log_topics(), Some(2)); + assert_eq!(LOG4.log_topics(), Some(4)); + } +} diff --git a/ethcore/evm/src/interpreter/gasometer.rs b/ethcore/evm/src/interpreter/gasometer.rs index 85ea8ee487e..dbb33383793 100644 --- a/ethcore/evm/src/interpreter/gasometer.rs +++ b/ethcore/evm/src/interpreter/gasometer.rs @@ -113,7 +113,7 @@ impl Gasometer { current_mem_size: usize, ) -> vm::Result> { let schedule = ext.schedule(); - let tier = instructions::get_tier_idx(info.tier); + let tier = info.tier.idx(); let default_gas = Gas::from(schedule.tier_step_gas[tier]); let cost = match instruction { @@ -179,8 +179,8 @@ impl Gasometer { instructions::EXTCODECOPY => { Request::GasMemCopy(schedule.extcodecopy_base_gas.into(), mem_needed(stack.peek(1), stack.peek(3))?, Gas::from_u256(*stack.peek(3))?) }, - instructions::LOG0...instructions::LOG4 => { - let no_of_topics = instructions::get_log_topics(instruction); + instructions::LOG0 | instructions::LOG1 | instructions::LOG2 | instructions::LOG3 | instructions::LOG4 => { + let no_of_topics = instruction.log_topics().expect("log_topics always return some for LOG* instructions; qed"); let log_gas = schedule.log_gas + schedule.log_topic_gas * no_of_topics; let data_gas = overflowing!(Gas::from_u256(*stack.peek(1))?.overflow_mul(Gas::from(schedule.log_data_gas))); diff --git a/ethcore/evm/src/interpreter/mod.rs b/ethcore/evm/src/interpreter/mod.rs index ef9b3fb9734..1119869138c 100644 --- a/ethcore/evm/src/interpreter/mod.rs +++ b/ethcore/evm/src/interpreter/mod.rs @@ -64,7 +64,6 @@ struct CodeReader<'a> { } impl<'a> CodeReader<'a> { - /// Create new code reader - starting at position 0. fn new(code: &'a [u8]) -> Self { CodeReader { @@ -81,7 +80,7 @@ impl<'a> CodeReader<'a> { U256::from(&self.code[pos..max]) } - fn len (&self) -> usize { + fn len(&self) -> usize { self.code.len() } } @@ -124,24 +123,31 @@ impl vm::Vm for Interpreter { let mut gasometer = Gasometer::::new(Cost::from_u256(params.gas)?); let mut stack = VecStack::with_capacity(ext.schedule().stack_limit, U256::zero()); let mut reader = CodeReader::new(code); - let infos = &*instructions::INSTRUCTIONS; while reader.position < code.len() { - let instruction = code[reader.position]; + let opcode = code[reader.position]; + let instruction = Instruction::from_u8(opcode); reader.position += 1; // TODO: make compile-time removable if too much of a performance hit. do_trace = do_trace && ext.trace_next_instruction( - reader.position - 1, instruction, gasometer.current_gas.as_u256(), + reader.position - 1, opcode, gasometer.current_gas.as_u256(), ); - let info = &infos[instruction as usize]; + if instruction.is_none() { + return Err(vm::Error::BadInstruction { + instruction: opcode + }); + } + let instruction = instruction.expect("None case is checked above; qed"); + + let info = instruction.info(); self.verify_instruction(ext, instruction, info, &stack)?; // Calculate gas cost let requirements = gasometer.requirements(ext, instruction, info, &stack, self.mem.size())?; if do_trace { - ext.trace_prepare_execute(reader.position - 1, instruction, requirements.gas_cost.as_u256()); + ext.trace_prepare_execute(reader.position - 1, opcode, requirements.gas_cost.as_u256()); } gasometer.verify_gas(&requirements.gas_cost)?; @@ -227,13 +233,7 @@ impl Interpreter { ((instruction == instructions::SHL || instruction == instructions::SHR || instruction == instructions::SAR) && !schedule.have_bitwise_shifting) { return Err(vm::Error::BadInstruction { - instruction: instruction - }); - } - - if info.tier == instructions::GasPriceTier::Invalid { - return Err(vm::Error::BadInstruction { - instruction: instruction + instruction: instruction as u8 }); } @@ -396,7 +396,7 @@ impl Interpreter { }, instructions::DELEGATECALL => (¶ms.sender, ¶ms.address, true, CallType::DelegateCall), instructions::STATICCALL => (¶ms.address, &code_address, true, CallType::StaticCall), - _ => panic!(format!("Unexpected instruction {} in CALL branch.", instruction)) + _ => panic!(format!("Unexpected instruction {:?} in CALL branch.", instruction)) }; // clear return data buffer before creating new call frame. @@ -453,8 +453,8 @@ impl Interpreter { ext.suicide(&u256_to_address(&address))?; return Ok(InstructionResult::StopExecution); }, - instructions::LOG0...instructions::LOG4 => { - let no_of_topics = instructions::get_log_topics(instruction); + instructions::LOG0 | instructions::LOG1 | instructions::LOG2 | instructions::LOG3 | instructions::LOG4 => { + let no_of_topics = instruction.log_topics().expect("log_topics always return some for LOG* instructions; qed"); let offset = stack.pop_back(); let size = stack.pop_back(); @@ -464,8 +464,15 @@ impl Interpreter { .collect(); ext.log(topics, self.mem.read_slice(offset, size))?; }, - instructions::PUSH1...instructions::PUSH32 => { - let bytes = instructions::get_push_bytes(instruction); + instructions::PUSH1 | instructions::PUSH2 | instructions::PUSH3 | instructions::PUSH4 | + instructions::PUSH5 | instructions::PUSH6 | instructions::PUSH7 | instructions::PUSH8 | + instructions::PUSH9 | instructions::PUSH10 | instructions::PUSH11 | instructions::PUSH12 | + instructions::PUSH13 | instructions::PUSH14 | instructions::PUSH15 | instructions::PUSH16 | + instructions::PUSH17 | instructions::PUSH18 | instructions::PUSH19 | instructions::PUSH20 | + instructions::PUSH21 | instructions::PUSH22 | instructions::PUSH23 | instructions::PUSH24 | + instructions::PUSH25 | instructions::PUSH26 | instructions::PUSH27 | instructions::PUSH28 | + instructions::PUSH29 | instructions::PUSH30 | instructions::PUSH31 | instructions::PUSH32 => { + let bytes = instruction.push_bytes().expect("push_bytes always return some for PUSH* instructions"); let val = code.read(bytes); stack.push(val); }, @@ -609,73 +616,22 @@ impl Interpreter { instructions::GASLIMIT => { stack.push(ext.env_info().gas_limit.clone()); }, - _ => { - self.exec_stack_instruction(instruction, stack)?; - } - }; - Ok(InstructionResult::Ok) - } - - fn copy_data_to_memory(mem: &mut Vec, stack: &mut Stack, source: &[u8]) { - let dest_offset = stack.pop_back(); - let source_offset = stack.pop_back(); - let size = stack.pop_back(); - let source_size = U256::from(source.len()); - let output_end = match source_offset > source_size || size > source_size || source_offset + size > source_size { - true => { - let zero_slice = if source_offset > source_size { - mem.writeable_slice(dest_offset, size) - } else { - mem.writeable_slice(dest_offset + source_size - source_offset, source_offset + size - source_size) - }; - for i in zero_slice.iter_mut() { - *i = 0; - } - source.len() - }, - false => (size.low_u64() + source_offset.low_u64()) as usize - }; - - if source_offset < source_size { - let output_begin = source_offset.low_u64() as usize; - mem.write_slice(dest_offset, &source[output_begin..output_end]); - } - } - - fn verify_jump(&self, jump_u: U256, valid_jump_destinations: &BitSet) -> vm::Result { - let jump = jump_u.low_u64() as usize; - - if valid_jump_destinations.contains(jump) && U256::from(jump) == jump_u { - Ok(jump) - } else { - Err(vm::Error::BadJumpDestination { - destination: jump - }) - } - } - - fn is_zero(&self, val: &U256) -> bool { - val.is_zero() - } - - fn bool_to_u256(&self, val: bool) -> U256 { - if val { - U256::one() - } else { - U256::zero() - } - } + // Stack instructions - fn exec_stack_instruction(&self, instruction: Instruction, stack: &mut Stack) -> vm::Result<()> { - match instruction { - instructions::DUP1...instructions::DUP16 => { - let position = instructions::get_dup_position(instruction); + instructions::DUP1 | instructions::DUP2 | instructions::DUP3 | instructions::DUP4 | + instructions::DUP5 | instructions::DUP6 | instructions::DUP7 | instructions::DUP8 | + instructions::DUP9 | instructions::DUP10 | instructions::DUP11 | instructions::DUP12 | + instructions::DUP13 | instructions::DUP14 | instructions::DUP15 | instructions::DUP16 => { + let position = instruction.dup_position().expect("dup_position always return some for DUP* instructions"); let val = stack.peek(position).clone(); stack.push(val); }, - instructions::SWAP1...instructions::SWAP16 => { - let position = instructions::get_swap_position(instruction); + instructions::SWAP1 | instructions::SWAP2 | instructions::SWAP3 | instructions::SWAP4 | + instructions::SWAP5 | instructions::SWAP6 | instructions::SWAP7 | instructions::SWAP8 | + instructions::SWAP9 | instructions::SWAP10 | instructions::SWAP11 | instructions::SWAP12 | + instructions::SWAP13 | instructions::SWAP14 | instructions::SWAP15 | instructions::SWAP16 => { + let position = instruction.swap_position().expect("swap_position always return some for SWAP* instructions"); stack.swap_with_top(position) }, instructions::POP => { @@ -923,15 +879,60 @@ impl Interpreter { }; stack.push(result); }, - _ => { - return Err(vm::Error::BadInstruction { - instruction: instruction - }); - } + }; + Ok(InstructionResult::Ok) + } + + fn copy_data_to_memory(mem: &mut Vec, stack: &mut Stack, source: &[u8]) { + let dest_offset = stack.pop_back(); + let source_offset = stack.pop_back(); + let size = stack.pop_back(); + let source_size = U256::from(source.len()); + + let output_end = match source_offset > source_size || size > source_size || source_offset + size > source_size { + true => { + let zero_slice = if source_offset > source_size { + mem.writeable_slice(dest_offset, size) + } else { + mem.writeable_slice(dest_offset + source_size - source_offset, source_offset + size - source_size) + }; + for i in zero_slice.iter_mut() { + *i = 0; + } + source.len() + }, + false => (size.low_u64() + source_offset.low_u64()) as usize + }; + + if source_offset < source_size { + let output_begin = source_offset.low_u64() as usize; + mem.write_slice(dest_offset, &source[output_begin..output_end]); } - Ok(()) } + fn verify_jump(&self, jump_u: U256, valid_jump_destinations: &BitSet) -> vm::Result { + let jump = jump_u.low_u64() as usize; + + if valid_jump_destinations.contains(jump) && U256::from(jump) == jump_u { + Ok(jump) + } else { + Err(vm::Error::BadJumpDestination { + destination: jump + }) + } + } + + fn is_zero(&self, val: &U256) -> bool { + val.is_zero() + } + + fn bool_to_u256(&self, val: bool) -> U256 { + if val { + U256::one() + } else { + U256::zero() + } + } } fn get_and_reset_sign(value: U256) -> (U256, bool) { diff --git a/ethcore/evm/src/interpreter/shared_cache.rs b/ethcore/evm/src/interpreter/shared_cache.rs index d4e992c90e8..f4a7f47f90f 100644 --- a/ethcore/evm/src/interpreter/shared_cache.rs +++ b/ethcore/evm/src/interpreter/shared_cache.rs @@ -21,7 +21,7 @@ use ethereum_types::H256; use parking_lot::Mutex; use memory_cache::MemoryLruCache; use bit_set::BitSet; -use super::super::instructions; +use super::super::instructions::{self, Instruction}; const DEFAULT_CACHE_SIZE: usize = 4 * 1024 * 1024; @@ -70,12 +70,14 @@ impl SharedCache { let mut position = 0; while position < code.len() { - let instruction = code[position]; - - if instruction == instructions::JUMPDEST { - jump_dests.insert(position); - } else if instructions::is_push(instruction) { - position += instructions::get_push_bytes(instruction); + let instruction = Instruction::from_u8(code[position]); + + if let Some(instruction) = instruction { + if instruction == instructions::JUMPDEST { + jump_dests.insert(position); + } else if let Some(push_bytes) = instruction.push_bytes() { + position += push_bytes; + } } position += 1; } diff --git a/ethcore/evm/src/lib.rs b/ethcore/evm/src/lib.rs index 6eca25f42f5..cd326a317ec 100644 --- a/ethcore/evm/src/lib.rs +++ b/ethcore/evm/src/lib.rs @@ -52,6 +52,6 @@ pub use vm::{ GasLeft, ReturnData }; pub use self::evm::{Finalize, FinalizationResult, CostType}; -pub use self::instructions::{InstructionInfo, INSTRUCTIONS, push_bytes}; +pub use self::instructions::{InstructionInfo, Instruction}; pub use self::vmtype::VMType; pub use self::factory::Factory; diff --git a/ethcore/light/Cargo.toml b/ethcore/light/Cargo.toml index ab347c62e83..ac3a70c3d82 100644 --- a/ethcore/light/Cargo.toml +++ b/ethcore/light/Cargo.toml @@ -35,7 +35,7 @@ keccak-hash = { path = "../../util/hash" } triehash = { path = "../../util/triehash" } kvdb = { path = "../../util/kvdb" } memory-cache = { path = "../../util/memory_cache" } -error-chain = { version = "0.11", default-features = false } +error-chain = { version = "0.12", default-features = false } [dev-dependencies] ethcore = { path = "..", features = ["test-helpers"] } diff --git a/ethcore/private-tx/Cargo.toml b/ethcore/private-tx/Cargo.toml index 441c9882e29..e32c81bc26f 100644 --- a/ethcore/private-tx/Cargo.toml +++ b/ethcore/private-tx/Cargo.toml @@ -6,7 +6,7 @@ license = "GPL-3.0" authors = ["Parity Technologies "] [dependencies] -error-chain = { version = "0.11", default-features = false } +error-chain = { version = "0.12", default-features = false } ethabi = "5.1" ethabi-contract = "5.0" ethabi-derive = "5.0" diff --git a/ethcore/service/Cargo.toml b/ethcore/service/Cargo.toml index 634ee55dba4..e9f16bc7a29 100644 --- a/ethcore/service/Cargo.toml +++ b/ethcore/service/Cargo.toml @@ -5,7 +5,7 @@ authors = ["Parity Technologies "] [dependencies] ansi_term = "0.10" -error-chain = { version = "0.11", default-features = false } +error-chain = { version = "0.12", default-features = false } ethcore = { path = ".." } ethcore-io = { path = "../../util/io" } ethcore-private-tx = { path = "../private-tx" } diff --git a/ethcore/src/account_provider/mod.rs b/ethcore/src/account_provider/mod.rs index a12aec8676b..e4289c60a57 100644 --- a/ethcore/src/account_provider/mod.rs +++ b/ethcore/src/account_provider/mod.rs @@ -20,21 +20,23 @@ mod stores; use self::stores::{AddressBook, DappsSettingsStore, NewDappsPolicy}; -use std::fmt; use std::collections::{HashMap, HashSet}; +use std::fmt; use std::time::{Instant, Duration}; -use parking_lot::RwLock; + +use ethstore::accounts_dir::MemoryDirectory; +use ethstore::ethkey::{Address, Message, Public, Secret, Password, Random, Generator}; +use ethjson::misc::AccountMeta; use ethstore::{ SimpleSecretStore, SecretStore, Error as SSError, EthStore, EthMultiStore, random_string, SecretVaultRef, StoreAccountRef, OpaqueSecret, }; -use ethstore::accounts_dir::MemoryDirectory; -use ethstore::ethkey::{Address, Message, Public, Secret, Password, Random, Generator}; -use ethjson::misc::AccountMeta; -use hardware_wallet::{Error as HardwareError, HardwareWalletManager, KeyPath, TransactionInfo}; -use super::transaction::{Action, Transaction}; +use parking_lot::RwLock; + pub use ethstore::ethkey::Signature; pub use ethstore::{Derivation, IndexDerivation, KeyFile}; +pub use hardware_wallet::{Error as HardwareError, HardwareWalletManager, KeyPath, TransactionInfo}; +pub use super::transaction::{Action, Transaction}; /// Type of unlock. #[derive(Clone, PartialEq)] @@ -165,6 +167,7 @@ impl AccountProvider { /// Creates new account provider. pub fn new(sstore: Box, settings: AccountProviderSettings) -> Self { let mut hardware_store = None; + if settings.enable_hardware_wallets { match HardwareWalletManager::new() { Ok(manager) => { @@ -289,8 +292,12 @@ impl AccountProvider { /// Returns addresses of hardware accounts. pub fn hardware_accounts(&self) -> Result, Error> { - let accounts = self.hardware_store.as_ref().map_or(Vec::new(), |h| h.list_wallets()); - Ok(accounts.into_iter().map(|a| a.address).collect()) + if let Some(accounts) = self.hardware_store.as_ref().map(|h| h.list_wallets()) { + if !accounts.is_empty() { + return Ok(accounts.into_iter().map(|a| a.address).collect()); + } + } + Err(SSError::Custom("No hardware wallet accounts were found".into())) } /// Get a list of paths to locked hardware wallets @@ -301,7 +308,7 @@ impl AccountProvider { Some(Ok(s)) => Ok(s), } } - + /// Provide a pin to a locked hardware wallet on USB path to unlock it pub fn hardware_pin_matrix_ack(&self, path: &str, pin: &str) -> Result { match self.hardware_store.as_ref().map(|h| h.pin_matrix_ack(path, pin)) { diff --git a/ethcore/src/blockchain/blockchain.rs b/ethcore/src/blockchain/blockchain.rs index fa79bd74556..e10368526bd 100644 --- a/ethcore/src/blockchain/blockchain.rs +++ b/ethcore/src/blockchain/blockchain.rs @@ -1450,18 +1450,24 @@ impl BlockChain { /// Returns general blockchain information pub fn chain_info(&self) -> BlockChainInfo { + // Make sure to call internal methods first to avoid + // recursive locking of `best_block`. + let first_block_hash = self.first_block(); + let first_block_number = self.first_block_number().into(); + let genesis_hash = self.genesis_hash(); + // ensure data consistencly by locking everything first let best_block = self.best_block.read(); let best_ancient_block = self.best_ancient_block.read(); BlockChainInfo { total_difficulty: best_block.total_difficulty, pending_total_difficulty: best_block.total_difficulty, - genesis_hash: self.genesis_hash(), + genesis_hash, best_block_hash: best_block.header.hash(), best_block_number: best_block.header.number(), best_block_timestamp: best_block.header.timestamp(), - first_block_hash: self.first_block(), - first_block_number: From::from(self.first_block_number()), + first_block_hash, + first_block_number, ancient_block_hash: best_ancient_block.as_ref().map(|b| b.hash), ancient_block_number: best_ancient_block.as_ref().map(|b| b.number), } diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 8d8b22c6a5d..f52afdcadec 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -75,7 +75,7 @@ extern crate ethcore_transaction as transaction; extern crate ethereum_types; extern crate ethjson; extern crate ethkey; -extern crate hardware_wallet; + extern crate hashdb; extern crate itertools; extern crate kvdb; @@ -99,7 +99,6 @@ extern crate ansi_term; extern crate unexpected; extern crate util_error; extern crate snappy; - extern crate ethabi; extern crate rustc_hex; extern crate stats; @@ -112,6 +111,12 @@ extern crate journaldb; #[cfg(any(test, feature = "json-tests", feature = "test-helpers"))] extern crate tempdir; +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))] +extern crate hardware_wallet; + +#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))] +extern crate fake_hardware_wallet as hardware_wallet; + #[macro_use] extern crate ethabi_derive; #[macro_use] diff --git a/ethkey/Cargo.toml b/ethkey/Cargo.toml index c93af468c50..ef828ac30df 100644 --- a/ethkey/Cargo.toml +++ b/ethkey/Cargo.toml @@ -13,7 +13,7 @@ lazy_static = "1.0" log = "0.3" mem = { path = "../util/mem" } parity-wordlist = "1.2" -quick-error = "1.2" +quick-error = "1.2.2" rand = "0.4" rustc-hex = "1.0" serde = "1.0" diff --git a/evmbin/src/display/json.rs b/evmbin/src/display/json.rs index ccee9c37170..613be1d2243 100644 --- a/evmbin/src/display/json.rs +++ b/evmbin/src/display/json.rs @@ -121,13 +121,13 @@ impl trace::VMTracer for Informant { } fn trace_executed(&mut self, gas_used: U256, stack_push: &[U256], mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) { - let info = ::evm::INSTRUCTIONS[self.instruction as usize]; + let info = ::evm::Instruction::from_u8(self.instruction).map(|i| i.info()); let trace = format!( "{{\"pc\":{pc},\"op\":{op},\"opName\":\"{name}\",\"gas\":\"0x{gas:x}\",\"gasCost\":\"0x{gas_cost:x}\",\"memory\":{memory},\"stack\":{stack},\"storage\":{storage},\"depth\":{depth}}}", pc = self.pc, op = self.instruction, - name = info.name, + name = info.map(|i| i.name).unwrap_or(""), gas = gas_used.saturating_add(self.gas_cost), gas_cost = self.gas_cost, memory = self.memory(), @@ -141,7 +141,8 @@ impl trace::VMTracer for Informant { self.gas_used = gas_used; let len = self.stack.len(); - self.stack.truncate(if len > info.args { len - info.args } else { 0 }); + let info_args = info.map(|i| i.args).unwrap_or(0); + self.stack.truncate(if len > info_args { len - info_args } else { 0 }); self.stack.extend_from_slice(stack_push); // TODO [ToDr] Align memory? diff --git a/evmbin/src/display/std_json.rs b/evmbin/src/display/std_json.rs index 6c4dac1626a..b3533ea2c4e 100644 --- a/evmbin/src/display/std_json.rs +++ b/evmbin/src/display/std_json.rs @@ -118,7 +118,7 @@ impl trace::VMTracer for Informant { type Output = (); fn trace_next_instruction(&mut self, pc: usize, instruction: u8, current_gas: U256) -> bool { - let info = ::evm::INSTRUCTIONS[instruction as usize]; + let info = ::evm::Instruction::from_u8(instruction).map(|i| i.info()); self.instruction = instruction; let storage = self.storage(); let stack = self.stack(); @@ -128,7 +128,7 @@ impl trace::VMTracer for Informant { "{{\"pc\":{pc},\"op\":{op},\"opName\":\"{name}\",\"gas\":\"0x{gas:x}\",\"stack\":{stack},\"storage\":{storage},\"depth\":{depth}}}", pc = pc, op = instruction, - name = info.name, + name = info.map(|i| i.name).unwrap_or(""), gas = current_gas, stack = stack, storage = storage, @@ -142,10 +142,11 @@ impl trace::VMTracer for Informant { } fn trace_executed(&mut self, _gas_used: U256, stack_push: &[U256], _mem_diff: Option<(usize, &[u8])>, store_diff: Option<(U256, U256)>) { - let info = ::evm::INSTRUCTIONS[self.instruction as usize]; + let info = ::evm::Instruction::from_u8(self.instruction).map(|i| i.info()); let len = self.stack.len(); - self.stack.truncate(if len > info.args { len - info.args } else { 0 }); + let info_args = info.map(|i| i.args).unwrap_or(0); + self.stack.truncate(if len > info_args { len - info_args } else { 0 }); self.stack.extend_from_slice(stack_push); if let Some((pos, val)) = store_diff { diff --git a/miner/Cargo.toml b/miner/Cargo.toml index e692d2f7083..53771e5c16e 100644 --- a/miner/Cargo.toml +++ b/miner/Cargo.toml @@ -16,7 +16,7 @@ url = "1" # Miner ansi_term = "0.10" -error-chain = "0.11" +error-chain = "0.12" ethcore-transaction = { path = "../ethcore/transaction" } ethereum-types = "0.3" futures = "0.1" diff --git a/parity/informant.rs b/parity/informant.rs index 1840be3badd..6f1227592f7 100644 --- a/parity/informant.rs +++ b/parity/informant.rs @@ -335,7 +335,13 @@ impl Informant { match sync_info.as_ref() { Some(ref sync_info) => format!("{}{}/{} peers", match importing { - true => format!("{} ", paint(Green.bold(), format!("{:>8}", format!("#{}", sync_info.last_imported_block_number)))), + true => format!("{}", + if self.target.executes_transactions() { + paint(Green.bold(), format!("{:>8} ", format!("#{}", sync_info.last_imported_block_number))) + } else { + String::new() + } + ), false => match sync_info.last_imported_old_block_number { Some(number) => format!("{} ", paint(Yellow.bold(), format!("{:>8}", format!("#{}", number)))), None => String::new(), diff --git a/rpc/Cargo.toml b/rpc/Cargo.toml index d227f45f535..8487844bd6f 100644 --- a/rpc/Cargo.toml +++ b/rpc/Cargo.toml @@ -64,6 +64,12 @@ rlp = { path = "../util/rlp" } stats = { path = "../util/stats" } vm = { path = "../ethcore/vm" } +[target.'cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))'.dependencies] +hardware-wallet = { path = "../hw" } + +[target.'cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))'.dependencies] +fake-hardware-wallet = { path = "../util/fake-hardware-wallet" } + [dev-dependencies] ethcore = { path = "../ethcore", features = ["test-helpers"] } ethcore-network = { path = "../util/network" } diff --git a/rpc/src/lib.rs b/rpc/src/lib.rs index 2d49a8c7717..6356dc28448 100644 --- a/rpc/src/lib.rs +++ b/rpc/src/lib.rs @@ -58,17 +58,21 @@ extern crate ethcore_transaction as transaction; extern crate ethereum_types; extern crate ethkey; extern crate ethstore; -extern crate vm; extern crate fetch; +extern crate keccak_hash as hash; extern crate node_health; extern crate parity_reactor; extern crate parity_updater as updater; extern crate parity_version as version; +extern crate patricia_trie as trie; extern crate rlp; extern crate stats; -extern crate keccak_hash as hash; +extern crate vm; + +#[cfg(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android"))] extern crate hardware_wallet; -extern crate patricia_trie as trie; +#[cfg(not(any(target_os = "linux", target_os = "macos", target_os = "windows", target_os = "android")))] +extern crate fake_hardware_wallet as hardware_wallet; #[macro_use] extern crate log; diff --git a/rpc/src/v1/helpers/dispatch.rs b/rpc/src/v1/helpers/dispatch.rs index b0e69edfb7a..c6f10400a58 100644 --- a/rpc/src/v1/helpers/dispatch.rs +++ b/rpc/src/v1/helpers/dispatch.rs @@ -24,7 +24,6 @@ use light::cache::Cache as LightDataCache; use light::client::LightChainClient; use light::on_demand::{request, OnDemand}; use light::TransactionQueue as LightTransactionQueue; -use rlp; use hash::keccak; use ethereum_types::{H256, H520, Address, U256}; use bytes::Bytes; @@ -52,6 +51,7 @@ use v1::types::{ SignRequest as RpcSignRequest, DecryptRequest as RpcDecryptRequest, }; +use rlp; pub use self::nonce::Reservations; @@ -323,7 +323,7 @@ impl LightDispatcher { x.map(move |acc| acc.map_or(account_start_nonce, |acc| acc.nonce)) .map_err(|_| errors::no_light_peers()) ), - None => Box::new(future::err(errors::network_disabled())) + None => Box::new(future::err(errors::network_disabled())) } } } @@ -699,7 +699,6 @@ pub fn execute( if accounts.is_hardware_address(&address) { return Box::new(future::err(errors::unsupported("Decrypting via hardware wallets is not supported.", None))); } - let res = decrypt(&accounts, address, data, pass) .map(|result| result .map(RpcBytes) @@ -737,8 +736,8 @@ fn hardware_signature(accounts: &AccountProvider, address: Address, t: Transacti SignedTransaction::new(t.with_signature(signature, chain_id)) .map_err(|e| { - debug!(target: "miner", "Hardware wallet has produced invalid signature: {}", e); - errors::account("Invalid signature generated", e) + debug!(target: "miner", "Hardware wallet has produced invalid signature: {}", e); + errors::account("Invalid signature generated", e) }) } diff --git a/rpc/src/v1/impls/light/parity.rs b/rpc/src/v1/impls/light/parity.rs index 6e93132b922..9ef316b70be 100644 --- a/rpc/src/v1/impls/light/parity.rs +++ b/rpc/src/v1/impls/light/parity.rs @@ -305,8 +305,8 @@ impl Parity for ParityClient { fn pending_transactions_stats(&self) -> Result> { let stats = self.light_dispatch.sync.transactions_stats(); Ok(stats.into_iter() - .map(|(hash, stats)| (hash.into(), stats.into())) - .collect() + .map(|(hash, stats)| (hash.into(), stats.into())) + .collect() ) } diff --git a/rpc/src/v1/impls/parity.rs b/rpc/src/v1/impls/parity.rs index d7c26014edd..acafbb1cd68 100644 --- a/rpc/src/v1/impls/parity.rs +++ b/rpc/src/v1/impls/parity.rs @@ -34,7 +34,6 @@ use ethcore::state::StateInfo; use ethcore_logger::RotatingLogger; use node_health::{NodeHealth, Health}; use updater::{Service as UpdateService}; - use jsonrpc_core::{BoxFuture, Result}; use jsonrpc_core::futures::{future, Future}; use jsonrpc_macros::Trailing; @@ -53,7 +52,7 @@ use v1::types::{ use Host; /// Parity implementation. -pub struct ParityClient { +pub struct ParityClient { client: Arc, miner: Arc, updater: Arc, @@ -143,11 +142,11 @@ impl Parity for ParityClient where .collect() ) } - + fn locked_hardware_accounts_info(&self) -> Result> { self.accounts.locked_hardware_accounts().map_err(|e| errors::account("Error communicating with hardware wallet.", e)) } - + fn default_account(&self, meta: Self::Metadata) -> Result { let dapp_id = meta.dapp_id(); @@ -312,9 +311,9 @@ impl Parity for ParityClient where ); Ok(ready_transactions - .into_iter() - .map(|t| Transaction::from_pending(t.pending().clone(), block_number, self.eip86_transition)) - .collect() + .into_iter() + .map(|t| Transaction::from_pending(t.pending().clone(), block_number, self.eip86_transition)) + .collect() ) } @@ -323,9 +322,9 @@ impl Parity for ParityClient where let all_transactions = self.miner.queued_transactions(); Ok(all_transactions - .into_iter() - .map(|t| Transaction::from_pending(t.pending().clone(), block_number, self.eip86_transition)) - .collect() + .into_iter() + .map(|t| Transaction::from_pending(t.pending().clone(), block_number, self.eip86_transition)) + .collect() ) } @@ -336,8 +335,8 @@ impl Parity for ParityClient where fn pending_transactions_stats(&self) -> Result> { let stats = self.sync.transactions_stats(); Ok(stats.into_iter() - .map(|(hash, stats)| (hash.into(), stats.into())) - .collect() + .map(|(hash, stats)| (hash.into(), stats.into())) + .collect() ) } @@ -345,9 +344,9 @@ impl Parity for ParityClient where let transactions = self.miner.local_transactions(); let block_number = self.client.chain_info().best_block_number; Ok(transactions - .into_iter() - .map(|(hash, status)| (hash.into(), LocalTransactionStatus::from(status, block_number, self.eip86_transition))) - .collect() + .into_iter() + .map(|(hash, status)| (hash.into(), LocalTransactionStatus::from(status, block_number, self.eip86_transition))) + .collect() ) } diff --git a/rpc/src/v1/impls/parity_accounts.rs b/rpc/src/v1/impls/parity_accounts.rs index 5a9aef3bafc..f9be594ad8b 100644 --- a/rpc/src/v1/impls/parity_accounts.rs +++ b/rpc/src/v1/impls/parity_accounts.rs @@ -22,7 +22,6 @@ use ethereum_types::Address; use ethkey::{Brain, Generator, Secret}; use ethstore::KeyFile; use ethcore::account_provider::AccountProvider; - use jsonrpc_core::Result; use v1::helpers::errors; use v1::traits::ParityAccounts; diff --git a/snap/snapcraft.yaml b/snap/snapcraft.yaml index c0ca5507bec..d67f6448af8 100644 --- a/snap/snapcraft.yaml +++ b/snap/snapcraft.yaml @@ -30,6 +30,8 @@ parts: parity: source: . plugin: rust + # rust-channel: stable # @TODO enable after https://bugs.launchpad.net/snapcraft/+bug/1778530 + rust-revision: 1.26.2 # @TODO remove after https://bugs.launchpad.net/snapcraft/+bug/1778530 build-attributes: [no-system-libraries] build-packages: [g++, libudev-dev, libssl-dev, make, pkg-config] stage-packages: [libc6, libssl1.0.0, libudev1, libstdc++6] diff --git a/transaction-pool/Cargo.toml b/transaction-pool/Cargo.toml index 0ba1790a47f..8af887d3cb9 100644 --- a/transaction-pool/Cargo.toml +++ b/transaction-pool/Cargo.toml @@ -6,7 +6,7 @@ license = "GPL-3.0" authors = ["Parity Technologies "] [dependencies] -error-chain = "0.11" +error-chain = "0.12" log = "0.3" smallvec = "0.4" trace-time = { path = "../util/trace-time", version = "0.1" } diff --git a/util/error/Cargo.toml b/util/error/Cargo.toml index d9da3e5c516..442935a5473 100644 --- a/util/error/Cargo.toml +++ b/util/error/Cargo.toml @@ -7,5 +7,5 @@ authors = ["Parity Technologies "] rlp = { path = "../rlp" } kvdb = { path = "../kvdb" } ethereum-types = "0.3" -error-chain = { version = "0.11", default-features = false } +error-chain = { version = "0.12", default-features = false } rustc-hex = "1.0" diff --git a/util/fake-hardware-wallet/Cargo.toml b/util/fake-hardware-wallet/Cargo.toml new file mode 100644 index 00000000000..600cd098c5d --- /dev/null +++ b/util/fake-hardware-wallet/Cargo.toml @@ -0,0 +1,10 @@ +[package] +description = "Fake hardware-wallet, for OS' that don't support libusb" +name = "fake-hardware-wallet" +version = "0.0.1" +license = "GPL-3.0" +authors = ["Parity Technologies "] + +[dependencies] +ethereum-types = "0.3" +ethkey = { path = "../../ethkey" } diff --git a/util/fake-hardware-wallet/src/lib.rs b/util/fake-hardware-wallet/src/lib.rs new file mode 100644 index 00000000000..2bf905d7bf7 --- /dev/null +++ b/util/fake-hardware-wallet/src/lib.rs @@ -0,0 +1,101 @@ +// 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 . + +//! Dummy module for platforms that does not provide support for hardware wallets (libusb) + +extern crate ethereum_types; +extern crate ethkey; + +use std::fmt; +use ethereum_types::U256; +use ethkey::{Address, Signature}; + +pub struct WalletInfo { + pub address: Address, + pub name: String, + pub manufacturer: String, +} + +#[derive(Debug)] +/// `ErrorType` for devices with no `hardware wallet` +pub enum Error { + NoWallet, + KeyNotFound, +} + +pub struct TransactionInfo { + /// Nonce + pub nonce: U256, + /// Gas price + pub gas_price: U256, + /// Gas limit + pub gas_limit: U256, + /// Receiver + pub to: Option
, + /// Value + pub value: U256, + /// Data + pub data: Vec, + /// Chain ID + pub chain_id: Option, +} + +pub enum KeyPath { + /// Ethereum. + Ethereum, + /// Ethereum classic. + EthereumClassic, +} + +/// `HardwareWalletManager` for devices with no `hardware wallet` +pub struct HardwareWalletManager; + +impl HardwareWalletManager { + pub fn new() -> Result { + Err(Error::NoWallet) + } + + pub fn set_key_path(&self, _key_path: KeyPath) {} + + pub fn wallet_info(&self, _: &Address) -> Option { + None + } + + pub fn list_wallets(&self) -> Vec { + Vec::with_capacity(0) + } + + pub fn list_locked_wallets(&self) -> Result, Error> { + Err(Error::NoWallet) + } + + pub fn pin_matrix_ack(&self, _: &str, _: &str) -> Result { + Err(Error::NoWallet) + } + + pub fn sign_transaction(&self, _address: &Address, _transaction: &TransactionInfo, _rlp_transaction: &[u8]) -> Result { + Err(Error::NoWallet) } + + pub fn sign_message(&self, _address: &Address, _msg: &[u8]) -> Result { + Err(Error::NoWallet) + } +} + +impl fmt::Display for Error { + fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result { + write!(f, "No hardware wallet!!") + } +} diff --git a/util/kvdb/Cargo.toml b/util/kvdb/Cargo.toml index 820f6e35fb4..859ebde20cf 100644 --- a/util/kvdb/Cargo.toml +++ b/util/kvdb/Cargo.toml @@ -5,5 +5,5 @@ authors = ["Parity Technologies "] [dependencies] elastic-array = "0.10" -error-chain = { version = "0.11", default-features = false } +error-chain = { version = "0.12", default-features = false } ethcore-bytes = { path = "../bytes" } diff --git a/util/migration-rocksdb/Cargo.toml b/util/migration-rocksdb/Cargo.toml index 3f0b8e75204..dd6ea3ef2b6 100644 --- a/util/migration-rocksdb/Cargo.toml +++ b/util/migration-rocksdb/Cargo.toml @@ -8,7 +8,7 @@ log = "0.3" macros = { path = "../macros" } kvdb = { path = "../kvdb" } kvdb-rocksdb = { path = "../kvdb-rocksdb" } -error-chain = { version = "0.11", default-features = false } +error-chain = { version = "0.12", default-features = false } [dev-dependencies] tempdir = "0.3" diff --git a/util/network-devp2p/Cargo.toml b/util/network-devp2p/Cargo.toml index 4a5d2d942ec..4b094da95b6 100644 --- a/util/network-devp2p/Cargo.toml +++ b/util/network-devp2p/Cargo.toml @@ -34,7 +34,7 @@ snappy = { git = "https://github.com/paritytech/rust-snappy" } serde = "1.0" serde_json = "1.0" serde_derive = "1.0" -error-chain = { version = "0.11", default-features = false } +error-chain = { version = "0.12", default-features = false } [dev-dependencies] tempdir = "0.3" diff --git a/util/network/Cargo.toml b/util/network/Cargo.toml index 4ae699098dd..6259e04af86 100644 --- a/util/network/Cargo.toml +++ b/util/network/Cargo.toml @@ -7,7 +7,7 @@ version = "1.12.0" authors = ["Parity Technologies "] [dependencies] -error-chain = { version = "0.11", default-features = false } +error-chain = { version = "0.12", default-features = false } ethcore-crypto = { path = "../../ethcore/crypto" } ethcore-io = { path = "../io" } ethereum-types = "0.3"