Merge branch 'work-notify' of github.com:ethcore/parity into work-notify

This commit is contained in:
Gav Wood 2016-06-29 20:14:32 +02:00
commit f24ba94fbd
14 changed files with 202 additions and 25 deletions

6
Cargo.lock generated
View File

@ -285,7 +285,7 @@ dependencies = [
"log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", "log 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)",
"mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)", "mime_guess 1.6.1 (registry+https://github.com/rust-lang/crates.io-index)",
"parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)", "parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)",
"parity-dapps-builtins 0.5.1 (git+https://github.com/ethcore/parity-dapps-builtins-rs.git)", "parity-dapps-builtins 0.5.2 (git+https://github.com/ethcore/parity-dapps-builtins-rs.git)",
"parity-dapps-status 0.5.0 (git+https://github.com/ethcore/parity-dapps-status-rs.git)", "parity-dapps-status 0.5.0 (git+https://github.com/ethcore/parity-dapps-status-rs.git)",
"parity-dapps-wallet 0.6.1 (git+https://github.com/ethcore/parity-dapps-wallet-rs.git)", "parity-dapps-wallet 0.6.1 (git+https://github.com/ethcore/parity-dapps-wallet-rs.git)",
"rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)", "rustc-serialize 0.3.19 (registry+https://github.com/rust-lang/crates.io-index)",
@ -910,8 +910,8 @@ dependencies = [
[[package]] [[package]]
name = "parity-dapps-builtins" name = "parity-dapps-builtins"
version = "0.5.1" version = "0.5.2"
source = "git+https://github.com/ethcore/parity-dapps-builtins-rs.git#7408838e8ca3b57c6b0cf5da2e31e0e275959955" source = "git+https://github.com/ethcore/parity-dapps-builtins-rs.git#01af2091d5d70dfe0aecbfd96308f0ae79fc61e6"
dependencies = [ dependencies = [
"parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)", "parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)",
] ]

View File

@ -23,7 +23,7 @@ ethcore-util = { path = "../util" }
parity-dapps = { git = "https://github.com/ethcore/parity-dapps-rs.git", version = "0.3" } parity-dapps = { git = "https://github.com/ethcore/parity-dapps-rs.git", version = "0.3" }
# List of apps # List of apps
parity-dapps-status = { git = "https://github.com/ethcore/parity-dapps-status-rs.git", version = "0.5.0" } parity-dapps-status = { git = "https://github.com/ethcore/parity-dapps-status-rs.git", version = "0.5.0" }
parity-dapps-builtins = { git = "https://github.com/ethcore/parity-dapps-builtins-rs.git", version = "0.5.0" } parity-dapps-builtins = { git = "https://github.com/ethcore/parity-dapps-builtins-rs.git", version = "0.5.2" }
parity-dapps-wallet = { git = "https://github.com/ethcore/parity-dapps-wallet-rs.git", version = "0.6.0", optional = true } parity-dapps-wallet = { git = "https://github.com/ethcore/parity-dapps-wallet-rs.git", version = "0.6.0", optional = true }
parity-dapps-dao = { git = "https://github.com/ethcore/parity-dapps-dao-rs.git", version = "0.4.0", optional = true } parity-dapps-dao = { git = "https://github.com/ethcore/parity-dapps-dao-rs.git", version = "0.4.0", optional = true }
parity-dapps-makerotc = { git = "https://github.com/ethcore/parity-dapps-makerotc-rs.git", version = "0.3.0", optional = true } parity-dapps-makerotc = { git = "https://github.com/ethcore/parity-dapps-makerotc-rs.git", version = "0.3.0", optional = true }

View File

@ -108,6 +108,12 @@ impl Account {
self.code_cache = code; self.code_cache = code;
} }
/// Reset this account's code to the given code.
pub fn reset_code(&mut self, code: Bytes) {
self.code_hash = None;
self.init_code(code);
}
/// Set (and cache) the contents of the trie's storage at `key` to `value`. /// Set (and cache) the contents of the trie's storage at `key` to `value`.
pub fn set_storage(&mut self, key: H256, value: H256) { pub fn set_storage(&mut self, key: H256, value: H256) {
self.storage_overlay.borrow_mut().insert(key, (Filth::Dirty, value)); self.storage_overlay.borrow_mut().insert(key, (Filth::Dirty, value));
@ -336,6 +342,21 @@ mod tests {
assert_eq!(a.code_hash().hex(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb"); assert_eq!(a.code_hash().hex(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb");
} }
#[test]
fn reset_code() {
let mut a = Account::new_contract(69.into(), 0.into());
let mut db = MemoryDB::new();
let mut db = AccountDBMut::new(&mut db, &Address::new());
a.init_code(vec![0x55, 0x44, 0xffu8]);
assert_eq!(a.code_hash(), SHA3_EMPTY);
a.commit_code(&mut db);
assert_eq!(a.code_hash().hex(), "af231e631776a517ca23125370d542873eca1fb4d613ed9b5d5335a46ae5b7eb");
a.reset_code(vec![0x55]);
assert_eq!(a.code_hash(), SHA3_EMPTY);
a.commit_code(&mut db);
assert_eq!(a.code_hash().hex(), "37bf2238b11b68cdc8382cece82651b59d3c3988873b6e0f33d79694aa45f1be");
}
#[test] #[test]
fn rlpio() { fn rlpio() {
let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new()); let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new());
@ -348,7 +369,6 @@ mod tests {
#[test] #[test]
fn new_account() { fn new_account() {
let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new()); let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new());
assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
assert_eq!(a.balance(), &U256::from(69u8)); assert_eq!(a.balance(), &U256::from(69u8));
@ -359,7 +379,6 @@ mod tests {
#[test] #[test]
fn create_account() { fn create_account() {
let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new()); let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new());
assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470"); assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
} }

View File

@ -515,9 +515,6 @@ impl BlockChainClient for Client {
ret ret
} }
fn vm_factory(&self) -> &EvmFactory {
&self.vm_factory
}
fn block_header(&self, id: BlockID) -> Option<Bytes> { fn block_header(&self, id: BlockID) -> Option<Bytes> {
Self::block_hash(&self.chain, id).and_then(|hash| self.chain.block(&hash).map(|bytes| BlockView::new(&bytes).rlp().at(0).as_raw().to_vec())) Self::block_hash(&self.chain, id).and_then(|hash| self.chain.block(&hash).map(|bytes| BlockView::new(&bytes).rlp().at(0).as_raw().to_vec()))
@ -829,6 +826,10 @@ impl MiningBlockChainClient for Client {
open_block open_block
} }
fn vm_factory(&self) -> &EvmFactory {
&self.vm_factory
}
} }
impl MayPanic for Client { impl MayPanic for Client {

View File

@ -172,9 +172,6 @@ pub trait BlockChainClient : Sync + Send {
// TODO: should be able to accept blockchain location for call. // TODO: should be able to accept blockchain location for call.
fn call(&self, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, ExecutionError>; fn call(&self, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, ExecutionError>;
/// Returns EvmFactory.
fn vm_factory(&self) -> &EvmFactory;
/// Returns traces matching given filter. /// Returns traces matching given filter.
fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>>; fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>>;
@ -253,4 +250,7 @@ pub trait MiningBlockChainClient : BlockChainClient {
/// Returns OpenBlock prepared for closing. /// Returns OpenBlock prepared for closing.
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes) fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes)
-> OpenBlock; -> OpenBlock;
/// Returns EvmFactory.
fn vm_factory(&self) -> &EvmFactory;
} }

View File

@ -244,6 +244,10 @@ impl MiningBlockChainClient for TestBlockChainClient {
fn prepare_open_block(&self, _author: Address, _gas_range_target: (U256, U256), _extra_data: Bytes) -> OpenBlock { fn prepare_open_block(&self, _author: Address, _gas_range_target: (U256, U256), _extra_data: Bytes) -> OpenBlock {
unimplemented!(); unimplemented!();
} }
fn vm_factory(&self) -> &EvmFactory {
unimplemented!();
}
} }
impl BlockChainClient for TestBlockChainClient { impl BlockChainClient for TestBlockChainClient {
@ -463,10 +467,6 @@ impl BlockChainClient for TestBlockChainClient {
} }
} }
fn vm_factory(&self) -> &EvmFactory {
unimplemented!();
}
fn filter_traces(&self, _filter: TraceFilter) -> Option<Vec<LocalizedTrace>> { fn filter_traces(&self, _filter: TraceFilter) -> Option<Vec<LocalizedTrace>> {
unimplemented!(); unimplemented!();
} }

View File

@ -16,6 +16,7 @@
use rayon::prelude::*; use rayon::prelude::*;
use std::sync::atomic::AtomicBool; use std::sync::atomic::AtomicBool;
use std::time::{Instant, Duration};
use util::*; use util::*;
use account_provider::AccountProvider; use account_provider::AccountProvider;
@ -53,12 +54,16 @@ pub struct MinerOptions {
pub reseal_on_external_tx: bool, pub reseal_on_external_tx: bool,
/// Reseal on receipt of new local transactions. /// Reseal on receipt of new local transactions.
pub reseal_on_own_tx: bool, pub reseal_on_own_tx: bool,
/// Minimum period between transaction-inspired reseals.
pub reseal_min_period: Duration,
/// Maximum amount of gas to bother considering for block insertion. /// Maximum amount of gas to bother considering for block insertion.
pub tx_gas_limit: U256, pub tx_gas_limit: U256,
/// Maximum size of the transaction queue. /// Maximum size of the transaction queue.
pub tx_queue_size: usize, pub tx_queue_size: usize,
/// Whether we should fallback to providing all the queue's transactions or just pending. /// Whether we should fallback to providing all the queue's transactions or just pending.
pub pending_set: PendingSet, pub pending_set: PendingSet,
/// How many historical work packages can we store before running out?
pub work_queue_size: usize,
} }
impl Default for MinerOptions { impl Default for MinerOptions {
@ -71,6 +76,8 @@ impl Default for MinerOptions {
tx_gas_limit: !U256::zero(), tx_gas_limit: !U256::zero(),
tx_queue_size: 1024, tx_queue_size: 1024,
pending_set: PendingSet::AlwaysQueue, pending_set: PendingSet::AlwaysQueue,
reseal_min_period: Duration::from_secs(0),
work_queue_size: 20,
} }
} }
} }
@ -84,6 +91,7 @@ pub struct Miner {
// for sealing... // for sealing...
options: MinerOptions, options: MinerOptions,
sealing_enabled: AtomicBool, sealing_enabled: AtomicBool,
next_allowed_reseal: Mutex<Instant>,
sealing_block_last_request: Mutex<u64>, sealing_block_last_request: Mutex<u64>,
gas_range_target: RwLock<(U256, U256)>, gas_range_target: RwLock<(U256, U256)>,
author: RwLock<Address>, author: RwLock<Address>,
@ -101,8 +109,9 @@ impl Miner {
transaction_queue: Mutex::new(TransactionQueue::new()), transaction_queue: Mutex::new(TransactionQueue::new()),
options: Default::default(), options: Default::default(),
sealing_enabled: AtomicBool::new(false), sealing_enabled: AtomicBool::new(false),
next_allowed_reseal: Mutex::new(Instant::now()),
sealing_block_last_request: Mutex::new(0), sealing_block_last_request: Mutex::new(0),
sealing_work: Mutex::new(UsingQueue::new(5)), sealing_work: Mutex::new(UsingQueue::new(20)),
gas_range_target: RwLock::new((U256::zero(), U256::zero())), gas_range_target: RwLock::new((U256::zero(), U256::zero())),
author: RwLock::new(Address::default()), author: RwLock::new(Address::default()),
extra_data: RwLock::new(Vec::new()), extra_data: RwLock::new(Vec::new()),
@ -118,12 +127,14 @@ impl Miner {
Arc::new(Miner { Arc::new(Miner {
transaction_queue: Mutex::new(TransactionQueue::with_limits(options.tx_queue_size, options.tx_gas_limit)), transaction_queue: Mutex::new(TransactionQueue::with_limits(options.tx_queue_size, options.tx_gas_limit)),
sealing_enabled: AtomicBool::new(options.force_sealing || !options.new_work_notify.is_empty()), sealing_enabled: AtomicBool::new(options.force_sealing || !options.new_work_notify.is_empty()),
options: options, next_allowed_reseal: Mutex::new(Instant::now()),
sealing_block_last_request: Mutex::new(0), sealing_block_last_request: Mutex::new(0),
sealing_work: Mutex::new(UsingQueue::new(5)), sealing_work: Mutex::new(UsingQueue::new(options.work_queue_size)),
options: options,
gas_range_target: RwLock::new((U256::zero(), U256::zero())), gas_range_target: RwLock::new((U256::zero(), U256::zero())),
author: RwLock::new(Address::default()), author: RwLock::new(Address::default()),
extra_data: RwLock::new(Vec::new()), extra_data: RwLock::new(Vec::new()),
options: options,
accounts: accounts, accounts: accounts,
spec: spec, spec: spec,
work_poster: work_poster, work_poster: work_poster,
@ -282,6 +293,9 @@ impl Miner {
// Return if // Return if
!have_work !have_work
} }
/// Are we allowed to do a non-mandatory reseal?
fn tx_reseal_allowed(&self) -> bool { Instant::now() > *self.next_allowed_reseal.lock().unwrap() }
} }
const SEALING_TIMEOUT_IN_BLOCKS : u64 = 5; const SEALING_TIMEOUT_IN_BLOCKS : u64 = 5;
@ -452,7 +466,7 @@ impl MinerService for Miner {
.map(|tx| transaction_queue.add(tx, &fetch_account, TransactionOrigin::External)) .map(|tx| transaction_queue.add(tx, &fetch_account, TransactionOrigin::External))
.collect() .collect()
}; };
if !results.is_empty() && self.options.reseal_on_external_tx { if !results.is_empty() && self.options.reseal_on_external_tx && self.tx_reseal_allowed() {
self.update_sealing(chain); self.update_sealing(chain);
} }
results results
@ -487,7 +501,7 @@ impl MinerService for Miner {
import import
}; };
if imported.is_ok() && self.options.reseal_on_own_tx { if imported.is_ok() && self.options.reseal_on_own_tx && self.tx_reseal_allowed() {
// Make sure to do it after transaction is imported and lock is droped. // Make sure to do it after transaction is imported and lock is droped.
// We need to create pending block and enable sealing // We need to create pending block and enable sealing
let prepared = self.enable_and_prepare_sealing(chain); let prepared = self.enable_and_prepare_sealing(chain);
@ -580,6 +594,7 @@ impl MinerService for Miner {
self.sealing_enabled.store(false, atomic::Ordering::Relaxed); self.sealing_enabled.store(false, atomic::Ordering::Relaxed);
self.sealing_work.lock().unwrap().reset(); self.sealing_work.lock().unwrap().reset();
} else { } else {
*self.next_allowed_reseal.lock().unwrap() = Instant::now() + self.options.reseal_min_period;
self.prepare_sealing(chain); self.prepare_sealing(chain);
} }
} }

View File

@ -441,7 +441,7 @@ impl TransactionQueue {
trace!(target: "miner", "Importing: {:?}", tx.hash()); trace!(target: "miner", "Importing: {:?}", tx.hash());
if tx.gas_price < self.minimal_gas_price { if tx.gas_price < self.minimal_gas_price && origin != TransactionOrigin::Local {
trace!(target: "miner", trace!(target: "miner",
"Dropping transaction below minimal gas price threshold: {:?} (gp: {} < {})", "Dropping transaction below minimal gas price threshold: {:?} (gp: {} < {})",
tx.hash(), tx.hash(),
@ -1055,7 +1055,7 @@ mod test {
} }
#[test] #[test]
fn should_not_import_transaction_below_min_gas_price_threshold() { fn should_not_import_transaction_below_min_gas_price_threshold_if_external() {
// given // given
let mut txq = TransactionQueue::new(); let mut txq = TransactionQueue::new();
let tx = new_tx(); let tx = new_tx();
@ -1074,6 +1074,23 @@ mod test {
assert_eq!(stats.future, 0); assert_eq!(stats.future, 0);
} }
#[test]
fn should_import_transaction_below_min_gas_price_threshold_if_local() {
// given
let mut txq = TransactionQueue::new();
let tx = new_tx();
txq.set_minimal_gas_price(tx.gas_price + U256::one());
// when
let res = txq.add(tx, &default_nonce, TransactionOrigin::Local);
// then
assert_eq!(res.unwrap(), TransactionImportResult::Current);
let stats = txq.status();
assert_eq!(stats.pending, 1);
assert_eq!(stats.future, 0);
}
#[test] #[test]
fn should_reject_incorectly_signed_transaction() { fn should_reject_incorectly_signed_transaction() {
// given // given

View File

@ -0,0 +1,105 @@
// Copyright 2015, 2016 Ethcore (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/>.
extern crate hyper;
use hyper::header::ContentType;
use hyper::method::Method;
use hyper::client::{Request, Response, Client};
use hyper::{Next};
use hyper::net::HttpStream;
use ethash::SeedHashCompute;
use hyper::Url;
use util::*;
use ethereum::ethash::Ethash;
pub struct WorkPoster {
urls: Vec<Url>,
client: Mutex<Client<PostHandler>>,
seed_compute: Mutex<SeedHashCompute>,
}
impl WorkPoster {
pub fn new(urls: &[String]) -> Self {
let urls = urls.into_iter().filter_map(|u| {
match Url::parse(&u) {
Ok(url) => Some(url),
Err(e) => {
warn!("Error parsing URL {} : {}", u, e);
None
}
}
}).collect();
let client = Client::<PostHandler>::configure()
.keep_alive(false)
.build().expect("Error creating HTTP client");
WorkPoster {
client: Mutex::new(client),
urls: urls,
seed_compute: Mutex::new(SeedHashCompute::new()),
}
}
pub fn notify(&self, pow_hash: H256, difficulty: U256, number: u64) {
// TODO: move this to engine
let target = Ethash::difficulty_to_boundary(&difficulty);
let seed_hash = &self.seed_compute.lock().unwrap().get_seedhash(number);
let seed_hash = H256::from_slice(&seed_hash[..]);
let body = format!(r#"{{ "result": ["0x{}","0x{}","0x{}","0x{:x}"] }}"#,
pow_hash.hex(), seed_hash.hex(), target.hex(), number);
let client = self.client.lock().unwrap();
for u in &self.urls {
if let Err(e) = client.request(u.clone(), PostHandler { body: body.clone() }) {
warn!("Error sending HTTP notification to {} : {}", u, e);
}
}
}
}
struct PostHandler {
body: String,
}
impl hyper::client::Handler<HttpStream> for PostHandler {
fn on_request(&mut self, request: &mut Request) -> Next {
request.set_method(Method::Post);
request.headers_mut().set(ContentType::json());
Next::write()
}
fn on_request_writable(&mut self, encoder: &mut hyper::Encoder<HttpStream>) -> Next {
if let Err(e) = encoder.write_all(self.body.as_bytes()) {
trace!("Error posting work data: {}", e);
}
encoder.close();
Next::read()
}
fn on_response(&mut self, _response: Response) -> Next {
Next::end()
}
fn on_response_readable(&mut self, _decoder: &mut hyper::Decoder<HttpStream>) -> Next {
Next::end()
}
fn on_error(&mut self, err: hyper::Error) -> Next {
trace!("Error posting work data: {}", err);
Next::end()
}
}

View File

@ -208,12 +208,17 @@ impl State {
self.require(a, false).set_storage(key, value) self.require(a, false).set_storage(key, value)
} }
/// Initialise the code of account `a` so that it is `value` for `key`. /// Initialise the code of account `a` so that it is `code`.
/// NOTE: Account should have been created with `new_contract`. /// NOTE: Account should have been created with `new_contract`.
pub fn init_code(&mut self, a: &Address, code: Bytes) { pub fn init_code(&mut self, a: &Address, code: Bytes) {
self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{}).init_code(code); self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{}).init_code(code);
} }
/// Reset the code of account `a` so that it is `code`.
pub fn reset_code(&mut self, a: &Address, code: Bytes) {
self.require_or_from(a, true, || Account::new_contract(0.into(), self.account_start_nonce), |_|{}).reset_code(code);
}
/// Execute a given transaction. /// Execute a given transaction.
/// This will change the state accordingly. /// This will change the state accordingly.
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, vm_factory: &EvmFactory, t: &SignedTransaction, tracing: bool) -> ApplyResult { pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, vm_factory: &EvmFactory, t: &SignedTransaction, tracing: bool) -> ApplyResult {

View File

@ -137,6 +137,13 @@ Sealing/Mining Options:
own - reseal only on a new local transaction; own - reseal only on a new local transaction;
ext - reseal only on a new external transaction; ext - reseal only on a new external transaction;
all - reseal on all new transactions [default: all]. all - reseal on all new transactions [default: all].
--reseal-min-period MS Specify the minimum time between reseals from
incoming transactions. MS is time measured in
milliseconds [default: 2000].
--work-queue-size ITEMS Specify the number of historical work packages
which are kept cached lest a solution is found for
them later. High values take more memory but result
in fewer unusable solutions [default: 20].
--tx-gas-limit GAS Apply a limit of GAS as the maximum amount of gas --tx-gas-limit GAS Apply a limit of GAS as the maximum amount of gas
a single transaction may have for it to be mined. a single transaction may have for it to be mined.
--relay-set SET Set of transactions to relay. SET may be: --relay-set SET Set of transactions to relay. SET may be:
@ -304,6 +311,8 @@ pub struct Args {
pub flag_no_token: bool, pub flag_no_token: bool,
pub flag_force_sealing: bool, pub flag_force_sealing: bool,
pub flag_reseal_on_txs: String, pub flag_reseal_on_txs: String,
pub flag_reseal_min_period: u64,
pub flag_work_queue_size: usize,
pub flag_tx_gas_limit: Option<String>, pub flag_tx_gas_limit: Option<String>,
pub flag_relay_set: String, pub flag_relay_set: String,
pub flag_author: Option<String>, pub flag_author: Option<String>,

View File

@ -16,6 +16,7 @@
use std::env; use std::env;
use std::fs::File; use std::fs::File;
use std::time::Duration;
use std::io::{BufRead, BufReader}; use std::io::{BufRead, BufReader};
use std::net::{SocketAddr, IpAddr}; use std::net::{SocketAddr, IpAddr};
use std::path::PathBuf; use std::path::PathBuf;
@ -108,6 +109,8 @@ impl Configuration {
"lenient" => PendingSet::SealingOrElseQueue, "lenient" => PendingSet::SealingOrElseQueue,
x => die!("{}: Invalid value for --relay-set option. Use --help for more information.", x) x => die!("{}: Invalid value for --relay-set option. Use --help for more information.", x)
}, },
reseal_min_period: Duration::from_millis(self.args.flag_reseal_min_period),
work_queue_size: self.args.flag_work_queue_size,
} }
} }

View File

@ -165,7 +165,7 @@ fn transaction_error(error: EthcoreError) -> Error {
"There is too many transactions in the queue. Your transaction was dropped due to limit. Try increasing the fee.".into() "There is too many transactions in the queue. Your transaction was dropped due to limit. Try increasing the fee.".into()
}, },
InsufficientGasPrice { minimal, got } => { InsufficientGasPrice { minimal, got } => {
format!("Transaction fee is to low. It does not satisfy your node's minimal fee (minimal: {}, got: {}). Try increasing the fee.", minimal, got) format!("Transaction fee is too low. It does not satisfy your node's minimal fee (minimal: {}, got: {}). Try increasing the fee.", minimal, got)
}, },
InsufficientBalance { balance, cost } => { InsufficientBalance { balance, cost } => {
format!("Insufficient funds. Account you try to send transaction from does not have enough funds. Required {} and got: {}.", cost, balance) format!("Insufficient funds. Account you try to send transaction from does not have enough funds. Required {} and got: {}.", cost, balance)

View File

@ -17,6 +17,7 @@
//! rpc integration tests. //! rpc integration tests.
use std::sync::Arc; use std::sync::Arc;
use std::str::FromStr; use std::str::FromStr;
use std::time::Duration;
use ethcore::client::{BlockChainClient, Client, ClientConfig}; use ethcore::client::{BlockChainClient, Client, ClientConfig};
use ethcore::ids::BlockID; use ethcore::ids::BlockID;
@ -57,6 +58,8 @@ fn miner_service(spec: Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
tx_queue_size: 1024, tx_queue_size: 1024,
tx_gas_limit: !U256::zero(), tx_gas_limit: !U256::zero(),
pending_set: PendingSet::SealingOrElseQueue, pending_set: PendingSet::SealingOrElseQueue,
reseal_min_period: Duration::from_secs(0),
work_queue_size: 50,
}, },
spec, spec,
Some(accounts) Some(accounts)