ethcore-builtin (#10850)
* ethcore-builtin * rename ethcore-builtin Impl to Implementation
This commit is contained in:
parent
c4c5d79a0f
commit
fe7bc545bf
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -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"
|
||||
|
@ -10,7 +10,6 @@ authors = ["Parity Technologies <admin@parity.io>"]
|
||||
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" }
|
||||
|
21
ethcore/builtin/Cargo.toml
Normal file
21
ethcore/builtin/Cargo.toml
Normal 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"
|
||||
|
@ -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<dyn Pricer>,
|
||||
native: Box<dyn Impl>,
|
||||
native: Box<dyn Implementation>,
|
||||
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<ethjson::spec::Builtin> for Builtin {
|
||||
@ -210,16 +201,16 @@ impl From<ethjson::spec::Builtin> for Builtin {
|
||||
}
|
||||
|
||||
/// Ethereum built-in factory.
|
||||
pub fn ethereum_builtin(name: &str) -> Box<dyn Impl> {
|
||||
fn ethereum_builtin(name: &str) -> Box<dyn Implementation> {
|
||||
match name {
|
||||
"identity" => Box::new(Identity) as Box<dyn Impl>,
|
||||
"ecrecover" => Box::new(EcRecover) as Box<dyn Impl>,
|
||||
"sha256" => Box::new(Sha256) as Box<dyn Impl>,
|
||||
"ripemd160" => Box::new(Ripemd160) as Box<dyn Impl>,
|
||||
"modexp" => Box::new(ModexpImpl) as Box<dyn Impl>,
|
||||
"alt_bn128_add" => Box::new(Bn128AddImpl) as Box<dyn Impl>,
|
||||
"alt_bn128_mul" => Box::new(Bn128MulImpl) as Box<dyn Impl>,
|
||||
"alt_bn128_pairing" => Box::new(Bn128PairingImpl) as Box<dyn Impl>,
|
||||
"identity" => Box::new(Identity) as Box<dyn Implementation>,
|
||||
"ecrecover" => Box::new(EcRecover) as Box<dyn Implementation>,
|
||||
"sha256" => Box::new(Sha256) as Box<dyn Implementation>,
|
||||
"ripemd160" => Box::new(Ripemd160) as Box<dyn Implementation>,
|
||||
"modexp" => Box::new(Modexp) as Box<dyn Implementation>,
|
||||
"alt_bn128_add" => Box::new(Bn128Add) as Box<dyn Implementation>,
|
||||
"alt_bn128_mul" => Box::new(Bn128Mul) as Box<dyn Implementation>,
|
||||
"alt_bn128_pairing" => Box::new(Bn128Pairing) as Box<dyn Implementation>,
|
||||
_ => 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<u8>, 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<bn::Fr, &'static str> {
|
||||
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<bn::G1, &'static str> {
|
||||
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 {
|
@ -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();
|
||||
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user