From 6d2f8e31d04d06c8b681075c4dd72b49f2048031 Mon Sep 17 00:00:00 2001 From: Robert Habermeier Date: Thu, 5 Jan 2017 21:16:33 +0100 Subject: [PATCH] ETC Config change backport (#4056) * delay bomb for Classic (ECIP-1010) (#3179) * delay bomb for classic (ECIP-1010) * formatting fix after core review, rel [e6b5093] * Replay protection for Classic * EIP-155 configuration for Ethereum Classic * EIP-160 configuration for Ethereum Classic * Testnet for Ethereum Classic * revert ETC to correct Network ID * reuse Morden for Classic Testnet * set CHAIN_ID for Classic (#3934) * configurable CHAIN_ID * set CHAIN_ID for Ethereum Classic * prettify classic json --- ethcore/res/ethereum/classic.json | 14 ++- ethcore/res/ethereum/morden.json | 16 ++-- ethcore/src/ethereum/ethash.rs | 150 ++++++++++++++++++++++++++++-- ethcore/src/spec/spec.rs | 3 + ethcore/src/tests/helpers.rs | 28 ++++++ json/src/spec/ethash.rs | 7 ++ json/src/spec/params.rs | 5 + parity/cli/usage.txt | 4 +- 8 files changed, 206 insertions(+), 21 deletions(-) diff --git a/ethcore/res/ethereum/classic.json b/ethcore/res/ethereum/classic.json index d8749ba9131..f2e33a344b4 100644 --- a/ethcore/res/ethereum/classic.json +++ b/ethcore/res/ethereum/classic.json @@ -10,12 +10,15 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "registrar" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b", - "homesteadTransition": "0x118c30", - "eip150Transition": "0x2625a0", - "eip155Transition": "0x7fffffffffffffff", - "eip160Transition": "0x7fffffffffffffff", + "homesteadTransition": 1150000, + "eip150Transition": 2500000, + "eip155Transition": 3000000, + "eip160Transition": 3000000, + "ecip1010PauseTransition": 3000000, + "ecip1010ContinueTransition": 5000000, + "eip161abcTransition": "0x7fffffffffffffff", - "eip161dTransition": "0x7fffffffffffffff" + "eip161dTransition": "0x7fffffffffffffff", } } }, @@ -24,6 +27,7 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x1", + "chainID": "0x3d", "forkBlock": "0x1d4c00", "forkCanonHash": "0x94365e3a8c0b35089c1d1195081fe7489b528a84b22199c916180db8b28ade7f" }, diff --git a/ethcore/res/ethereum/morden.json b/ethcore/res/ethereum/morden.json index 6e725e8bfc4..56cf7eaf8ba 100644 --- a/ethcore/res/ethereum/morden.json +++ b/ethcore/res/ethereum/morden.json @@ -9,12 +9,15 @@ "durationLimit": "0x0d", "blockReward": "0x4563918244F40000", "registrar": "0x52dff57a8a1532e6afb3dc07e2af58bb9eb05b3d", - "homesteadTransition": "0x789b0", - "eip150Transition": "0x1b34d8", - "eip155Transition": 1885000, - "eip160Transition": 1885000, - "eip161abcTransition": 1885000, - "eip161dTransition": 1885000 + "homesteadTransition": 494000, + "eip150Transition": 1783000, + "eip155Transition": 1915000, + "eip160Transition": 1915000, + "ecip1010PauseTransition": 1915000, + "ecip1010ContinueTransition": 3415000, + + "eip161abcTransition": "0x7fffffffffffffff", + "eip161dTransition": "0x7fffffffffffffff" } } }, @@ -23,6 +26,7 @@ "maximumExtraDataSize": "0x20", "minGasLimit": "0x1388", "networkID" : "0x2", + "chainID": "0x3e", "forkBlock": "0x1b34d8", "forkCanonHash": "0xf376243aeff1f256d970714c3de9fd78fa4e63cf63e32a51fe1169e375d98145" }, diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 1410d9933d0..0caf36a289f 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, /// Maximum amount of code that can be deploying into a contract. pub max_code_size: u64, } @@ -96,6 +100,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(u64::max_value(), 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), max_code_size: p.max_code_size.map_or(u64::max_value(), Into::into), } } @@ -159,7 +165,7 @@ impl Engine for Ethash { fn signing_network_id(&self, env_info: &EnvInfo) -> Option { if env_info.number >= self.ethash_params.eip155_transition { - Some(self.params().network_id) + Some(self.params().chain_id) } else { None } @@ -308,7 +314,7 @@ impl Engine for Ethash { } if let Some(n) = t.network_id() { - if header.number() < self.ethash_params.eip155_transition || n != self.params().network_id { + if header.number() < self.ethash_params.eip155_transition || n != self.params().chain_id { return Err(TransactionError::InvalidNetworkId.into()) } } @@ -357,9 +363,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 @@ -418,8 +435,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] @@ -641,5 +658,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/spec/spec.rs b/ethcore/src/spec/spec.rs index ff6d3e2e3dc..faa220b9028 100644 --- a/ethcore/src/spec/spec.rs +++ b/ethcore/src/spec/spec.rs @@ -39,6 +39,8 @@ pub struct CommonParams { pub maximum_extra_data_size: usize, /// Network id. pub network_id: u64, + /// Chain id. + pub chain_id: u64, /// Main subprotocol name. pub subprotocol_name: String, /// Minimum gas limit. @@ -53,6 +55,7 @@ impl From for CommonParams { account_start_nonce: p.account_start_nonce.into(), maximum_extra_data_size: p.maximum_extra_data_size.into(), network_id: p.network_id.into(), + chain_id: if let Some(n) = p.chain_id { n.into() } else { p.network_id.into() }, subprotocol_name: p.subprotocol_name.unwrap_or_else(|| "eth".to_owned()), min_gas_limit: p.min_gas_limit.into(), fork_block: if let (Some(n), Some(h)) = (p.fork_block, p.fork_hash) { Some((n.into(), h.into())) } else { None }, diff --git a/ethcore/src/tests/helpers.rs b/ethcore/src/tests/helpers.rs index ac8ce1885b2..6b3a97814f3 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,30 @@ 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, + max_code_size: 0x7fffffffffffffff, + } +} diff --git a/json/src/spec/ethash.rs b/json/src/spec/ethash.rs index 812d7708ef4..5f3ed51ec1f 100644 --- a/json/src/spec/ethash.rs +++ b/json/src/spec/ethash.rs @@ -89,6 +89,13 @@ pub struct EthashParams { /// See main EthashParams docs. #[serde(rename="maxCodeSize")] pub max_code_size: 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. diff --git a/json/src/spec/params.rs b/json/src/spec/params.rs index aa634221d9f..a4021fd8810 100644 --- a/json/src/spec/params.rs +++ b/json/src/spec/params.rs @@ -35,6 +35,10 @@ pub struct Params { /// Network id. #[serde(rename="networkID")] pub network_id: Uint, + /// Chain id. + #[serde(rename="chainID")] + pub chain_id: Option, + /// Name of the main ("eth") subprotocol. #[serde(rename="subprotocolName")] pub subprotocol_name: Option, @@ -58,6 +62,7 @@ mod tests { "homesteadTransition": "0x118c30", "maximumExtraDataSize": "0x20", "networkID" : "0x1", + "chainID" : "0x15", "subprotocolName" : "exp", "minGasLimit": "0x1388", "accountStartNonce": "0x00" diff --git a/parity/cli/usage.txt b/parity/cli/usage.txt index 5d6c33060b3..845e1d0e920 100644 --- a/parity/cli/usage.txt +++ b/parity/cli/usage.txt @@ -32,8 +32,8 @@ Operating Options: (default: {flag_mode_alarm}). --chain CHAIN Specify the blockchain type. CHAIN may be either a JSON chain specification file or olympic, frontier, - homestead, mainnet, ropsten, morden, classic, expanse or - testnet (default: {flag_chain}). + homestead, mainnet, ropsten, morden, classic, expanse, + or testnet (default: {flag_chain}). -d --db-path PATH Specify the database & configuration directory path (default: {flag_db_path}). --keys-path PATH Specify the path for JSON key files to be found