|
|
|
|
@@ -77,6 +77,8 @@ pub struct EthashParams {
|
|
|
|
|
pub ecip1010_pause_transition: u64,
|
|
|
|
|
/// Number of first block where ECIP-1010 ends.
|
|
|
|
|
pub ecip1010_continue_transition: u64,
|
|
|
|
|
/// Total block number for one ECIP-1017 era.
|
|
|
|
|
pub ecip1017_era_rounds: 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.
|
|
|
|
|
@@ -113,6 +115,7 @@ impl From<ethjson::spec::EthashParams> for EthashParams {
|
|
|
|
|
eip161d_transition: p.eip161d_transition.map_or(u64::max_value(), Into::into),
|
|
|
|
|
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),
|
|
|
|
|
ecip1017_era_rounds: p.ecip1017_era_rounds.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),
|
|
|
|
|
@@ -249,6 +252,8 @@ impl Engine for Ethash {
|
|
|
|
|
fn on_close_block(&self, block: &mut ExecutedBlock) {
|
|
|
|
|
let reward = self.ethash_params.block_reward;
|
|
|
|
|
let fields = block.fields_mut();
|
|
|
|
|
let eras_rounds = self.ethash_params.ecip1017_era_rounds;
|
|
|
|
|
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, fields.header.number());
|
|
|
|
|
|
|
|
|
|
// Bestow block reward
|
|
|
|
|
let res = fields.state.add_balance(
|
|
|
|
|
@@ -264,12 +269,19 @@ impl Engine for Ethash {
|
|
|
|
|
// Bestow uncle rewards
|
|
|
|
|
let current_number = fields.header.number();
|
|
|
|
|
for u in fields.uncles.iter() {
|
|
|
|
|
let res = fields.state.add_balance(
|
|
|
|
|
u.author(),
|
|
|
|
|
&(reward * U256::from(8 + u.number() - current_number) / U256::from(8)),
|
|
|
|
|
CleanupMode::NoEmpty
|
|
|
|
|
);
|
|
|
|
|
|
|
|
|
|
let res = if eras == 0 {
|
|
|
|
|
fields.state.add_balance(
|
|
|
|
|
u.author(),
|
|
|
|
|
&(reward * U256::from(8 + u.number() - current_number) / U256::from(8)),
|
|
|
|
|
CleanupMode::NoEmpty
|
|
|
|
|
)
|
|
|
|
|
} else {
|
|
|
|
|
fields.state.add_balance(
|
|
|
|
|
u.author(),
|
|
|
|
|
&(reward / U256::from(32)),
|
|
|
|
|
CleanupMode::NoEmpty
|
|
|
|
|
)
|
|
|
|
|
};
|
|
|
|
|
if let Err(e) = res {
|
|
|
|
|
warn!("Failed to give uncle reward: {}", e);
|
|
|
|
|
}
|
|
|
|
|
@@ -398,6 +410,18 @@ fn round_block_gas_limit(gas_limit: U256, lower_limit: U256, upper_limit: U256)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fn ecip1017_eras_block_reward(era_rounds: u64, mut reward: U256, block_number:u64) -> (u64, U256){
|
|
|
|
|
let eras = if block_number != 0 && block_number % era_rounds == 0 {
|
|
|
|
|
block_number / era_rounds - 1
|
|
|
|
|
} else {
|
|
|
|
|
block_number / era_rounds
|
|
|
|
|
};
|
|
|
|
|
for _ in 0..eras {
|
|
|
|
|
reward = reward / U256::from(5) * U256::from(4);
|
|
|
|
|
}
|
|
|
|
|
(eras, reward)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
|
|
|
|
impl Ethash {
|
|
|
|
|
fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 {
|
|
|
|
|
@@ -500,7 +524,7 @@ mod tests {
|
|
|
|
|
use error::{BlockError, Error};
|
|
|
|
|
use header::Header;
|
|
|
|
|
use super::super::{new_morden, new_homestead_test};
|
|
|
|
|
use super::{Ethash, EthashParams, PARITY_GAS_LIMIT_DETERMINANT};
|
|
|
|
|
use super::{Ethash, EthashParams, PARITY_GAS_LIMIT_DETERMINANT, ecip1017_eras_block_reward};
|
|
|
|
|
use rlp;
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
@@ -756,6 +780,42 @@ mod tests {
|
|
|
|
|
assert_eq!(U256::from_str("1fc50f118efe").unwrap(), difficulty);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn has_valid_ecip1017_eras_block_reward() {
|
|
|
|
|
let ethparams = EthashParams {
|
|
|
|
|
// see ethcore/res/ethereum/classic.json
|
|
|
|
|
ecip1017_era_rounds: 5000000,
|
|
|
|
|
block_reward: U256::from_str("4563918244F40000").unwrap(),
|
|
|
|
|
..get_default_ethash_params()
|
|
|
|
|
};
|
|
|
|
|
let eras_rounds = ethparams.ecip1017_era_rounds;
|
|
|
|
|
let reward = ethparams.block_reward;
|
|
|
|
|
let block_number = 0;
|
|
|
|
|
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number);
|
|
|
|
|
assert_eq!(0, eras);
|
|
|
|
|
assert_eq!(U256::from_str("4563918244F40000").unwrap(), reward);
|
|
|
|
|
let reward = ethparams.block_reward;
|
|
|
|
|
let block_number = 5000000;
|
|
|
|
|
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number);
|
|
|
|
|
assert_eq!(0, eras);
|
|
|
|
|
assert_eq!(U256::from_str("4563918244F40000").unwrap(), reward);
|
|
|
|
|
let reward = ethparams.block_reward;
|
|
|
|
|
let block_number = 10000000;
|
|
|
|
|
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number);
|
|
|
|
|
assert_eq!(1, eras);
|
|
|
|
|
assert_eq!(U256::from_str("3782DACE9D900000").unwrap(), reward);
|
|
|
|
|
let reward = ethparams.block_reward;
|
|
|
|
|
let block_number = 20000000;
|
|
|
|
|
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number);
|
|
|
|
|
assert_eq!(3, eras);
|
|
|
|
|
assert_eq!(U256::from_str("2386F26FC1000000").unwrap(), reward);
|
|
|
|
|
let reward = ethparams.block_reward;
|
|
|
|
|
let block_number = 80000000;
|
|
|
|
|
let (eras, reward) = ecip1017_eras_block_reward(eras_rounds, reward, block_number);
|
|
|
|
|
assert_eq!(15, eras);
|
|
|
|
|
assert_eq!(U256::from_str("271000000000000").unwrap(), reward);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[test]
|
|
|
|
|
fn difficulty_classic_bomb_delay() {
|
|
|
|
|
let spec = new_homestead_test();
|
|
|
|
|
|