Configuration map of block reward contract addresses (#10875)
* configuration map of block reward contract addresses * Revert test module updates. * re-added block reward transition map tests and docs * review comment
This commit is contained in:
		
							parent
							
								
									175051bac7
								
							
						
					
					
						commit
						efb390eb60
					
				@ -87,10 +87,8 @@ pub struct AuthorityRoundParams {
 | 
			
		||||
	pub immediate_transitions: bool,
 | 
			
		||||
	/// Block reward in base units.
 | 
			
		||||
	pub block_reward: U256,
 | 
			
		||||
	/// Block reward contract transition block.
 | 
			
		||||
	pub block_reward_contract_transition: u64,
 | 
			
		||||
	/// Block reward contract.
 | 
			
		||||
	pub block_reward_contract: Option<BlockRewardContract>,
 | 
			
		||||
	/// Block reward contract addresses with their associated starting block numbers.
 | 
			
		||||
	pub block_reward_contract_transitions: BTreeMap<u64, BlockRewardContract>,
 | 
			
		||||
	/// Number of accepted uncles transition block.
 | 
			
		||||
	pub maximum_uncle_count_transition: u64,
 | 
			
		||||
	/// Number of accepted uncles.
 | 
			
		||||
@ -114,6 +112,30 @@ impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
 | 
			
		||||
			step_duration_usize = U16_MAX;
 | 
			
		||||
			warn!(target: "engine", "step_duration is too high ({}), setting it to {}", step_duration_usize, U16_MAX);
 | 
			
		||||
		}
 | 
			
		||||
		let transition_block_num = p.block_reward_contract_transition.map_or(0, Into::into);
 | 
			
		||||
		let mut br_transitions: BTreeMap<_, _> = p.block_reward_contract_transitions
 | 
			
		||||
			.unwrap_or_default()
 | 
			
		||||
			.into_iter()
 | 
			
		||||
			.map(|(block_num, address)|
 | 
			
		||||
				 (block_num.into(), BlockRewardContract::new_from_address(address.into())))
 | 
			
		||||
			.collect();
 | 
			
		||||
		if (p.block_reward_contract_code.is_some() || p.block_reward_contract_address.is_some()) &&
 | 
			
		||||
			br_transitions.keys().next().map_or(false, |&block_num| block_num <= transition_block_num)
 | 
			
		||||
		{
 | 
			
		||||
			let s = "blockRewardContractTransition";
 | 
			
		||||
			panic!("{} should be less than any of the keys in {}s", s, s);
 | 
			
		||||
		}
 | 
			
		||||
		if let Some(code) = p.block_reward_contract_code {
 | 
			
		||||
			br_transitions.insert(
 | 
			
		||||
				transition_block_num,
 | 
			
		||||
				BlockRewardContract::new_from_code(Arc::new(code.into()))
 | 
			
		||||
			);
 | 
			
		||||
		} else if let Some(address) = p.block_reward_contract_address {
 | 
			
		||||
			br_transitions.insert(
 | 
			
		||||
				transition_block_num,
 | 
			
		||||
				BlockRewardContract::new_from_address(address.into())
 | 
			
		||||
			);
 | 
			
		||||
		}
 | 
			
		||||
		AuthorityRoundParams {
 | 
			
		||||
			step_duration: step_duration_usize as u16,
 | 
			
		||||
			validators: new_validator_set(p.validators),
 | 
			
		||||
@ -122,12 +144,7 @@ impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
 | 
			
		||||
			validate_step_transition: p.validate_step_transition.map_or(0, Into::into),
 | 
			
		||||
			immediate_transitions: p.immediate_transitions.unwrap_or(false),
 | 
			
		||||
			block_reward: p.block_reward.map_or_else(Default::default, Into::into),
 | 
			
		||||
			block_reward_contract_transition: p.block_reward_contract_transition.map_or(0, Into::into),
 | 
			
		||||
			block_reward_contract: match (p.block_reward_contract_code, p.block_reward_contract_address) {
 | 
			
		||||
				(Some(code), _) => Some(BlockRewardContract::new_from_code(Arc::new(code.into()))),
 | 
			
		||||
				(_, Some(address)) => Some(BlockRewardContract::new_from_address(address.into())),
 | 
			
		||||
				(None, None) => None,
 | 
			
		||||
			},
 | 
			
		||||
			block_reward_contract_transitions: br_transitions,
 | 
			
		||||
			maximum_uncle_count_transition: p.maximum_uncle_count_transition.map_or(0, Into::into),
 | 
			
		||||
			maximum_uncle_count: p.maximum_uncle_count.map_or(0, Into::into),
 | 
			
		||||
			empty_steps_transition: p.empty_steps_transition.map_or(u64::max_value(), |n| ::std::cmp::max(n.into(), 1)),
 | 
			
		||||
@ -454,8 +471,7 @@ pub struct AuthorityRound {
 | 
			
		||||
	epoch_manager: Mutex<EpochManager>,
 | 
			
		||||
	immediate_transitions: bool,
 | 
			
		||||
	block_reward: U256,
 | 
			
		||||
	block_reward_contract_transition: u64,
 | 
			
		||||
	block_reward_contract: Option<BlockRewardContract>,
 | 
			
		||||
	block_reward_contract_transitions: BTreeMap<u64, BlockRewardContract>,
 | 
			
		||||
	maximum_uncle_count_transition: u64,
 | 
			
		||||
	maximum_uncle_count: usize,
 | 
			
		||||
	empty_steps_transition: u64,
 | 
			
		||||
@ -724,8 +740,7 @@ impl AuthorityRound {
 | 
			
		||||
				epoch_manager: Mutex::new(EpochManager::blank(our_params.two_thirds_majority_transition)),
 | 
			
		||||
				immediate_transitions: our_params.immediate_transitions,
 | 
			
		||||
				block_reward: our_params.block_reward,
 | 
			
		||||
				block_reward_contract_transition: our_params.block_reward_contract_transition,
 | 
			
		||||
				block_reward_contract: our_params.block_reward_contract,
 | 
			
		||||
				block_reward_contract_transitions: our_params.block_reward_contract_transitions,
 | 
			
		||||
				maximum_uncle_count_transition: our_params.maximum_uncle_count_transition,
 | 
			
		||||
				maximum_uncle_count: our_params.maximum_uncle_count,
 | 
			
		||||
				empty_steps_transition: our_params.empty_steps_transition,
 | 
			
		||||
@ -1295,16 +1310,16 @@ impl Engine for AuthorityRound {
 | 
			
		||||
		let author = *block.header.author();
 | 
			
		||||
		beneficiaries.push((author, RewardKind::Author));
 | 
			
		||||
 | 
			
		||||
		let rewards: Vec<_> = match self.block_reward_contract {
 | 
			
		||||
			Some(ref c) if block.header.number() >= self.block_reward_contract_transition => {
 | 
			
		||||
				let mut call = engine::default_system_or_code_call(&self.machine, block);
 | 
			
		||||
 | 
			
		||||
				let rewards = c.reward(beneficiaries, &mut call)?;
 | 
			
		||||
				rewards.into_iter().map(|(author, amount)| (author, RewardKind::External, amount)).collect()
 | 
			
		||||
			},
 | 
			
		||||
			_ => {
 | 
			
		||||
				beneficiaries.into_iter().map(|(author, reward_kind)| (author, reward_kind, self.block_reward)).collect()
 | 
			
		||||
			},
 | 
			
		||||
		let block_reward_contract_transition = self
 | 
			
		||||
			.block_reward_contract_transitions
 | 
			
		||||
			.range(..=block.header.number())
 | 
			
		||||
			.last();
 | 
			
		||||
		let rewards: Vec<_> = if let Some((_, contract)) = block_reward_contract_transition {
 | 
			
		||||
			let mut call = engine::default_system_or_code_call(&self.machine, block);
 | 
			
		||||
			let rewards = contract.reward(beneficiaries, &mut call)?;
 | 
			
		||||
			rewards.into_iter().map(|(author, amount)| (author, RewardKind::External, amount)).collect()
 | 
			
		||||
		} else {
 | 
			
		||||
			beneficiaries.into_iter().map(|(author, reward_kind)| (author, reward_kind, self.block_reward)).collect()
 | 
			
		||||
		};
 | 
			
		||||
 | 
			
		||||
		block_reward::apply_block_rewards(&rewards, block, &self.machine)
 | 
			
		||||
@ -1645,6 +1660,7 @@ impl Engine for AuthorityRound {
 | 
			
		||||
#[cfg(test)]
 | 
			
		||||
mod tests {
 | 
			
		||||
	use std::collections::BTreeMap;
 | 
			
		||||
	use std::str::FromStr;
 | 
			
		||||
	use std::sync::Arc;
 | 
			
		||||
	use std::sync::atomic::{AtomicUsize, Ordering as AtomicOrdering};
 | 
			
		||||
	use hash::keccak;
 | 
			
		||||
@ -1665,9 +1681,11 @@ mod tests {
 | 
			
		||||
	};
 | 
			
		||||
	use crate::spec::{Spec, self};
 | 
			
		||||
	use engine::Engine;
 | 
			
		||||
	use engines::block_reward::BlockRewardContract;
 | 
			
		||||
	use engines::validator_set::{TestSet, SimpleList};
 | 
			
		||||
	use super::{AuthorityRoundParams, AuthorityRound, EmptyStep, SealedEmptyStep, calculate_score};
 | 
			
		||||
	use machine::Machine;
 | 
			
		||||
	use ethjson;
 | 
			
		||||
 | 
			
		||||
	fn build_aura<F>(f: F) -> Arc<AuthorityRound> where
 | 
			
		||||
		F: FnOnce(&mut AuthorityRoundParams),
 | 
			
		||||
@ -1684,8 +1702,7 @@ mod tests {
 | 
			
		||||
			empty_steps_transition: u64::max_value(),
 | 
			
		||||
			maximum_empty_steps: 0,
 | 
			
		||||
			block_reward: Default::default(),
 | 
			
		||||
			block_reward_contract_transition: 0,
 | 
			
		||||
			block_reward_contract: Default::default(),
 | 
			
		||||
			block_reward_contract_transitions: Default::default(),
 | 
			
		||||
			strict_empty_steps_transition: 0,
 | 
			
		||||
			two_thirds_majority_transition: 0,
 | 
			
		||||
		};
 | 
			
		||||
@ -2452,4 +2469,55 @@ mod tests {
 | 
			
		||||
		set_empty_steps_seal(&mut header, step, &signature, &empty_steps);
 | 
			
		||||
		assert_eq!(engine.verify_block_family(&header, &parent).unwrap(), ());
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#[test]
 | 
			
		||||
	fn should_collect_block_reward_transitions() {
 | 
			
		||||
		let config = r#"{
 | 
			
		||||
			"params": {
 | 
			
		||||
				"stepDuration": "5",
 | 
			
		||||
				"validators": {
 | 
			
		||||
					"list" : ["0x1000000000000000000000000000000000000001"]
 | 
			
		||||
				},
 | 
			
		||||
                "blockRewardContractTransition": "0",
 | 
			
		||||
				"blockRewardContractAddress": "0x2000000000000000000000000000000000000002",
 | 
			
		||||
				"blockRewardContractTransitions": {
 | 
			
		||||
					"7": "0x3000000000000000000000000000000000000003",
 | 
			
		||||
					"42": "0x4000000000000000000000000000000000000004"
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}"#;
 | 
			
		||||
		let deserialized: ethjson::spec::AuthorityRound = serde_json::from_str(config).unwrap();
 | 
			
		||||
		let params = AuthorityRoundParams::from(deserialized.params);
 | 
			
		||||
		for ((block_num1, address1), (block_num2, address2)) in
 | 
			
		||||
			params.block_reward_contract_transitions.iter().zip(
 | 
			
		||||
				[(0u64, BlockRewardContract::new_from_address(Address::from_str("2000000000000000000000000000000000000002").unwrap())),
 | 
			
		||||
				 (7u64, BlockRewardContract::new_from_address(Address::from_str("3000000000000000000000000000000000000003").unwrap())),
 | 
			
		||||
				 (42u64, BlockRewardContract::new_from_address(Address::from_str("4000000000000000000000000000000000000004").unwrap())),
 | 
			
		||||
				].iter())
 | 
			
		||||
		{
 | 
			
		||||
			assert_eq!(block_num1, block_num2);
 | 
			
		||||
			assert_eq!(address1, address2);
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	#[test]
 | 
			
		||||
	#[should_panic(expected="blockRewardContractTransition should be less than any of the keys in blockRewardContractTransitions")]
 | 
			
		||||
	fn should_reject_out_of_order_block_reward_transition() {
 | 
			
		||||
		let config = r#"{
 | 
			
		||||
			"params": {
 | 
			
		||||
				"stepDuration": "5",
 | 
			
		||||
				"validators": {
 | 
			
		||||
					"list" : ["0x1000000000000000000000000000000000000001"]
 | 
			
		||||
				},
 | 
			
		||||
                "blockRewardContractTransition": "7",
 | 
			
		||||
				"blockRewardContractAddress": "0x2000000000000000000000000000000000000002",
 | 
			
		||||
				"blockRewardContractTransitions": {
 | 
			
		||||
					"0": "0x3000000000000000000000000000000000000003",
 | 
			
		||||
					"42": "0x4000000000000000000000000000000000000004"
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}"#;
 | 
			
		||||
		let deserialized: ethjson::spec::AuthorityRound = serde_json::from_str(config).unwrap();
 | 
			
		||||
		AuthorityRoundParams::from(deserialized.params);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -14,8 +14,31 @@
 | 
			
		||||
// You should have received a copy of the GNU General Public License
 | 
			
		||||
// along with Parity Ethereum.  If not, see <http://www.gnu.org/licenses/>.
 | 
			
		||||
 | 
			
		||||
//! Authority params deserialization.
 | 
			
		||||
//! Authority Round parameter deserialization.
 | 
			
		||||
//!
 | 
			
		||||
//! Here is an example of input parameters where the step duration is constant at 5 seconds, the set
 | 
			
		||||
//! of validators is decided by the contract at address `0x10..01` starting from block 0, and where
 | 
			
		||||
//! the address of the contract that computes block rewards is set to `0x20..02` for blocks 0
 | 
			
		||||
//! through 41 and to `0x30.03` for all blocks starting from block 42.
 | 
			
		||||
//!
 | 
			
		||||
//! ```ignore
 | 
			
		||||
//! "params": {
 | 
			
		||||
//!     "stepDuration": "5",
 | 
			
		||||
//!     "validators": {
 | 
			
		||||
//!         "multi": {
 | 
			
		||||
//!             "0": {
 | 
			
		||||
//!                 "contract": "0x1000000000000000000000000000000000000001"
 | 
			
		||||
//!             }
 | 
			
		||||
//!         }
 | 
			
		||||
//!     },
 | 
			
		||||
//!     "blockRewardContractTransitions": {
 | 
			
		||||
//!         "0": "0x2000000000000000000000000000000000000002",
 | 
			
		||||
//!         "42": "0x3000000000000000000000000000000000000003"
 | 
			
		||||
//!     }
 | 
			
		||||
//! }
 | 
			
		||||
//! ```
 | 
			
		||||
 | 
			
		||||
use std::collections::BTreeMap;
 | 
			
		||||
use hash::Address;
 | 
			
		||||
use uint::Uint;
 | 
			
		||||
use bytes::Bytes;
 | 
			
		||||
@ -41,11 +64,24 @@ pub struct AuthorityRoundParams {
 | 
			
		||||
	pub immediate_transitions: Option<bool>,
 | 
			
		||||
	/// Reward per block in wei.
 | 
			
		||||
	pub block_reward: Option<Uint>,
 | 
			
		||||
	/// Block at which the block reward contract should start being used.
 | 
			
		||||
	/// Block at which the block reward contract should start being used. This option allows one to
 | 
			
		||||
	/// add a single block reward contract transition and is compatible with the multiple address
 | 
			
		||||
	/// option `block_reward_contract_transitions` below.
 | 
			
		||||
	pub block_reward_contract_transition: Option<Uint>,
 | 
			
		||||
	/// Block reward contract address (setting the block reward contract
 | 
			
		||||
	/// overrides the static block reward definition).
 | 
			
		||||
	/// Block reward contract address which overrides the `block_reward` setting. This option allows
 | 
			
		||||
	/// one to add a single block reward contract address and is compatible with the multiple
 | 
			
		||||
	/// address option `block_reward_contract_transitions` below.
 | 
			
		||||
	pub block_reward_contract_address: Option<Address>,
 | 
			
		||||
	/// Block reward contract addresses with their associated starting block numbers.
 | 
			
		||||
	///
 | 
			
		||||
	/// Setting the block reward contract overrides `block_reward`. If the single block reward
 | 
			
		||||
	/// contract address is also present then it is added into the map at the block number stored in
 | 
			
		||||
	/// `block_reward_contract_transition` or 0 if that block number is not provided. Therefore both
 | 
			
		||||
	/// a single block reward contract transition and a map of reward contract transitions can be
 | 
			
		||||
	/// used simulataneously in the same configuration. In such a case the code requires that the
 | 
			
		||||
	/// block number of the single transition is strictly less than any of the block numbers in the
 | 
			
		||||
	/// map.
 | 
			
		||||
	pub block_reward_contract_transitions: Option<BTreeMap<Uint, Address>>,
 | 
			
		||||
	/// Block reward code. This overrides the block reward contract address.
 | 
			
		||||
	pub block_reward_contract_code: Option<Bytes>,
 | 
			
		||||
	/// Block at which maximum uncle count should be considered.
 | 
			
		||||
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user