Merge branch 'master' into ui-2

# Conflicts:
#	js/package-lock.json
#	js/package.json
#	js/src/api/api.js
#	js/src/api/local/accounts/accounts.js
#	js/src/api/local/localAccountsMiddleware.js
#	js/src/api/local/transactions.js
#	js/src/api/pubsub/signer/signer.js
#	js/src/api/subscriptions/signer.js
#	js/src/api/transport/jsonRpcBase.js
#	js/src/api/transport/middleware.js
#	js/src/api/util/format.js
#	js/src/api/util/format.spec.js
#	js/src/contracts/abi/index.js
#	js/src/contracts/badgereg.js
#	js/src/dapps/tokenreg/Application/application.css
#	js/src/dapps/tokenreg/Application/application.js
#	js/src/modals/CreateWallet/WalletDetails/walletDetails.js
#	js/src/modals/CreateWallet/WalletDetails/walletDetails.spec.js
#	js/src/modals/CreateWallet/createWalletStore.js
#	js/src/modals/DeployContract/ParametersStep/parametersStep.js
#	js/src/modals/DeployContract/deployContract.js
#	js/src/modals/ExecuteContract/DetailsStep/detailsStep.js
#	js/src/modals/WalletSettings/walletSettings.js
#	js/src/redux/providers/certifications/actions.js
#	js/src/redux/providers/certifications/middleware.js
#	js/src/redux/providers/certifications/reducer.js
#	js/src/redux/providers/requestsActions.js
#	js/src/redux/providers/tokensActions.js
#	js/src/ui/AccountCard/accountCard.css
#	js/src/ui/Balance/balance.js
#	js/src/ui/Balance/balance.spec.js
#	js/src/ui/DappCard/dappCard.js
#	js/src/ui/Form/AddressSelect/addressSelect.js
#	js/src/ui/Form/AddressSelect/addressSelectStore.js
#	js/src/ui/Form/InputAddressSelect/inputAddressSelect.js
#	js/src/ui/Form/TypedInput/typedInput.js
#	js/src/ui/IdentityIcon/identityIcon.js
#	js/src/ui/MethodDecoding/tokenValue.js
#	js/src/util/tx.js
#	js/src/util/wallets.js
#	js/src/util/wallets/consensys-wallet.js
#	js/src/util/wallets/foundation-wallet.js
#	js/src/views/Account/account.js
#	js/src/views/Accounts/List/list.js
#	js/src/views/Contract/Queries/inputQuery.js
#	js/src/views/Contract/Queries/queries.js
#	js/src/views/Contract/contract.js
#	js/src/views/Signer/components/SignRequest/signRequest.css
#	js/src/views/Signer/components/SignRequest/signRequest.js
#	js/src/views/Signer/components/SignRequest/signRequest.spec.js
This commit is contained in:
Jaco Greeff
2017-10-16 12:41:41 +02:00
174 changed files with 6014 additions and 20547 deletions

View File

@@ -3,7 +3,7 @@ description = "Ethcore library"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "ethcore"
version = "1.8.0"
version = "1.9.0"
authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs"
@@ -55,6 +55,11 @@ rayon = "0.8"
rand = "0.3"
rlp = { path = "../util/rlp" }
rlp_derive = { path = "../util/rlp_derive" }
kvdb = { path = "../util/kvdb" }
util-error = { path = "../util/error" }
snappy = { path = "../util/snappy" }
migration = { path = "../util/migration" }
macros = { path = "../util/macros" }
rust-crypto = "0.2.34"
rustc-hex = "1.0"
stats = { path = "../util/stats" }

View File

