From b9c4a64602df92ff99f8af9528a66f8588a59b87 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Thu, 12 Jan 2017 21:25:07 +0300 Subject: [PATCH 1/7] gas_limit for new blocks will divide evenly by 13 --- ethcore/src/ethereum/ethash.rs | 73 +++++++++++++++++++++++++++++++--- 1 file changed, 68 insertions(+), 5 deletions(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 909480570ee..60878ad5e26 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -31,6 +31,9 @@ use ethjson; use rlp::{self, UntrustedRlp, View}; use blockchain::extras::BlockDetails; +/// Parity tries to round block.gas_limit to multiplier of this constant +pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([13, 0, 0, 0]); + /// Ethash params. #[derive(Debug, PartialEq)] pub struct EthashParams { @@ -181,12 +184,27 @@ impl Engine for Ethash { let lower_limit = gas_limit - gas_limit / bound_divisor + 1.into(); let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into(); if gas_limit < gas_floor_target { - min(gas_floor_target, upper_limit) + let gas_limit = min(gas_floor_target, upper_limit); + gas_limit - gas_limit % PARITY_GAS_LIMIT_DETERMINANT } else if gas_limit > gas_ceil_target { - max(gas_ceil_target, lower_limit) + let gas_limit = max(gas_ceil_target, lower_limit); + gas_limit + (PARITY_GAS_LIMIT_DETERMINANT - gas_limit % PARITY_GAS_LIMIT_DETERMINANT) } else { - max(gas_floor_target, min(min(gas_ceil_target, upper_limit), - lower_limit + (header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor)) + let total_upper_limit = min(gas_ceil_target, upper_limit); + let gas_limit = max(gas_floor_target, min(total_upper_limit, + lower_limit + (header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor)); + let increased_gas_limit = gas_limit + (PARITY_GAS_LIMIT_DETERMINANT - gas_limit % PARITY_GAS_LIMIT_DETERMINANT); + if increased_gas_limit > total_upper_limit { + let total_lower_limit = max(gas_floor_target, lower_limit); + let decreased_gas_limit = increased_gas_limit - PARITY_GAS_LIMIT_DETERMINANT; + if decreased_gas_limit < total_lower_limit { + gas_limit + } else { + decreased_gas_limit + } + } else { + increased_gas_limit + } } }; header.set_difficulty(difficulty); @@ -435,11 +453,12 @@ mod tests { use util::*; use block::*; use tests::helpers::*; + use engines::Engine; use env_info::EnvInfo; use error::{BlockError, Error}; use header::Header; use super::super::{new_morden, new_homestead_test}; - use super::{Ethash, EthashParams}; + use super::{Ethash, EthashParams, PARITY_GAS_LIMIT_DETERMINANT}; use rlp; #[test] @@ -777,4 +796,48 @@ mod tests { ethash.calculate_difficulty(&header, &parent_header) ); } + + #[test] + fn gas_limit_is_multiplier_of_determinant() { + let spec = new_homestead_test(); + let ethash = Ethash::new(spec.params, get_default_ethash_params(), BTreeMap::new()); + let mut parent = Header::new(); + let mut header = Header::new(); + header.set_number(1); + + // this test will work for this constant only + assert_eq!(PARITY_GAS_LIMIT_DETERMINANT, U256::from(13)); + + // when parent.gas_limit < gas_floor_target: + parent.set_gas_limit(U256::from(50_000)); + ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(200_000)); + assert_eq!(*header.gas_limit(), U256::from(50_037)); + + // when parent.gas_limit > gas_ceil_target: + parent.set_gas_limit(U256::from(250_000)); + ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(200_000)); + assert_eq!(*header.gas_limit(), U256::from(249_769)); + + // when parent.gas_limit is in miner's range + header.set_gas_used(U256::from(150_000)); + parent.set_gas_limit(U256::from(150_000)); + ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(200_000)); + assert_eq!(*header.gas_limit(), U256::from(150_033)); + + // when parent.gas_limit is in miner's range + // && we can NOT increase it to be multiplier of constant + header.set_gas_used(U256::from(150_000)); + parent.set_gas_limit(U256::from(150_000)); + ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(150_002)); + assert_eq!(*header.gas_limit(), U256::from(149_994)); + + // when parent.gas_limit is in miner's range + // && we can NOT increase it to be multiplier of constant + // && we can NOT decrease it to be multiplier of constant + header.set_gas_used(U256::from(150_000)); + parent.set_gas_limit(U256::from(150_000)); + ethash.populate_from_parent(&mut header, &parent, U256::from(150_000), U256::from(150_002)); + assert_eq!(*header.gas_limit(), U256::from(150_002)); + + } } From 6ab5e6f16e3078f7f255907c2ec792b89cedca7b Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 13 Jan 2017 12:42:48 +0300 Subject: [PATCH 2/7] increased PARITY_GAS_LIMIT_DETERMINANT to 37 --- ethcore/src/ethereum/ethash.rs | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index a5af129866f..1553afa924a 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -32,7 +32,7 @@ use rlp::{self, UntrustedRlp, View}; use blockchain::extras::BlockDetails; /// Parity tries to round block.gas_limit to multiplier of this constant -pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([13, 0, 0, 0]); +pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]); /// Ethash params. #[derive(Debug, PartialEq)] @@ -802,30 +802,30 @@ mod tests { header.set_number(1); // this test will work for this constant only - assert_eq!(PARITY_GAS_LIMIT_DETERMINANT, U256::from(13)); + assert_eq!(PARITY_GAS_LIMIT_DETERMINANT, U256::from(37)); // when parent.gas_limit < gas_floor_target: parent.set_gas_limit(U256::from(50_000)); ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(200_000)); - assert_eq!(*header.gas_limit(), U256::from(50_037)); + assert_eq!(*header.gas_limit(), U256::from(50_024)); // when parent.gas_limit > gas_ceil_target: parent.set_gas_limit(U256::from(250_000)); ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(200_000)); - assert_eq!(*header.gas_limit(), U256::from(249_769)); + assert_eq!(*header.gas_limit(), U256::from(249_787)); // when parent.gas_limit is in miner's range header.set_gas_used(U256::from(150_000)); parent.set_gas_limit(U256::from(150_000)); ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(200_000)); - assert_eq!(*header.gas_limit(), U256::from(150_033)); + assert_eq!(*header.gas_limit(), U256::from(150_035)); // when parent.gas_limit is in miner's range // && we can NOT increase it to be multiplier of constant header.set_gas_used(U256::from(150_000)); parent.set_gas_limit(U256::from(150_000)); ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(150_002)); - assert_eq!(*header.gas_limit(), U256::from(149_994)); + assert_eq!(*header.gas_limit(), U256::from(149_998)); // when parent.gas_limit is in miner's range // && we can NOT increase it to be multiplier of constant @@ -834,6 +834,5 @@ mod tests { parent.set_gas_limit(U256::from(150_000)); ethash.populate_from_parent(&mut header, &parent, U256::from(150_000), U256::from(150_002)); assert_eq!(*header.gas_limit(), U256::from(150_002)); - } } From e8c370632448441b28ac1d7ba03437bb1e320208 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 13 Jan 2017 15:29:21 +0300 Subject: [PATCH 3/7] separate method for marking mined block --- ethcore/src/ethereum/ethash.rs | 37 ++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 15 deletions(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 1553afa924a..6c6a7000da9 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -185,26 +185,16 @@ impl Engine for Ethash { let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into(); if gas_limit < gas_floor_target { let gas_limit = min(gas_floor_target, upper_limit); - gas_limit - gas_limit % PARITY_GAS_LIMIT_DETERMINANT + self.round_block_gas_limit(gas_limit, lower_limit, upper_limit) } else if gas_limit > gas_ceil_target { let gas_limit = max(gas_ceil_target, lower_limit); - gas_limit + (PARITY_GAS_LIMIT_DETERMINANT - gas_limit % PARITY_GAS_LIMIT_DETERMINANT) + self.round_block_gas_limit(gas_limit, lower_limit, upper_limit) } else { - let total_upper_limit = min(gas_ceil_target, upper_limit); + let total_lower_limit = max(lower_limit, gas_floor_target); + let total_upper_limit = min(upper_limit, gas_ceil_target); let gas_limit = max(gas_floor_target, min(total_upper_limit, lower_limit + (header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor)); - let increased_gas_limit = gas_limit + (PARITY_GAS_LIMIT_DETERMINANT - gas_limit % PARITY_GAS_LIMIT_DETERMINANT); - if increased_gas_limit > total_upper_limit { - let total_lower_limit = max(gas_floor_target, lower_limit); - let decreased_gas_limit = increased_gas_limit - PARITY_GAS_LIMIT_DETERMINANT; - if decreased_gas_limit < total_lower_limit { - gas_limit - } else { - decreased_gas_limit - } - } else { - increased_gas_limit - } + self.round_block_gas_limit(gas_limit, total_lower_limit, total_upper_limit) } }; header.set_difficulty(difficulty); @@ -425,6 +415,23 @@ impl Ethash { (((U256::one() << 255) / *difficulty) << 1).into() } } + + // Try to round gas_limit a bit so that: + // 1) it will still be in desired range + // 2) it will be a nearest (with tendency to increase) multiplier of PARITY_GAS_LIMIT_DETERMINANT + fn round_block_gas_limit(&self, gas_limit: U256, lower_limit: U256, upper_limit: U256) -> U256 { + let increased_gas_limit = gas_limit + (PARITY_GAS_LIMIT_DETERMINANT - gas_limit % PARITY_GAS_LIMIT_DETERMINANT); + if increased_gas_limit > upper_limit { + let decreased_gas_limit = increased_gas_limit - PARITY_GAS_LIMIT_DETERMINANT; + if decreased_gas_limit < lower_limit { + gas_limit + } else { + decreased_gas_limit + } + } else { + increased_gas_limit + } + } } impl Header { From d6f57ecbcfa23bdb8806201af8252876047f9b31 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 13 Jan 2017 20:01:58 +0300 Subject: [PATCH 4/7] debug_asserts(gas_limit within protocol range) --- ethcore/src/ethereum/ethash.rs | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 6c6a7000da9..376fe9323ba 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -183,7 +183,7 @@ impl Engine for Ethash { let bound_divisor = self.ethash_params.gas_limit_bound_divisor; let lower_limit = gas_limit - gas_limit / bound_divisor + 1.into(); let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into(); - if gas_limit < gas_floor_target { + let gas_limit = if gas_limit < gas_floor_target { let gas_limit = min(gas_floor_target, upper_limit); self.round_block_gas_limit(gas_limit, lower_limit, upper_limit) } else if gas_limit > gas_ceil_target { @@ -195,7 +195,11 @@ impl Engine for Ethash { let gas_limit = max(gas_floor_target, min(total_upper_limit, lower_limit + (header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor)); self.round_block_gas_limit(gas_limit, total_lower_limit, total_upper_limit) - } + }; + // ensure that we are not violating protocol limits + debug_assert!(gas_limit >= lower_limit); + debug_assert!(gas_limit <= upper_limit); + gas_limit }; header.set_difficulty(difficulty); header.set_gas_limit(gas_limit); From e7a142fbfb70b4de17e681dc76385163d7488a8e Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Fri, 13 Jan 2017 22:58:09 +0300 Subject: [PATCH 5/7] round_block_gas_limit method is now static --- ethcore/src/ethereum/ethash.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 376fe9323ba..d56bf42654e 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -185,16 +185,16 @@ impl Engine for Ethash { let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into(); let gas_limit = if gas_limit < gas_floor_target { let gas_limit = min(gas_floor_target, upper_limit); - self.round_block_gas_limit(gas_limit, lower_limit, upper_limit) + Ethash::round_block_gas_limit(gas_limit, lower_limit, upper_limit) } else if gas_limit > gas_ceil_target { let gas_limit = max(gas_ceil_target, lower_limit); - self.round_block_gas_limit(gas_limit, lower_limit, upper_limit) + Ethash::round_block_gas_limit(gas_limit, lower_limit, upper_limit) } else { let total_lower_limit = max(lower_limit, gas_floor_target); let total_upper_limit = min(upper_limit, gas_ceil_target); let gas_limit = max(gas_floor_target, min(total_upper_limit, lower_limit + (header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor)); - self.round_block_gas_limit(gas_limit, total_lower_limit, total_upper_limit) + Ethash::round_block_gas_limit(gas_limit, total_lower_limit, total_upper_limit) }; // ensure that we are not violating protocol limits debug_assert!(gas_limit >= lower_limit); @@ -423,7 +423,7 @@ impl Ethash { // Try to round gas_limit a bit so that: // 1) it will still be in desired range // 2) it will be a nearest (with tendency to increase) multiplier of PARITY_GAS_LIMIT_DETERMINANT - fn round_block_gas_limit(&self, gas_limit: U256, lower_limit: U256, upper_limit: U256) -> U256 { + fn round_block_gas_limit(gas_limit: U256, lower_limit: U256, upper_limit: U256) -> U256 { let increased_gas_limit = gas_limit + (PARITY_GAS_LIMIT_DETERMINANT - gas_limit % PARITY_GAS_LIMIT_DETERMINANT); if increased_gas_limit > upper_limit { let decreased_gas_limit = increased_gas_limit - PARITY_GAS_LIMIT_DETERMINANT; From fdd6bfc12da9ae9307b07a9d75b3d90ff4639c84 Mon Sep 17 00:00:00 2001 From: Svyatoslav Nikolsky Date: Sat, 14 Jan 2017 00:31:52 +0300 Subject: [PATCH 6/7] made round_block_gas_limit free-function --- ethcore/src/ethereum/ethash.rs | 40 +++++++++++++++++----------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index d56bf42654e..8905ec16561 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -185,16 +185,16 @@ impl Engine for Ethash { let upper_limit = gas_limit + gas_limit / bound_divisor - 1.into(); let gas_limit = if gas_limit < gas_floor_target { let gas_limit = min(gas_floor_target, upper_limit); - Ethash::round_block_gas_limit(gas_limit, lower_limit, upper_limit) + round_block_gas_limit(gas_limit, lower_limit, upper_limit) } else if gas_limit > gas_ceil_target { let gas_limit = max(gas_ceil_target, lower_limit); - Ethash::round_block_gas_limit(gas_limit, lower_limit, upper_limit) + round_block_gas_limit(gas_limit, lower_limit, upper_limit) } else { let total_lower_limit = max(lower_limit, gas_floor_target); let total_upper_limit = min(upper_limit, gas_ceil_target); let gas_limit = max(gas_floor_target, min(total_upper_limit, lower_limit + (header.gas_used().clone() * 6.into() / 5.into()) / bound_divisor)); - Ethash::round_block_gas_limit(gas_limit, total_lower_limit, total_upper_limit) + round_block_gas_limit(gas_limit, total_lower_limit, total_upper_limit) }; // ensure that we are not violating protocol limits debug_assert!(gas_limit >= lower_limit); @@ -346,6 +346,23 @@ pub fn is_new_best_block(best_total_difficulty: U256, parent_details: &BlockDeta parent_details.total_difficulty + new_header.difficulty() > best_total_difficulty } +// Try to round gas_limit a bit so that: +// 1) it will still be in desired range +// 2) it will be a nearest (with tendency to increase) multiplier of PARITY_GAS_LIMIT_DETERMINANT +fn round_block_gas_limit(gas_limit: U256, lower_limit: U256, upper_limit: U256) -> U256 { + let increased_gas_limit = gas_limit + (PARITY_GAS_LIMIT_DETERMINANT - gas_limit % PARITY_GAS_LIMIT_DETERMINANT); + if increased_gas_limit > upper_limit { + let decreased_gas_limit = increased_gas_limit - PARITY_GAS_LIMIT_DETERMINANT; + if decreased_gas_limit < lower_limit { + gas_limit + } else { + decreased_gas_limit + } + } else { + increased_gas_limit + } +} + #[cfg_attr(feature="dev", allow(wrong_self_convention))] impl Ethash { fn calculate_difficulty(&self, header: &Header, parent: &Header) -> U256 { @@ -419,23 +436,6 @@ impl Ethash { (((U256::one() << 255) / *difficulty) << 1).into() } } - - // Try to round gas_limit a bit so that: - // 1) it will still be in desired range - // 2) it will be a nearest (with tendency to increase) multiplier of PARITY_GAS_LIMIT_DETERMINANT - fn round_block_gas_limit(gas_limit: U256, lower_limit: U256, upper_limit: U256) -> U256 { - let increased_gas_limit = gas_limit + (PARITY_GAS_LIMIT_DETERMINANT - gas_limit % PARITY_GAS_LIMIT_DETERMINANT); - if increased_gas_limit > upper_limit { - let decreased_gas_limit = increased_gas_limit - PARITY_GAS_LIMIT_DETERMINANT; - if decreased_gas_limit < lower_limit { - gas_limit - } else { - decreased_gas_limit - } - } else { - increased_gas_limit - } - } } impl Header { From dae18c42e0ed4ea2963fb5581228e979640ffff6 Mon Sep 17 00:00:00 2001 From: keorn Date: Mon, 16 Jan 2017 13:52:13 +0100 Subject: [PATCH 7/7] multiplier->multiple [ci skip] --- ethcore/src/ethereum/ethash.rs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/ethcore/src/ethereum/ethash.rs b/ethcore/src/ethereum/ethash.rs index 8905ec16561..ef8a275447f 100644 --- a/ethcore/src/ethereum/ethash.rs +++ b/ethcore/src/ethereum/ethash.rs @@ -31,7 +31,7 @@ use ethjson; use rlp::{self, UntrustedRlp, View}; use blockchain::extras::BlockDetails; -/// Parity tries to round block.gas_limit to multiplier of this constant +/// Parity tries to round block.gas_limit to multiple of this constant pub const PARITY_GAS_LIMIT_DETERMINANT: U256 = U256([37, 0, 0, 0]); /// Ethash params. @@ -348,7 +348,7 @@ pub fn is_new_best_block(best_total_difficulty: U256, parent_details: &BlockDeta // Try to round gas_limit a bit so that: // 1) it will still be in desired range -// 2) it will be a nearest (with tendency to increase) multiplier of PARITY_GAS_LIMIT_DETERMINANT +// 2) it will be a nearest (with tendency to increase) multiple of PARITY_GAS_LIMIT_DETERMINANT fn round_block_gas_limit(gas_limit: U256, lower_limit: U256, upper_limit: U256) -> U256 { let increased_gas_limit = gas_limit + (PARITY_GAS_LIMIT_DETERMINANT - gas_limit % PARITY_GAS_LIMIT_DETERMINANT); if increased_gas_limit > upper_limit { @@ -805,7 +805,7 @@ mod tests { } #[test] - fn gas_limit_is_multiplier_of_determinant() { + fn gas_limit_is_multiple_of_determinant() { let spec = new_homestead_test(); let ethash = Ethash::new(spec.params, get_default_ethash_params(), BTreeMap::new()); let mut parent = Header::new(); @@ -832,15 +832,15 @@ mod tests { assert_eq!(*header.gas_limit(), U256::from(150_035)); // when parent.gas_limit is in miner's range - // && we can NOT increase it to be multiplier of constant + // && we can NOT increase it to be multiple of constant header.set_gas_used(U256::from(150_000)); parent.set_gas_limit(U256::from(150_000)); ethash.populate_from_parent(&mut header, &parent, U256::from(100_000), U256::from(150_002)); assert_eq!(*header.gas_limit(), U256::from(149_998)); // when parent.gas_limit is in miner's range - // && we can NOT increase it to be multiplier of constant - // && we can NOT decrease it to be multiplier of constant + // && we can NOT increase it to be multiple of constant + // && we can NOT decrease it to be multiple of constant header.set_gas_used(U256::from(150_000)); parent.set_gas_limit(U256::from(150_000)); ethash.populate_from_parent(&mut header, &parent, U256::from(150_000), U256::from(150_002));