Gas price statistics. (#1291)
* Gas price statistics. Affects eth_gasPrice. Added ethcore_gasPriceStatistics. Closes #1265 * Fix a bug in eth_gasPrice * Fix tests. * Revert minor alteration. * Tests for gas_price_statistics. - Tests; - Additional infrastructure for generating test blocks with transactions.
This commit is contained in:
@@ -153,15 +153,23 @@ impl<C, S, A, M, EM> EthClient<C, S, A, M, EM> where
|
||||
}
|
||||
}
|
||||
|
||||
fn default_gas_price(&self) -> Result<U256, Error> {
|
||||
let miner = take_weak!(self.miner);
|
||||
Ok(take_weak!(self.client)
|
||||
.gas_price_statistics(100, 8)
|
||||
.map(|x| x[4])
|
||||
.unwrap_or_else(|_| miner.sensible_gas_price())
|
||||
)
|
||||
}
|
||||
|
||||
fn sign_call(&self, request: CallRequest) -> Result<SignedTransaction, Error> {
|
||||
let client = take_weak!(self.client);
|
||||
let miner = take_weak!(self.miner);
|
||||
let from = request.from.unwrap_or(Address::zero());
|
||||
Ok(EthTransaction {
|
||||
nonce: request.nonce.unwrap_or_else(|| client.latest_nonce(&from)),
|
||||
action: request.to.map_or(Action::Create, Action::Call),
|
||||
gas: request.gas.unwrap_or(U256::from(50_000_000)),
|
||||
gas_price: request.gas_price.unwrap_or_else(|| miner.sensible_gas_price()),
|
||||
gas_price: request.gas_price.unwrap_or_else(|| self.default_gas_price().expect("call only fails if client or miner are unavailable; client and miner are both available to be here; qed")),
|
||||
value: request.value.unwrap_or_else(U256::zero),
|
||||
data: request.data.map_or_else(Vec::new, |d| d.to_vec())
|
||||
}.fake_sign(from))
|
||||
@@ -293,7 +301,7 @@ impl<C, S, A, M, EM> Eth for EthClient<C, S, A, M, EM> where
|
||||
|
||||
fn gas_price(&self, params: Params) -> Result<Value, Error> {
|
||||
match params {
|
||||
Params::None => to_value(&take_weak!(self.miner).sensible_gas_price()),
|
||||
Params::None => to_value(&try!(self.default_gas_price())),
|
||||
_ => Err(Error::invalid_params())
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,30 +15,34 @@
|
||||
// along with Parity. If not, see <http://www.gnu.org/licenses/>.
|
||||
|
||||
//! Ethcore-specific rpc implementation.
|
||||
use util::RotatingLogger;
|
||||
use util::{RotatingLogger};
|
||||
use util::network_settings::NetworkSettings;
|
||||
use util::misc::version_data;
|
||||
use std::sync::{Arc, Weak};
|
||||
use std::ops::Deref;
|
||||
use std::collections::BTreeMap;
|
||||
use std::collections::{BTreeMap};
|
||||
use ethcore::client::{MiningBlockChainClient};
|
||||
use jsonrpc_core::*;
|
||||
use ethcore::miner::MinerService;
|
||||
use v1::traits::Ethcore;
|
||||
use v1::types::{Bytes};
|
||||
|
||||
/// Ethcore implementation.
|
||||
pub struct EthcoreClient<M> where
|
||||
pub struct EthcoreClient<C, M> where
|
||||
C: MiningBlockChainClient,
|
||||
M: MinerService {
|
||||
|
||||
client: Weak<C>,
|
||||
miner: Weak<M>,
|
||||
logger: Arc<RotatingLogger>,
|
||||
settings: Arc<NetworkSettings>,
|
||||
}
|
||||
|
||||
impl<M> EthcoreClient<M> where M: MinerService {
|
||||
impl<C, M> EthcoreClient<C, M> where C: MiningBlockChainClient, M: MinerService {
|
||||
/// Creates new `EthcoreClient`.
|
||||
pub fn new(miner: &Arc<M>, logger: Arc<RotatingLogger>, settings: Arc<NetworkSettings>) -> Self {
|
||||
pub fn new(client: &Arc<C>, miner: &Arc<M>, logger: Arc<RotatingLogger>, settings: Arc<NetworkSettings>) -> Self {
|
||||
EthcoreClient {
|
||||
client: Arc::downgrade(client),
|
||||
miner: Arc::downgrade(miner),
|
||||
logger: logger,
|
||||
settings: settings,
|
||||
@@ -46,7 +50,7 @@ impl<M> EthcoreClient<M> where M: MinerService {
|
||||
}
|
||||
}
|
||||
|
||||
impl<M> Ethcore for EthcoreClient<M> where M: MinerService + 'static {
|
||||
impl<C, M> Ethcore for EthcoreClient<C, M> where M: MinerService + 'static, C: MiningBlockChainClient + 'static {
|
||||
|
||||
fn transactions_limit(&self, _: Params) -> Result<Value, Error> {
|
||||
to_value(&take_weak!(self.miner).transactions_limit())
|
||||
@@ -97,8 +101,23 @@ impl<M> Ethcore for EthcoreClient<M> where M: MinerService + 'static {
|
||||
Ok(Value::Object(map))
|
||||
}
|
||||
|
||||
fn default_extra_data(&self, _params: Params) -> Result<Value, Error> {
|
||||
let version = version_data();
|
||||
to_value(&Bytes::new(version))
|
||||
fn default_extra_data(&self, params: Params) -> Result<Value, Error> {
|
||||
match params {
|
||||
Params::None => to_value(&Bytes::new(version_data())),
|
||||
_ => Err(Error::invalid_params()),
|
||||
}
|
||||
}
|
||||
|
||||
fn gas_price_statistics(&self, params: Params) -> Result<Value, Error> {
|
||||
match params {
|
||||
Params::None => match take_weak!(self.client).gas_price_statistics(100, 8) {
|
||||
Ok(stats) => to_value(&stats
|
||||
.iter()
|
||||
.map(|x| to_value(&x).expect("x must be U256; qed"))
|
||||
.collect::<Vec<_>>()),
|
||||
_ => Err(Error::internal_error()),
|
||||
},
|
||||
_ => Err(Error::invalid_params()),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ use jsonrpc_core::IoHandler;
|
||||
use v1::{Ethcore, EthcoreClient, EthcoreSet, EthcoreSetClient};
|
||||
use ethcore::miner::MinerService;
|
||||
use v1::tests::helpers::TestMinerService;
|
||||
use ethcore::client::{TestBlockChainClient};
|
||||
use util::numbers::*;
|
||||
use rustc_serialize::hex::FromHex;
|
||||
use util::log::RotatingLogger;
|
||||
@@ -29,6 +30,10 @@ fn miner_service() -> Arc<TestMinerService> {
|
||||
Arc::new(TestMinerService::default())
|
||||
}
|
||||
|
||||
fn client_service() -> Arc<TestBlockChainClient> {
|
||||
Arc::new(TestBlockChainClient::default())
|
||||
}
|
||||
|
||||
fn logger() -> Arc<RotatingLogger> {
|
||||
Arc::new(RotatingLogger::new("rpc=trace".to_owned()))
|
||||
}
|
||||
@@ -45,19 +50,20 @@ fn settings() -> Arc<NetworkSettings> {
|
||||
})
|
||||
}
|
||||
|
||||
fn ethcore_client(miner: &Arc<TestMinerService>) -> EthcoreClient<TestMinerService> {
|
||||
EthcoreClient::new(&miner, logger(), settings())
|
||||
fn ethcore_client(client: &Arc<TestBlockChainClient>, miner: &Arc<TestMinerService>) -> EthcoreClient<TestBlockChainClient, TestMinerService> {
|
||||
EthcoreClient::new(client, miner, logger(), settings())
|
||||
}
|
||||
|
||||
fn ethcore_set_client(miner: &Arc<TestMinerService>) -> EthcoreSetClient<TestMinerService> {
|
||||
EthcoreSetClient::new(&miner)
|
||||
EthcoreSetClient::new(miner)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rpc_ethcore_extra_data() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_extraData", "params": [], "id": 1}"#;
|
||||
@@ -72,8 +78,9 @@ fn rpc_ethcore_default_extra_data() {
|
||||
use util::ToPretty;
|
||||
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_defaultExtraData", "params": [], "id": 1}"#;
|
||||
@@ -85,8 +92,9 @@ fn rpc_ethcore_default_extra_data() {
|
||||
#[test]
|
||||
fn rpc_ethcore_gas_floor_target() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_gasFloorTarget", "params": [], "id": 1}"#;
|
||||
@@ -98,8 +106,9 @@ fn rpc_ethcore_gas_floor_target() {
|
||||
#[test]
|
||||
fn rpc_ethcore_min_gas_price() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_minGasPrice", "params": [], "id": 1}"#;
|
||||
@@ -111,8 +120,9 @@ fn rpc_ethcore_min_gas_price() {
|
||||
#[test]
|
||||
fn rpc_ethcore_set_min_gas_price() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setMinGasPrice", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
@@ -125,8 +135,9 @@ fn rpc_ethcore_set_min_gas_price() {
|
||||
#[test]
|
||||
fn rpc_ethcore_set_gas_floor_target() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setGasFloorTarget", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
@@ -139,8 +150,9 @@ fn rpc_ethcore_set_gas_floor_target() {
|
||||
#[test]
|
||||
fn rpc_ethcore_set_extra_data() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setExtraData", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
@@ -153,8 +165,9 @@ fn rpc_ethcore_set_extra_data() {
|
||||
#[test]
|
||||
fn rpc_ethcore_set_author() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setAuthor", "params":["0xcd1722f3947def4cf144679da39c4c32bdc35681"], "id": 1}"#;
|
||||
@@ -167,10 +180,11 @@ fn rpc_ethcore_set_author() {
|
||||
#[test]
|
||||
fn rpc_ethcore_dev_logs() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let logger = logger();
|
||||
logger.append("a".to_owned());
|
||||
logger.append("b".to_owned());
|
||||
let ethcore = EthcoreClient::new(&miner, logger.clone(), settings()).to_delegate();
|
||||
let ethcore = EthcoreClient::new(&client, &miner, logger.clone(), settings()).to_delegate();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore);
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
@@ -184,8 +198,9 @@ fn rpc_ethcore_dev_logs() {
|
||||
#[test]
|
||||
fn rpc_ethcore_dev_logs_levels() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_devLogsLevels", "params":[], "id": 1}"#;
|
||||
@@ -196,8 +211,9 @@ fn rpc_ethcore_dev_logs_levels() {
|
||||
#[test]
|
||||
fn rpc_ethcore_set_transactions_limit() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_setTransactionsLimit", "params":[10240240], "id": 1}"#;
|
||||
@@ -210,8 +226,9 @@ fn rpc_ethcore_set_transactions_limit() {
|
||||
#[test]
|
||||
fn rpc_ethcore_transactions_limit() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_transactionsLimit", "params":[], "id": 1}"#;
|
||||
@@ -223,8 +240,9 @@ fn rpc_ethcore_transactions_limit() {
|
||||
#[test]
|
||||
fn rpc_ethcore_net_chain() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netChain", "params":[], "id": 1}"#;
|
||||
@@ -236,8 +254,9 @@ fn rpc_ethcore_net_chain() {
|
||||
#[test]
|
||||
fn rpc_ethcore_net_max_peers() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netMaxPeers", "params":[], "id": 1}"#;
|
||||
@@ -249,8 +268,9 @@ fn rpc_ethcore_net_max_peers() {
|
||||
#[test]
|
||||
fn rpc_ethcore_net_port() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_netPort", "params":[], "id": 1}"#;
|
||||
@@ -262,8 +282,9 @@ fn rpc_ethcore_net_port() {
|
||||
#[test]
|
||||
fn rpc_ethcore_rpc_settings() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_rpcSettings", "params":[], "id": 1}"#;
|
||||
@@ -275,8 +296,9 @@ fn rpc_ethcore_rpc_settings() {
|
||||
#[test]
|
||||
fn rpc_ethcore_node_name() {
|
||||
let miner = miner_service();
|
||||
let client = client_service();
|
||||
let io = IoHandler::new();
|
||||
io.add_delegate(ethcore_client(&miner).to_delegate());
|
||||
io.add_delegate(ethcore_client(&client, &miner).to_delegate());
|
||||
io.add_delegate(ethcore_set_client(&miner).to_delegate());
|
||||
|
||||
let request = r#"{"jsonrpc": "2.0", "method": "ethcore_nodeName", "params":[], "id": 1}"#;
|
||||
|
||||
@@ -57,6 +57,9 @@ pub trait Ethcore: Sized + Send + Sync + 'static {
|
||||
/// Returns default extra data
|
||||
fn default_extra_data(&self, _: Params) -> Result<Value, Error>;
|
||||
|
||||
/// Returns distribution of gas price in latest blocks.
|
||||
fn gas_price_statistics(&self, _: Params) -> Result<Value, Error>;
|
||||
|
||||
/// Should be used to convert object to io delegate.
|
||||
fn to_delegate(self) -> IoDelegate<Self> {
|
||||
let mut delegate = IoDelegate::new(Arc::new(self));
|
||||
@@ -73,6 +76,7 @@ pub trait Ethcore: Sized + Send + Sync + 'static {
|
||||
delegate.add_method("ethcore_rpcSettings", Ethcore::rpc_settings);
|
||||
delegate.add_method("ethcore_nodeName", Ethcore::node_name);
|
||||
delegate.add_method("ethcore_defaultExtraData", Ethcore::default_extra_data);
|
||||
delegate.add_method("ethcore_gasPriceStatistics", Ethcore::gas_price_statistics);
|
||||
|
||||
delegate
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user