ethcore-builtin (#10850)

* ethcore-builtin

* rename ethcore-builtin Impl to Implementation
This commit is contained in:
Marek Kotewicz 2019-07-07 16:59:30 +02:00 committed by GitHub
parent c4c5d79a0f
commit fe7bc545bf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 114 additions and 93 deletions

20
Cargo.lock generated
View File

@ -812,7 +812,6 @@ dependencies = [
"account-db 0.1.0", "account-db 0.1.0",
"ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
"blooms-db 0.1.0", "blooms-db 0.1.0",
"bn 0.4.4 (git+https://github.com/paritytech/bn)",
"common-types 0.1.0", "common-types 0.1.0",
"criterion 0.2.5 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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-accounts 0.1.0",
"ethcore-blockchain 0.1.0", "ethcore-blockchain 0.1.0",
"ethcore-bloom-journal 0.1.0", "ethcore-bloom-journal 0.1.0",
"ethcore-builtin 0.1.0",
"ethcore-call-contract 0.1.0", "ethcore-call-contract 0.1.0",
"ethcore-db 0.1.0", "ethcore-db 0.1.0",
"ethcore-io 1.12.0", "ethcore-io 1.12.0",
@ -851,10 +851,8 @@ dependencies = [
"macros 0.1.0", "macros 0.1.0",
"memory-cache 0.1.0", "memory-cache 0.1.0",
"memory-db 0.12.4 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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-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-runtime 0.1.0",
"parity-snappy 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "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)", "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)", "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]] [[package]]
name = "ethcore-call-contract" name = "ethcore-call-contract"
version = "0.1.0" version = "0.1.0"

View File

@ -10,7 +10,6 @@ authors = ["Parity Technologies <admin@parity.io>"]
account-db = { path = "account-db" } account-db = { path = "account-db" }
ansi_term = "0.11" ansi_term = "0.11"
blooms-db = { path = "../util/blooms-db", optional = true } blooms-db = { path = "../util/blooms-db", optional = true }
bn = { git = "https://github.com/paritytech/bn", default-features = false }
common-types = { path = "types" } common-types = { path = "types" }
crossbeam-utils = "0.6" crossbeam-utils = "0.6"
derive_more = "0.14.0" derive_more = "0.14.0"
@ -21,6 +20,7 @@ ethabi-derive = "8.0"
ethash = { path = "../ethash" } ethash = { path = "../ethash" }
ethcore-blockchain = { path = "./blockchain" } ethcore-blockchain = { path = "./blockchain" }
ethcore-bloom-journal = { path = "../util/bloom" } ethcore-bloom-journal = { path = "../util/bloom" }
ethcore-builtin = { path = "./builtin" }
ethcore-call-contract = { path = "./call-contract" } ethcore-call-contract = { path = "./call-contract" }
ethcore-db = { path = "./db" } ethcore-db = { path = "./db" }
ethcore-io = { path = "../util/io" } ethcore-io = { path = "../util/io" }
@ -47,10 +47,8 @@ lru-cache = "0.1"
macros = { path = "../util/macros" } macros = { path = "../util/macros" }
memory-cache = { path = "../util/memory-cache" } memory-cache = { path = "../util/memory-cache" }
memory-db = "0.12.4" memory-db = "0.12.4"
num = { version = "0.1", default-features = false, features = ["bigint"] }
num_cpus = "1.2" num_cpus = "1.2"
parity-bytes = "0.1" parity-bytes = "0.1"
parity-crypto = "0.4.0"
parity-snappy = "0.1" parity-snappy = "0.1"
parking_lot = "0.8" parking_lot = "0.8"
pod-account = { path = "pod-account" } pod-account = { path = "pod-account" }

View File

@ -0,0 +1,21 @@
[package]
description = "ethereum vm builtin"
name = "ethcore-builtin"
version = "0.1.0"
authors = ["Parity Technologies <admin@parity.io>"]
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"

View File

