diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index d8749ba91..7c1e9454e 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -15,7 +15,9 @@ "eip155Transition": "0x7fffffffffffffff", "eip160Transition": "0x7fffffffffffffff", "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "eip161dTransition": "0x7fffffffffffffff", + "ecip1010PauseTransition": "0x2dc6c0", + "ecip1010ContinueTransition": "0x4c4b40" } } }, diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index f2468dc95..8b9688569 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -70,6 +70,10 @@ pub struct EthashParams { pub eip161abc_transition: u64, /// Number of first block where EIP-161.d begins. pub eip161d_transition: u64, + /// Number of first block where ECIP-1010 begins. + pub ecip1010_pause_transition: u64, + /// Number of first block where ECIP-1010 ends. + pub ecip1010_continue_transition: u64 } impl From for EthashParams { @@ -94,6 +98,8 @@ impl From for EthashParams { eip160_transition: p.eip160_transition.map_or(0, Into::into), eip161abc_transition: p.eip161abc_transition.map_or(0, Into::into), eip161d_transition: p.eip161d_transition.map_or(0x7fffffffffffffff, Into::into), + ecip1010_pause_transition: p.ecip1010_pause_transition.map_or(0x7fffffffffffffff, Into::into), + ecip1010_continue_transition: p.ecip1010_continue_transition.map_or(0x7fffffffffffffff, Into::into), } } } @@ -353,9 +359,20 @@ impl Ethash { }; target = max(min_difficulty, target); if header.number() < self.ethash_params.bomb_defuse_transition { - let period = ((parent.number() + 1) / EXP_DIFF_PERIOD) as usize; - if period > 1 { - target = max(min_difficulty, target + (U256::from(1) << (period - 2))); + if header.number() < self.ethash_params.ecip1010_pause_transition { + let period = ((parent.number() + 1) / EXP_DIFF_PERIOD) as usize; + if period > 1 { + target = max(min_difficulty, target + (U256::from(1) << (period - 2))); + } + } + else if header.number() < self.ethash_params.ecip1010_continue_transition { + let fixed_difficulty = ((self.ethash_params.ecip1010_pause_transition / EXP_DIFF_PERIOD) - 2) as usize; + target = max(min_difficulty, target + (U256::from(1) << fixed_difficulty)); + } + else { + let period = ((parent.number() + 1) / EXP_DIFF_PERIOD) as usize; + let delay = ((self.ethash_params.ecip1010_continue_transition - self.ethash_params.ecip1010_pause_transition) / EXP_DIFF_PERIOD) as usize; + target = max(min_difficulty, target + (U256::from(1) << (period - delay - 2))); } } target @@ -414,8 +431,8 @@ mod tests { use env_info::EnvInfo; use error::{BlockError, Error}; use header::Header; - use super::super::new_morden; - use super::Ethash; + use super::super::{new_morden, new_homestead_test}; + use super::{Ethash, EthashParams}; use rlp; #[test] @@ -637,5 +654,122 @@ mod tests { assert_eq!(Ethash::difficulty_to_boundary(&U256::from(32)), H256::from_str("0800000000000000000000000000000000000000000000000000000000000000").unwrap()); } - // TODO: difficulty test + #[test] + fn difficulty_frontier() { + let spec = new_homestead_test(); + let ethparams = get_default_ethash_params(); + let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new()); + + let mut parent_header = Header::default(); + parent_header.set_number(1000000); + parent_header.set_difficulty(U256::from_str("b69de81a22b").unwrap()); + parent_header.set_timestamp(1455404053); + let mut header = Header::default(); + header.set_number(parent_header.number() + 1); + header.set_timestamp(1455404058); + + let difficulty = ethash.calculate_difficulty(&header, &parent_header); + assert_eq!(U256::from_str("b6b4bbd735f").unwrap(), difficulty); + } + + #[test] + fn difficulty_homestead() { + let spec = new_homestead_test(); + let ethparams = get_default_ethash_params(); + let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new()); + + let mut parent_header = Header::default(); + parent_header.set_number(1500000); + parent_header.set_difficulty(U256::from_str("1fd0fd70792b").unwrap()); + parent_header.set_timestamp(1463003133); + let mut header = Header::default(); + header.set_number(parent_header.number() + 1); + header.set_timestamp(1463003177); + + let difficulty = ethash.calculate_difficulty(&header, &parent_header); + assert_eq!(U256::from_str("1fc50f118efe").unwrap(), difficulty); + } + + #[test] + fn difficulty_classic_bomb_delay() { + let spec = new_homestead_test(); + let ethparams = EthashParams { + ecip1010_pause_transition: 3000000, + ..get_default_ethash_params() + }; + let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new()); + + let mut parent_header = Header::default(); + parent_header.set_number(3500000); + parent_header.set_difficulty(U256::from_str("6F62EAF8D3C").unwrap()); + parent_header.set_timestamp(1452838500); + let mut header = Header::default(); + header.set_number(parent_header.number() + 1); + + header.set_timestamp(parent_header.timestamp() + 20); + assert_eq!( + U256::from_str("6F55FE9B74B").unwrap(), + ethash.calculate_difficulty(&header, &parent_header) + ); + header.set_timestamp(parent_header.timestamp() + 5); + assert_eq!( + U256::from_str("6F71D75632D").unwrap(), + ethash.calculate_difficulty(&header, &parent_header) + ); + header.set_timestamp(parent_header.timestamp() + 80); + assert_eq!( + U256::from_str("6F02746B3A5").unwrap(), + ethash.calculate_difficulty(&header, &parent_header) + ); + } + + #[test] + fn test_difficulty_bomb_continue() { + let spec = new_homestead_test(); + let ethparams = EthashParams { + ecip1010_pause_transition: 3000000, + ecip1010_continue_transition: 5000000, + ..get_default_ethash_params() + }; + let ethash = Ethash::new(spec.params, ethparams, BTreeMap::new()); + + let mut parent_header = Header::default(); + parent_header.set_number(5000102); + parent_header.set_difficulty(U256::from_str("14944397EE8B").unwrap()); + parent_header.set_timestamp(1513175023); + let mut header = Header::default(); + header.set_number(parent_header.number() + 1); + header.set_timestamp(parent_header.timestamp() + 6); + assert_eq!( + U256::from_str("1496E6206188").unwrap(), + ethash.calculate_difficulty(&header, &parent_header) + ); + parent_header.set_number(5100123); + parent_header.set_difficulty(U256::from_str("14D24B39C7CF").unwrap()); + parent_header.set_timestamp(1514609324); + header.set_number(parent_header.number() + 1); + header.set_timestamp(parent_header.timestamp() + 41); + assert_eq!( + U256::from_str("14CA9C5D9227").unwrap(), + ethash.calculate_difficulty(&header, &parent_header) + ); + parent_header.set_number(6150001); + parent_header.set_difficulty(U256::from_str("305367B57227").unwrap()); + parent_header.set_timestamp(1529664575); + header.set_number(parent_header.number() + 1); + header.set_timestamp(parent_header.timestamp() + 105); + assert_eq!( + U256::from_str("309D09E0C609").unwrap(), + ethash.calculate_difficulty(&header, &parent_header) + ); + parent_header.set_number(8000000); + parent_header.set_difficulty(U256::from_str("1180B36D4CE5B6A").unwrap()); + parent_header.set_timestamp(1535431724); + header.set_number(parent_header.number() + 1); + header.set_timestamp(parent_header.timestamp() + 420); + assert_eq!( + U256::from_str("5126FFD5BCBB9E7").unwrap(), + ethash.calculate_difficulty(&header, &parent_header) + ); + } } diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index ac8ce1885..96d5f8366 100644 --- a/ethcore/src/tests/helpers.rs +++ b/ethcore/src/tests/helpers.rs @@ -28,6 +28,7 @@ use evm::Schedule; use engines::Engine; use env_info::EnvInfo; use ethereum; +use ethereum::ethash::EthashParams; use devtools::*; use miner::Miner; use header::Header; @@ -421,3 +422,29 @@ pub fn get_bad_state_dummy_block() -> Bytes { create_test_block(&block_header) } + +pub fn get_default_ethash_params() -> EthashParams{ + EthashParams { + gas_limit_bound_divisor: U256::from(1024), + minimum_difficulty: U256::from(131072), + difficulty_bound_divisor: U256::from(2048), + difficulty_increment_divisor: 10, + duration_limit: 13, + block_reward: U256::from(0), + registrar: "0000000000000000000000000000000000000001".into(), + homestead_transition: 1150000, + dao_hardfork_transition: 0x7fffffffffffffff, + dao_hardfork_beneficiary: "0000000000000000000000000000000000000001".into(), + dao_hardfork_accounts: vec![], + difficulty_hardfork_transition: 0x7fffffffffffffff, + difficulty_hardfork_bound_divisor: U256::from(0), + bomb_defuse_transition: 0x7fffffffffffffff, + eip150_transition: 0x7fffffffffffffff, + eip155_transition: 0x7fffffffffffffff, + eip160_transition: 0x7fffffffffffffff, + eip161abc_transition: 0x7fffffffffffffff, + eip161d_transition: 0x7fffffffffffffff, + ecip1010_pause_transition: 0x7fffffffffffffff, + ecip1010_continue_transition: 0x7fffffffffffffff + } +} diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs index f8412bb97..10f0c6293 100644 --- a/json/src/spec/ethash.rs +++ b/json/src/spec/ethash.rs @@ -85,6 +85,13 @@ pub struct EthashParams { /// See main EthashParams docs. #[serde(rename="eip161dTransition")] pub eip161d_transition: Option, + + /// See main EthashParams docs. + #[serde(rename="ecip1010PauseTransition")] + pub ecip1010_pause_transition: Option, + /// See main EthashParams docs. + #[serde(rename="ecip1010ContinueTransition")] + pub ecip1010_continue_transition: Option, } /// Ethash engine deserialization.