Merge branch 'work-notify' of github.com:ethcore/parity into work-notify
This commit is contained in:
commit
f24ba94fbd
6
Cargo.lock
generated
6
Cargo.lock
generated
@ -285,7 +285,7 @@ dependencies = [
|
||||
"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)",
|
||||
"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-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)",
|
||||
@ -910,8 +910,8 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "parity-dapps-builtins"
|
||||
version = "0.5.1"
|
||||
source = "git+https://github.com/ethcore/parity-dapps-builtins-rs.git#7408838e8ca3b57c6b0cf5da2e31e0e275959955"
|
||||
version = "0.5.2"
|
||||
source = "git+https://github.com/ethcore/parity-dapps-builtins-rs.git#01af2091d5d70dfe0aecbfd96308f0ae79fc61e6"
|
||||
dependencies = [
|
||||
"parity-dapps 0.3.0 (git+https://github.com/ethcore/parity-dapps-rs.git)",
|
||||
]
|
||||
|
@ -23,7 +23,7 @@ ethcore-util = { path = "../util" }
|
||||
parity-dapps = { git = "https://github.com/ethcore/parity-dapps-rs.git", version = "0.3" }
|
||||
# List of apps
|
||||
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-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 }
|
||||
|
@ -108,6 +108,12 @@ impl Account {
|
||||
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`.
|
||||
pub fn set_storage(&mut self, key: H256, value: H256) {
|
||||
self.storage_overlay.borrow_mut().insert(key, (Filth::Dirty, value));
|
||||
@ -336,6 +342,21 @@ mod tests {
|
||||
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]
|
||||
fn rlpio() {
|
||||
let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new());
|
||||
@ -348,7 +369,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn new_account() {
|
||||
|
||||
let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new());
|
||||
assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
|
||||
assert_eq!(a.balance(), &U256::from(69u8));
|
||||
@ -359,7 +379,6 @@ mod tests {
|
||||
|
||||
#[test]
|
||||
fn create_account() {
|
||||
|
||||
let a = Account::new(U256::from(69u8), U256::from(0u8), HashMap::new(), Bytes::new());
|
||||
assert_eq!(a.rlp().to_hex(), "f8448045a056e81f171bcc55a6ff8345e692c0f86e5b48e01b996cadc001622fb5e363b421a0c5d2460186f7233c927e7db2dcc703c0e500b653ca82273b7bfad8045d85a470");
|
||||
}
|
||||
|
@ -515,9 +515,6 @@ impl BlockChainClient for Client {
|
||||
ret
|
||||
}
|
||||
|
||||
fn vm_factory(&self) -> &EvmFactory {
|
||||
&self.vm_factory
|
||||
}
|
||||
|
||||
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()))
|
||||
@ -829,6 +826,10 @@ impl MiningBlockChainClient for Client {
|
||||
|
||||
open_block
|
||||
}
|
||||
|
||||
fn vm_factory(&self) -> &EvmFactory {
|
||||
&self.vm_factory
|
||||
}
|
||||
}
|
||||
|
||||
impl MayPanic for Client {
|
||||
|
@ -172,9 +172,6 @@ pub trait BlockChainClient : Sync + Send {
|
||||
// TODO: should be able to accept blockchain location for call.
|
||||
fn call(&self, t: &SignedTransaction, analytics: CallAnalytics) -> Result<Executed, ExecutionError>;
|
||||
|
||||
/// Returns EvmFactory.
|
||||
fn vm_factory(&self) -> &EvmFactory;
|
||||
|
||||
/// Returns traces matching given filter.
|
||||
fn filter_traces(&self, filter: TraceFilter) -> Option<Vec<LocalizedTrace>>;
|
||||
|
||||
@ -253,4 +250,7 @@ pub trait MiningBlockChainClient : BlockChainClient {
|
||||
/// Returns OpenBlock prepared for closing.
|
||||
fn prepare_open_block(&self, author: Address, gas_range_target: (U256, U256), extra_data: Bytes)
|
||||
-> OpenBlock;
|
||||
|
||||
/// Returns EvmFactory.
|
||||
fn vm_factory(&self) -> &EvmFactory;
|
||||
}
|
||||
|
@ -244,6 +244,10 @@ impl MiningBlockChainClient for TestBlockChainClient {
|
||||
fn prepare_open_block(&self, _author: Address, _gas_range_target: (U256, U256), _extra_data: Bytes) -> OpenBlock {
|
||||
unimplemented!();
|
||||
}
|
||||
|
||||
fn vm_factory(&self) -> &EvmFactory {
|
||||
unimplemented!();
|
||||
}
|
||||
}
|
||||
|
||||
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>> {
|
||||
unimplemented!();
|
||||
}
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
use rayon::prelude::*;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::time::{Instant, Duration};
|
||||
|
||||
use util::*;
|
||||
use account_provider::AccountProvider;
|
||||
@ -53,12 +54,16 @@ pub struct MinerOptions {
|
||||
pub reseal_on_external_tx: bool,
|
||||
/// Reseal on receipt of new local transactions.
|
||||
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.
|
||||
pub tx_gas_limit: U256,
|
||||
/// Maximum size of the transaction queue.
|
||||
pub tx_queue_size: usize,
|
||||
/// Whether we should fallback to providing all the queue's transactions or just pending.
|
||||
pub pending_set: PendingSet,
|
||||
/// How many historical work packages can we store before running out?
|
||||
pub work_queue_size: usize,
|
||||
}
|
||||
|
||||
impl Default for MinerOptions {
|
||||
@ -71,6 +76,8 @@ impl Default for MinerOptions {
|
||||
tx_gas_limit: !U256::zero(),
|
||||
tx_queue_size: 1024,
|
||||
pending_set: PendingSet::AlwaysQueue,
|
||||
reseal_min_period: Duration::from_secs(0),
|
||||
work_queue_size: 20,
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -84,6 +91,7 @@ pub struct Miner {
|
||||
// for sealing...
|
||||
options: MinerOptions,
|
||||
sealing_enabled: AtomicBool,
|
||||
next_allowed_reseal: Mutex<Instant>,
|
||||
sealing_block_last_request: Mutex<u64>,
|
||||
gas_range_target: RwLock<(U256, U256)>,
|
||||
author: RwLock<Address>,
|
||||
@ -101,8 +109,9 @@ impl Miner {
|
||||
transaction_queue: Mutex::new(TransactionQueue::new()),
|
||||
options: Default::default(),
|
||||
sealing_enabled: AtomicBool::new(false),
|
||||
next_allowed_reseal: Mutex::new(Instant::now()),
|
||||
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())),
|
||||
author: RwLock::new(Address::default()),
|
||||
extra_data: RwLock::new(Vec::new()),
|
||||
@ -118,12 +127,14 @@ impl Miner {
|
||||
Arc::new(Miner {
|
||||
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()),
|
||||
options: options,
|
||||
next_allowed_reseal: Mutex::new(Instant::now()),
|
||||
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())),
|
||||
author: RwLock::new(Address::default()),
|
||||
extra_data: RwLock::new(Vec::new()),
|
||||
options: options,
|
||||
accounts: accounts,
|
||||
spec: spec,
|
||||
work_poster: work_poster,
|
||||
@ -282,6 +293,9 @@ impl Miner {
|
||||
// Return if
|
||||
!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;
|
||||
@ -452,7 +466,7 @@ impl MinerService for Miner {
|
||||
.map(|tx| transaction_queue.add(tx, &fetch_account, TransactionOrigin::External))
|
||||
.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);
|
||||
}
|
||||
results
|
||||
@ -487,7 +501,7 @@ impl MinerService for Miner {
|
||||
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.
|
||||
// We need to create pending block and enable sealing
|
||||
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_work.lock().unwrap().reset();
|
||||
} else {
|
||||
*self.next_allowed_reseal.lock().unwrap() = Instant::now() + self.options.reseal_min_period;
|
||||
self.prepare_sealing(chain);
|
||||
}
|
||||
}
|
||||
|
@ -441,7 +441,7 @@ impl TransactionQueue {
|
||||
|
||||
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",
|
||||
"Dropping transaction below minimal gas price threshold: {:?} (gp: {} < {})",
|
||||
tx.hash(),
|
||||
@ -1055,7 +1055,7 @@ mod 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
|
||||
let mut txq = TransactionQueue::new();
|
||||
let tx = new_tx();
|
||||
@ -1074,6 +1074,23 @@ mod test {
|
||||
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]
|
||||
fn should_reject_incorectly_signed_transaction() {
|
||||
// given
|
||||
|
105
ethcore/src/miner/work_notify.rs
Normal file
105
ethcore/src/miner/work_notify.rs
Normal 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()
|
||||
}
|
||||
}
|
||||
|
@ -208,12 +208,17 @@ impl State {
|
||||
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`.
|
||||
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);
|
||||
}
|
||||
|
||||
/// 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.
|
||||
/// This will change the state accordingly.
|
||||
pub fn apply(&mut self, env_info: &EnvInfo, engine: &Engine, vm_factory: &EvmFactory, t: &SignedTransaction, tracing: bool) -> ApplyResult {
|
||||
|
@ -137,6 +137,13 @@ Sealing/Mining Options:
|
||||
own - reseal only on a new local transaction;
|
||||
ext - reseal only on a new external transaction;
|
||||
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
|
||||
a single transaction may have for it to be mined.
|
||||
--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_force_sealing: bool,
|
||||
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_relay_set: String,
|
||||
pub flag_author: Option<String>,
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
use std::env;
|
||||
use std::fs::File;
|
||||
use std::time::Duration;
|
||||
use std::io::{BufRead, BufReader};
|
||||
use std::net::{SocketAddr, IpAddr};
|
||||
use std::path::PathBuf;
|
||||
@ -108,6 +109,8 @@ impl Configuration {
|
||||
"lenient" => PendingSet::SealingOrElseQueue,
|
||||
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,
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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()
|
||||
},
|
||||
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 } => {
|
||||
format!("Insufficient funds. Account you try to send transaction from does not have enough funds. Required {} and got: {}.", cost, balance)
|
||||
|
@ -17,6 +17,7 @@
|
||||
//! rpc integration tests.
|
||||
use std::sync::Arc;
|
||||
use std::str::FromStr;
|
||||
use std::time::Duration;
|
||||
|
||||
use ethcore::client::{BlockChainClient, Client, ClientConfig};
|
||||
use ethcore::ids::BlockID;
|
||||
@ -57,6 +58,8 @@ fn miner_service(spec: Spec, accounts: Arc<AccountProvider>) -> Arc<Miner> {
|
||||
tx_queue_size: 1024,
|
||||
tx_gas_limit: !U256::zero(),
|
||||
pending_set: PendingSet::SealingOrElseQueue,
|
||||
reseal_min_period: Duration::from_secs(0),
|
||||
work_queue_size: 50,
|
||||
},
|
||||
spec,
|
||||
Some(accounts)
|
||||
|
Loading…
Reference in New Issue
Block a user