@ -16,42 +16,29 @@
//! Standard built-in contracts. //! Standard built-in contracts.
use std::cmp::{max, min}; use std::{
use std::io::{self, Read}; cmp::{max, min},
io::{self, Read},
};
use parity_crypto::digest; use bn;
use num::{BigUint, Zero, One};
use hash::keccak;
use ethereum_types::{H256, U256}; use ethereum_types::{H256, U256};
use bytes::BytesRef;
use ethkey::{Signature, recover as ec_recover};
use ethjson; use ethjson;
use ethkey::{Signature, recover as ec_recover};
/// Execution error. use keccak_hash::keccak;
#[derive(Debug)] use log::{warn, trace};
pub struct Error(pub &'static str); use num::{BigUint, Zero, One};
use parity_bytes::BytesRef;
impl From<&'static str> for Error { use parity_crypto::digest;
fn from(val: &'static str) -> Self {
Error(val)
}
}
impl Into<::vm::Error> for Error {
fn into(self) -> ::vm::Error {
::vm::Error::BuiltIn(self.0)
}
}
/// Native implementation of a built-in contract. /// 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. /// 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. /// 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. /// The gas cost of running this built-in for the given input data.
fn cost(&self, input: &[u8]) -> U256; fn cost(&self, input: &[u8]) -> U256;
} }
@ -157,21 +144,25 @@ impl ModexpPricer {
/// Unless `is_active` is true, /// Unless `is_active` is true,
pub struct Builtin { pub struct Builtin {
pricer: Box<dyn Pricer>, pricer: Box<dyn Pricer>,
native: Box<dyn Impl>, native: Box<dyn Implementation>,
activate_at: u64, activate_at: u64,
} }
impl Builtin { impl Builtin {
/// Simple forwarder for cost. /// 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. /// 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) self.native.execute(input, output)
} }
/// Whether the builtin is activated at the given block number. /// 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<ethjson::spec::Builtin> for Builtin { impl From<ethjson::spec::Builtin> for Builtin {
@ -210,16 +201,16 @@ impl From<ethjson::spec::Builtin> for Builtin {
} }
/// Ethereum built-in factory. /// Ethereum built-in factory.
pub fn ethereum_builtin(name: &str) -> Box<dyn Impl> { fn ethereum_builtin(name: &str) -> Box<dyn Implementation> {
match name { match name {
"identity" => Box::new(Identity) as Box<dyn Impl>, "identity" => Box::new(Identity) as Box<dyn Implementation>,
"ecrecover" => Box::new(EcRecover) as Box<dyn Impl>, "ecrecover" => Box::new(EcRecover) as Box<dyn Implementation>,
"sha256" => Box::new(Sha256) as Box<dyn Impl>, "sha256" => Box::new(Sha256) as Box<dyn Implementation>,
"ripemd160" => Box::new(Ripemd160) as Box<dyn Impl>, "ripemd160" => Box::new(Ripemd160) as Box<dyn Implementation>,
"modexp" => Box::new(ModexpImpl) as Box<dyn Impl>, "modexp" => Box::new(Modexp) as Box<dyn Implementation>,
"alt_bn128_add" => Box::new(Bn128AddImpl) as Box<dyn Impl>, "alt_bn128_add" => Box::new(Bn128Add) as Box<dyn Implementation>,
"alt_bn128_mul" => Box::new(Bn128MulImpl) as Box<dyn Impl>, "alt_bn128_mul" => Box::new(Bn128Mul) as Box<dyn Implementation>,
"alt_bn128_pairing" => Box::new(Bn128PairingImpl) as Box<dyn Impl>, "alt_bn128_pairing" => Box::new(Bn128Pairing) as Box<dyn Implementation>,
_ => panic!("invalid builtin name: {}", name), _ => panic!("invalid builtin name: {}", name),
} }
} }
@ -245,26 +236,26 @@ struct Sha256;
struct Ripemd160; struct Ripemd160;
#[derive(Debug)] #[derive(Debug)]
struct ModexpImpl; struct Modexp;
#[derive(Debug)] #[derive(Debug)]
struct Bn128AddImpl; struct Bn128Add;
#[derive(Debug)] #[derive(Debug)]
struct Bn128MulImpl; struct Bn128Mul;
#[derive(Debug)] #[derive(Debug)]
struct Bn128PairingImpl; struct Bn128Pairing;
impl Impl for Identity { impl Implementation for Identity {
fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> {
output.write(0, input); output.write(0, input);
Ok(()) Ok(())
} }
} }
impl Impl for EcRecover { impl Implementation for EcRecover {
fn execute(&self, i: &[u8], output: &mut BytesRef) -> Result<(), Error> { fn execute(&self, i: &[u8], output: &mut BytesRef) -> Result<(), &'static str> {
let len = min(i.len(), 128); let len = min(i.len(), 128);
let mut input = [0; 128]; let mut input = [0; 128];
@ -293,16 +284,16 @@ impl Impl for EcRecover {
} }
} }
impl Impl for Sha256 { impl Implementation for Sha256 {
fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> {
let d = digest::sha256(input); let d = digest::sha256(input);
output.write(0, &*d); output.write(0, &*d);
Ok(()) Ok(())
} }
} }
impl Impl for Ripemd160 { impl Implementation for Ripemd160 {
fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> {
let hash = digest::ripemd160(input); let hash = digest::ripemd160(input);
output.write(0, &[0; 12][..]); output.write(0, &[0; 12][..]);
output.write(12, &hash); output.write(12, &hash);
@ -358,8 +349,8 @@ fn modexp(mut base: BigUint, exp: Vec<u8>, modulus: BigUint) -> BigUint {
result result
} }
impl Impl for ModexpImpl { impl Implementation for Modexp {
fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { fn execute(&self, input: &[u8], output: &mut BytesRef) -> Result<(), &'static str> {
let mut reader = input.chain(io::repeat(0)); let mut reader = input.chain(io::repeat(0));
let mut buf = [0; 32]; 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<bn::Fr, &'static str> {
let mut buf = [0u8; 32]; let mut buf = [0u8; 32];
reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); 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<bn::G1, &'static str> {
use bn::{Fq, AffineG1, G1, Group}; use bn::{Fq, AffineG1, G1, Group};
let mut buf = [0u8; 32]; let mut buf = [0u8; 32];
reader.read_exact(&mut buf[..]).expect("reading from zero-extended memory cannot fail; qed"); 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"); 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( Ok(
if px == Fq::zero() && py == Fq::zero() { if px == Fq::zero() && py == Fq::zero() {
G1::zero() G1::zero()
} else { } 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 // 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; use bn::AffineG1;
let mut padded_input = input.chain(io::repeat(0)); 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 // 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; use bn::AffineG1;
let mut padded_input = input.chain(io::repeat(0)); 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: /// Can fail if:
/// - input length is not a multiple of 192 /// - input length is not a multiple of 192
/// - any of odd points does not belong to bn128 curve /// - 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) /// - 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 { if input.len() % 192 != 0 {
return Err("Invalid input length, must be multiple of 192 (3 * (32*2))".into()) return Err("Invalid input length, must be multiple of 192 (3 * (32*2))".into())
} }
@ -497,8 +488,8 @@ impl Impl for Bn128PairingImpl {
} }
} }
impl Bn128PairingImpl { impl Bn128Pairing {
fn execute_with_error(&self, input: &[u8], output: &mut BytesRef) -> Result<(), Error> { 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}; 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) 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(); let mut vals = Vec::new();
for idx in 0..elements { for idx in 0..elements {
let a_x = Fq::from_slice(&input[idx*192..idx*192+32]) 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]) 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]) 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]) 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]) 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]) 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_a = Fq2::new(b_a_x, b_a_y);
let b_b = Fq2::new(b_b_x, b_b_y); let b_b = Fq2::new(b_b_x, b_b_y);
let b = if b_a.is_zero() && b_b.is_zero() { let b = if b_a.is_zero() && b_b.is_zero() {
G2::zero() G2::zero()
} else { } 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() { let a = if a_x.is_zero() && a_y.is_zero() {
G1::zero() G1::zero()
} else { } 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)); vals.push((a, b));
}; };
@ -559,12 +550,12 @@ impl Bn128PairingImpl {
#[cfg(test)] #[cfg(test)]
mod tests { mod tests {
use super::{Builtin, Linear, ethereum_builtin, Pricer, ModexpPricer, modexp as me};
use ethjson;
use ethereum_types::U256; use ethereum_types::U256;
use bytes::BytesRef; use ethjson;
use rustc_hex::FromHex;
use num::{BigUint, Zero, One}; 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] #[test]
fn modexp_func() { fn modexp_func() {
@ -946,8 +937,8 @@ mod tests {
let res = f.execute(input, &mut BytesRef::Fixed(&mut output[..])); let res = f.execute(input, &mut BytesRef::Fixed(&mut output[..]));
if let Some(msg) = msg_contains { if let Some(msg) = msg_contains {
if let Err(e) = res { if let Err(e) = res {
if !e.0.contains(msg) { if !e.contains(msg) {
panic!("There should be error containing '{}' here, but got: '{}'", msg, e.0); panic!("There should be error containing '{}' here, but got: '{}'", msg, e);
} }
} }
} else { } else {

View File

@ -406,7 +406,7 @@ impl<'a> CallCreateExecutive<'a> {
if let Err(e) = result { if let Err(e) = result {
state.revert_to_checkpoint(); state.revert_to_checkpoint();
Err(e.into()) Err(vm::Error::BuiltIn(e))
} else { } else {
state.discard_checkpoint(); state.discard_checkpoint();

View File

@ -55,13 +55,13 @@
extern crate account_db; extern crate account_db;
extern crate ansi_term; extern crate ansi_term;
extern crate bn;
extern crate common_types as types; extern crate common_types as types;
extern crate crossbeam_utils; extern crate crossbeam_utils;
extern crate ethabi; extern crate ethabi;
extern crate ethash; extern crate ethash;
extern crate ethcore_blockchain as blockchain; extern crate ethcore_blockchain as blockchain;
extern crate ethcore_bloom_journal as bloom_journal; 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_call_contract as call_contract;
extern crate ethcore_db as db; extern crate ethcore_db as db;
extern crate ethcore_io as io; extern crate ethcore_io as io;
@ -83,10 +83,8 @@ extern crate len_caching_lock;
extern crate lru_cache; extern crate lru_cache;
extern crate memory_cache; extern crate memory_cache;
extern crate memory_db; extern crate memory_db;
extern crate num;
extern crate num_cpus; extern crate num_cpus;
extern crate parity_bytes as bytes; extern crate parity_bytes as bytes;
extern crate parity_crypto;
extern crate parity_snappy as snappy; extern crate parity_snappy as snappy;
extern crate parking_lot; extern crate parking_lot;
extern crate pod_account; extern crate pod_account;
@ -153,7 +151,6 @@ extern crate fetch;
extern crate parity_runtime; extern crate parity_runtime;
pub mod block; pub mod block;
pub mod builtin;
pub mod client; pub mod client;
pub mod engines; pub mod engines;
pub mod error; pub mod error;