Expose default gas price percentile configuration in CLI (#7497)
* Expose gas price percentile. * Fix light eth_call. * fix gas_price in light client
This commit is contained in:
parent
1e8533acbc
commit
69d7c4f519
@ -346,6 +346,7 @@ usage! {
|
|||||||
ARG arg_password: (Vec<String>) = Vec::new(), or |c: &Config| otry!(c.account).password.clone(),
|
ARG arg_password: (Vec<String>) = Vec::new(), or |c: &Config| otry!(c.account).password.clone(),
|
||||||
"--password=[FILE]...",
|
"--password=[FILE]...",
|
||||||
"Provide a file containing a password for unlocking an account. Leading and trailing whitespace is trimmed.",
|
"Provide a file containing a password for unlocking an account. Leading and trailing whitespace is trimmed.",
|
||||||
|
|
||||||
["UI options"]
|
["UI options"]
|
||||||
FLAG flag_force_ui: (bool) = false, or |c: &Config| otry!(c.ui).force.clone(),
|
FLAG flag_force_ui: (bool) = false, or |c: &Config| otry!(c.ui).force.clone(),
|
||||||
"--force-ui",
|
"--force-ui",
|
||||||
@ -696,6 +697,10 @@ usage! {
|
|||||||
"--min-gas-price=[STRING]",
|
"--min-gas-price=[STRING]",
|
||||||
"Minimum amount of Wei per GAS to be paid for a transaction to be accepted for mining. Overrides --usd-per-tx.",
|
"Minimum amount of Wei per GAS to be paid for a transaction to be accepted for mining. Overrides --usd-per-tx.",
|
||||||
|
|
||||||
|
ARG arg_gas_price_percentile: (usize) = 50usize, or |c: &Config| otry!(c.mining).gas_price_percentile,
|
||||||
|
"--gas-price-percentile=[PCT]",
|
||||||
|
"Set PCT percentile gas price value from last 100 blocks as default gas price when sending transactions.",
|
||||||
|
|
||||||
ARG arg_author: (Option<String>) = None, or |c: &Config| otry!(c.mining).author.clone(),
|
ARG arg_author: (Option<String>) = None, or |c: &Config| otry!(c.mining).author.clone(),
|
||||||
"--author=[ADDRESS]",
|
"--author=[ADDRESS]",
|
||||||
"Specify the block author (aka \"coinbase\") address for sending block rewards from sealed blocks. NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.", // Sealing/Mining Option
|
"Specify the block author (aka \"coinbase\") address for sending block rewards from sealed blocks. NOTE: MINING WILL NOT WORK WITHOUT THIS OPTION.", // Sealing/Mining Option
|
||||||
@ -1142,6 +1147,7 @@ struct Mining {
|
|||||||
tx_time_limit: Option<u64>,
|
tx_time_limit: Option<u64>,
|
||||||
relay_set: Option<String>,
|
relay_set: Option<String>,
|
||||||
min_gas_price: Option<u64>,
|
min_gas_price: Option<u64>,
|
||||||
|
gas_price_percentile: Option<usize>,
|
||||||
usd_per_tx: Option<String>,
|
usd_per_tx: Option<String>,
|
||||||
usd_per_eth: Option<String>,
|
usd_per_eth: Option<String>,
|
||||||
price_update_period: Option<String>,
|
price_update_period: Option<String>,
|
||||||
@ -1546,6 +1552,7 @@ mod tests {
|
|||||||
arg_tx_time_limit: Some(100u64),
|
arg_tx_time_limit: Some(100u64),
|
||||||
arg_relay_set: "cheap".into(),
|
arg_relay_set: "cheap".into(),
|
||||||
arg_min_gas_price: Some(0u64),
|
arg_min_gas_price: Some(0u64),
|
||||||
|
arg_gas_price_percentile: 50usize,
|
||||||
arg_usd_per_tx: "0.0025".into(),
|
arg_usd_per_tx: "0.0025".into(),
|
||||||
arg_usd_per_eth: "auto".into(),
|
arg_usd_per_eth: "auto".into(),
|
||||||
arg_price_update_period: "hourly".into(),
|
arg_price_update_period: "hourly".into(),
|
||||||
@ -1794,6 +1801,7 @@ mod tests {
|
|||||||
work_queue_size: None,
|
work_queue_size: None,
|
||||||
relay_set: None,
|
relay_set: None,
|
||||||
min_gas_price: None,
|
min_gas_price: None,
|
||||||
|
gas_price_percentile: None,
|
||||||
usd_per_tx: None,
|
usd_per_tx: None,
|
||||||
usd_per_eth: None,
|
usd_per_eth: None,
|
||||||
price_update_period: Some("hourly".into()),
|
price_update_period: Some("hourly".into()),
|
||||||
|
@ -339,6 +339,7 @@ impl Configuration {
|
|||||||
daemon: daemon,
|
daemon: daemon,
|
||||||
logger_config: logger_config.clone(),
|
logger_config: logger_config.clone(),
|
||||||
miner_options: self.miner_options()?,
|
miner_options: self.miner_options()?,
|
||||||
|
gas_price_percentile: self.args.arg_gas_price_percentile,
|
||||||
ntp_servers: self.ntp_servers(),
|
ntp_servers: self.ntp_servers(),
|
||||||
ws_conf: ws_conf,
|
ws_conf: ws_conf,
|
||||||
http_conf: http_conf,
|
http_conf: http_conf,
|
||||||
@ -1357,6 +1358,7 @@ mod tests {
|
|||||||
daemon: None,
|
daemon: None,
|
||||||
logger_config: Default::default(),
|
logger_config: Default::default(),
|
||||||
miner_options: Default::default(),
|
miner_options: Default::default(),
|
||||||
|
gas_price_percentile: 50,
|
||||||
ntp_servers: vec![
|
ntp_servers: vec![
|
||||||
"0.parity.pool.ntp.org:123".into(),
|
"0.parity.pool.ntp.org:123".into(),
|
||||||
"1.parity.pool.ntp.org:123".into(),
|
"1.parity.pool.ntp.org:123".into(),
|
||||||
|
@ -226,6 +226,7 @@ pub struct FullDependencies {
|
|||||||
pub fetch: FetchClient,
|
pub fetch: FetchClient,
|
||||||
pub remote: parity_reactor::Remote,
|
pub remote: parity_reactor::Remote,
|
||||||
pub whisper_rpc: Option<::whisper::RpcFactory>,
|
pub whisper_rpc: Option<::whisper::RpcFactory>,
|
||||||
|
pub gas_price_percentile: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl FullDependencies {
|
impl FullDependencies {
|
||||||
@ -241,7 +242,7 @@ impl FullDependencies {
|
|||||||
($namespace:ident, $handler:expr, $deps:expr, $nonces:expr) => {
|
($namespace:ident, $handler:expr, $deps:expr, $nonces:expr) => {
|
||||||
{
|
{
|
||||||
let deps = &$deps;
|
let deps = &$deps;
|
||||||
let dispatcher = FullDispatcher::new(deps.client.clone(), deps.miner.clone(), $nonces);
|
let dispatcher = FullDispatcher::new(deps.client.clone(), deps.miner.clone(), $nonces, deps.gas_price_percentile);
|
||||||
if deps.signer_service.is_enabled() {
|
if deps.signer_service.is_enabled() {
|
||||||
$handler.extend_with($namespace::to_delegate(SigningQueueClient::new(&deps.signer_service, dispatcher, deps.remote.clone(), &deps.secret_store)))
|
$handler.extend_with($namespace::to_delegate(SigningQueueClient::new(&deps.signer_service, dispatcher, deps.remote.clone(), &deps.secret_store)))
|
||||||
} else {
|
} else {
|
||||||
@ -256,6 +257,7 @@ impl FullDependencies {
|
|||||||
self.client.clone(),
|
self.client.clone(),
|
||||||
self.miner.clone(),
|
self.miner.clone(),
|
||||||
nonces.clone(),
|
nonces.clone(),
|
||||||
|
self.gas_price_percentile,
|
||||||
);
|
);
|
||||||
for api in apis {
|
for api in apis {
|
||||||
match *api {
|
match *api {
|
||||||
@ -277,6 +279,7 @@ impl FullDependencies {
|
|||||||
pending_nonce_from_queue: self.geth_compatibility,
|
pending_nonce_from_queue: self.geth_compatibility,
|
||||||
allow_pending_receipt_query: !self.geth_compatibility,
|
allow_pending_receipt_query: !self.geth_compatibility,
|
||||||
send_block_number_in_get_work: !self.geth_compatibility,
|
send_block_number_in_get_work: !self.geth_compatibility,
|
||||||
|
gas_price_percentile: self.gas_price_percentile,
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
handler.extend_with(client.to_delegate());
|
handler.extend_with(client.to_delegate());
|
||||||
@ -422,6 +425,7 @@ pub struct LightDependencies<T> {
|
|||||||
pub geth_compatibility: bool,
|
pub geth_compatibility: bool,
|
||||||
pub remote: parity_reactor::Remote,
|
pub remote: parity_reactor::Remote,
|
||||||
pub whisper_rpc: Option<::whisper::RpcFactory>,
|
pub whisper_rpc: Option<::whisper::RpcFactory>,
|
||||||
|
pub gas_price_percentile: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C: LightChainClient + 'static> LightDependencies<C> {
|
impl<C: LightChainClient + 'static> LightDependencies<C> {
|
||||||
@ -440,6 +444,7 @@ impl<C: LightChainClient + 'static> LightDependencies<C> {
|
|||||||
self.cache.clone(),
|
self.cache.clone(),
|
||||||
self.transaction_queue.clone(),
|
self.transaction_queue.clone(),
|
||||||
Arc::new(Mutex::new(dispatch::Reservations::with_pool(self.fetch.pool()))),
|
Arc::new(Mutex::new(dispatch::Reservations::with_pool(self.fetch.pool()))),
|
||||||
|
self.gas_price_percentile,
|
||||||
);
|
);
|
||||||
|
|
||||||
macro_rules! add_signing_methods {
|
macro_rules! add_signing_methods {
|
||||||
@ -477,6 +482,7 @@ impl<C: LightChainClient + 'static> LightDependencies<C> {
|
|||||||
self.transaction_queue.clone(),
|
self.transaction_queue.clone(),
|
||||||
self.secret_store.clone(),
|
self.secret_store.clone(),
|
||||||
self.cache.clone(),
|
self.cache.clone(),
|
||||||
|
self.gas_price_percentile,
|
||||||
);
|
);
|
||||||
handler.extend_with(Eth::to_delegate(client.clone()));
|
handler.extend_with(Eth::to_delegate(client.clone()));
|
||||||
|
|
||||||
@ -492,6 +498,7 @@ impl<C: LightChainClient + 'static> LightDependencies<C> {
|
|||||||
self.sync.clone(),
|
self.sync.clone(),
|
||||||
self.cache.clone(),
|
self.cache.clone(),
|
||||||
self.remote.clone(),
|
self.remote.clone(),
|
||||||
|
self.gas_price_percentile,
|
||||||
);
|
);
|
||||||
self.client.add_listener(
|
self.client.add_listener(
|
||||||
Arc::downgrade(&client.handler()) as Weak<::light::client::LightChainNotify>
|
Arc::downgrade(&client.handler()) as Weak<::light::client::LightChainNotify>
|
||||||
@ -521,6 +528,7 @@ impl<C: LightChainClient + 'static> LightDependencies<C> {
|
|||||||
signer,
|
signer,
|
||||||
self.dapps_address.clone(),
|
self.dapps_address.clone(),
|
||||||
self.ws_address.clone(),
|
self.ws_address.clone(),
|
||||||
|
self.gas_price_percentile,
|
||||||
).to_delegate());
|
).to_delegate());
|
||||||
|
|
||||||
if !for_generic_pubsub {
|
if !for_generic_pubsub {
|
||||||
|
@ -87,6 +87,7 @@ pub struct RunCmd {
|
|||||||
pub daemon: Option<String>,
|
pub daemon: Option<String>,
|
||||||
pub logger_config: LogConfig,
|
pub logger_config: LogConfig,
|
||||||
pub miner_options: MinerOptions,
|
pub miner_options: MinerOptions,
|
||||||
|
pub gas_price_percentile: usize,
|
||||||
pub ntp_servers: Vec<String>,
|
pub ntp_servers: Vec<String>,
|
||||||
pub ws_conf: rpc::WsConfiguration,
|
pub ws_conf: rpc::WsConfiguration,
|
||||||
pub http_conf: rpc::HttpConfiguration,
|
pub http_conf: rpc::HttpConfiguration,
|
||||||
@ -358,6 +359,7 @@ fn execute_light(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) ->
|
|||||||
geth_compatibility: cmd.geth_compatibility,
|
geth_compatibility: cmd.geth_compatibility,
|
||||||
remote: event_loop.remote(),
|
remote: event_loop.remote(),
|
||||||
whisper_rpc: whisper_factory,
|
whisper_rpc: whisper_factory,
|
||||||
|
gas_price_percentile: cmd.gas_price_percentile,
|
||||||
});
|
});
|
||||||
|
|
||||||
let dependencies = rpc::Dependencies {
|
let dependencies = rpc::Dependencies {
|
||||||
@ -761,6 +763,7 @@ pub fn execute(cmd: RunCmd, can_restart: bool, logger: Arc<RotatingLogger>) -> R
|
|||||||
fetch: fetch.clone(),
|
fetch: fetch.clone(),
|
||||||
remote: event_loop.remote(),
|
remote: event_loop.remote(),
|
||||||
whisper_rpc: whisper_factory,
|
whisper_rpc: whisper_factory,
|
||||||
|
gas_price_percentile: cmd.gas_price_percentile,
|
||||||
});
|
});
|
||||||
|
|
||||||
let dependencies = rpc::Dependencies {
|
let dependencies = rpc::Dependencies {
|
||||||
|
@ -88,6 +88,7 @@ pub struct FullDispatcher<C, M> {
|
|||||||
client: Arc<C>,
|
client: Arc<C>,
|
||||||
miner: Arc<M>,
|
miner: Arc<M>,
|
||||||
nonces: Arc<Mutex<nonce::Reservations>>,
|
nonces: Arc<Mutex<nonce::Reservations>>,
|
||||||
|
gas_price_percentile: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<C, M> FullDispatcher<C, M> {
|
impl<C, M> FullDispatcher<C, M> {
|
||||||
@ -96,11 +97,13 @@ impl<C, M> FullDispatcher<C, M> {
|
|||||||
client: Arc<C>,
|
client: Arc<C>,
|
||||||
miner: Arc<M>,
|
miner: Arc<M>,
|
||||||
nonces: Arc<Mutex<nonce::Reservations>>,
|
nonces: Arc<Mutex<nonce::Reservations>>,
|
||||||
|
gas_price_percentile: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
FullDispatcher {
|
FullDispatcher {
|
||||||
client,
|
client,
|
||||||
miner,
|
miner,
|
||||||
nonces,
|
nonces,
|
||||||
|
gas_price_percentile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -111,6 +114,7 @@ impl<C, M> Clone for FullDispatcher<C, M> {
|
|||||||
client: self.client.clone(),
|
client: self.client.clone(),
|
||||||
miner: self.miner.clone(),
|
miner: self.miner.clone(),
|
||||||
nonces: self.nonces.clone(),
|
nonces: self.nonces.clone(),
|
||||||
|
gas_price_percentile: self.gas_price_percentile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -148,7 +152,9 @@ impl<C: MiningBlockChainClient, M: MinerService> Dispatcher for FullDispatcher<C
|
|||||||
used_default_from: request.from.is_none(),
|
used_default_from: request.from.is_none(),
|
||||||
to: request.to,
|
to: request.to,
|
||||||
nonce,
|
nonce,
|
||||||
gas_price: request.gas_price.unwrap_or_else(|| default_gas_price(&*self.client, &*self.miner)),
|
gas_price: request.gas_price.unwrap_or_else(|| {
|
||||||
|
default_gas_price(&*self.client, &*self.miner, self.gas_price_percentile)
|
||||||
|
}),
|
||||||
gas: request.gas.unwrap_or_else(|| self.miner.sensible_gas_limit()),
|
gas: request.gas.unwrap_or_else(|| self.miner.sensible_gas_limit()),
|
||||||
value: request.value.unwrap_or_else(|| 0.into()),
|
value: request.value.unwrap_or_else(|| 0.into()),
|
||||||
data: request.data.unwrap_or_else(Vec::new),
|
data: request.data.unwrap_or_else(Vec::new),
|
||||||
@ -218,8 +224,8 @@ pub fn fetch_gas_price_corpus(
|
|||||||
})
|
})
|
||||||
})
|
})
|
||||||
.map(move |prices| {
|
.map(move |prices| {
|
||||||
// produce a corpus from the vector, cache it, and return
|
// produce a corpus from the vector and cache it.
|
||||||
// the median as the intended gas price.
|
// It's later used to get a percentile for default gas price.
|
||||||
let corpus: ::stats::Corpus<_> = prices.into();
|
let corpus: ::stats::Corpus<_> = prices.into();
|
||||||
cache.lock().set_gas_price_corpus(corpus.clone());
|
cache.lock().set_gas_price_corpus(corpus.clone());
|
||||||
corpus
|
corpus
|
||||||
@ -258,6 +264,8 @@ pub struct LightDispatcher {
|
|||||||
pub transaction_queue: Arc<RwLock<LightTransactionQueue>>,
|
pub transaction_queue: Arc<RwLock<LightTransactionQueue>>,
|
||||||
/// Nonce reservations
|
/// Nonce reservations
|
||||||
pub nonces: Arc<Mutex<nonce::Reservations>>,
|
pub nonces: Arc<Mutex<nonce::Reservations>>,
|
||||||
|
/// Gas Price percentile value used as default gas price.
|
||||||
|
pub gas_price_percentile: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LightDispatcher {
|
impl LightDispatcher {
|
||||||
@ -271,6 +279,7 @@ impl LightDispatcher {
|
|||||||
cache: Arc<Mutex<LightDataCache>>,
|
cache: Arc<Mutex<LightDataCache>>,
|
||||||
transaction_queue: Arc<RwLock<LightTransactionQueue>>,
|
transaction_queue: Arc<RwLock<LightTransactionQueue>>,
|
||||||
nonces: Arc<Mutex<nonce::Reservations>>,
|
nonces: Arc<Mutex<nonce::Reservations>>,
|
||||||
|
gas_price_percentile: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
LightDispatcher {
|
LightDispatcher {
|
||||||
sync,
|
sync,
|
||||||
@ -279,6 +288,7 @@ impl LightDispatcher {
|
|||||||
cache,
|
cache,
|
||||||
transaction_queue,
|
transaction_queue,
|
||||||
nonces,
|
nonces,
|
||||||
|
gas_price_percentile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -345,6 +355,7 @@ impl Dispatcher for LightDispatcher {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// fast path for known gas price.
|
// fast path for known gas price.
|
||||||
|
let gas_price_percentile = self.gas_price_percentile;
|
||||||
let gas_price = match request_gas_price {
|
let gas_price = match request_gas_price {
|
||||||
Some(gas_price) => Either::A(future::ok(with_gas_price(gas_price))),
|
Some(gas_price) => Either::A(future::ok(with_gas_price(gas_price))),
|
||||||
None => Either::B(fetch_gas_price_corpus(
|
None => Either::B(fetch_gas_price_corpus(
|
||||||
@ -352,8 +363,8 @@ impl Dispatcher for LightDispatcher {
|
|||||||
self.client.clone(),
|
self.client.clone(),
|
||||||
self.on_demand.clone(),
|
self.on_demand.clone(),
|
||||||
self.cache.clone()
|
self.cache.clone()
|
||||||
).and_then(|corp| match corp.median() {
|
).and_then(move |corp| match corp.percentile(gas_price_percentile) {
|
||||||
Some(median) => Ok(*median),
|
Some(percentile) => Ok(*percentile),
|
||||||
None => Ok(DEFAULT_GAS_PRICE), // fall back to default on error.
|
None => Ok(DEFAULT_GAS_PRICE), // fall back to default on error.
|
||||||
}).map(with_gas_price))
|
}).map(with_gas_price))
|
||||||
};
|
};
|
||||||
@ -738,11 +749,11 @@ fn decrypt(accounts: &AccountProvider, address: Address, msg: Bytes, password: S
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Extract the default gas price from a client and miner.
|
/// Extract the default gas price from a client and miner.
|
||||||
pub fn default_gas_price<C, M>(client: &C, miner: &M) -> U256 where
|
pub fn default_gas_price<C, M>(client: &C, miner: &M, percentile: usize) -> U256 where
|
||||||
C: MiningBlockChainClient,
|
C: MiningBlockChainClient,
|
||||||
M: MinerService,
|
M: MinerService,
|
||||||
{
|
{
|
||||||
client.gas_price_corpus(100).median().cloned().unwrap_or_else(|| miner.sensible_gas_price())
|
client.gas_price_corpus(100).percentile(percentile).cloned().unwrap_or_else(|| miner.sensible_gas_price())
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Convert RPC confirmation payload to signer confirmation payload.
|
/// Convert RPC confirmation payload to signer confirmation payload.
|
||||||
|
@ -60,6 +60,8 @@ pub struct LightFetch {
|
|||||||
pub sync: Arc<LightSync>,
|
pub sync: Arc<LightSync>,
|
||||||
/// The light data cache.
|
/// The light data cache.
|
||||||
pub cache: Arc<Mutex<Cache>>,
|
pub cache: Arc<Mutex<Cache>>,
|
||||||
|
/// Gas Price percentile
|
||||||
|
pub gas_price_percentile: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Extract a transaction at given index.
|
/// Extract a transaction at given index.
|
||||||
@ -203,6 +205,7 @@ impl LightFetch {
|
|||||||
None => Either::B(self.account(from, id).map(|acc| acc.map(|a| a.nonce))),
|
None => Either::B(self.account(from, id).map(|acc| acc.map(|a| a.nonce))),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
let gas_price_percentile = self.gas_price_percentile;
|
||||||
let gas_price_fut = match req.gas_price {
|
let gas_price_fut = match req.gas_price {
|
||||||
Some(price) => Either::A(future::ok(price)),
|
Some(price) => Either::A(future::ok(price)),
|
||||||
None => Either::B(dispatch::fetch_gas_price_corpus(
|
None => Either::B(dispatch::fetch_gas_price_corpus(
|
||||||
@ -210,8 +213,8 @@ impl LightFetch {
|
|||||||
self.client.clone(),
|
self.client.clone(),
|
||||||
self.on_demand.clone(),
|
self.on_demand.clone(),
|
||||||
self.cache.clone(),
|
self.cache.clone(),
|
||||||
).map(|corp| match corp.median() {
|
).map(move |corp| match corp.percentile(gas_price_percentile) {
|
||||||
Some(median) => *median,
|
Some(percentile) => *percentile,
|
||||||
None => DEFAULT_GAS_PRICE.into(),
|
None => DEFAULT_GAS_PRICE.into(),
|
||||||
}))
|
}))
|
||||||
};
|
};
|
||||||
|
@ -66,6 +66,8 @@ pub struct EthClientOptions {
|
|||||||
pub allow_pending_receipt_query: bool,
|
pub allow_pending_receipt_query: bool,
|
||||||
/// Send additional block number when asking for work
|
/// Send additional block number when asking for work
|
||||||
pub send_block_number_in_get_work: bool,
|
pub send_block_number_in_get_work: bool,
|
||||||
|
/// Gas Price Percentile used as default gas price.
|
||||||
|
pub gas_price_percentile: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl EthClientOptions {
|
impl EthClientOptions {
|
||||||
@ -84,6 +86,7 @@ impl Default for EthClientOptions {
|
|||||||
pending_nonce_from_queue: false,
|
pending_nonce_from_queue: false,
|
||||||
allow_pending_receipt_query: true,
|
allow_pending_receipt_query: true,
|
||||||
send_block_number_in_get_work: true,
|
send_block_number_in_get_work: true,
|
||||||
|
gas_price_percentile: 50,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -338,7 +341,7 @@ impl<C, SN: ?Sized, S: ?Sized, M, EM> Eth for EthClient<C, SN, S, M, EM> where
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn gas_price(&self) -> Result<RpcU256> {
|
fn gas_price(&self) -> Result<RpcU256> {
|
||||||
Ok(RpcU256::from(default_gas_price(&*self.client, &*self.miner)))
|
Ok(RpcU256::from(default_gas_price(&*self.client, &*self.miner, self.options.gas_price_percentile)))
|
||||||
}
|
}
|
||||||
|
|
||||||
fn accounts(&self, meta: Metadata) -> Result<Vec<RpcH160>> {
|
fn accounts(&self, meta: Metadata) -> Result<Vec<RpcH160>> {
|
||||||
|
@ -92,12 +92,14 @@ impl EthPubSubClient<LightFetch> {
|
|||||||
sync: Arc<LightSync>,
|
sync: Arc<LightSync>,
|
||||||
cache: Arc<Mutex<Cache>>,
|
cache: Arc<Mutex<Cache>>,
|
||||||
remote: Remote,
|
remote: Remote,
|
||||||
|
gas_price_percentile: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
let fetch = LightFetch {
|
let fetch = LightFetch {
|
||||||
client,
|
client,
|
||||||
on_demand,
|
on_demand,
|
||||||
sync,
|
sync,
|
||||||
cache
|
cache,
|
||||||
|
gas_price_percentile,
|
||||||
};
|
};
|
||||||
EthPubSubClient::new(Arc::new(fetch), remote)
|
EthPubSubClient::new(Arc::new(fetch), remote)
|
||||||
}
|
}
|
||||||
|
@ -62,6 +62,7 @@ pub struct EthClient<T> {
|
|||||||
accounts: Arc<AccountProvider>,
|
accounts: Arc<AccountProvider>,
|
||||||
cache: Arc<Mutex<LightDataCache>>,
|
cache: Arc<Mutex<LightDataCache>>,
|
||||||
polls: Mutex<PollManager<PollFilter>>,
|
polls: Mutex<PollManager<PollFilter>>,
|
||||||
|
gas_price_percentile: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T> Clone for EthClient<T> {
|
impl<T> Clone for EthClient<T> {
|
||||||
@ -75,6 +76,7 @@ impl<T> Clone for EthClient<T> {
|
|||||||
accounts: self.accounts.clone(),
|
accounts: self.accounts.clone(),
|
||||||
cache: self.cache.clone(),
|
cache: self.cache.clone(),
|
||||||
polls: Mutex::new(PollManager::new()),
|
polls: Mutex::new(PollManager::new()),
|
||||||
|
gas_price_percentile: self.gas_price_percentile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -89,15 +91,17 @@ impl<T: LightChainClient + 'static> EthClient<T> {
|
|||||||
transaction_queue: Arc<RwLock<TransactionQueue>>,
|
transaction_queue: Arc<RwLock<TransactionQueue>>,
|
||||||
accounts: Arc<AccountProvider>,
|
accounts: Arc<AccountProvider>,
|
||||||
cache: Arc<Mutex<LightDataCache>>,
|
cache: Arc<Mutex<LightDataCache>>,
|
||||||
|
gas_price_percentile: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
EthClient {
|
EthClient {
|
||||||
sync: sync,
|
sync,
|
||||||
client: client,
|
client,
|
||||||
on_demand: on_demand,
|
on_demand,
|
||||||
transaction_queue: transaction_queue,
|
transaction_queue,
|
||||||
accounts: accounts,
|
accounts,
|
||||||
cache: cache,
|
cache,
|
||||||
polls: Mutex::new(PollManager::new()),
|
polls: Mutex::new(PollManager::new()),
|
||||||
|
gas_price_percentile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -108,6 +112,7 @@ impl<T: LightChainClient + 'static> EthClient<T> {
|
|||||||
on_demand: self.on_demand.clone(),
|
on_demand: self.on_demand.clone(),
|
||||||
sync: self.sync.clone(),
|
sync: self.sync.clone(),
|
||||||
cache: self.cache.clone(),
|
cache: self.cache.clone(),
|
||||||
|
gas_price_percentile: self.gas_price_percentile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -239,7 +244,7 @@ impl<T: LightChainClient + 'static> Eth for EthClient<T> {
|
|||||||
|
|
||||||
fn gas_price(&self) -> Result<RpcU256> {
|
fn gas_price(&self) -> Result<RpcU256> {
|
||||||
Ok(self.cache.lock().gas_price_corpus()
|
Ok(self.cache.lock().gas_price_corpus()
|
||||||
.and_then(|c| c.median().cloned())
|
.and_then(|c| c.percentile(self.gas_price_percentile).cloned())
|
||||||
.map(RpcU256::from)
|
.map(RpcU256::from)
|
||||||
.unwrap_or_else(Default::default))
|
.unwrap_or_else(Default::default))
|
||||||
}
|
}
|
||||||
|
@ -60,6 +60,7 @@ pub struct ParityClient {
|
|||||||
dapps_address: Option<Host>,
|
dapps_address: Option<Host>,
|
||||||
ws_address: Option<Host>,
|
ws_address: Option<Host>,
|
||||||
eip86_transition: u64,
|
eip86_transition: u64,
|
||||||
|
gas_price_percentile: usize,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl ParityClient {
|
impl ParityClient {
|
||||||
@ -74,6 +75,7 @@ impl ParityClient {
|
|||||||
signer: Option<Arc<SignerService>>,
|
signer: Option<Arc<SignerService>>,
|
||||||
dapps_address: Option<Host>,
|
dapps_address: Option<Host>,
|
||||||
ws_address: Option<Host>,
|
ws_address: Option<Host>,
|
||||||
|
gas_price_percentile: usize,
|
||||||
) -> Self {
|
) -> Self {
|
||||||
ParityClient {
|
ParityClient {
|
||||||
light_dispatch,
|
light_dispatch,
|
||||||
@ -85,7 +87,8 @@ impl ParityClient {
|
|||||||
dapps_address,
|
dapps_address,
|
||||||
ws_address,
|
ws_address,
|
||||||
eip86_transition: client.eip86_transition(),
|
eip86_transition: client.eip86_transition(),
|
||||||
client: client,
|
client,
|
||||||
|
gas_price_percentile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -96,6 +99,7 @@ impl ParityClient {
|
|||||||
on_demand: self.light_dispatch.on_demand.clone(),
|
on_demand: self.light_dispatch.on_demand.clone(),
|
||||||
sync: self.light_dispatch.sync.clone(),
|
sync: self.light_dispatch.sync.clone(),
|
||||||
cache: self.light_dispatch.cache.clone(),
|
cache: self.light_dispatch.cache.clone(),
|
||||||
|
gas_price_percentile: self.gas_price_percentile,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -153,7 +153,7 @@ impl EthTester {
|
|||||||
|
|
||||||
let reservations = Arc::new(Mutex::new(nonce::Reservations::new()));
|
let reservations = Arc::new(Mutex::new(nonce::Reservations::new()));
|
||||||
|
|
||||||
let dispatcher = FullDispatcher::new(client.clone(), miner_service.clone(), reservations);
|
let dispatcher = FullDispatcher::new(client.clone(), miner_service.clone(), reservations, 50);
|
||||||
let eth_sign = SigningUnsafeClient::new(
|
let eth_sign = SigningUnsafeClient::new(
|
||||||
&opt_account_provider,
|
&opt_account_provider,
|
||||||
dispatcher,
|
dispatcher,
|
||||||
|
@ -93,11 +93,12 @@ impl EthTester {
|
|||||||
let snapshot = snapshot_service();
|
let snapshot = snapshot_service();
|
||||||
let hashrates = Arc::new(Mutex::new(HashMap::new()));
|
let hashrates = Arc::new(Mutex::new(HashMap::new()));
|
||||||
let external_miner = Arc::new(ExternalMiner::new(hashrates.clone()));
|
let external_miner = Arc::new(ExternalMiner::new(hashrates.clone()));
|
||||||
|
let gas_price_percentile = options.gas_price_percentile;
|
||||||
let eth = EthClient::new(&client, &snapshot, &sync, &opt_ap, &miner, &external_miner, options).to_delegate();
|
let eth = EthClient::new(&client, &snapshot, &sync, &opt_ap, &miner, &external_miner, options).to_delegate();
|
||||||
let filter = EthFilterClient::new(client.clone(), miner.clone()).to_delegate();
|
let filter = EthFilterClient::new(client.clone(), miner.clone()).to_delegate();
|
||||||
let reservations = Arc::new(Mutex::new(nonce::Reservations::new()));
|
let reservations = Arc::new(Mutex::new(nonce::Reservations::new()));
|
||||||
|
|
||||||
let dispatcher = FullDispatcher::new(client.clone(), miner.clone(), reservations);
|
let dispatcher = FullDispatcher::new(client.clone(), miner.clone(), reservations, gas_price_percentile);
|
||||||
let sign = SigningUnsafeClient::new(&opt_ap, dispatcher).to_delegate();
|
let sign = SigningUnsafeClient::new(&opt_ap, dispatcher).to_delegate();
|
||||||
let mut io: IoHandler<Metadata> = IoHandler::default();
|
let mut io: IoHandler<Metadata> = IoHandler::default();
|
||||||
io.extend_with(eth);
|
io.extend_with(eth);
|
||||||
|
@ -56,7 +56,7 @@ fn setup() -> PersonalTester {
|
|||||||
let miner = miner_service();
|
let miner = miner_service();
|
||||||
let reservations = Arc::new(Mutex::new(nonce::Reservations::new()));
|
let reservations = Arc::new(Mutex::new(nonce::Reservations::new()));
|
||||||
|
|
||||||
let dispatcher = FullDispatcher::new(client, miner.clone(), reservations);
|
let dispatcher = FullDispatcher::new(client, miner.clone(), reservations, 50);
|
||||||
let personal = PersonalClient::new(opt_accounts, dispatcher, false);
|
let personal = PersonalClient::new(opt_accounts, dispatcher, false);
|
||||||
|
|
||||||
let mut io = IoHandler::default();
|
let mut io = IoHandler::default();
|
||||||
@ -112,7 +112,7 @@ fn invalid_password_test(method: &str)
|
|||||||
"value": "0x9184e72a"
|
"value": "0x9184e72a"
|
||||||
}, "password321"],
|
}, "password321"],
|
||||||
"id": 1
|
"id": 1
|
||||||
}"#;
|
}"#;
|
||||||
|
|
||||||
let response = r#"{"jsonrpc":"2.0","error":{"code":-32021,"message":"Account password is invalid or account does not exist.","data":"SStore(InvalidPassword)"},"id":1}"#;
|
let response = r#"{"jsonrpc":"2.0","error":{"code":-32021,"message":"Account password is invalid or account does not exist.","data":"SStore(InvalidPassword)"},"id":1}"#;
|
||||||
|
|
||||||
|
@ -65,7 +65,7 @@ fn signer_tester() -> SignerTester {
|
|||||||
let reservations = Arc::new(Mutex::new(nonce::Reservations::new()));
|
let reservations = Arc::new(Mutex::new(nonce::Reservations::new()));
|
||||||
let event_loop = EventLoop::spawn();
|
let event_loop = EventLoop::spawn();
|
||||||
|
|
||||||
let dispatcher = FullDispatcher::new(client, miner.clone(), reservations);
|
let dispatcher = FullDispatcher::new(client, miner.clone(), reservations, 50);
|
||||||
let mut io = IoHandler::default();
|
let mut io = IoHandler::default();
|
||||||
io.extend_with(SignerClient::new(&opt_accounts, dispatcher, &signer, event_loop.remote()).to_delegate());
|
io.extend_with(SignerClient::new(&opt_accounts, dispatcher, &signer, event_loop.remote()).to_delegate());
|
||||||
|
|
||||||
|
@ -61,7 +61,7 @@ impl Default for SigningTester {
|
|||||||
let reservations = Arc::new(Mutex::new(nonce::Reservations::new()));
|
let reservations = Arc::new(Mutex::new(nonce::Reservations::new()));
|
||||||
let mut io = IoHandler::default();
|
let mut io = IoHandler::default();
|
||||||
|
|
||||||
let dispatcher = FullDispatcher::new(client.clone(), miner.clone(), reservations);
|
let dispatcher = FullDispatcher::new(client.clone(), miner.clone(), reservations, 50);
|
||||||
|
|
||||||
let remote = Remote::new_thread_per_future();
|
let remote = Remote::new_thread_per_future();
|
||||||
|
|
||||||
|
@ -46,6 +46,18 @@ impl<T> Deref for Corpus<T> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Ord> Corpus<T> {
|
impl<T: Ord> Corpus<T> {
|
||||||
|
/// Get given percentile (approximated).
|
||||||
|
pub fn percentile(&self, val: usize) -> Option<&T> {
|
||||||
|
let len = self.0.len();
|
||||||
|
let x = val * len / 100;
|
||||||
|
let x = ::std::cmp::min(x, len);
|
||||||
|
if x == 0 {
|
||||||
|
return None;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.0.get(x - 1)
|
||||||
|
}
|
||||||
|
|
||||||
/// Get the median element, if it exists.
|
/// Get the median element, if it exists.
|
||||||
pub fn median(&self) -> Option<&T> {
|
pub fn median(&self) -> Option<&T> {
|
||||||
self.0.get(self.0.len() / 2)
|
self.0.get(self.0.len() / 2)
|
||||||
@ -121,7 +133,19 @@ impl<T: Ord + Copy + ::std::fmt::Display> Histogram<T>
|
|||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::Histogram;
|
use super::*;
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn check_corpus() {
|
||||||
|
let corpus = Corpus::from(vec![1, 2, 3, 4, 5, 6, 7, 8, 9, 10]);
|
||||||
|
assert_eq!(corpus.percentile(0), None);
|
||||||
|
assert_eq!(corpus.percentile(1), None);
|
||||||
|
assert_eq!(corpus.percentile(101), Some(&10));
|
||||||
|
assert_eq!(corpus.percentile(100), Some(&10));
|
||||||
|
assert_eq!(corpus.percentile(50), Some(&5));
|
||||||
|
assert_eq!(corpus.percentile(60), Some(&6));
|
||||||
|
assert_eq!(corpus.median(), Some(&6));
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn check_histogram() {
|
fn check_histogram() {
|
||||||
|
Loading…
Reference in New Issue
Block a user