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:
@@ -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" }
|
||||
|
||||
@@ -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]);
|
||||
|
||||
@@ -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"
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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 = []
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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"
|
||||
},
|
||||
|
||||
@@ -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": {
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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)]
|
||||
|
||||
@@ -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("\
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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};
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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())
|
||||
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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,
|
||||
})
|
||||
}
|
||||
|
||||
@@ -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"}
|
||||
|
||||
71
ethcore/src/json_tests/difficulty.rs
Normal file
71
ethcore/src/json_tests/difficulty.rs
Normal 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"}
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -22,3 +22,4 @@ mod executive;
|
||||
mod state;
|
||||
mod chain;
|
||||
mod trie;
|
||||
mod difficulty;
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
|
||||
//! Database migrations.
|
||||
|
||||
use util::migration::ChangeColumns;
|
||||
use migration::ChangeColumns;
|
||||
|
||||
pub mod state;
|
||||
pub mod blocks;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(¤t_nonce) {
|
||||
// remove also from priority and gas_price
|
||||
self.future.by_priority.remove(&order);
|
||||
|
||||
@@ -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),
|
||||
}
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)) => {},
|
||||
|
||||
@@ -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();
|
||||
|
||||
|
||||
@@ -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),
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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(),
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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" }
|
||||
|
||||
@@ -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(),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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(¶ms.data.unwrap_or_default())
|
||||
.map_err(Error)?;
|
||||
|
||||
|
||||
@@ -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> {
|
||||
|
||||
@@ -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));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user