Ethereum Classic Monetary Policy (#5741)
* Ethereum Classic Monetary Policy Create a new parameter `ecip1017EraRounds`. When the block number passes one era rounds, the reward is reduced by 20%. See https://github.com/ethereumproject/ECIPs/blob/master/ECIPs/ECIP-1017.md * Update rewards for uncle miners for ECIP1017 In the monetary policy, the rewards are changed from "up to 7/8 of the reward" to "1/32 of the reward". * Fix an off-by-one error in ECIP1017 era calculation According to https://github.com/ethereumproject/ECIPs/blob/master/ECIPs/ECIP-1017.md, when in block number 5,000,000, it should still be in Era 1 (which in our code `era == 0`). So we need to check whether the `rem` equals to zero and act accordingly when calculating the era. * `ecip1017_era_rounds` missing from EthashParams when run in build bot * strip out ecip1017_eras_block_reward function and add unit test
This commit is contained in:
parent
a19be3cb51
commit
d152fa3e85
@ -16,6 +16,7 @@
|
|||||||
"eip160Transition": 3000000,
|
"eip160Transition": 3000000,
|
||||||
"ecip1010PauseTransition": 3000000,
|
"ecip1010PauseTransition": 3000000,
|
||||||
"ecip1010ContinueTransition": 5000000,
|
"ecip1010ContinueTransition": 5000000,
|
||||||
|
"ecip1017EraRounds": 5000000,
|
||||||
|
|
||||||
"eip161abcTransition": "0x7fffffffffffffff",
|
"eip161abcTransition": "0x7fffffffffffffff",
|
||||||
"eip161dTransition": "0x7fffffffffffffff"
|
"eip161dTransition": "0x7fffffffffffffff"
|
||||||
|
@ -86,6 +86,8 @@ pub struct EthashParams {
|
|||||||
pub ecip1010_pause_transition: u64,
|
pub ecip1010_pause_transition: u64,
|
||||||
/// Number of first block where ECIP-1010 ends.
|
/// Number of first block where ECIP-1010 ends.
|
||||||
pub ecip1010_continue_transition: u64,
|
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.
|
/// Maximum amount of code that can be deploying into a contract.
|
||||||
pub max_code_size: u64,
|
pub max_code_size: u64,
|
||||||
/// Number of first block where the max gas limit becomes effective.
|
/// Number of first block where the max gas limit becomes effective.
|
||||||
@ -124,6 +126,7 @@ impl From<ethjson::spec::EthashParams> for EthashParams {
|
|||||||
eip161d_transition: p.eip161d_transition.map_or(u64::max_value(), Into::into),
|
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_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),
|
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_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_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),
|
max_gas_limit: p.max_gas_limit.map_or(U256::max_value(), Into::into),
|
||||||
@ -272,6 +275,8 @@ impl Engine for Arc<Ethash> {
|
|||||||
fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
|
fn on_close_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
|
||||||
let reward = self.ethash_params.block_reward;
|
let reward = self.ethash_params.block_reward;
|
||||||
let fields = block.fields_mut();
|
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
|
// Bestow block reward
|
||||||
fields.state.add_balance(
|
fields.state.add_balance(
|
||||||
@ -283,11 +288,19 @@ impl Engine for Arc<Ethash> {
|
|||||||
// Bestow uncle rewards
|
// Bestow uncle rewards
|
||||||
let current_number = fields.header.number();
|
let current_number = fields.header.number();
|
||||||
for u in fields.uncles.iter() {
|
for u in fields.uncles.iter() {
|
||||||
|
if eras == 0 {
|
||||||
fields.state.add_balance(
|
fields.state.add_balance(
|
||||||
u.author(),
|
u.author(),
|
||||||
&(reward * U256::from(8 + u.number() - current_number) / U256::from(8)),
|
&(reward * U256::from(8 + u.number() - current_number) / U256::from(8)),
|
||||||
CleanupMode::NoEmpty
|
CleanupMode::NoEmpty
|
||||||
)?;
|
)
|
||||||
|
} else {
|
||||||
|
fields.state.add_balance(
|
||||||
|
u.author(),
|
||||||
|
&(reward / U256::from(32)),
|
||||||
|
CleanupMode::NoEmpty
|
||||||
|
)
|
||||||
|
}?;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Commit state so that we can actually figure out the state root.
|
// Commit state so that we can actually figure out the state root.
|
||||||
@ -413,6 +426,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))]
|
#[cfg_attr(feature="dev", allow(wrong_self_convention))]
|
||||||
impl Ethash {
|
impl Ethash {
|
||||||
fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 {
|
fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 {
|
||||||
@ -524,7 +549,7 @@ mod tests {
|
|||||||
use error::{BlockError, Error};
|
use error::{BlockError, Error};
|
||||||
use header::Header;
|
use header::Header;
|
||||||
use super::super::{new_morden, new_homestead_test};
|
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;
|
use rlp;
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
@ -760,6 +785,42 @@ mod tests {
|
|||||||
assert_eq!(U256::from_str("1fc50f118efe").unwrap(), difficulty);
|
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]
|
#[test]
|
||||||
fn difficulty_classic_bomb_delay() {
|
fn difficulty_classic_bomb_delay() {
|
||||||
let spec = new_homestead_test();
|
let spec = new_homestead_test();
|
||||||
|
@ -418,6 +418,7 @@ pub fn get_default_ethash_params() -> EthashParams{
|
|||||||
eip161d_transition: u64::max_value(),
|
eip161d_transition: u64::max_value(),
|
||||||
ecip1010_pause_transition: u64::max_value(),
|
ecip1010_pause_transition: u64::max_value(),
|
||||||
ecip1010_continue_transition: u64::max_value(),
|
ecip1010_continue_transition: u64::max_value(),
|
||||||
|
ecip1017_era_rounds: u64::max_value(),
|
||||||
max_code_size: u64::max_value(),
|
max_code_size: u64::max_value(),
|
||||||
max_gas_limit_transition: u64::max_value(),
|
max_gas_limit_transition: u64::max_value(),
|
||||||
max_gas_limit: U256::max_value(),
|
max_gas_limit: U256::max_value(),
|
||||||
|
@ -100,6 +100,10 @@ pub struct EthashParams {
|
|||||||
#[serde(rename="ecip1010ContinueTransition")]
|
#[serde(rename="ecip1010ContinueTransition")]
|
||||||
pub ecip1010_continue_transition: Option<Uint>,
|
pub ecip1010_continue_transition: Option<Uint>,
|
||||||
|
|
||||||
|
/// See main EthashParams docs.
|
||||||
|
#[serde(rename="ecip1017EraRounds")]
|
||||||
|
pub ecip1017_era_rounds: Option<Uint>,
|
||||||
|
|
||||||
/// See main EthashParams docs.
|
/// See main EthashParams docs.
|
||||||
#[serde(rename="maxCodeSize")]
|
#[serde(rename="maxCodeSize")]
|
||||||
pub max_code_size: Option<Uint>,
|
pub max_code_size: Option<Uint>,
|
||||||
|
Loading…
Reference in New Issue
Block a user