diff --git a/Cargo.lock b/Cargo.lock index a1f84828ee..ea2778f18e 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -51,6 +51,17 @@ version = "0.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "739f4a8db6605981345c5654f3a85b056ce52f37a39d34da03f25bf2151ea16e" +[[package]] +name = "ahash" +version = "0.7.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fcb51a0695d8f838b1ee009b3fbf66bda078cd64590202a864a8f3e8c4315c47" +dependencies = [ + "getrandom 0.2.3", + "once_cell", + "version_check", +] + [[package]] name = "arrayvec" version = "0.7.1" @@ -60,8 +71,7 @@ checksum = "be4dc07131ffa69b8072d35f5007352af944213cde02545e2103680baed38fcd" [[package]] name = "auto_impl" version = "0.4.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42cbf586c80ada5e5ccdecae80d3ef0854f224e2dd74435f8d87e6831b8d0a38" +source = "git+https://github.com/dimpolo/auto_impl.git?rev=61874ef#61874eff148e8cc6a8f54d9e263987ac095d7a81" dependencies = [ "proc-macro-error", "proc-macro2", @@ -144,7 +154,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "18dda7dc709193c0d86a1a51050a926dc3df1cf262ec46a23a25dba421ea1924" dependencies = [ "borsh-derive", - "hashbrown", + "hashbrown 0.9.1", ] [[package]] @@ -182,6 +192,12 @@ dependencies = [ "syn", ] +[[package]] +name = "bumpalo" +version = "3.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f1e260c3a9040a7c19a12468758f4c16f31a81a1fe087482be9570ec864bb6c" + [[package]] name = "byte-slice-cast" version = "1.2.0" @@ -382,8 +398,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7fcd999463524c52659517fe2cea98493cfe485d10565e7b0fb07dbba7ad2753" dependencies = [ "cfg-if", + "js-sys", "libc", "wasi 0.10.2+wasi-snapshot-preview1", + "wasm-bindgen", ] [[package]] @@ -398,7 +416,16 @@ version = "0.9.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d7afe4a420e3fe79967a00898cc1f4db7c8a49a9333a29f8a4bd76a253d5cd04" dependencies = [ - "ahash", + "ahash 0.4.7", +] + +[[package]] +name = "hashbrown" +version = "0.11.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ab5ef0d4909ef3724cc8cce6ccc8572c5c817592e9285f5464f8e86f8bd3726e" +dependencies = [ + "ahash 0.7.6", ] [[package]] @@ -473,6 +500,15 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "js-sys" +version = "0.3.55" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7cc9ffccd38c451a86bf13657df244e9c3f37493cce8e5e21e940963777acc84" +dependencies = [ + "wasm-bindgen", +] + [[package]] name = "keccak" version = "0.1.0" @@ -494,6 +530,15 @@ version = "0.2.105" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "869d572136620d55835903746bcb5cdc54cb2851fd0aeec53220b4bb65ef3013" +[[package]] +name = "log" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "51b9bbe6c47d51fc3e1a9b945965946b4c44142ab8792c50835a980d362c2710" +dependencies = [ + "cfg-if", +] + [[package]] name = "num" version = "0.4.0" @@ -992,6 +1037,7 @@ version = "0.3.1" dependencies = [ "auto_impl", "bytes", + "hashbrown 0.11.2", "hex", "num_enum", "primitive-types", @@ -1006,6 +1052,7 @@ version = "0.1.0" dependencies = [ "bytes", "hash-db", + "hashbrown 0.11.2", "hex", "indicatif", "plain_hasher", @@ -1059,10 +1106,21 @@ dependencies = [ "parity-crypto", "primitive-types", "ripemd160", + "secp256k1", "sha2", + "sha3", "substrate-bn", ] +[[package]] +name = "revm_wasm" +version = "0.1.0" +dependencies = [ + "getrandom 0.2.3", + "revm", + "wasm-bindgen", +] + [[package]] name = "ripemd160" version = "0.9.1" @@ -1361,6 +1419,60 @@ version = "0.10.2+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fd6fbd9a79829dd1ad0cc20627bf1ed606756a7f77edff7b66b7064f9cb327c6" +[[package]] +name = "wasm-bindgen" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "632f73e236b219150ea279196e54e610f5dbafa5d61786303d4da54f84e47fce" +dependencies = [ + "cfg-if", + "wasm-bindgen-macro", +] + +[[package]] +name = "wasm-bindgen-backend" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a317bf8f9fba2476b4b2c85ef4c4af8ff39c3c7f0cdfeed4f82c34a880aa837b" +dependencies = [ + "bumpalo", + "lazy_static", + "log", + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-macro" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d56146e7c495528bf6587663bea13a8eb588d39b36b679d83972e1a2dbbdacf9" +dependencies = [ + "quote", + "wasm-bindgen-macro-support", +] + +[[package]] +name = "wasm-bindgen-macro-support" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7803e0eea25835f8abdc585cd3021b3deb11543c6fe226dcd30b228857c5c5ab" +dependencies = [ + "proc-macro2", + "quote", + "syn", + "wasm-bindgen-backend", + "wasm-bindgen-shared", +] + +[[package]] +name = "wasm-bindgen-shared" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0237232789cf037d5480773fe568aac745bfe2afbc11a863e97901780a6b47cc" + [[package]] name = "winapi" version = "0.3.9" diff --git a/Cargo.toml b/Cargo.toml index 994b7f162f..64cffc0023 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,7 +1,9 @@ + [workspace] +resolver = "2" members = [ "crates/*", "bins/*", ] -default-members = ["crates/revm"] \ No newline at end of file +default-members = ["crates/revm"] diff --git a/bins/revm-ethereum-tests/Cargo.toml b/bins/revm-ethereum-tests/Cargo.toml index 8355da7433..237aed1f10 100644 --- a/bins/revm-ethereum-tests/Cargo.toml +++ b/bins/revm-ethereum-tests/Cargo.toml @@ -22,3 +22,4 @@ sha3 = {version = "0.9", default-features = false} thiserror = "1.0" triehash = "0.8" walkdir = "2.3" +hashbrown = "0.11" \ No newline at end of file diff --git a/bins/revm-ethereum-tests/src/merkle_trie.rs b/bins/revm-ethereum-tests/src/merkle_trie.rs index 7e77958930..73d2e705bf 100644 --- a/bins/revm-ethereum-tests/src/merkle_trie.rs +++ b/bins/revm-ethereum-tests/src/merkle_trie.rs @@ -9,7 +9,7 @@ use rlp::RlpStream; use sha3::{Digest, Keccak256}; use revm::AccountInfo; -use std::collections::HashMap as Map; +use hashbrown::HashMap as Map; pub fn merkle_trie_root( accounts: &Map, diff --git a/bins/revm-ethereum-tests/src/runner.rs b/bins/revm-ethereum-tests/src/runner.rs index b78cde98bc..74922ea5fa 100644 --- a/bins/revm-ethereum-tests/src/runner.rs +++ b/bins/revm-ethereum-tests/src/runner.rs @@ -68,7 +68,8 @@ pub fn execute_test_suit( if path.file_name() == Some(OsStr::new("CALLBlake2f_MaxRounds.json")) { return Ok(()); } - //*/ + // */ + let json_reader = std::fs::read(&path).unwrap(); let suit: TestSuit = serde_json::from_reader(&*json_reader)?; let skip_test_unit: HashSet<_> = vec![ @@ -251,7 +252,7 @@ pub fn run(test_files: Vec, i let mut joins = Vec::new(); let queue = Arc::new(Mutex::new((0, test_files))); let elapsed = Arc::new(Mutex::new(std::time::Duration::ZERO)); - for _ in 0..10 { + for _ in 0..1 { let queue = queue.clone(); let endjob = endjob.clone(); let console_bar = console_bar.clone(); diff --git a/crates/revm/Cargo.toml b/crates/revm/Cargo.toml index 9a58607279..273a024826 100644 --- a/crates/revm/Cargo.toml +++ b/crates/revm/Cargo.toml @@ -15,7 +15,13 @@ primitive-types = {version = "0.10", features = ["rlp"]} revm_precompiles = {path = "../revm_precompiles", version="0.1"} rlp = {version = "0.5", default-features = false}#used for create2 address calculation sha3 = {version = "0.9", default-features = false} -auto_impl = "0.4" +auto_impl = {version="0.4", git="https://github.com/dimpolo/auto_impl.git", rev="61874ef"} +hashbrown = "0.11" [dev-dependencies] hex = "0.4" + + +[features] +default = ["std"] +std = ["bytes/std","num_enum/std","primitive-types/std", "sha3/std","rlp/std"] \ No newline at end of file diff --git a/crates/revm/src/db/db.rs b/crates/revm/src/db/db.rs index 76d8fb1dd0..bcd4f5ae7f 100644 --- a/crates/revm/src/db/db.rs +++ b/crates/revm/src/db/db.rs @@ -1,4 +1,5 @@ -use crate::{collection::Map, Account}; +use crate::Account; +use hashbrown::HashMap as Map; use primitive_types::{H160, H256, U256}; @@ -47,9 +48,7 @@ pub struct RefDBWrapper<'a> { impl<'a> RefDBWrapper<'a> { pub fn new(db: &'a dyn DatabaseRef) -> Self { - Self { - db - } + Self { db } } } diff --git a/crates/revm/src/db/dummy_db_impl.rs b/crates/revm/src/db/dummy_db_impl.rs index 81ba7677a4..6ccbbd777c 100644 --- a/crates/revm/src/db/dummy_db_impl.rs +++ b/crates/revm/src/db/dummy_db_impl.rs @@ -1,9 +1,11 @@ use crate::{ - collection::{vec::Vec, Entry, Map}, subroutine::Filth, Database, KECCAK_EMPTY, }; +use alloc::vec::Vec; +use hashbrown::{HashMap as Map, hash_map::Entry}; + use primitive_types::{H160, H256, U256}; use crate::{Account, AccountInfo, Log}; diff --git a/crates/revm/src/error.rs b/crates/revm/src/error.rs index 7edaaa8c59..716ecaf5c6 100644 --- a/crates/revm/src/error.rs +++ b/crates/revm/src/error.rs @@ -1,4 +1,4 @@ -use crate::collection::Cow; +use alloc::borrow::Cow; use revm_precompiles::ExitError as PrecompileError; /// Exit reason. diff --git a/crates/revm/src/evm.rs b/crates/revm/src/evm.rs index d6ca11ed81..a9a0a63a10 100644 --- a/crates/revm/src/evm.rs +++ b/crates/revm/src/evm.rs @@ -6,6 +6,7 @@ use crate::{ BerlinSpec, ByzantineSpec, Env, Inspector, IstanbulSpec, LatestSpec, LondonSpec, NoOpInspector, Spec, SpecId, TransactOut, }; +use alloc::boxed::Box; use revm_precompiles::Precompiles; /// Struct that takes Database and enabled transact to update state dirrectly to database. /// additionaly it allows user to set all environment parameters. diff --git a/crates/revm/src/evm_impl.rs b/crates/revm/src/evm_impl.rs index 8ddd40b421..18486f51d7 100644 --- a/crates/revm/src/evm_impl.rs +++ b/crates/revm/src/evm_impl.rs @@ -1,9 +1,9 @@ use core::{cmp::min, marker::PhantomData}; use primitive_types::{H160, H256, U256}; use sha3::{Digest, Keccak256}; - +use alloc::vec::Vec; +use hashbrown::HashMap as Map; use crate::{ - collection::{vec::Vec, Map}, db::Database, error::{ExitError, ExitReason, ExitSucceed}, machine, diff --git a/crates/revm/src/lib.rs b/crates/revm/src/lib.rs index ae5999e7a1..38891e6a73 100644 --- a/crates/revm/src/lib.rs +++ b/crates/revm/src/lib.rs @@ -1,6 +1,6 @@ #![allow(dead_code)] //#![forbid(unsafe_code, unused_variables, unused_imports)] -//#![cfg_attr(not(feature = "std"), no_std)] +#![no_std] mod db; mod error; @@ -16,7 +16,7 @@ mod util; use evm_impl::Handler; -pub use db::{DatabaseCommit, Database, DummyStateDB}; +pub use db::{Database, DatabaseCommit, DummyStateDB}; pub use error::*; pub use evm::{new, EVM}; pub use inspector::{Inspector, NoOpInspector}; @@ -27,23 +27,11 @@ pub use spec::*; pub use subroutine::Account; /// libraries for no_std flag -#[cfg(no_std)] -pub mod collection { - extern crate alloc; - pub use alloc::{ - borrow::{Borrow, Cow}, - collections::{btree_map::Entry, BTreeMap as Map}, - vec, - vec::Vec, - }; -} - -#[cfg(not(no_std))] -pub mod collection { - pub use std::{ - borrow::{Cow, Cow::Borrowed}, - collections::{hash_map::Entry, HashMap as Map}, - vec, - vec::Vec, - }; -} +//#[cfg(no_std)] +extern crate alloc; +pub use alloc::{ + borrow::{Borrow, Cow}, + collections::{btree_map::Entry, BTreeMap as Map}, + vec, + vec::Vec, +}; \ No newline at end of file diff --git a/crates/revm/src/machine/contract.rs b/crates/revm/src/machine/contract.rs index 0c875e45cd..54c64b27e4 100644 --- a/crates/revm/src/machine/contract.rs +++ b/crates/revm/src/machine/contract.rs @@ -1,4 +1,4 @@ -use crate::{collection::vec::Vec, CallContext, ExitError, ExitReason, ExitSucceed}; +use crate::{alloc::vec::Vec, CallContext, ExitError, ExitReason, ExitSucceed}; use bytes::Bytes; use primitive_types::{H160, U256}; diff --git a/crates/revm/src/machine/machine.rs b/crates/revm/src/machine/machine.rs index 2f2ba18fb5..cde30a5d31 100644 --- a/crates/revm/src/machine/machine.rs +++ b/crates/revm/src/machine/machine.rs @@ -1,4 +1,4 @@ -use crate::{collection::vec::Vec, opcode::eval, ExitError}; +use crate::{alloc::vec::Vec, opcode::eval, ExitError}; use bytes::Bytes; use core::{cmp::max, ops::Range}; use primitive_types::U256; diff --git a/crates/revm/src/machine/memory.rs b/crates/revm/src/machine/memory.rs index 6c3346b1fb..bd16c4bd19 100644 --- a/crates/revm/src/machine/memory.rs +++ b/crates/revm/src/machine/memory.rs @@ -1,5 +1,5 @@ use crate::{ - collection::vec::Vec, + alloc::vec::Vec, error::{ExitError, ExitFatal}, }; use bytes::Bytes; diff --git a/crates/revm/src/machine/stack.rs b/crates/revm/src/machine/stack.rs index fe51b3b061..8b42958c23 100644 --- a/crates/revm/src/machine/stack.rs +++ b/crates/revm/src/machine/stack.rs @@ -1,4 +1,4 @@ -use crate::{collection::vec::Vec, error::ExitError}; +use crate::{alloc::vec::Vec, error::ExitError}; use primitive_types::H256; /// EVM stack. diff --git a/crates/revm/src/models.rs b/crates/revm/src/models.rs index 9e074df014..79b13c17a1 100644 --- a/crates/revm/src/models.rs +++ b/crates/revm/src/models.rs @@ -1,6 +1,6 @@ use core::cmp::min; -use crate::{collection::vec::Vec, SpecId}; +use crate::{alloc::vec::Vec, SpecId}; use bytes::Bytes; use primitive_types::{H160, H256, U256}; diff --git a/crates/revm/src/opcode/arithmetic.rs b/crates/revm/src/opcode/arithmetic.rs index 4abcf2ac8d..7d31c1cd98 100644 --- a/crates/revm/src/opcode/arithmetic.rs +++ b/crates/revm/src/opcode/arithmetic.rs @@ -132,7 +132,7 @@ pub fn signextend(op1: U256, op2: U256) -> U256 { #[cfg(test)] mod tests { - use crate::collection::vec; + use alloc::vec; use super::{signextend, U256}; diff --git a/crates/revm/src/opcode/system.rs b/crates/revm/src/opcode/system.rs index 3994673e21..89914c2c8a 100644 --- a/crates/revm/src/opcode/system.rs +++ b/crates/revm/src/opcode/system.rs @@ -7,7 +7,7 @@ use crate::{ // CallScheme, Capture, CallContext, CreateScheme, , // , Runtime, Transfer, // }; -use crate::{collection::vec::Vec, spec::SpecId::*}; +use crate::{alloc::vec::Vec, spec::SpecId::*}; use bytes::Bytes; use core::cmp::min; use primitive_types::{H256, U256}; diff --git a/crates/revm/src/subroutine.rs b/crates/revm/src/subroutine.rs index e3c6f22bbb..831db46910 100644 --- a/crates/revm/src/subroutine.rs +++ b/crates/revm/src/subroutine.rs @@ -1,8 +1,6 @@ -use crate::{ - collection::{vec, vec::Vec, Entry, Map}, - models::SelfDestructResult, - ExitRevert, KECCAK_EMPTY, -}; +use crate::{models::SelfDestructResult, ExitRevert, KECCAK_EMPTY}; +use alloc::{vec, vec::Vec}; +use hashbrown::{hash_map::Entry, HashMap as Map}; use core::mem::{self}; diff --git a/crates/revm_precompiles/Cargo.toml b/crates/revm_precompiles/Cargo.toml index e656cd1566..2e1a1e795c 100644 --- a/crates/revm_precompiles/Cargo.toml +++ b/crates/revm_precompiles/Cargo.toml @@ -10,14 +10,17 @@ keywords = ["no_std", "ethereum", "evm", "precompiles"] [dependencies] -primitive-types = {version ="0.10", features = ["rlp"]} -bytes = "1.1" +primitive-types = {version ="0.10", default-features = false, features = ["rlp"]} +bytes = {version="1.1", default-features = false} num = { version = "0.4.0", default-features = false, features = ["alloc"] } sha2 = { version = "0.9.3", default-features = false } +sha3 = { version = "0.9.1", default-features = false } borsh = { version = "0.9", default-features = false } ripemd160 = { version = "0.9.1", default-features = false } parity-crypto = { version = "0.9.0", default-features = false, features = [ "publickey" ] } +secp256k1 = { version = "0.20", features = ["global-context", "recovery"] } bn = { package="substrate-bn", version="0.6", default-features = false } +#k256 = { version="0.9", default-features = false, features = ["ecdsa","keccak256"]} [dev-dependencies] diff --git a/crates/revm_precompiles/src/blake2.rs b/crates/revm_precompiles/src/blake2.rs index fb1fd95897..7c8cfca1e6 100644 --- a/crates/revm_precompiles/src/blake2.rs +++ b/crates/revm_precompiles/src/blake2.rs @@ -1,8 +1,8 @@ use crate::{gas_query, ExitError, StandardPrecompileFn}; -use crate::{collection::Borrowed, Precompile, PrecompileOutput, PrecompileResult}; +use crate::{Precompile, PrecompileOutput, PrecompileResult}; use core::convert::TryInto; - +use alloc::borrow::Cow; use primitive_types::H160 as Address; const F_ROUND: u64 = 1; @@ -18,7 +18,7 @@ pub const FUN: (Address, Precompile) = ( /// [4 bytes for rounds][64 bytes for h][128 bytes for m][8 bytes for t_0][8 bytes for t_1][1 byte for f] fn run(input: &[u8], target_gas: u64) -> PrecompileResult { if input.len() != INPUT_LENGTH { - return Err(ExitError::Other(Borrowed("Invalid last flag for blake2"))); + return Err(ExitError::Other(Cow::Borrowed("Invalid last flag for blake2"))); } // rounds 4 bytes @@ -42,7 +42,7 @@ fn run(input: &[u8], target_gas: u64) -> PrecompileResult { let f = match input[212] { 1 => true, 0 => false, - _ => return Err(ExitError::Other(Borrowed("Invalid last flag for blake2"))), + _ => return Err(ExitError::Other(Cow::Borrowed("Invalid last flag for blake2"))), }; algo::compress(rounds, &mut h, m, t, f); diff --git a/crates/revm_precompiles/src/bn128.rs b/crates/revm_precompiles/src/bn128.rs index 699a1a437f..18cbee7fd3 100644 --- a/crates/revm_precompiles/src/bn128.rs +++ b/crates/revm_precompiles/src/bn128.rs @@ -1,5 +1,6 @@ -use crate::{collection::*, gas_query, ExitError, Precompile, PrecompileOutput, PrecompileResult}; +use crate::{gas_query, ExitError, Precompile, PrecompileOutput, PrecompileResult}; +use alloc::{vec::Vec,borrow::Cow}; use primitive_types::{H160 as Address, U256}; pub mod add { @@ -88,18 +89,18 @@ fn read_point(input: &[u8], pos: usize) -> Result { let mut px_buf = [0u8; 32]; px_buf.copy_from_slice(&input[pos..(pos + 32)]); let px = - Fq::from_slice(&px_buf).map_err(|_e| ExitError::Other(Borrowed("ERR_BN128_INVALID_X")))?; + Fq::from_slice(&px_buf).map_err(|_e| ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_X")))?; let mut py_buf = [0u8; 32]; py_buf.copy_from_slice(&input[(pos + 32)..(pos + 64)]); let py = - Fq::from_slice(&py_buf).map_err(|_e| ExitError::Other(Borrowed("ERR_BN128_INVALID_Y")))?; + Fq::from_slice(&py_buf).map_err(|_e| ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_Y")))?; Ok(if px == Fq::zero() && py == bn::Fq::zero() { G1::zero() } else { AffineG1::new(px, py) - .map_err(|_| ExitError::Other(Borrowed("ERR_BN128_INVALID_POINT")))? + .map_err(|_| ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_POINT")))? .into() }) } @@ -142,7 +143,7 @@ fn run_mul(input: &[u8], cost: u64, target_gas: u64) -> PrecompileResult { let mut fr_buf = [0u8; 32]; fr_buf.copy_from_slice(&input[64..96]); let fr = bn::Fr::from_slice(&fr_buf[..]) - .map_err(|_| ExitError::Other(Borrowed("Invalid field element")))?; + .map_err(|_| ExitError::Other(Cow::Borrowed("Invalid field element")))?; let mut out = [0u8; 64]; if let Some(mul) = AffineG1::from_jacobian(p * fr) { @@ -165,7 +166,7 @@ fn run_pair( use bn::{AffineG1, AffineG2, Fq, Fq2, Group, Gt, G1, G2}; if input.len() % PAIR_ELEMENT_LEN != 0 { - return Err(ExitError::Other(Borrowed("ERR_BN128_INVALID_LEN"))); + return Err(ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_LEN"))); } let output = if input.is_empty() { @@ -179,32 +180,32 @@ fn run_pair( buf.copy_from_slice(&input[(idx * PAIR_ELEMENT_LEN)..(idx * PAIR_ELEMENT_LEN + 32)]); let ax = Fq::from_slice(&buf) - .map_err(|_e| ExitError::Other(Borrowed("ERR_BN128_INVALID_AX")))?; + .map_err(|_e| ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_AX")))?; buf.copy_from_slice( &input[(idx * PAIR_ELEMENT_LEN + 32)..(idx * PAIR_ELEMENT_LEN + 64)], ); let ay = Fq::from_slice(&buf) - .map_err(|_e| ExitError::Other(Borrowed("ERR_BN128_INVALID_AY")))?; + .map_err(|_e| ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_AY")))?; buf.copy_from_slice( &input[(idx * PAIR_ELEMENT_LEN + 64)..(idx * PAIR_ELEMENT_LEN + 96)], ); let bay = Fq::from_slice(&buf) - .map_err(|_e| ExitError::Other(Borrowed("ERR_BN128_INVALID_B_AY")))?; + .map_err(|_e| ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_B_AY")))?; buf.copy_from_slice( &input[(idx * PAIR_ELEMENT_LEN + 96)..(idx * PAIR_ELEMENT_LEN + 128)], ); let bax = Fq::from_slice(&buf) - .map_err(|_e| ExitError::Other(Borrowed("ERR_BN128_INVALID_B_AX")))?; + .map_err(|_e| ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_B_AX")))?; buf.copy_from_slice( &input[(idx * PAIR_ELEMENT_LEN + 128)..(idx * PAIR_ELEMENT_LEN + 160)], ); let bby = Fq::from_slice(&buf) - .map_err(|_e| ExitError::Other(Borrowed("ERR_BN128_INVALID_B_BY")))?; + .map_err(|_e| ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_B_BY")))?; buf.copy_from_slice( &input[(idx * PAIR_ELEMENT_LEN + 160)..(idx * PAIR_ELEMENT_LEN + 192)], ); let bbx = Fq::from_slice(&buf) - .map_err(|_e| ExitError::Other(Borrowed("ERR_BN128_INVALID_B_BX")))?; + .map_err(|_e| ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_B_BX")))?; let a = { if ax.is_zero() && ay.is_zero() { @@ -212,7 +213,7 @@ fn run_pair( } else { G1::from( AffineG1::new(ax, ay) - .map_err(|_e| ExitError::Other(Borrowed("ERR_BN128_INVALID_A")))?, + .map_err(|_e| ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_A")))?, ) } }; @@ -225,7 +226,7 @@ fn run_pair( } else { G2::from( AffineG2::new(ba, bb) - .map_err(|_e| ExitError::Other(Borrowed("ERR_BN128_INVALID_B")))?, + .map_err(|_e| ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_B")))?, ) } }; @@ -338,7 +339,7 @@ mod tests { let res = Bn128Add::::run(&input, 500, &new_context(), false); assert!(matches!( res, - Err(ExitError::Other(Borrowed("ERR_BN128_INVALID_POINT"))) + Err(ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_POINT"))) )); } @@ -420,7 +421,7 @@ mod tests { let res = Bn128Mul::::run(&input, 40_000, &new_context(), false); assert!(matches!( res, - Err(ExitError::Other(Borrowed("ERR_BN128_INVALID_POINT"))) + Err(ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_POINT"))) )); } @@ -497,7 +498,7 @@ mod tests { let res = Bn128Pair::::run(&input, 260_000, &new_context(), false); assert!(matches!( res, - Err(ExitError::Other(Borrowed("ERR_BN128_INVALID_A"))) + Err(ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_A"))) )); // invalid input length @@ -513,7 +514,7 @@ mod tests { let res = Bn128Pair::::run(&input, 260_000, &new_context(), false); assert!(matches!( res, - Err(ExitError::Other(Borrowed("ERR_BN128_INVALID_LEN",))) + Err(ExitError::Other(Cow::Borrowed("ERR_BN128_INVALID_LEN",))) )); } } diff --git a/crates/revm_precompiles/src/error.rs b/crates/revm_precompiles/src/error.rs index 01518a029c..63dba3f880 100644 --- a/crates/revm_precompiles/src/error.rs +++ b/crates/revm_precompiles/src/error.rs @@ -1,4 +1,4 @@ -use crate::collection::Cow; +use alloc::borrow::Cow; #[derive(Clone, Debug, Eq, PartialEq)] pub enum ExitError { diff --git a/crates/revm_precompiles/src/lib.rs b/crates/revm_precompiles/src/lib.rs index f1737519de..8436f8f4b8 100644 --- a/crates/revm_precompiles/src/lib.rs +++ b/crates/revm_precompiles/src/lib.rs @@ -1,6 +1,9 @@ +#![no_std] + use bytes::Bytes; use primitive_types::{H160 as Address, H256, U256}; + mod blake2; mod bn128; mod error; @@ -9,29 +12,13 @@ mod identity; mod modexp; mod secp256k1; + pub use error::ExitError; /// libraries for no_std flag -#[cfg(no_std)] -pub mod collection { - extern crate alloc; - pub use alloc::{ - borrow::{Borrow, Cow}, - collections::{btree_map::Entry, BTreeMap as Map}, - vec, - vec::Vec, - }; -} - -#[cfg(not(no_std))] -pub mod collection { - pub use std::{ - borrow::{Cow, Cow::Borrowed}, - collections::{hash_map::Entry, HashMap as Map}, - vec, - vec::Vec, - }; -} +#[macro_use] +extern crate alloc; +use alloc::vec::Vec; pub fn calc_linear_cost_u32(len: usize, base: u64, word: u64) -> u64 { (len as u64 + 32 - 1) / 32 * word + base diff --git a/crates/revm_precompiles/src/modexp.rs b/crates/revm_precompiles/src/modexp.rs index b2cc49f178..fc1376720b 100644 --- a/crates/revm_precompiles/src/modexp.rs +++ b/crates/revm_precompiles/src/modexp.rs @@ -1,7 +1,8 @@ use super::gas_query; use crate::{ - collection::Vec, Precompile, PrecompileOutput, PrecompileResult, StandardPrecompileFn, + Precompile, PrecompileOutput, PrecompileResult, StandardPrecompileFn, }; +use alloc::vec::{self, Vec}; use core::{ cmp::{max, min}, mem::size_of, diff --git a/crates/revm_precompiles/src/secp256k1.rs b/crates/revm_precompiles/src/secp256k1.rs index 3fd72053a8..6592c719fb 100644 --- a/crates/revm_precompiles/src/secp256k1.rs +++ b/crates/revm_precompiles/src/secp256k1.rs @@ -1,7 +1,13 @@ use crate::{gas_query, Precompile, PrecompileOutput, PrecompileResult, StandardPrecompileFn}; -use core::cmp::min; +use alloc::vec::Vec; +use core::{cmp::min, convert::TryFrom}; use parity_crypto::publickey::{public_to_address, recover, Error as ParityCryptoError, Signature}; -use primitive_types::{H160 as Address, H256}; +// use k256::{ +// ecdsa::{recoverable, signature::Signer, Error, SigningKey}, +// EncodedPoint as K256PublicKey, +// }; +use primitive_types::{H160 as Address, H256, H512}; +use sha3::{Digest, Keccak256}; const ECRECOVER_BASE: u64 = 3_000; @@ -10,15 +16,96 @@ pub const ECRECOVER: (Address, Precompile) = ( Precompile::Standard(ec_recover_run as StandardPrecompileFn), ); +/// Error verifying ECDSA signature +//#[derive(Encode, Decode)] +pub enum EcdsaVerifyError { + /// Incorrect value of R or S + BadRS, + /// Incorrect value of V + BadV, + /// Invalid signature + BadSignature, +} + +/// Verify and recover a SECP256k1 ECDSA signature. +/// +/// - `sig` is passed in RSV format. V should be either `0/1` or `27/28`. +/// - `msg` is the blake2-256 hash of the message. +/// +/// Returns `Err` if the signature is bad, otherwise the 64-byte pubkey +/// (doesn't include the 0x04 prefix). +// fn sp_secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result { +// let rs = libsecp256k1::Signature::parse_overflowing_slice(&sig[0..64]) +// .map_err(|_| EcdsaVerifyError::BadRS)?; +// let v = +// libsecp256k1::RecoveryId::parse(if sig[64] > 26 { sig[64] - 27 } else { sig[64] } as u8) +// .map_err(|_| EcdsaVerifyError::BadV)?; +// let pubkey = libsecp256k1::recover(&libsecp256k1::Message::parse(msg), &rs, &v) +// .map_err(|_| EcdsaVerifyError::BadSignature)?; +// let mut res = [0u8; 64]; +// res.copy_from_slice(&pubkey.serialize()[1..65]); +// let hash = Keccak256::digest(&res[1..]); +// let mut address = Address::zero(); +// address.as_bytes_mut().copy_from_slice(&hash[12..]); +// Ok(address) +// //Ok(res) +// } + +/* +fn secp256k1_ecdsa_recover(sig: &mut [u8; 65], msg: &[u8; 32]) -> Result { + sig[64] -= 27; + let sig = recoverable::Signature::try_from(sig.as_ref()).unwrap(); + let verify_key = sig.recover_verify_key(msg)?; + let uncompressed_pub_key = K256PublicKey::from(&verify_key).decompress(); + if let Some(public_key) = uncompressed_pub_key { + let public_key = public_key.as_bytes(); + debug_assert_eq!(public_key[0], 0x04); + let hash = if public_key[0] == 0x04 { + //println!("\n\n public_key {:?} \n\n",hex::encode(public_key)); + let hash = Keccak256::digest(public_key[1..].as_ref()); + //println!("\n\n hash {:?} \n\n",hex::encode(hash)); + hash + } else { + Keccak256::digest(&public_key[1..]) + }; + //let hash = Keccak256::digest(&public_key[1..]); + let mut address = Address::zero(); + address.as_bytes_mut().copy_from_slice(&hash[12..]); + Ok(address) + } else { + Err(Error::new()) + } +}*/ + // return padded address as H256 + +/* fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result { let rs = Signature::from_electrum(&sig[..]); if rs == Signature::default() { return Err(ParityCryptoError::InvalidSignature); } - let msg = H256::from_slice(msg); - let address = public_to_address(&recover(&rs, &msg)?); - Ok(address) + //let msg = H256::from_slice(msg); + let address = public_to_address(&recover(&rs, &msg.into())?); + Ok( Address(address.0)) +}*/ +use secp256k1::{ + recovery::{RecoverableSignature, RecoveryId}, + Message, SECP256K1, +}; + +fn secp256k1_ecdsa_recover(sig: &[u8; 65], msg: &[u8; 32]) -> Result { + let sig = RecoverableSignature::from_compact( + &sig[0..64], + RecoveryId::from_i32((sig[64] - 27) as i32)?, + )?; + + let public = &SECP256K1 + .recover(&Message::from_slice(&msg[..32])?, &sig)?; + + let mut out = vec![0; 20]; + out.copy_from_slice(&Keccak256::digest(&public.serialize_uncompressed()[1..])[12..]); + Ok(Address::from_slice(&out)) } fn ec_recover_run(i: &[u8], target_gas: u64) -> PrecompileResult { @@ -41,7 +128,7 @@ fn ec_recover_run(i: &[u8], target_gas: u64) -> PrecompileResult { // TODO hm it will fail for chainId that are more then one byte; sig[64] = input[63]; - let out = match secp256k1_ecdsa_recover(&sig, &msg) { + let out = match secp256k1_ecdsa_recover(&mut sig, &msg) { Ok(out) => H256::from(out).as_bytes().to_vec(), Err(_) => Vec::new(), }; diff --git a/crates/revm_wasm/Cargo.toml b/crates/revm_wasm/Cargo.toml new file mode 100644 index 0000000000..1b00fed34f --- /dev/null +++ b/crates/revm_wasm/Cargo.toml @@ -0,0 +1,19 @@ +[package] +name = "revm_wasm" +version = "0.1.0" +authors = ["Dragan Rakita "] +description = "REVM WASM - Rust Ethereum Virtual Machine Web Assembly lib" +license = "MIT/Apache-2.0" +repository = "https://github.com/bluealloy/revm" +edition = "2018" + +[lib] +crate-type = ["cdylib"] + +[dependencies] +wasm-bindgen = "0.2" +revm = {path = "../revm", version="0.3"} +getrandom = {version="0.2", features=["js"]} + +#[target.wasm32-unknown-unknown.dependencies] +#wasm-bindgen-getrandom = "0.1" \ No newline at end of file diff --git a/crates/revm_wasm/src/lib.rs b/crates/revm_wasm/src/lib.rs new file mode 100644 index 0000000000..6495a7ebc3 --- /dev/null +++ b/crates/revm_wasm/src/lib.rs @@ -0,0 +1,11 @@ +use wasm_bindgen::prelude::*; + +#[wasm_bindgen] +extern { + pub fn alert(s: &str); +} + +#[wasm_bindgen] +pub fn greet(name: &str) { + alert(&format!("Hello, {}!", name)); +} \ No newline at end of file