diff --git a/Cargo.lock b/Cargo.lock index 613808708..88ed2ba15 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -812,7 +812,6 @@ dependencies = [ "account-db 0.1.0", "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "blooms-db 0.1.0", - "bn 0.4.4 (git+https://github.com/paritytech/bn)", "common-types 0.1.0", "criterion 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "crossbeam-utils 0.6.5 (registry+https://github.com/rust-lang/crates.io-index)", @@ -825,6 +824,7 @@ dependencies = [ "ethcore-accounts 0.1.0", "ethcore-blockchain 0.1.0", "ethcore-bloom-journal 0.1.0", + "ethcore-builtin 0.1.0", "ethcore-call-contract 0.1.0", "ethcore-db 0.1.0", "ethcore-io 1.12.0", @@ -851,10 +851,8 @@ dependencies = [ "macros 0.1.0", "memory-cache 0.1.0", "memory-db 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", - "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", "num_cpus 1.10.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "parity-crypto 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-runtime 0.1.0", "parity-snappy 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "parity-util-mem 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", @@ -934,6 +932,22 @@ dependencies = [ "siphasher 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ethcore-builtin" +version = "0.1.0" +dependencies = [ + "bn 0.4.4 (git+https://github.com/paritytech/bn)", + "ethereum-types 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)", + "ethjson 0.1.0", + "ethkey 0.3.0", + "keccak-hash 0.2.0 (registry+https://github.com/rust-lang/crates.io-index)", + "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)", + "num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-bytes 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "parity-crypto 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)", + "rustc-hex 1.0.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "ethcore-call-contract" version = "0.1.0" diff --git a/ethcore/Cargo.toml b/ethcore/Cargo.toml index 6e5a3977c..a37cc12d9 100644 --- a/ethcore/Cargo.toml +++ b/ethcore/Cargo.toml @@ -10,7 +10,6 @@ authors = ["Parity Technologies "] account-db = { path = "account-db" } ansi_term = "0.11" blooms-db = { path = "../util/blooms-db", optional = true } -bn = { git = "https://github.com/paritytech/bn", default-features = false } common-types = { path = "types" } crossbeam-utils = "0.6" derive_more = "0.14.0" @@ -21,6 +20,7 @@ ethabi-derive = "8.0" ethash = { path = "../ethash" } ethcore-blockchain = { path = "./blockchain" } ethcore-bloom-journal = { path = "../util/bloom" } +ethcore-builtin = { path = "./builtin" } ethcore-call-contract = { path = "./call-contract" } ethcore-db = { path = "./db" } ethcore-io = { path = "../util/io" } @@ -47,10 +47,8 @@ lru-cache = "0.1" macros = { path = "../util/macros" } memory-cache = { path = "../util/memory-cache" } memory-db = "0.12.4" -num = { version = "0.1", default-features = false, features = ["bigint"] } num_cpus = "1.2" parity-bytes = "0.1" -parity-crypto = "0.4.0" parity-snappy = "0.1" parking_lot = "0.8" pod-account = { path = "pod-account" } diff --git a/ethcore/builtin/Cargo.toml b/ethcore/builtin/Cargo.toml new file mode 100644 index 000000000..5080fd7a8 --- /dev/null +++ b/ethcore/builtin/Cargo.toml @@ -0,0 +1,21 @@ +[package] +description = "ethereum vm builtin" +name = "ethcore-builtin" +version = "0.1.0" +authors = ["Parity Technologies "] +edition = "2018" + +[dependencies] +bn = { git = "https://github.com/paritytech/bn", default-features = false } +ethereum-types = "0.6.0" +ethjson = { path = "../../json" } +ethkey = { path = "../../accounts/ethkey" } +keccak-hash = "0.2.0" +log = "0.4" +num = { version = "0.1", default-features = false, features = ["bigint"] } +parity-bytes = "0.1" +parity-crypto = "0.4.0" + +[dev-dependencies] +rustc-hex = "1.0" + diff --git a/ethcore/src/builtin.rs b/ethcore/builtin/src/lib.rs similarity index 92% rename from ethcore/src/builtin.rs rename to ethcore/builtin/src/lib.rs index 6a52c9cdd..d6f498441 100644 --- a/ethcore/src/builtin.rs +++ b/ethcore/builtin/src/lib.rs @@ -16,42 +16,29 @@ //! Standard built-in contracts. -use std::cmp::{max, min}; -use std::io::{self, Read}; +use std::{ + cmp::{max, min}, + io::{self, Read}, +}; -use parity_crypto::digest; -use num::{BigUint, Zero, One}; - -use hash::keccak; +use bn; use ethereum_types::{H256, U256}; -use bytes::BytesRef; -use ethkey::{Signature, recover as ec_recover}; use ethjson; - -/// Execution error. -#[derive(Debug)] -pub struct Error(pub &'static str); - -impl From<&'static str> for Error { - fn from(val: &'static str) -> Self { - Error(val) - } -} - -impl Into<::vm::Error> for Error { - fn into(self) -> ::vm::Error { - ::vm::Error::BuiltIn(self.0) - } -} +use ethkey::{Signature, recover as ec_recover}; +use keccak_hash::keccak; +use log::{warn, trace}; +use num::{BigUint, Zero, One}; +use parity_bytes::BytesRef; +use parity_crypto::digest; /// Native implementation of a built-in contract. -pub trait Impl: Send + Sync { +trait Implementation: Send + Sync { /// execute this built-in on the given input, writing to the given output. - fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error>; + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str>; } /// A gas pricing scheme for built-in contracts. -pub trait Pricer: Send + Sync { +trait Pricer: Send + Sync { /// The gas cost of running this built-in for the given input data. fn cost(&self, input: &[u8]) -> U256; } @@ -157,21 +144,25 @@ impl ModexpPricer { /// Unless `is_active` is true, pub struct Builtin { pricer: Box, - native: Box, + native: Box, activate_at: u64, } impl Builtin { /// Simple forwarder for cost. - pub fn cost(&self, input: &[u8]) -> U256 { self.pricer.cost(input) } + pub fn cost(&self, input: &[u8]) -> U256 { + self.pricer.cost(input) + } /// Simple forwarder for execute. - pub fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { + pub fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { self.native.execute(input, output) } /// Whether the builtin is activated at the given block number. - pub fn is_active(&self, at: u64) -> bool { at >= self.activate_at } + pub fn is_active(&self, at: u64) -> bool { + at >= self.activate_at + } } impl From for Builtin { @@ -210,16 +201,16 @@ impl From for Builtin { } /// Ethereum built-in factory. -pub fn ethereum_builtin(name: &str) -> Box { +fn ethereum_builtin(name: &str) -> Box { match name { - "identity" => Box::new(Identity) as Box, - "ecrecover" => Box::new(EcRecover) as Box, - "sha256" => Box::new(Sha256) as Box, - "ripemd160" => Box::new(Ripemd160) as Box, - "modexp" => Box::new(ModexpImpl) as Box, - "alt_bn128_add" => Box::new(Bn128AddImpl) as Box, - "alt_bn128_mul" => Box::new(Bn128MulImpl) as Box, - "alt_bn128_pairing" => Box::new(Bn128PairingImpl) as Box, + "identity" => Box::new(Identity) as Box, + "ecrecover" => Box::new(EcRecover) as Box, + "sha256" => Box::new(Sha256) as Box, + "ripemd160" => Box::new(Ripemd160) as Box, + "modexp" => Box::new(Modexp) as Box, + "alt_bn128_add" => Box::new(Bn128Add) as Box, + "alt_bn128_mul" => Box::new(Bn128Mul) as Box, + "alt_bn128_pairing" => Box::new(Bn128Pairing) as Box, _ => panic!("invalid builtin name: {}", name), } } @@ -245,26 +236,26 @@ struct Sha256; struct Ripemd160; #[derive(Debug)] -struct ModexpImpl; +struct Modexp; #[derive(Debug)] -struct Bn128AddImpl; +struct Bn128Add; #[derive(Debug)] -struct Bn128MulImpl; +struct Bn128Mul; #[derive(Debug)] -struct Bn128PairingImpl; +struct Bn128Pairing; -impl Impl for Identity { - fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { +impl Implementation for Identity { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { output.write(0, input); Ok(()) } } -impl Impl for EcRecover { - fn execute(&self, i: &[u8], output: &mut BytesRef) -> Result<(), Error> { +impl Implementation for EcRecover { + fn execute(&self, i: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { let len = min(i.len(), 128); let mut input = [0; 128]; @@ -293,16 +284,16 @@ impl Impl for EcRecover { } } -impl Impl for Sha256 { - fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { +impl Implementation for Sha256 { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { let d = digest::sha256(input); output.write(0, &*d); Ok(()) } } -impl Impl for Ripemd160 { - fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { +impl Implementation for Ripemd160 { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { let hash = digest::ripemd160(input); output.write(0, &[0; 12][..]); output.write(12, &hash); @@ -358,8 +349,8 @@ fn modexp(mut base: BigUint, exp: Vec, modulus: BigUint) -> BigUint { result } -impl Impl for ModexpImpl { - fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { +impl Implementation for Modexp { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { let mut reader = input.chain(io::repeat(0)); let mut buf = [0; 32]; @@ -412,35 +403,35 @@ impl Impl for ModexpImpl { } } -fn read_fr(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result<::bn::Fr, Error> { +fn read_fr(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result { let mut buf = [0u8; 32]; reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); - ::bn::Fr::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid field element")) + bn::Fr::from_slice(&buf[0..32]).map_err(|_| "Invalid field element") } -fn read_point(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result<::bn::G1, Error> { +fn read_point(reader: &mut io::Chain<&[u8], io::Repeat>) -> Result { use bn::{Fq, AffineG1, G1, Group}; let mut buf = [0u8; 32]; reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); - let px = Fq::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid point x coordinate"))?; + let px = Fq::from_slice(&buf[0..32]).map_err(|_| "Invalid point x coordinate")?; reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); - let py = Fq::from_slice(&buf[0..32]).map_err(|_| Error::from("Invalid point y coordinate"))?; + let py = Fq::from_slice(&buf[0..32]).map_err(|_| "Invalid point y coordinate")?; Ok( if px == Fq::zero() && py == Fq::zero() { G1::zero() } else { - AffineG1::new(px, py).map_err(|_| Error::from("Invalid curve point"))?.into() + AffineG1::new(px, py).map_err(|_| "Invalid curve point")?.into() } ) } -impl Impl for Bn128AddImpl { +impl Implementation for Bn128Add { // Can fail if any of the 2 points does not belong the bn128 curve - fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { use bn::AffineG1; let mut padded_input = input.chain(io::repeat(0)); @@ -459,9 +450,9 @@ impl Impl for Bn128AddImpl { } } -impl Impl for Bn128MulImpl { +impl Implementation for Bn128Mul { // Can fail if first paramter (bn128 curve point) does not actually belong to the curve - fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { use bn::AffineG1; let mut padded_input = input.chain(io::repeat(0)); @@ -479,12 +470,12 @@ impl Impl for Bn128MulImpl { } } -impl Impl for Bn128PairingImpl { +impl Implementation for Bn128Pairing { /// Can fail if: /// - input length is not a multiple of 192 /// - any of odd points does not belong to bn128 curve /// - any of even points does not belong to the twisted bn128 curve over the field F_p^2 = F_p[i] / (i^2 + 1) - fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { + fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { if input.len() % 192 != 0 { return Err("Invalid input length, must be multiple of 192 (3 * (32*2))".into()) } @@ -497,8 +488,8 @@ impl Impl for Bn128PairingImpl { } } -impl Bn128PairingImpl { - fn execute_with_error(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { +impl Bn128Pairing { + fn execute_with_error(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> { use bn::{AffineG1, AffineG2, Fq, Fq2, pairing_batch, G1, G2, Gt, Group}; let elements = input.len() / 192; // (a, b_a, b_b - each 64-byte affine coordinates) @@ -508,34 +499,34 @@ impl Bn128PairingImpl { let mut vals = Vec::new(); for idx in 0..elements { let a_x = Fq::from_slice(&input[idx*192..idx*192+32]) - .map_err(|_| Error::from("Invalid a argument x coordinate"))?; + .map_err(|_| "Invalid a argument x coordinate")?; let a_y = Fq::from_slice(&input[idx*192+32..idx*192+64]) - .map_err(|_| Error::from("Invalid a argument y coordinate"))?; + .map_err(|_| "Invalid a argument y coordinate")?; let b_a_y = Fq::from_slice(&input[idx*192+64..idx*192+96]) - .map_err(|_| Error::from("Invalid b argument imaginary coeff x coordinate"))?; + .map_err(|_| "Invalid b argument imaginary coeff x coordinate")?; let b_a_x = Fq::from_slice(&input[idx*192+96..idx*192+128]) - .map_err(|_| Error::from("Invalid b argument imaginary coeff y coordinate"))?; + .map_err(|_| "Invalid b argument imaginary coeff y coordinate")?; let b_b_y = Fq::from_slice(&input[idx*192+128..idx*192+160]) - .map_err(|_| Error::from("Invalid b argument real coeff x coordinate"))?; + .map_err(|_| "Invalid b argument real coeff x coordinate")?; let b_b_x = Fq::from_slice(&input[idx*192+160..idx*192+192]) - .map_err(|_| Error::from("Invalid b argument real coeff y coordinate"))?; + .map_err(|_| "Invalid b argument real coeff y coordinate")?; let b_a = Fq2::new(b_a_x, b_a_y); let b_b = Fq2::new(b_b_x, b_b_y); let b = if b_a.is_zero() && b_b.is_zero() { G2::zero() } else { - G2::from(AffineG2::new(b_a, b_b).map_err(|_| Error::from("Invalid b argument - not on curve"))?) + G2::from(AffineG2::new(b_a, b_b).map_err(|_| "Invalid b argument - not on curve")?) }; let a = if a_x.is_zero() && a_y.is_zero() { G1::zero() } else { - G1::from(AffineG1::new(a_x, a_y).map_err(|_| Error::from("Invalid a argument - not on curve"))?) + G1::from(AffineG1::new(a_x, a_y).map_err(|_| "Invalid a argument - not on curve")?) }; vals.push((a, b)); }; @@ -559,12 +550,12 @@ impl Bn128PairingImpl { #[cfg(test)] mod tests { - use super::{Builtin, Linear, ethereum_builtin, Pricer, ModexpPricer, modexp as me}; - use ethjson; use ethereum_types::U256; - use bytes::BytesRef; - use rustc_hex::FromHex; + use ethjson; use num::{BigUint, Zero, One}; + use parity_bytes::BytesRef; + use rustc_hex::FromHex; + use super::{Builtin, Linear, ethereum_builtin, Pricer, ModexpPricer, modexp as me}; #[test] fn modexp_func() { @@ -946,8 +937,8 @@ mod tests { let res = f.execute(input, &mut BytesRef::Fixed(&mut output[..])); if let Some(msg) = msg_contains { if let Err(e) = res { - if !e.0.contains(msg) { - panic!("There should be error containing '{}' here, but got: '{}'", msg, e.0); + if !e.contains(msg) { + panic!("There should be error containing '{}' here, but got: '{}'", msg, e); } } } else { diff --git a/ethcore/src/executive.rs b/ethcore/src/executive.rs index 9078c3458..bb11580b0 100644 --- a/ethcore/src/executive.rs +++ b/ethcore/src/executive.rs @@ -406,7 +406,7 @@ impl<'a> CallCreateExecutive<'a> { if let Err(e) = result { state.revert_to_checkpoint(); - Err(e.into()) + Err(vm::Error::BuiltIn(e)) } else { state.discard_checkpoint(); diff --git a/ethcore/src/lib.rs b/ethcore/src/lib.rs index 52a129f18..cf328fece 100644 --- a/ethcore/src/lib.rs +++ b/ethcore/src/lib.rs @@ -55,13 +55,13 @@ extern crate account_db; extern crate ansi_term; -extern crate bn; extern crate common_types as types; extern crate crossbeam_utils; extern crate ethabi; extern crate ethash; extern crate ethcore_blockchain as blockchain; extern crate ethcore_bloom_journal as bloom_journal; +extern crate ethcore_builtin as builtin; extern crate ethcore_call_contract as call_contract; extern crate ethcore_db as db; extern crate ethcore_io as io; @@ -83,10 +83,8 @@ extern crate len_caching_lock; extern crate lru_cache; extern crate memory_cache; extern crate memory_db; -extern crate num; extern crate num_cpus; extern crate parity_bytes as bytes; -extern crate parity_crypto; extern crate parity_snappy as snappy; extern crate parking_lot; extern crate pod_account; @@ -153,7 +151,6 @@ extern crate fetch; extern crate parity_runtime; pub mod block; -pub mod builtin; pub mod client; pub mod engines; pub mod error;