Max gas limit and min gas price (#4661)
* Max gas limit and min gas price * Tests * Limit gas limit ceiling
This commit is contained in:
parent
af45d05aee
commit
ef7998f473
@ -79,6 +79,14 @@ pub struct EthashParams {
|
||||
pub ecip1010_continue_transition: u64,
|
||||
/// Maximum amount of code that can be deploying into a contract.
|
||||
pub max_code_size: u64,
|
||||
/// Number of first block where the max gas limit becomes effective.
|
||||
pub max_gas_limit_transition: u64,
|
||||
/// Maximum valid block gas limit,
|
||||
pub max_gas_limit: U256,
|
||||
/// Number of first block where the minimum gas price becomes effective.
|
||||
pub min_gas_price_transition: u64,
|
||||
/// Do not alow transactions with lower gas price.
|
||||
pub min_gas_price: U256,
|
||||
}
|
||||
|
||||
impl From<ethjson::spec::EthashParams> for EthashParams {
|
||||
@ -106,6 +114,10 @@ impl From<ethjson::spec::EthashParams> for EthashParams {
|
||||
ecip1010_pause_transition: p.ecip1010_pause_transition.map_or(u64::max_value(), Into::into),
|
||||
ecip1010_continue_transition: p.ecip1010_continue_transition.map_or(u64::max_value(), Into::into),
|
||||
max_code_size: p.max_code_size.map_or(u64::max_value(), Into::into),
|
||||
max_gas_limit_transition: p.max_gas_limit_transition.map_or(u64::max_value(), Into::into),
|
||||
max_gas_limit: p.max_gas_limit.map_or(U256::max_value(), Into::into),
|
||||
min_gas_price_transition: p.min_gas_price_transition.map_or(u64::max_value(), Into::into),
|
||||
min_gas_price: p.min_gas_price.map_or(U256::zero(), Into::into),
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -174,8 +186,12 @@ impl Engine for Ethash {
|
||||
}
|
||||
}
|
||||
|
||||
fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, gas_ceil_target: U256) {
|
||||
fn populate_from_parent(&self, header: &mut Header, parent: &Header, gas_floor_target: U256, mut gas_ceil_target: U256) {
|
||||
let difficulty = self.calculate_difficulty(header, parent);
|
||||
if header.number() >= self.ethash_params.max_gas_limit_transition && gas_ceil_target > self.ethash_params.max_gas_limit {
|
||||
warn!("Gas limit target is limited to {}", self.ethash_params.max_gas_limit);
|
||||
gas_ceil_target = self.ethash_params.max_gas_limit;
|
||||
}
|
||||
let gas_limit = {
|
||||
let gas_limit = parent.gas_limit().clone();
|
||||
let bound_divisor = self.ethash_params.gas_limit_bound_divisor;
|
||||
@ -312,11 +328,15 @@ impl Engine for Ethash {
|
||||
return Err(From::from(BlockError::InvalidDifficulty(Mismatch { expected: expected_difficulty, found: header.difficulty().clone() })))
|
||||
}
|
||||
let gas_limit_divisor = self.ethash_params.gas_limit_bound_divisor;
|
||||
let min_gas = parent.gas_limit().clone() - parent.gas_limit().clone() / gas_limit_divisor;
|
||||
let max_gas = parent.gas_limit().clone() + parent.gas_limit().clone() / gas_limit_divisor;
|
||||
let parent_gas_limit = *parent.gas_limit();
|
||||
let min_gas = parent_gas_limit - parent_gas_limit / gas_limit_divisor;
|
||||
let max_gas = parent_gas_limit + parent_gas_limit / gas_limit_divisor;
|
||||
if header.gas_limit() <= &min_gas || header.gas_limit() >= &max_gas {
|
||||
return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(max_gas), found: header.gas_limit().clone() })));
|
||||
}
|
||||
if header.number() >= self.ethash_params.max_gas_limit_transition && header.gas_limit() > &self.ethash_params.max_gas_limit && header.gas_limit() > &parent_gas_limit {
|
||||
return Err(From::from(BlockError::InvalidGasLimit(OutOfBounds { min: Some(min_gas), max: Some(self.ethash_params.max_gas_limit), found: header.gas_limit().clone() })));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -331,6 +351,10 @@ impl Engine for Ethash {
|
||||
}
|
||||
}
|
||||
|
||||
if header.number() >= self.ethash_params.min_gas_price_transition && t.gas_price < self.ethash_params.min_gas_price {
|
||||
return Err(TransactionError::InsufficientGasPrice { minimal: self.ethash_params.min_gas_price, got: t.gas_price }.into());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -853,4 +877,82 @@ mod tests {
|
||||
let difficulty = ethash.calculate_difficulty(&header, &parent_header);
|
||||
assert_eq!(U256::from(12543204905719u64), difficulty);
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_blocks_over_max_gas_limit() {
|
||||
let spec = new_homestead_test();
|
||||
let mut ethparams = get_default_ethash_params();
|
||||
ethparams.max_gas_limit_transition = 10;
|
||||
ethparams.max_gas_limit = 100_000.into();
|
||||
|
||||
let mut parent_header = Header::default();
|
||||
parent_header.set_number(1);
|
||||
parent_header.set_gas_limit(100_000.into());
|
||||
let mut header = Header::default();
|
||||
header.set_number(parent_header.number() + 1);
|
||||
header.set_gas_limit(100_001.into());
|
||||
header.set_difficulty(ethparams.minimum_difficulty);
|
||||
let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new());
|
||||
assert!(ethash.verify_block_family(&header, &parent_header, None).is_ok());
|
||||
|
||||
parent_header.set_number(9);
|
||||
header.set_number(parent_header.number() + 1);
|
||||
|
||||
parent_header.set_gas_limit(99_999.into());
|
||||
header.set_gas_limit(100_000.into());
|
||||
assert!(ethash.verify_block_family(&header, &parent_header, None).is_ok());
|
||||
|
||||
parent_header.set_gas_limit(200_000.into());
|
||||
header.set_gas_limit(200_000.into());
|
||||
assert!(ethash.verify_block_family(&header, &parent_header, None).is_ok());
|
||||
|
||||
parent_header.set_gas_limit(100_000.into());
|
||||
header.set_gas_limit(100_001.into());
|
||||
assert!(ethash.verify_block_family(&header, &parent_header, None).is_err());
|
||||
|
||||
parent_header.set_gas_limit(200_000.into());
|
||||
header.set_gas_limit(200_001.into());
|
||||
assert!(ethash.verify_block_family(&header, &parent_header, None).is_err());
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn rejects_transactions_below_min_gas_price() {
|
||||
use ethkey::{Generator, Random};
|
||||
use types::transaction::{Transaction, Action};
|
||||
|
||||
let spec = new_homestead_test();
|
||||
let mut ethparams = get_default_ethash_params();
|
||||
ethparams.min_gas_price_transition = 10;
|
||||
ethparams.min_gas_price = 100000.into();
|
||||
|
||||
let mut header = Header::default();
|
||||
header.set_number(1);
|
||||
|
||||
let keypair = Random.generate().unwrap();
|
||||
let tx1 = Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::zero(),
|
||||
data: Vec::new(),
|
||||
gas: 100_000.into(),
|
||||
gas_price: 100_000.into(),
|
||||
nonce: U256::zero(),
|
||||
}.sign(keypair.secret(), None).into();
|
||||
|
||||
let tx2 = Transaction {
|
||||
action: Action::Create,
|
||||
value: U256::zero(),
|
||||
data: Vec::new(),
|
||||
gas: 100_000.into(),
|
||||
gas_price: 99_999.into(),
|
||||
nonce: U256::zero(),
|
||||
}.sign(keypair.secret(), None).into();
|
||||
|
||||
let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new());
|
||||
assert!(ethash.verify_transaction_basic(&tx1, &header).is_ok());
|
||||
assert!(ethash.verify_transaction_basic(&tx2, &header).is_ok());
|
||||
|
||||
header.set_number(10);
|
||||
assert!(ethash.verify_transaction_basic(&tx1, &header).is_ok());
|
||||
assert!(ethash.verify_transaction_basic(&tx2, &header).is_err());
|
||||
}
|
||||
}
|
||||
|
@ -456,5 +456,9 @@ pub fn get_default_ethash_params() -> EthashParams{
|
||||
ecip1010_pause_transition: u64::max_value(),
|
||||
ecip1010_continue_transition: u64::max_value(),
|
||||
max_code_size: u64::max_value(),
|
||||
max_gas_limit_transition: u64::max_value(),
|
||||
max_gas_limit: U256::max_value(),
|
||||
min_gas_price_transition: u64::max_value(),
|
||||
min_gas_price: U256::zero(),
|
||||
}
|
||||
}
|
||||
|
@ -97,6 +97,21 @@ pub struct EthashParams {
|
||||
#[serde(rename="maxCodeSize")]
|
||||
pub max_code_size: Option<Uint>,
|
||||
|
||||
/// See main EthashParams docs.
|
||||
#[serde(rename="maxGasLimitTransition")]
|
||||
pub max_gas_limit_transition: Option<Uint>,
|
||||
|
||||
/// See main EthashParams docs.
|
||||
#[serde(rename="maxGasLimit")]
|
||||
pub max_gas_limit: Option<Uint>,
|
||||
|
||||
/// See main EthashParams docs.
|
||||
#[serde(rename="minGasPriceTransition")]
|
||||
pub min_gas_price_transition: Option<Uint>,
|
||||
|
||||
/// See main EthashParams docs.
|
||||
#[serde(rename="minGasPrice")]
|
||||
pub min_gas_price: Option<Uint>,
|
||||
}
|
||||
|
||||
/// Ethash engine deserialization.
|
||||
|
Loading…
Reference in New Issue
Block a user