@@ -21,8 +21,9 @@ extern crate ethcore_util as util;
extern crate rand;
extern crate bn;
extern crate crypto;
extern crate rustc_serialize;
extern crate ethkey;
extern crate rustc_hex;
extern crate ethcore_bigint;
use self::test::{Bencher};
use rand::{StdRng};
@@ -75,9 +76,9 @@ fn sha256(b: &mut Bencher) {
#[bench]
fn ecrecover(b: &mut Bencher) {
use rustc_serialize::hex::FromHex;
use rustc_hex::FromHex;
use ethkey::{Signature, recover as ec_recover};
use util::H256;
use ethcore_bigint::hash::H256;
let input = FromHex::from_hex("47173285a8d7341e5e972fc677286384f802f8ef42a5ec5f03bbfa254cb01fad000000000000000000000000000000000000000000000000000000000000001b650acf9d3f5f0a2c799776a1254355d5f4061762a237396a99a0e0e3fc2bcd6729514a0dacb2e623ac4abd157cb18163ff942280db4d5caad66ddf941ba12e03").unwrap();
let hash = H256::from_slice(&input[0..32]);
let v = H256::from_slice(&input[32..64]);

View File

@@ -5,19 +5,13 @@ authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
bit-set = "0.4"
byteorder = "1.0"
common-types = { path = "../types" }
ethcore-util = { path = "../../util" }
ethcore-bigint = { path = "../../util/bigint" }
evmjit = { path = "../../evmjit", optional = true }
ethjson = { path = "../../json" }
heapsize = "0.4"
lazy_static = "0.2"
log = "0.3"
rlp = { path = "../../util/rlp" }
vm = { path = "../vm" }
ethcore-logger = { path = "../../logger" }
wasm-utils = { git = "https://github.com/paritytech/wasm-utils" }
hash = { path = "../../util/hash" }
parking_lot = "0.4"

View File

@@ -574,7 +574,7 @@ impl<Cost: CostType> Interpreter<Cost> {
let source_offset = stack.peek(1);
let size = stack.peek(2);
let return_data_len = U256::from(self.return_data.len());
if source_offset.overflow_add(*size).0 > return_data_len {
if source_offset.saturating_add(*size) > return_data_len {
return Err(vm::Error::OutOfBounds);
}
}
@@ -940,4 +940,25 @@ mod tests {
assert_eq!(ext.calls.len(), 1);
assert_eq!(gas_left, 248_212.into());
}
#[test]
fn should_not_overflow_returndata() {
let code = "6001600160000360003e00".from_hex().unwrap();
let mut params = ActionParams::default();
params.address = 5.into();
params.gas = 300_000.into();
params.gas_price = 1.into();
params.code = Some(Arc::new(code));
let mut ext = FakeExt::new_byzantium();
ext.balances.insert(5.into(), 1_000_000_000.into());
ext.tracing = true;
let err = {
let mut vm = Factory::new(VMType::Interpreter, 1).create(params.gas);
test_finalize(vm.exec(params, &mut ext)).err().unwrap()
};
assert_eq!(err, ::vm::Error::OutOfBounds);
}
}

View File

@@ -16,16 +16,10 @@
//! Ethereum virtual machine.
extern crate byteorder;
extern crate bit_set;
extern crate common_types as types;
extern crate ethcore_util as util;
extern crate ethcore_bigint as bigint;
extern crate ethjson;
extern crate rlp;
extern crate parking_lot;
extern crate wasm_utils;
extern crate ethcore_logger;
extern crate heapsize;
extern crate vm;
extern crate hash;

View File

@@ -3,7 +3,7 @@ description = "Parity Light Client Implementation"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "ethcore-light"
version = "1.8.0"
version = "1.9.0"
authors = ["Parity Technologies <admin@parity.io>"]
build = "build.rs"
@@ -39,6 +39,7 @@ parking_lot = "0.4"
stats = { path = "../../util/stats" }
hash = { path = "../../util/hash" }
triehash = { path = "../../util/triehash" }
kvdb = { path = "../../util/kvdb" }
[features]
default = []

View File

@@ -45,7 +45,7 @@ use rlp::{Encodable, Decodable, DecoderError, RlpStream, Rlp, UntrustedRlp};
use heapsize::HeapSizeOf;
use bigint::prelude::U256;
use bigint::hash::{H256, H256FastMap, H264};
use util::kvdb::{DBTransaction, KeyValueDB};
use kvdb::{DBTransaction, KeyValueDB};
use cache::Cache;
use parking_lot::{Mutex, RwLock};
@@ -728,12 +728,13 @@ mod tests {
use ethcore::header::Header;
use ethcore::spec::Spec;
use cache::Cache;
use kvdb::{in_memory, KeyValueDB};
use time::Duration;
use parking_lot::Mutex;
fn make_db() -> Arc<::util::KeyValueDB> {
Arc::new(::util::kvdb::in_memory(0))
fn make_db() -> Arc<KeyValueDB> {
Arc::new(in_memory(0))
}
#[test]

View File

@@ -36,7 +36,7 @@ use bigint::prelude::U256;
use bigint::hash::H256;
use futures::{IntoFuture, Future};
use util::kvdb::{KeyValueDB, CompactionProfile};
use kvdb::{KeyValueDB, CompactionProfile};
use self::fetch::ChainDataFetcher;
use self::header_chain::{AncestryIter, HeaderChain};
@@ -214,7 +214,7 @@ impl<T: ChainDataFetcher> Client<T> {
io_channel: IoChannel<ClientIoMessage>,
cache: Arc<Mutex<Cache>>
) -> Self {
let db = ::util::kvdb::in_memory(0);
let db = ::kvdb::in_memory(0);
Client::new(
config,

View File

@@ -25,7 +25,7 @@ use ethcore::db;
use ethcore::service::ClientIoMessage;
use ethcore::spec::Spec;
use io::{IoContext, IoError, IoHandler, IoService};
use util::kvdb::{Database, DatabaseConfig};
use kvdb::{Database, DatabaseConfig};
use cache::Cache;
use parking_lot::Mutex;

View File

@@ -91,6 +91,7 @@ extern crate time;
extern crate vm;
extern crate hash;
extern crate triehash;
extern crate kvdb;
#[cfg(feature = "ipc")]
extern crate ethcore_ipc as ipc;

View File

@@ -3,7 +3,7 @@ description = "Parity smart network connections"
homepage = "http://parity.io"
license = "GPL-3.0"
name = "node-filter"
version = "1.8.0"
version = "1.9.0"
authors = ["Parity Technologies <admin@parity.io>"]
[dependencies]
@@ -13,6 +13,7 @@ ethcore-bigint = { path = "../../util/bigint" }
ethcore-bytes = { path = "../../util/bytes" }
ethcore-io = { path = "../../util/io" }
ethcore-network = { path = "../../util/network" }
kvdb = { path = "../../util/kvdb" }
native-contracts = { path = "../native_contracts" }
futures = "0.1"
log = "0.3"

View File

@@ -24,6 +24,7 @@ extern crate ethcore_network as network;
extern crate native_contracts;
extern crate futures;
extern crate parking_lot;
extern crate kvdb;
#[cfg(test)] extern crate ethcore_io as io;
#[macro_use] extern crate log;
@@ -134,7 +135,7 @@ mod test {
let contract_addr = Address::from_str("0000000000000000000000000000000000000005").unwrap();
let data = include_bytes!("../res/node_filter.json");
let spec = Spec::load(&::std::env::temp_dir(), &data[..]).unwrap();
let client_db = Arc::new(::util::kvdb::in_memory(::ethcore::db::NUM_COLUMNS.unwrap_or(0)));
let client_db = Arc::new(::kvdb::in_memory(::ethcore::db::NUM_COLUMNS.unwrap_or(0)));
let client = Client::new(
ClientConfig::default(),

View File

@@ -132,7 +132,10 @@
"eip150Transition": "0x259518",
"eip160Transition": 2675000,
"eip161abcTransition": 2675000,
"eip161dTransition": 2675000
"eip161dTransition": 2675000,
"eip649Reward": "0x29A2241AF62C0000",
"eip100bTransition": 4370000,
"eip649Transition": 4370000
}
}
},
@@ -146,10 +149,13 @@
"forkBlock": "0x1d4c00",
"forkCanonHash": "0x4985f5ca3d2afbec36529aa96f74de3cc10a2a4a6c44f2157a57d2c6059a11bb",
"eip155Transition": 2675000,
"eip98Transition": "0x7fffffffffffff",
"eip86Transition": "0x7fffffffffffff",
"maxCodeSize": 24576
"maxCodeSize": 24576,
"eip140Transition": 4370000,
"eip211Transition": 4370000,
"eip214Transition": 4370000,
"eip658Transition": 4370000
},
"genesis": {
"seal": {
@@ -191,10 +197,10 @@
"0000000000000000000000000000000000000002": { "builtin": { "name": "sha256", "pricing": { "linear": { "base": 60, "word": 12 } } } },
"0000000000000000000000000000000000000003": { "builtin": { "name": "ripemd160", "pricing": { "linear": { "base": 600, "word": 120 } } } },
"0000000000000000000000000000000000000004": { "builtin": { "name": "identity", "pricing": { "linear": { "base": 15, "word": 3 } } } },
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": "0x7fffffffffffff", "pricing": { "modexp": { "divisor": 100 } } } },
"0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": "0x7fffffffffffff", "pricing": { "linear": { "base": 2000, "word": 0 } } } },
"0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": "0x7fffffffffffff", "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } },
"0000000000000000000000000000000000000005": { "builtin": { "name": "modexp", "activate_at": 4370000, "pricing": { "modexp": { "divisor": 20 } } } },
"0000000000000000000000000000000000000006": { "builtin": { "name": "alt_bn128_add", "activate_at": 4370000, "pricing": { "linear": { "base": 500, "word": 0 } } } },
"0000000000000000000000000000000000000007": { "builtin": { "name": "alt_bn128_mul", "activate_at": 4370000, "pricing": { "linear": { "base": 40000, "word": 0 } } } },
"0000000000000000000000000000000000000008": { "builtin": { "name": "alt_bn128_pairing", "activate_at": 4370000, "pricing": { "alt_bn128_pairing": { "base": 100000, "pair": 80000 } } } },
"3282791d6fd713f1e94f4bfd565eaa78b3a0599d": {
"balance": "1337000000000000000000"
},

View File

@@ -30,11 +30,14 @@
"params": {
"gasLimitBoundDivisor": "0x400",
"registrar" : "0xfAb104398BBefbd47752E7702D9fE23047E1Bca3",
"maximumExtraDataSize": "0x20",
"maximumExtraDataSize": "0x20",
"minGasLimit": "0x1388",
"networkID" : "0x2A",
"forkBlock": 4297256,
"forkCanonHash": "0x0a66d93c2f727dca618fabaf70c39b37018c73d78b939d8b11efbbd09034778f",
"validateReceiptsTransition" : 1000000,
"eip155Transition": 1000000
"eip155Transition": 1000000,
"validateChainIdTransition": 1000000
},
"genesis": {
"seal": {

View File

@@ -64,7 +64,7 @@ impl AddressBook {
/// Sets new name for given address.
pub fn set_name(&mut self, a: Address, name: String) {
{
let mut x = self.cache.entry(a)
let x = self.cache.entry(a)
.or_insert_with(|| AccountMeta {name: Default::default(), meta: "{}".to_owned(), uuid: None});
x.name = name;
}
@@ -74,7 +74,7 @@ impl AddressBook {
/// Sets new meta for given address.
pub fn set_meta(&mut self, a: Address, meta: String) {
{
let mut x = self.cache.entry(a)
let x = self.cache.entry(a)
.or_insert_with(|| AccountMeta {name: "Anonymous".to_owned(), meta: Default::default(), uuid: None});
x.meta = meta;
}
@@ -253,7 +253,7 @@ impl DappsSettingsStore {
/// Marks recent dapp as used
pub fn mark_dapp_used(&mut self, dapp: DappId) {
{
let mut entry = self.history.entry(dapp).or_insert_with(|| Default::default());
let entry = self.history.entry(dapp).or_insert_with(|| Default::default());
entry.last_accessed = self.time.get();
}
// Clear extraneous entries
@@ -280,7 +280,7 @@ impl DappsSettingsStore {
/// Sets accounts for specific dapp.
pub fn set_accounts(&mut self, id: DappId, accounts: Option<Vec<Address>>) {
{
let mut settings = self.settings.entry(id).or_insert_with(DappsSettings::default);
let settings = self.settings.entry(id).or_insert_with(DappsSettings::default);
settings.accounts = accounts;
}
self.settings.save(JsonSettings::write);
@@ -289,7 +289,7 @@ impl DappsSettingsStore {
/// Sets a default account for specific dapp.
pub fn set_default(&mut self, id: DappId, default: Address) {
{
let mut settings = self.settings.entry(id).or_insert_with(DappsSettings::default);
let settings = self.settings.entry(id).or_insert_with(DappsSettings::default);
settings.default = Some(default);
}
self.settings.save(JsonSettings::write);

View File

@@ -26,7 +26,6 @@ use bigint::prelude::U256;
use bigint::hash::{H256, H2048};
use parking_lot::{Mutex, RwLock};
use bytes::Bytes;
use util::*;
use rlp::*;
use header::*;
use super::extras::*;
@@ -47,6 +46,7 @@ use encoded;
use engines::epoch::{Transition as EpochTransition, PendingTransition as PendingEpochTransition};
use rayon::prelude::*;
use ansi_term::Colour;
use kvdb::{DBTransaction, KeyValueDB};
const LOG_BLOOMS_LEVELS: usize = 3;
const LOG_BLOOMS_ELEMENTS_PER_INDEX: usize = 16;
@@ -1479,7 +1479,7 @@ mod tests {
use std::sync::Arc;
use rustc_hex::FromHex;
use hash::keccak;
use util::kvdb::KeyValueDB;
use kvdb::{in_memory, KeyValueDB};
use bigint::hash::*;
use receipt::{Receipt, TransactionOutcome};
use blockchain::{BlockProvider, BlockChain, Config, ImportRoute};
@@ -1493,7 +1493,7 @@ mod tests {
use header::BlockNumber;
fn new_db() -> Arc<KeyValueDB> {
Arc::new(::util::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0)))
Arc::new(in_memory(::db::NUM_COLUMNS.unwrap_or(0)))
}
fn new_chain(genesis: &[u8], db: Arc<KeyValueDB>) -> BlockChain {

View File

@@ -28,7 +28,7 @@ use receipt::Receipt;
use heapsize::HeapSizeOf;
use bigint::prelude::U256;
use bigint::hash::{H256, H264};
use util::kvdb::PREFIX_LEN as DB_PREFIX_LEN;
use kvdb::PREFIX_LEN as DB_PREFIX_LEN;
/// Represents index of extra data in database
#[derive(Copy, Debug, Hash, Eq, PartialEq, Clone)]

View File

@@ -101,18 +101,17 @@ impl Pricer for ModexpPricer {
let exp_len = read_len();
let mod_len = read_len();
let max_len = U256::from(u32::max_value() / 2);
if base_len > max_len || mod_len > max_len {
return U256::max_value();
if mod_len.is_zero() && base_len.is_zero() {
return U256::zero()
}
let base_len = base_len.low_u64();
let exp_len = exp_len.low_u64();
let mod_len = mod_len.low_u64();
let m = max(mod_len, base_len);
if m == 0 {
return U256::zero();
let max_len = U256::from(u32::max_value() / 2);
if base_len > max_len || mod_len > max_len || exp_len > max_len {
return U256::max_value();
}
let (base_len, exp_len, mod_len) = (base_len.low_u64(), exp_len.low_u64(), mod_len.low_u64());
let m = max(mod_len, base_len);
// read fist 32-byte word of the exponent.
let exp_low = if base_len + 96 >= input.len() as u64 { U256::zero() } else {
let mut buf = [0; 32];
@@ -124,7 +123,11 @@ impl Pricer for ModexpPricer {
let adjusted_exp_len = Self::adjusted_exp_len(exp_len, exp_low);
(Self::mult_complexity(m) * max(adjusted_exp_len, 1) / self.divisor as u64).into()
let (gas, overflow) = Self::mult_complexity(m).overflowing_mul(max(adjusted_exp_len, 1));
if overflow {
return U256::max_value();
}
(gas / self.divisor as u64).into()
}
}
@@ -133,8 +136,7 @@ impl ModexpPricer {
let bit_index = if exp_low.is_zero() { 0 } else { (255 - exp_low.leading_zeros()) as u64 };
if len <= 32 {
bit_index
}
else {
} else {
8 * (len - 32) + bit_index
}
}
@@ -707,6 +709,32 @@ mod tests {
native: ethereum_builtin("modexp"),
activate_at: 0,
};
// test for potential gas cost multiplication overflow
{
let input = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000001000000000000000000000000000000000000000000000000000000003b27bafd00000000000000000000000000000000000000000000000000000000503c8ac3").unwrap();
let expected_cost = U256::max_value();
assert_eq!(f.cost(&input[..]), expected_cost.into());
}
// test for potential exp len overflow
{
let input = FromHex::from_hex("\
00000000000000000000000000000000000000000000000000000000000000ff\
2a1e530000000000000000000000000000000000000000000000000000000000\
0000000000000000000000000000000000000000000000000000000000000000"
).unwrap();
let mut output = vec![0u8; 32];
let expected = FromHex::from_hex("0000000000000000000000000000000000000000000000000000000000000000").unwrap();
let expected_cost = U256::max_value();
f.execute(&input[..], &mut BytesRef::Fixed(&mut output[..])).expect("Builtin should fail");
assert_eq!(output, expected);
assert_eq!(f.cost(&input[..]), expected_cost.into());
}
// fermat's little theorem example.
{
let input = FromHex::from_hex("\

View File

@@ -26,10 +26,10 @@ use itertools::Itertools;
use hash::keccak;
use timer::PerfTimer;
use bytes::Bytes;
use util::{journaldb, DBValue};
use util::{Address, UtilError};
use util::{Address, journaldb, DBValue};
use util_error::UtilError;
use trie::{TrieSpec, TrieFactory, Trie};
use util::kvdb::*;
use kvdb::*;
// other
use bigint::prelude::U256;
@@ -988,9 +988,11 @@ impl Client {
/// Tick the client.
// TODO: manage by real events.
pub fn tick(&self) {
pub fn tick(&self, prevent_sleep: bool) {
self.check_garbage();
self.check_snooze();
if !prevent_sleep {
self.check_snooze();
}
}
fn check_garbage(&self) {
@@ -1098,7 +1100,7 @@ impl Client {
if !self.liveness.load(AtomicOrdering::Relaxed) {
self.liveness.store(true, AtomicOrdering::Relaxed);
self.notify(|n| n.start());
trace!(target: "mode", "wake_up: Waking.");
info!(target: "mode", "wake_up: Waking.");
}
}
@@ -1108,11 +1110,11 @@ impl Client {
if self.queue_info().total_queue_size() <= MAX_QUEUE_SIZE_TO_SLEEP_ON {
self.liveness.store(false, AtomicOrdering::Relaxed);
self.notify(|n| n.stop());
trace!(target: "mode", "sleep: Sleeping.");
info!(target: "mode", "sleep: Sleeping.");
} else {
trace!(target: "mode", "sleep: Cannot sleep - syncing ongoing.");
info!(target: "mode", "sleep: Cannot sleep - syncing ongoing.");
// TODO: Consider uncommenting.
//*self.last_activity.lock() = Some(Instant::now());
//(*self.sleep_state.lock()).last_activity = Some(Instant::now());
}
}
}
@@ -2090,7 +2092,7 @@ mod tests {
use std::time::Duration;
use std::sync::Arc;
use std::sync::atomic::{AtomicBool, Ordering};
use util::kvdb::DBTransaction;
use kvdb::DBTransaction;
let client = generate_dummy_client(0);
let genesis = client.chain_info().best_block_hash;

View File

@@ -20,7 +20,8 @@ use std::fmt::{Display, Formatter, Error as FmtError};
use mode::Mode as IpcMode;
use verification::{VerifierType, QueueConfig};
use util::{journaldb, CompactionProfile};
use util::journaldb;
use kvdb::CompactionProfile;
pub use std::time::Duration;
pub use blockchain::Config as BlockChainConfig;

View File

@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use util::UtilError;
use util_error::UtilError;
use std::fmt::{Display, Formatter, Error as FmtError};
use trie::TrieError;

View File

@@ -23,7 +23,7 @@ use bigint::hash::H256;
use util::journaldb;
use trie;
use bytes;
use util::kvdb::{self, KeyValueDB};
use kvdb::{self, KeyValueDB};
use {state, state_db, client, executive, trace, transaction, db, spec, pod_state};
use factory::Factories;
use evm::{self, VMType, FinalizationResult};

View File

@@ -27,6 +27,7 @@ use bigint::prelude::U256;
use bigint::hash::H256;
use parking_lot::RwLock;
use util::*;
use kvdb::{Database, DatabaseConfig};
use bytes::Bytes;
use rlp::*;
use ethkey::{Generator, Random};

View File

@@ -20,7 +20,7 @@ use std::ops::Deref;
use std::hash::Hash;
use std::collections::HashMap;
use parking_lot::RwLock;
use util::{DBTransaction, KeyValueDB};
use kvdb::{DBTransaction, KeyValueDB};
use rlp;

View File

@@ -421,7 +421,7 @@ pub mod common {
.and_then(|_| fields.state.commit());
let block_author = fields.header.author().clone();
fields.traces.as_mut().map(move |mut traces| {
fields.traces.as_mut().map(move |traces| {
let mut tracer = ExecutiveTracer::default();
tracer.trace_reward(block_author, reward, RewardType::Block);
traces.push(tracer.drain())

View File

@@ -17,9 +17,12 @@
//! General error types for use in ethcore.
use std::fmt;
use kvdb;
use bigint::prelude::U256;
use bigint::hash::H256;
use util::*;
use util_error::UtilError;
use snappy::InvalidInput;
use unexpected::{Mismatch, OutOfBounds};
use trie::TrieError;
use io::*;
@@ -299,6 +302,8 @@ impl From<Error> for TransactionImportError {
pub enum Error {
/// Client configuration error.
Client(ClientError),
/// Database error.
Database(kvdb::Error),
/// Error concerning a utility.
Util(UtilError),
/// Error concerning block processing.
@@ -322,7 +327,7 @@ pub enum Error {
/// Standard io error.
StdIo(::std::io::Error),
/// Snappy error.
Snappy(::util::snappy::InvalidInput),
Snappy(InvalidInput),
/// Snapshot error.
Snapshot(SnapshotError),
/// Consensus vote error.
@@ -337,6 +342,7 @@ impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match *self {
Error::Client(ref err) => err.fmt(f),
Error::Database(ref err) => err.fmt(f),
Error::Util(ref err) => err.fmt(f),
Error::Io(ref err) => err.fmt(f),
Error::Block(ref err) => err.fmt(f),
@@ -370,6 +376,12 @@ impl From<ClientError> for Error {
}
}
impl From<kvdb::Error> for Error {
fn from(err: kvdb::Error) -> Error {
Error::Database(err)
}
}
impl From<TransactionError> for Error {
fn from(err: TransactionError) -> Error {
Error::Transaction(err)
@@ -434,8 +446,8 @@ impl From<BlockImportError> for Error {
}
}
impl From<snappy::InvalidInput> for Error {
fn from(err: snappy::InvalidInput) -> Error {
impl From<::snappy::InvalidInput> for Error {
fn from(err: ::snappy::InvalidInput) -> Error {
Error::Snappy(err)
}
}

View File

@@ -416,18 +416,24 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
let cost = builtin.cost(data);
if cost <= params.gas {
if let Err(e) = builtin.execute(data, &mut output) {
let mut builtin_out_buffer = Vec::new();
let result = {
let mut builtin_output = BytesRef::Flexible(&mut builtin_out_buffer);
builtin.execute(data, &mut builtin_output)
};
if let Err(e) = result {
self.state.revert_to_checkpoint();
let evm_err: vm::Error = e.into();
tracer.trace_failed_call(trace_info, vec![], evm_err.clone().into());
Err(evm_err)
} else {
self.state.discard_checkpoint();
output.write(0, &builtin_out_buffer);
// trace only top level calls to builtins to avoid DDoS attacks
if self.depth == 0 {
let mut trace_output = tracer.prepare_trace_output();
if let Some(mut out) = trace_output.as_mut() {
if let Some(out) = trace_output.as_mut() {
*out = output.to_owned();
}
@@ -439,9 +445,10 @@ impl<'a, B: 'a + StateBackend> Executive<'a, B> {
);
}
let out_len = builtin_out_buffer.len();
Ok(FinalizationResult {
gas_left: params.gas - cost,
return_data: ReturnData::new(output.to_owned(), 0, output.len()),
return_data: ReturnData::new(builtin_out_buffer, 0, out_len),
apply_state: true,
})
}

View File

@@ -57,9 +57,11 @@ pub fn json_chain_test(json_data: &[u8]) -> Vec<String> {
};
{
let db = Arc::new(::util::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0)));
let db = Arc::new(::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0)));
let mut config = ClientConfig::default();
config.history = 8;
let client = Client::new(
ClientConfig::default(),
config,
&spec,
db,
Arc::new(Miner::with_spec(&spec)),
@@ -101,7 +103,7 @@ mod block_tests {
declare_test!{BlockchainTests_bcMultiChainTest, "BlockchainTests/bcMultiChainTest"}
declare_test!{BlockchainTests_bcRandomBlockhashTest, "BlockchainTests/bcRandomBlockhashTest"}
declare_test!{BlockchainTests_bcTotalDifficultyTest, "BlockchainTests/bcTotalDifficultyTest"}
declare_test!{BlockchainTests_bcUncleHeaderValiditiy, "BlockchainTests/bcUncleHeaderValiditiy"}
declare_test!{BlockchainTests_bcUncleHeaderValidity, "BlockchainTests/bcUncleHeaderValidity"}
declare_test!{BlockchainTests_bcUncleTest, "BlockchainTests/bcUncleTest"}
declare_test!{BlockchainTests_bcValidBlockTest, "BlockchainTests/bcValidBlockTest"}
declare_test!{BlockchainTests_bcWalletTest, "BlockchainTests/bcWalletTest"}

View File

@@ -0,0 +1,71 @@
// Copyright 2015-2017 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 <http://www.gnu.org/licenses/>.
use ethjson;
use header::Header;
use bigint::prelude::U256;
use spec::Spec;
pub fn json_difficulty_test(json_data: &[u8], spec: Spec) -> Vec<String> {
::ethcore_logger::init_log();
let tests = ethjson::test::DifficultyTest::load(json_data).unwrap();
let engine = &spec.engine;
for (name, test) in tests.into_iter() {
flush!(" - {}...", name);
println!(" - {}...", name);
let mut parent_header = Header::new();
let block_number: u64 = test.current_block_number.into();
parent_header.set_number(block_number - 1);
parent_header.set_gas_limit(0x20000.into());
parent_header.set_timestamp(test.parent_timestamp.into());
parent_header.set_difficulty(test.parent_difficulty.into());
parent_header.set_uncles_hash(test.parent_uncles.into());
let mut header = Header::new();
header.set_number(block_number);
header.set_timestamp(test.current_timestamp.into());
engine.populate_from_parent(&mut header, &parent_header);
let expected_difficulty: U256 = test.current_difficulty.into();
assert_eq!(header.difficulty(), &expected_difficulty);
flushln!("ok");
}
vec![]
}
mod difficulty_test_byzantium {
use super::json_difficulty_test;
fn do_json_test(json_data: &[u8]) -> Vec<String> {
json_difficulty_test(json_data, ::ethereum::new_byzantium_test())
}
declare_test!{DifficultyTests_difficultyByzantium, "BasicTests/difficultyByzantium.json"}
}
mod difficulty_test_foundation {
use super::json_difficulty_test;
fn do_json_test(json_data: &[u8]) -> Vec<String> {
json_difficulty_test(json_data, ::ethereum::new_foundation(&::std::env::temp_dir()))
}
declare_test!{DifficultyTests_difficultyMainNetwork, "BasicTests/difficultyMainNetwork.json"}
}

View File

@@ -22,3 +22,4 @@ mod executive;
mod state;
mod chain;
mod trie;
mod difficulty;

View File

@@ -112,6 +112,10 @@ extern crate triehash;
extern crate ansi_term;
extern crate semantic_version;
extern crate unexpected;
extern crate kvdb;
extern crate util_error;
extern crate snappy;
extern crate migration;
#[macro_use]
extern crate rlp_derive;
@@ -124,11 +128,12 @@ extern crate table;
extern crate bloomable;
extern crate vm;
extern crate wasm;
extern crate ethcore_util as util;
#[macro_use]
extern crate log;
extern crate macros;
#[macro_use]
extern crate ethcore_util as util;
extern crate log;
#[macro_use]
extern crate lazy_static;
#[macro_use]

View File

@@ -351,7 +351,9 @@ impl EthereumMachine {
None => true,
};
let chain_id = if header.number() >= self.params().eip155_transition {
let chain_id = if header.number() < self.params().validate_chain_id_transition {
t.chain_id()
} else if header.number() >= self.params().eip155_transition {
Some(self.params().chain_id)
} else {
None

View File

@@ -16,7 +16,7 @@
//! This migration compresses the state db.
use util::migration::{SimpleMigration, Progress};
use migration::{SimpleMigration, Progress};
use rlp::{Compressible, UntrustedRlp, RlpType};
/// Compressing migration.

View File

@@ -14,7 +14,7 @@
// You should have received a copy of the GNU General Public License
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
use util::migration::SimpleMigration;
use migration::SimpleMigration;
/// This migration reduces the sizes of keys and moves `ExtrasIndex` byte from back to the front.
pub struct ToV6;

View File

@@ -16,7 +16,7 @@
//! Database migrations.
use util::migration::ChangeColumns;
use migration::ChangeColumns;
pub mod state;
pub mod blocks;

View File

@@ -22,8 +22,8 @@ use std::collections::HashMap;
use bigint::hash::H256;
use util::Address;
use bytes::Bytes;
use util::kvdb::Database;
use util::migration::{Batch, Config, Error, Migration, SimpleMigration, Progress};
use kvdb::Database;
use migration::{Batch, Config, Error, Migration, SimpleMigration, Progress};
use hash::keccak;
use std::sync::Arc;

View File

@@ -22,11 +22,11 @@ use state_db::{ACCOUNT_BLOOM_SPACE, DEFAULT_ACCOUNT_PRESET, StateDB};
use trie::TrieDB;
use views::HeaderView;
use bloom_journal::Bloom;
use util::migration::{Error, Migration, Progress, Batch, Config};
use migration::{Error, Migration, Progress, Batch, Config};
use util::journaldb;
use bigint::hash::H256;
use trie::Trie;
use util::{Database, DBTransaction};
use kvdb::{Database, DBTransaction};
/// Account bloom upgrade routine. If bloom already present, does nothing.
/// If database empty (no best block), does nothing.

View File

@@ -18,8 +18,8 @@
//! This migration consolidates all databases into single one using Column Families.
use rlp::{Rlp, RlpStream};
use util::kvdb::Database;
use util::migration::{Batch, Config, Error, Migration, Progress};
use kvdb::Database;
use migration::{Batch, Config, Error, Migration, Progress};
use std::sync::Arc;
/// Which part of block to preserve

View File

@@ -149,7 +149,7 @@ impl BanningTransactionQueue {
/// queue.
fn ban_sender(&mut self, address: Address) -> bool {
let count = {
let mut count = self.senders_bans.entry(address).or_insert_with(|| 0);
let count = self.senders_bans.entry(address).or_insert_with(|| 0);
*count = count.saturating_add(1);
*count
};
@@ -169,7 +169,7 @@ impl BanningTransactionQueue {
/// Returns true if bans threshold has been reached.
fn ban_recipient(&mut self, address: Address) -> bool {
let count = {
let mut count = self.recipients_bans.entry(address).or_insert_with(|| 0);
let count = self.recipients_bans.entry(address).or_insert_with(|| 0);
*count = count.saturating_add(1);
*count
};
@@ -185,7 +185,7 @@ impl BanningTransactionQueue {
/// If bans threshold is reached all subsequent transactions to contracts with this codehash will be rejected.
/// Returns true if bans threshold has been reached.
fn ban_codehash(&mut self, code_hash: H256) -> bool {
let mut count = self.codes_bans.entry(code_hash).or_insert_with(|| 0);
let count = self.codes_bans.entry(code_hash).or_insert_with(|| 0);
*count = count.saturating_add(1);
match self.ban_threshold {

View File

@@ -341,7 +341,7 @@ impl GasPriceQueue {
/// Remove an item from a BTreeMap/HashSet "multimap".
/// Returns true if the item was removed successfully.
pub fn remove(&mut self, gas_price: &U256, hash: &H256) -> bool {
if let Some(mut hashes) = self.backing.get_mut(gas_price) {
if let Some(hashes) = self.backing.get_mut(gas_price) {
let only_one_left = hashes.len() == 1;
if !only_one_left {
// Operation may be ok: only if hash is in gas-price's Set.
@@ -1225,7 +1225,7 @@ impl TransactionQueue {
if by_nonce.is_none() {
return;
}
let mut by_nonce = by_nonce.expect("None is tested in early-exit condition above; qed");
let by_nonce = by_nonce.expect("None is tested in early-exit condition above; qed");
while let Some(order) = by_nonce.remove(&current_nonce) {
// remove also from priority and gas_price
self.future.by_priority.remove(&order);

View File

@@ -19,7 +19,7 @@
use std::sync::Arc;
use std::path::Path;
use bigint::hash::H256;
use util::*;
use kvdb::{Database, DatabaseConfig, KeyValueDB};
use bytes::Bytes;
use io::*;
use spec::Spec;
@@ -27,7 +27,7 @@ use error::*;
use client::{Client, ClientConfig, ChainNotify};
use miner::Miner;
use snapshot::ManifestData;
use snapshot::{ManifestData, RestorationStatus};
use snapshot::service::{Service as SnapshotService, ServiceParams as SnapServiceParams};
use std::sync::atomic::AtomicBool;
use ansi_term::Colour;
@@ -180,7 +180,11 @@ impl IoHandler<ClientIoMessage> for ClientIoHandler {
fn timeout(&self, _io: &IoContext<ClientIoMessage>, timer: TimerToken) {
match timer {
CLIENT_TICK_TIMER => self.client.tick(),
CLIENT_TICK_TIMER => {
use snapshot::SnapshotService;
let snapshot_restoration = if let RestorationStatus::Ongoing{..} = self.snapshot.status() { true } else { false };
self.client.tick(snapshot_restoration)
},
SNAPSHOT_TICK_TIMER => self.snapshot.tick(),
_ => warn!("IO service triggered unregistered timer '{}'", timer),
}

View File

@@ -35,7 +35,7 @@ use snapshot::{Error, ManifestData};
use itertools::{Position, Itertools};
use rlp::{RlpStream, UntrustedRlp};
use bigint::hash::H256;
use util::KeyValueDB;
use kvdb::KeyValueDB;
use bytes::Bytes;
/// Snapshot creation and restoration for PoA chains.

View File

@@ -25,7 +25,7 @@ use engines::EthEngine;
use snapshot::{Error, ManifestData};
use bigint::hash::H256;
use util::kvdb::KeyValueDB;
use kvdb::KeyValueDB;
mod authority;
mod work;

View File

@@ -31,7 +31,7 @@ use engines::EthEngine;
use snapshot::{Error, ManifestData};
use snapshot::block::AbridgedBlock;
use bigint::hash::H256;
use util::KeyValueDB;
use kvdb::KeyValueDB;
use bytes::Bytes;
use rlp::{RlpStream, UntrustedRlp};
use rand::OsRng;

View File

@@ -32,11 +32,12 @@ use ids::BlockId;
use bigint::prelude::U256;
use bigint::hash::H256;
use util::{HashDB, DBValue, snappy};
use util::{HashDB, DBValue};
use snappy;
use bytes::Bytes;
use parking_lot::Mutex;
use util::journaldb::{self, Algorithm, JournalDB};
use util::kvdb::KeyValueDB;
use kvdb::KeyValueDB;
use trie::{TrieDB, TrieDBMut, Trie, TrieMut};
use rlp::{RlpStream, UntrustedRlp};
use bloom_journal::Bloom;

View File

@@ -37,11 +37,11 @@ use io::IoChannel;
use bigint::hash::H256;
use parking_lot::{Mutex, RwLock, RwLockReadGuard};
use util::UtilError;
use util_error::UtilError;
use bytes::Bytes;
use util::journaldb::Algorithm;
use util::kvdb::{Database, DatabaseConfig};
use util::snappy;
use kvdb::{Database, DatabaseConfig};
use snappy;
/// Helper for removing directories in case of error.
struct Guard(bool, PathBuf);
@@ -682,7 +682,7 @@ mod tests {
#[test]
fn cannot_finish_with_invalid_chunks() {
use bigint::hash::H256;
use util::kvdb::DatabaseConfig;
use kvdb::DatabaseConfig;
let spec = get_test_spec();
let dir = RandomTempPath::new();

View File

@@ -31,7 +31,8 @@ use snapshot::io::{SnapshotReader, PackedWriter, PackedReader};
use devtools::{RandomTempPath, GuardedTempResult};
use rand::Rng;
use util::{DBValue, KeyValueDB};
use util::DBValue;
use kvdb::KeyValueDB;
use bigint::hash::H256;
use hashdb::HashDB;
use util::journaldb;
@@ -165,7 +166,7 @@ pub fn restore(
genesis: &[u8],
) -> Result<(), ::error::Error> {
use std::sync::atomic::AtomicBool;
use util::snappy;
use snappy;
let flag = AtomicBool::new(true);
let components = engine.snapshot_components().unwrap();

View File

@@ -31,7 +31,7 @@ use tests::helpers;
use transaction::{Transaction, Action, SignedTransaction};
use util::Address;
use util::kvdb;
use kvdb;
const PASS: &'static str = "";
const TRANSITION_BLOCK_1: usize = 2; // block at which the contract becomes activated.

View File

@@ -25,8 +25,8 @@ use snapshot::{chunk_secondary, Error as SnapshotError, Progress, SnapshotCompon
use snapshot::io::{PackedReader, PackedWriter, SnapshotReader, SnapshotWriter};
use parking_lot::Mutex;
use util::snappy;
use util::kvdb::{self, KeyValueDB, DBTransaction};
use snappy;
use kvdb::{self, KeyValueDB, DBTransaction};
use std::sync::Arc;
use std::sync::atomic::AtomicBool;

View File

@@ -27,7 +27,7 @@ use tests::helpers::generate_dummy_client_with_spec_and_data;
use devtools::RandomTempPath;
use io::IoChannel;
use util::kvdb::{Database, DatabaseConfig};
use kvdb::{Database, DatabaseConfig};
struct NoopDBRestore;

View File

@@ -27,7 +27,7 @@ use error::Error;
use rand::{XorShiftRng, SeedableRng};
use bigint::hash::H256;
use util::journaldb::{self, Algorithm};
use util::kvdb::{Database, DatabaseConfig};
use kvdb::{Database, DatabaseConfig};
use memorydb::MemoryDB;
use parking_lot::Mutex;
use devtools::RandomTempPath;
@@ -76,7 +76,7 @@ fn snap_and_restore() {
for chunk_hash in &reader.manifest().state_hashes {
let raw = reader.chunk(*chunk_hash).unwrap();
let chunk = ::util::snappy::decompress(&raw).unwrap();
let chunk = ::snappy::decompress(&raw).unwrap();
rebuilder.feed(&chunk, &flag).unwrap();
}
@@ -190,7 +190,7 @@ fn checks_flag() {
for chunk_hash in &reader.manifest().state_hashes {
let raw = reader.chunk(*chunk_hash).unwrap();
let chunk = ::util::snappy::decompress(&raw).unwrap();
let chunk = ::snappy::decompress(&raw).unwrap();
match rebuilder.feed(&chunk, &flag) {
Err(Error::Snapshot(SnapshotError::RestorationAborted)) => {},

View File

@@ -85,6 +85,8 @@ pub struct CommonParams {
pub eip155_transition: BlockNumber,
/// Validate block receipts root.
pub validate_receipts_transition: BlockNumber,
/// Validate transaction chain id.
pub validate_chain_id_transition: BlockNumber,
/// Number of first block where EIP-86 (Metropolis) rules begin.
pub eip86_transition: BlockNumber,
/// Number of first block where EIP-140 (Metropolis: REVERT opcode) rules begin.
@@ -153,7 +155,7 @@ impl CommonParams {
self.validate_receipts_transition != 0 && self.eip86_transition != 0 &&
self.eip140_transition != 0 && self.eip210_transition != 0 &&
self.eip211_transition != 0 && self.eip214_transition != 0 &&
self.dust_protection_transition != 0
self.validate_chain_id_transition != 0 && self.dust_protection_transition != 0
}
}
@@ -178,6 +180,7 @@ impl From<ethjson::spec::Params> for CommonParams {
eip98_transition: p.eip98_transition.map_or(0, Into::into),
eip155_transition: p.eip155_transition.map_or(0, Into::into),
validate_receipts_transition: p.validate_receipts_transition.map_or(0, Into::into),
validate_chain_id_transition: p.validate_chain_id_transition.map_or(0, Into::into),
eip86_transition: p.eip86_transition.map_or(
BlockNumber::max_value(),
Into::into,
@@ -667,7 +670,8 @@ impl Spec {
/// constructor.
pub fn genesis_epoch_data(&self) -> Result<Vec<u8>, String> {
use transaction::{Action, Transaction};
use util::{journaldb, kvdb};
use util::journaldb;
use kvdb;
let genesis = self.genesis_header();

View File

@@ -962,7 +962,7 @@ impl<B: Backend> State<B> {
// at this point the entry is guaranteed to be in the cache.
Ok(RefMut::map(self.cache.borrow_mut(), |c| {
let mut entry = c.get_mut(a).expect("entry known to exist in the cache; qed");
let entry = c.get_mut(a).expect("entry known to exist in the cache; qed");
match &mut entry.account {
&mut Some(ref mut acc) => not_default(acc),

View File

@@ -19,14 +19,15 @@ use std::sync::Arc;
use lru_cache::LruCache;
use util::cache::MemoryLruCache;
use util::journaldb::JournalDB;
use util::kvdb::KeyValueDB;
use kvdb::{KeyValueDB, DBTransaction};
use bigint::hash::H256;
use hashdb::HashDB;
use state::{self, Account};
use header::BlockNumber;
use hash::keccak;
use parking_lot::Mutex;
use util::{Address, DBTransaction, UtilError};
use util::Address;
use util_error::UtilError;
use bloom_journal::{Bloom, BloomJournal};
use db::COL_ACCOUNT_BLOOM;
use byteorder::{LittleEndian, ByteOrder};
@@ -210,7 +211,7 @@ impl StateDB {
pub fn sync_cache(&mut self, enacted: &[H256], retracted: &[H256], is_best: bool) {
trace!("sync_cache id = (#{:?}, {:?}), parent={:?}, best={}", self.commit_number, self.commit_hash, self.parent_hash, is_best);
let mut cache = self.account_cache.lock();
let mut cache = &mut *cache;
let cache = &mut *cache;
// Purge changes from re-enacted and retracted blocks.
// Filter out commiting block if any.
@@ -460,7 +461,8 @@ impl state::Backend for StateDB {
mod tests {
use bigint::prelude::U256;
use bigint::hash::H256;
use util::{Address, DBTransaction};
use util::Address;
use kvdb::DBTransaction;
use tests::helpers::*;
use state::{Account, Backend};
use ethcore_logger::init_log;

View File

@@ -27,6 +27,7 @@ use tests::helpers::*;
use types::filter::Filter;
use bigint::prelude::U256;
use util::*;
use kvdb::{Database, DatabaseConfig};
use devtools::*;
use miner::Miner;
use spec::Spec;
@@ -194,7 +195,7 @@ fn imports_block_sequence() {
#[test]
fn can_collect_garbage() {
let client = generate_dummy_client(100);
client.tick();
client.tick(true);
assert!(client.blockchain_cache_info().blocks < 100 * 1024);
}

View File

@@ -231,8 +231,8 @@ pub fn get_test_client_with_blocks(blocks: Vec<Bytes>) -> Arc<Client> {
client
}
fn new_db() -> Arc<KeyValueDB> {
Arc::new(::util::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0)))
fn new_db() -> Arc<::kvdb::KeyValueDB> {
Arc::new(::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0)))
}
pub fn generate_dummy_blockchain(block_number: u32) -> BlockChain {

View File

@@ -27,7 +27,7 @@ use client::*;
use tests::helpers::*;
use devtools::RandomTempPath;
use client::{BlockChainClient, Client, ClientConfig};
use util::kvdb::{Database, DatabaseConfig};
use kvdb::{Database, DatabaseConfig};
use std::sync::Arc;
use header::Header;
use miner::Miner;

View File

@@ -22,7 +22,7 @@ use bloomchain::{Number, Config as BloomConfig};
use bloomchain::group::{BloomGroupDatabase, BloomGroupChain, GroupPosition, BloomGroup};
use heapsize::HeapSizeOf;
use bigint::hash::{H256, H264};
use util::{KeyValueDB, DBTransaction};
use kvdb::{KeyValueDB, DBTransaction};
use parking_lot::RwLock;
use header::BlockNumber;
use trace::{LocalizedTrace, Config, Filter, Database as TraceDatabase, ImportRequest, DatabaseExtras};
@@ -415,7 +415,8 @@ mod tests {
use std::sync::Arc;
use bigint::prelude::U256;
use bigint::hash::H256;
use util::{Address, DBTransaction};
use util::Address;
use kvdb::{DBTransaction, in_memory, KeyValueDB};
use header::BlockNumber;
use trace::{Config, TraceDB, Database as TraceDatabase, DatabaseExtras, ImportRequest};
use trace::{Filter, LocalizedTrace, AddressesFilter, TraceError};
@@ -465,8 +466,8 @@ mod tests {
}
}
fn new_db() -> Arc<::util::kvdb::KeyValueDB> {
Arc::new(::util::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0)))
fn new_db() -> Arc<KeyValueDB> {
Arc::new(in_memory(::db::NUM_COLUMNS.unwrap_or(0)))
}
#[test]

View File

@@ -39,7 +39,8 @@ pub use self::types::filter::{Filter, AddressesFilter};
use bigint::prelude::U256;
use bigint::hash::H256;
use util::{Address, DBTransaction};
use util::Address;
use kvdb::DBTransaction;
use bytes::Bytes;
use self::trace::{Call, Create};
use vm::ActionParams;

View File

@@ -178,7 +178,7 @@ mod test {
"#;
let spec = Spec::load(&::std::env::temp_dir(), spec_data.as_bytes()).unwrap();
let client_db = Arc::new(::util::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0)));
let client_db = Arc::new(::kvdb::in_memory(::db::NUM_COLUMNS.unwrap_or(0)));
let client = Client::new(
ClientConfig::default(),

View File

@@ -522,7 +522,7 @@ impl<K: Kind> VerificationQueue<K> {
return;
}
let mut verified_lock = self.verification.verified.lock();
let mut verified = &mut *verified_lock;
let verified = &mut *verified_lock;
let mut bad = self.verification.bad.lock();
let mut processing = self.processing.write();
bad.reserve(hashes.len());

View File

@@ -11,8 +11,6 @@ ethcore-bigint = { path = "../../util/bigint" }
patricia_trie = { path = "../../util/patricia_trie" }
log = "0.3"
common-types = { path = "../types" }
evmjit = { path = "../../evmjit", optional = true }
ethjson = { path = "../../json" }
lazy_static = "0.2"
rlp = { path = "../../util/rlp" }
hash = { path = "../../util/hash" }

View File

@@ -113,6 +113,49 @@ pub struct Schedule {
pub kill_dust: CleanDustMode,
/// Enable EIP-86 rules
pub eip86: bool,
/// Wasm extra schedule settings
pub wasm: WasmCosts,
}
/// Wasm cost table
pub struct WasmCosts {
/// Arena allocator cost, per byte
pub alloc: u32,
/// Div operations multiplier.
pub div: u32,
/// Div operations multiplier.
pub mul: u32,
/// Memory (load/store) operations multiplier.
pub mem: u32,
/// Memory copy operation.
pub mem_copy: u32,
/// Static region charge, per byte.
pub static_region: u32,
/// General static query of u64 value from env-info
pub static_u64: u32,
/// General static query of U256 value from env-info
pub static_u256: u32,
/// General static query of Address value from env-info
pub static_address: u32,
}
impl Default for WasmCosts {
fn default() -> Self {
WasmCosts {
alloc: 2,
div: 16,
mul: 4,
mem: 2,
mem_copy: 1,
static_region: 1,
// due to runtime issues, this can be slow
static_u64: 32,
static_u256: 64,
static_address: 40,
}
}
}
/// Dust accounts cleanup mode.
@@ -187,6 +230,7 @@ impl Schedule {
have_static_call: false,
kill_dust: CleanDustMode::Off,
eip86: false,
wasm: Default::default(),
}
}
@@ -249,6 +293,7 @@ impl Schedule {
have_static_call: false,
kill_dust: CleanDustMode::Off,
eip86: false,
wasm: Default::default(),
}
}
}

View File

@@ -80,6 +80,12 @@ impl FakeExt {
pub fn new() -> Self {
FakeExt::default()
}
pub fn new_byzantium() -> Self {
let mut ext = FakeExt::default();
ext.schedule = Schedule::new_byzantium();
ext
}
}
impl Ext for FakeExt {

View File

@@ -122,9 +122,18 @@ impl vm::Vm for WasmInterpreter {
&mut cursor
).map_err(|err| {
vm::Error::Wasm(format!("Error deserializing contract code ({:?})", err))
})?
})?,
runtime.gas_rules(),
);
let data_section_length = contract_module.data_section()
.map(|section| section.entries().iter().fold(0, |sum, entry| sum + entry.value().len()))
.unwrap_or(0)
as u64;
let static_segment_cost = data_section_length * runtime.ext().schedule().wasm.static_region as u64;
runtime.charge(|_| static_segment_cost).map_err(Error)?;
let d_ptr = runtime.write_descriptor(&params.data.unwrap_or_default())
.map_err(Error)?;

View File

@@ -22,6 +22,7 @@ use byteorder::{LittleEndian, ByteOrder};
use vm;
use parity_wasm::interpreter;
use wasm_utils::rules;
use bigint::prelude::U256;
use bigint::hash::H256;
use util::Address;
@@ -111,6 +112,7 @@ pub struct Runtime<'a, 'b> {
memory: Arc<InterpreterMemoryInstance>,
context: RuntimeContext,
instance: &'b InterpreterProgramInstance,
gas_rules: rules::Set,
}
impl<'a, 'b> Runtime<'a, 'b> {
@@ -123,6 +125,20 @@ impl<'a, 'b> Runtime<'a, 'b> {
context: RuntimeContext,
program_instance: &'d InterpreterProgramInstance,
) -> Runtime<'c, 'd> {
let rules = {
let schedule = ext.schedule();
rules::Set::new({
let mut vals = ::std::collections::HashMap::with_capacity(4);
vals.insert(rules::InstructionType::Load, schedule.wasm.mem as u32);
vals.insert(rules::InstructionType::Store, schedule.wasm.mem as u32);
vals.insert(rules::InstructionType::Div, schedule.wasm.div as u32);
vals.insert(rules::InstructionType::Mul, schedule.wasm.mul as u32);
vals
})
};
Runtime {
gas_counter: 0,
gas_limit: gas_limit,
@@ -131,6 +147,7 @@ impl<'a, 'b> Runtime<'a, 'b> {
ext: ext,
context: context,
instance: program_instance,
gas_rules: rules,
}
}
@@ -143,6 +160,8 @@ impl<'a, 'b> Runtime<'a, 'b> {
let key = self.pop_h256(&mut context)?;
trace!(target: "wasm", "storage_write: value {} at @{}", &val, &key);
self.charge(|schedule| schedule.sstore_set_gas as u64)?;
self.ext.set_storage(key, val).map_err(|_| UserTrap::StorageUpdateError)?;
Ok(Some(0i32.into()))
@@ -155,9 +174,10 @@ impl<'a, 'b> Runtime<'a, 'b> {
let mut context = context;
let val_ptr = context.value_stack.pop_as::<i32>()?;
let key = self.pop_h256(&mut context)?;
let val = self.ext.storage_at(&key).map_err(|_| UserTrap::StorageReadError)?;
self.charge(|schedule| schedule.sload_gas as u64)?;
self.memory.set(val_ptr as u32, &*val)?;
Ok(Some(0.into()))
@@ -170,6 +190,9 @@ impl<'a, 'b> Runtime<'a, 'b> {
let mut context = context;
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
let address = self.pop_address(&mut context)?;
self.charge(|schedule| schedule.balance_gas as u64)?;
let balance = self.ext.balance(&address).map_err(|_| UserTrap::BalanceQueryError)?;
let value: H256 = balance.into();
self.memory.set(return_ptr, &*value)?;
@@ -183,12 +206,32 @@ impl<'a, 'b> Runtime<'a, 'b> {
let mut context = context;
let refund_address = self.pop_address(&mut context)?;
if self.ext.exists(&refund_address).map_err(|_| UserTrap::SuicideAbort)? {
trace!(target: "wasm", "Suicide: refund to existing address {}", refund_address);
self.charge(|schedule| schedule.suicide_gas as u64)?;
} else {
trace!(target: "wasm", "Suicide: refund to new address {}", refund_address);
self.charge(|schedule| schedule.suicide_to_new_account_cost as u64)?;
}
self.ext.suicide(&refund_address).map_err(|_| UserTrap::SuicideAbort)?;
// We send trap to interpreter so it should abort further execution
Err(UserTrap::Suicide.into())
}
/// Charge gas according to closure
pub fn charge<F>(&mut self, f: F) -> Result<(), InterpreterError>
where F: FnOnce(&vm::Schedule) -> u64
{
let amount = f(self.ext.schedule());
if !self.charge_gas(amount as u64) {
Err(UserTrap::GasLimit.into())
} else {
Ok(())
}
}
/// Invoke create in the state runtime
pub fn create(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
@@ -211,6 +254,9 @@ impl<'a, 'b> Runtime<'a, 'b> {
let code = self.memory.get(code_ptr, code_len as usize)?;
self.charge(|schedule| schedule.create_gas as u64)?;
self.charge(|schedule| schedule.create_data_gas as u64 * code.len() as u64)?;
let gas_left = self.gas_left()
.map_err(|_| UserTrap::InvalidGasState)?
.into();
@@ -312,6 +358,8 @@ impl<'a, 'b> Runtime<'a, 'b> {
}
}
self.charge(|schedule| schedule.call_gas as u64)?;
let mut result = Vec::with_capacity(result_alloc_len as usize);
result.resize(result_alloc_len as usize, 0);
let gas = self.gas_left()
@@ -369,6 +417,9 @@ impl<'a, 'b> Runtime<'a, 'b> {
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let amount = context.value_stack.pop_as::<i32>()? as u32;
self.charge(|schedule| schedule.wasm.alloc as u64 * amount as u64)?;
let previous_top = self.dynamic_top;
self.dynamic_top = previous_top + amount;
Ok(Some((previous_top as i32).into()))
@@ -492,13 +543,15 @@ impl<'a, 'b> Runtime<'a, 'b> {
&*self.memory
}
fn mem_copy(&self, context: InterpreterCallerContext)
fn mem_copy(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let len = context.value_stack.pop_as::<i32>()? as u32;
let dst = context.value_stack.pop_as::<i32>()? as u32;
let src = context.value_stack.pop_as::<i32>()? as u32;
self.charge(|schedule| schedule.wasm.mem_copy as u64 * len as u64)?;
let mem = self.memory().get(src, len as usize)?;
self.memory().set(dst, &mem)?;
@@ -542,6 +595,8 @@ impl<'a, 'b> Runtime<'a, 'b> {
let block_hi = context.value_stack.pop_as::<i32>()? as u32;
let block_lo = context.value_stack.pop_as::<i32>()? as u32;
self.charge(|schedule| schedule.blockhash_gas as u64)?;
let block_num = (block_hi as u64) << 32 | block_lo as u64;
trace!("Requesting block hash for block #{}", block_num);
@@ -552,44 +607,72 @@ impl<'a, 'b> Runtime<'a, 'b> {
Ok(Some(0i32.into()))
}
fn return_address_ptr(&mut self, ptr: u32, val: Address) -> Result<(), InterpreterError>
{
self.charge(|schedule| schedule.wasm.static_address as u64)?;
self.memory.set(ptr, &*val)?;
Ok(())
}
fn return_u256_ptr(&mut self, ptr: u32, val: U256) -> Result<(), InterpreterError> {
let value: H256 = val.into();
self.charge(|schedule| schedule.wasm.static_u256 as u64)?;
self.memory.set(ptr, &*value)?;
Ok(())
}
fn coinbase(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
self.memory.set(return_ptr, &*self.ext.env_info().author)?;
let author = self.ext.env_info().author;
self.return_address_ptr(
context.value_stack.pop_as::<i32>()? as u32,
author,
)?;
Ok(None)
}
fn sender(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
self.memory.set(return_ptr, &*self.context.sender)?;
Ok(None)
let sender = self.context.sender;
self.return_address_ptr(
context.value_stack.pop_as::<i32>()? as u32,
sender,
)?;
Ok(None)
}
fn address(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
self.memory.set(return_ptr, &*self.context.address)?;
Ok(None)
let addr = self.context.address;
self.return_address_ptr(
context.value_stack.pop_as::<i32>()? as u32,
addr,
)?;
Ok(None)
}
fn origin(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
self.memory.set(return_ptr, &*self.context.origin)?;
Ok(None)
let origin = self.context.origin;
self.return_address_ptr(
context.value_stack.pop_as::<i32>()? as u32,
origin,
)?;
Ok(None)
}
fn value(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
let value: H256 = self.context.value.clone().into();
self.memory.set(return_ptr, &*value)?;
let value = self.context.value;
self.return_u256_ptr(
context.value_stack.pop_as::<i32>()? as u32,
value,
)?;
Ok(None)
}
@@ -610,22 +693,28 @@ impl<'a, 'b> Runtime<'a, 'b> {
fn difficulty(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
let difficulty: H256 = self.ext.env_info().difficulty.into();
self.memory.set(return_ptr, &*difficulty)?;
let difficulty = self.ext.env_info().difficulty;
self.return_u256_ptr(
context.value_stack.pop_as::<i32>()? as u32,
difficulty,
)?;
Ok(None)
}
fn ext_gas_limit(&mut self, context: InterpreterCallerContext)
-> Result<Option<interpreter::RuntimeValue>, InterpreterError>
{
let return_ptr = context.value_stack.pop_as::<i32>()? as u32;
let gas_limit: H256 = self.ext.env_info().gas_limit.into();
self.memory.set(return_ptr, &*gas_limit)?;
Ok(None)
let gas_limit = self.ext.env_info().gas_limit;
self.return_u256_ptr(
context.value_stack.pop_as::<i32>()? as u32,
gas_limit,
)?;
Ok(None)
}
fn return_i64(&mut self, val: i64) -> Result<Option<interpreter::RuntimeValue>, InterpreterError> {
self.charge(|schedule| schedule.wasm.static_u64 as u64)?;
let uval = val as u64;
let hi = (uval >> 32) as i32;
let lo = (uval << 32 >> 32) as i32;
@@ -656,6 +745,14 @@ impl<'a, 'b> Runtime<'a, 'b> {
)
)
}
pub fn gas_rules(&self) -> &rules::Set {
&self.gas_rules
}
pub fn ext(&mut self) -> &mut vm::Ext {
self.ext
}
}
impl<'a, 'b> interpreter::UserFunctionExecutor<UserTrap> for Runtime<'a, 'b> {

View File

@@ -60,7 +60,7 @@ fn empty() {
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
};
assert_eq!(gas_left, U256::from(99_992));
assert_eq!(gas_left, U256::from(99_976));
}
// This test checks if the contract deserializes payload header properly.
@@ -68,6 +68,8 @@ fn empty() {
// logger.wasm writes all these provided fixed header fields to some arbitrary storage keys.
#[test]
fn logger() {
::ethcore_logger::init_log();
let code = load_sample!("logger.wasm");
let address: Address = "0f572e5295c57f15886f9b263e2f6d2d6c7b5ec6".parse().unwrap();
let sender: Address = "0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d0d".parse().unwrap();
@@ -87,8 +89,7 @@ fn logger() {
test_finalize(interpreter.exec(params, &mut ext)).unwrap()
};
println!("ext.store: {:?}", ext.store);
assert_eq!(gas_left, U256::from(98_731));
assert_eq!(gas_left, U256::from(15_177));
let address_val: H256 = address.into();
assert_eq!(
ext.store.get(&"0100000000000000000000000000000000000000000000000000000000000000".parse().unwrap()).expect("storage key to exist"),
@@ -141,7 +142,7 @@ fn identity() {
}
};
assert_eq!(gas_left, U256::from(99_812));
assert_eq!(gas_left, U256::from(99_695));
assert_eq!(
Address::from_slice(&result),
@@ -175,7 +176,7 @@ fn dispersion() {
}
};
assert_eq!(gas_left, U256::from(99_474));
assert_eq!(gas_left, U256::from(96_543));
assert_eq!(
result,
@@ -204,7 +205,7 @@ fn suicide_not() {
}
};
assert_eq!(gas_left, U256::from(99_691));
assert_eq!(gas_left, U256::from(96_822));
assert_eq!(
result,
@@ -214,6 +215,8 @@ fn suicide_not() {
#[test]
fn suicide() {
::ethcore_logger::init_log();
let code = load_sample!("suicidal.wasm");
let refund: Address = "01030507090b0d0f11131517191b1d1f21232527".parse().unwrap();
@@ -238,7 +241,7 @@ fn suicide() {
}
};
assert_eq!(gas_left, U256::from(99_490));
assert_eq!(gas_left, U256::from(96_580));
assert!(ext.suicides.contains(&refund));
}
@@ -269,7 +272,7 @@ fn create() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Create,
gas: U256::from(99_144),
gas: U256::from(62_324),
sender_address: None,
receive_address: None,
value: Some(1_000_000_000.into()),
@@ -277,7 +280,7 @@ fn create() {
code_address: None,
}
));
assert_eq!(gas_left, U256::from(99_113));
assert_eq!(gas_left, U256::from(62_289));
}
@@ -311,7 +314,7 @@ fn call_code() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
gas: U256::from(99_138),
gas: U256::from(95_585),
sender_address: Some(sender),
receive_address: Some(receiver),
value: None,
@@ -319,7 +322,7 @@ fn call_code() {
code_address: Some("0d13710000000000000000000000000000000000".parse().unwrap()),
}
));
assert_eq!(gas_left, U256::from(94_269));
assert_eq!(gas_left, U256::from(90_665));
// siphash result
let res = LittleEndian::read_u32(&result[..]);
@@ -356,7 +359,7 @@ fn call_static() {
assert!(ext.calls.contains(
&FakeCall {
call_type: FakeCallType::Call,
gas: U256::from(99_138),
gas: U256::from(95_585),
sender_address: Some(sender),
receive_address: Some(receiver),
value: None,
@@ -364,7 +367,7 @@ fn call_static() {
code_address: Some("13077bfb00000000000000000000000000000000".parse().unwrap()),
}
));
assert_eq!(gas_left, U256::from(94_269));
assert_eq!(gas_left, U256::from(90_665));
// siphash result
let res = LittleEndian::read_u32(&result[..]);
@@ -390,7 +393,7 @@ fn realloc() {
GasLeft::NeedsReturn { gas_left: gas, data: result, apply_state: _apply } => (gas, result.to_vec()),
}
};
assert_eq!(gas_left, U256::from(99_614));
assert_eq!(gas_left, U256::from(96_811));
assert_eq!(result, vec![0u8; 2]);
}
@@ -416,7 +419,7 @@ fn storage_read() {
}
};
assert_eq!(gas_left, U256::from(99_695));
assert_eq!(gas_left, U256::from(96_645));
assert_eq!(Address::from(&result[12..32]), address);
}
@@ -443,7 +446,7 @@ fn keccak() {
};
assert_eq!(H256::from_slice(&result), H256::from("68371d7e884c168ae2022c82bd837d51837718a7f7dfb7aa3f753074a35e1d87"));
assert_eq!(gas_left, U256::from(84_026));
assert_eq!(gas_left, U256::from(80_452));
}
@@ -497,7 +500,7 @@ fn math_add() {
}
).expect("Interpreter to execute without any errors");
assert_eq!(gas_left, U256::from(98_241));
assert_eq!(gas_left, U256::from(94_666));
assert_eq!(
U256::from_dec_str("1888888888888888888888888888887").unwrap(),
(&result[..]).into()
@@ -519,7 +522,7 @@ fn math_mul() {
}
).expect("Interpreter to execute without any errors");
assert_eq!(gas_left, U256::from(97_390));
assert_eq!(gas_left, U256::from(93_719));
assert_eq!(
U256::from_dec_str("888888888888888888888888888887111111111111111111111111111112").unwrap(),
(&result[..]).into()
@@ -541,7 +544,7 @@ fn math_sub() {
}
).expect("Interpreter to execute without any errors");
assert_eq!(gas_left, U256::from(98_285));
assert_eq!(gas_left, U256::from(94_718));
assert_eq!(
U256::from_dec_str("111111111111111111111111111111").unwrap(),
(&result[..]).into()
@@ -580,7 +583,7 @@ fn math_div() {
}
).expect("Interpreter to execute without any errors");
assert_eq!(gas_left, U256::from(91_574));
assert_eq!(gas_left, U256::from(86_996));
assert_eq!(
U256::from_dec_str("1125000").unwrap(),
(&result[..]).into()
@@ -672,5 +675,5 @@ fn externs() {
"Gas limit requested and returned does not match"
);
assert_eq!(gas_left, U256::from(96_284));
assert_eq!(gas_left, U256::from(91_857));
}