AuRa multi block reward (#290)
* Multi block reward for AuRa * Added test * Better error on wrong config
This commit is contained in:
parent
dbc5f94241
commit
6f50061f0c
@ -43,7 +43,7 @@ use engines::{
|
||||
};
|
||||
use error::{BlockError, Error, ErrorKind};
|
||||
use ethereum_types::{Address, H256, H520, U128, U256};
|
||||
use ethjson;
|
||||
use ethjson::{self, uint::Uint};
|
||||
use ethkey::{self, Signature};
|
||||
use hash::keccak;
|
||||
use io::{IoContext, IoHandler, IoService, TimerToken};
|
||||
@ -80,7 +80,7 @@ pub struct AuthorityRoundParams {
|
||||
/// Immediate transitions.
|
||||
pub immediate_transitions: bool,
|
||||
/// Block reward in base units.
|
||||
pub block_reward: U256,
|
||||
pub block_reward: BTreeMap<BlockNumber, U256>,
|
||||
/// Block reward contract transition block.
|
||||
pub block_reward_contract_transition: u64,
|
||||
/// Block reward contract.
|
||||
@ -113,7 +113,33 @@ impl From<ethjson::spec::AuthorityRoundParams> for AuthorityRoundParams {
|
||||
validate_score_transition: p.validate_score_transition.map_or(0, Into::into),
|
||||
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: p.block_reward.map_or_else(
|
||||
|| {
|
||||
let mut ret = BTreeMap::new();
|
||||
ret.insert(0, U256::zero());
|
||||
ret
|
||||
},
|
||||
|reward| match reward {
|
||||
ethjson::spec::BlockReward::Single(reward) => {
|
||||
let mut ret = BTreeMap::new();
|
||||
ret.insert(0, reward.into());
|
||||
ret
|
||||
}
|
||||
ethjson::spec::BlockReward::Multi(mut multi) => {
|
||||
if multi.is_empty() {
|
||||
panic!("No block rewards are found in config");
|
||||
}
|
||||
// add block reward from genesis and put reward to zero.
|
||||
multi
|
||||
.entry(Uint(U256::from(0)))
|
||||
.or_insert(Uint(U256::from(0)));
|
||||
multi
|
||||
.into_iter()
|
||||
.map(|(block, reward)| (block.into(), reward.into()))
|
||||
.collect()
|
||||
}
|
||||
},
|
||||
),
|
||||
block_reward_contract_transition: p
|
||||
.block_reward_contract_transition
|
||||
.map_or(0, Into::into),
|
||||
@ -457,7 +483,7 @@ pub struct AuthorityRound {
|
||||
empty_steps: Mutex<BTreeSet<EmptyStep>>,
|
||||
epoch_manager: Mutex<EpochManager>,
|
||||
immediate_transitions: bool,
|
||||
block_reward: U256,
|
||||
block_reward: BTreeMap<BlockNumber, U256>,
|
||||
block_reward_contract_transition: u64,
|
||||
block_reward_contract: Option<BlockRewardContract>,
|
||||
maximum_uncle_count_transition: u64,
|
||||
@ -1374,10 +1400,11 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
}
|
||||
|
||||
let author = *block.header.author();
|
||||
let number = block.header.number();
|
||||
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 => {
|
||||
Some(ref c) if number >= self.block_reward_contract_transition => {
|
||||
let mut call = super::default_system_or_code_call(&self.machine, block);
|
||||
|
||||
let rewards = c.reward(&beneficiaries, &mut call)?;
|
||||
@ -1386,10 +1413,18 @@ impl Engine<EthereumMachine> for AuthorityRound {
|
||||
.map(|(author, amount)| (author, RewardKind::External, amount))
|
||||
.collect()
|
||||
}
|
||||
_ => beneficiaries
|
||||
.into_iter()
|
||||
.map(|(author, reward_kind)| (author, reward_kind, self.block_reward))
|
||||
.collect(),
|
||||
_ => {
|
||||
let (_, reward) = self.block_reward.iter()
|
||||
.rev()
|
||||
.find(|&(block, _)| *block <= number)
|
||||
.expect("Current block's reward is not found; this indicates a chain config error; qed");
|
||||
let reward = *reward;
|
||||
|
||||
beneficiaries
|
||||
.into_iter()
|
||||
.map(|(author, reward_kind)| (author, reward_kind, reward))
|
||||
.collect()
|
||||
}
|
||||
};
|
||||
|
||||
block_reward::apply_block_rewards(&rewards, block, &self.machine)
|
||||
|
@ -17,7 +17,7 @@
|
||||
use std::{cmp, collections::BTreeMap, path::Path, sync::Arc};
|
||||
|
||||
use ethereum_types::{H256, H64, U256};
|
||||
use ethjson;
|
||||
use ethjson::{self, uint::Uint};
|
||||
use hash::KECCAK_EMPTY_LIST_RLP;
|
||||
use rlp::Rlp;
|
||||
use types::{
|
||||
@ -145,10 +145,19 @@ impl From<ethjson::spec::EthashParams> for EthashParams {
|
||||
ret.insert(0, reward.into());
|
||||
ret
|
||||
}
|
||||
ethjson::spec::BlockReward::Multi(multi) => multi
|
||||
.into_iter()
|
||||
.map(|(block, reward)| (block.into(), reward.into()))
|
||||
.collect(),
|
||||
ethjson::spec::BlockReward::Multi(mut multi) => {
|
||||
if multi.is_empty() {
|
||||
panic!("No block rewards are found in config");
|
||||
}
|
||||
// add block reward from genesis and put reward to zero.
|
||||
multi
|
||||
.entry(Uint(U256::from(0)))
|
||||
.or_insert(Uint(U256::from(0)));
|
||||
multi
|
||||
.into_iter()
|
||||
.map(|(block, reward)| (block.into(), reward.into()))
|
||||
.collect()
|
||||
}
|
||||
},
|
||||
),
|
||||
expip2_transition: p.expip2_transition.map_or(u64::max_value(), Into::into),
|
||||
|
@ -16,7 +16,7 @@
|
||||
|
||||
//! Authority params deserialization.
|
||||
|
||||
use super::ValidatorSet;
|
||||
use super::{BlockReward, ValidatorSet};
|
||||
use bytes::Bytes;
|
||||
use hash::Address;
|
||||
use uint::Uint;
|
||||
@ -40,7 +40,7 @@ pub struct AuthorityRoundParams {
|
||||
/// Whether transitions should be immediate.
|
||||
pub immediate_transitions: Option<bool>,
|
||||
/// Reward per block in wei.
|
||||
pub block_reward: Option<Uint>,
|
||||
pub block_reward: Option<BlockReward>,
|
||||
/// Block at which the block reward contract should start being used.
|
||||
pub block_reward_contract_transition: Option<Uint>,
|
||||
/// Block reward contract address (setting the block reward contract
|
||||
@ -70,6 +70,9 @@ pub struct AuthorityRound {
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
use super::BlockReward;
|
||||
use ethereum_types::{H160, U256};
|
||||
use hash::Address;
|
||||
use serde_json;
|
||||
@ -110,5 +113,41 @@ mod tests {
|
||||
deserialized.params.maximum_uncle_count,
|
||||
Some(Uint(5.into()))
|
||||
);
|
||||
assert_eq!(
|
||||
deserialized.params.block_reward,
|
||||
Some(BlockReward::Single(Uint(5000000.into())))
|
||||
)
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn authority_round_deserialization_multi_block() {
|
||||
let s = r#"{
|
||||
"params": {
|
||||
"stepDuration": "0x02",
|
||||
"validators": {
|
||||
"contract" : "0xc6d9d2cd449a754c494264e1809c50e34d64562b"
|
||||
},
|
||||
"blockReward": {
|
||||
"0": 5000000,
|
||||
"100": 150
|
||||
}
|
||||
}
|
||||
}"#;
|
||||
|
||||
let deserialized: AuthorityRound = serde_json::from_str(s).unwrap();
|
||||
assert_eq!(deserialized.params.step_duration, Uint(U256::from(0x02)));
|
||||
assert_eq!(
|
||||
deserialized.params.validators,
|
||||
ValidatorSet::Contract(Address(H160::from(
|
||||
"0xc6d9d2cd449a754c494264e1809c50e34d64562b"
|
||||
)))
|
||||
);
|
||||
let mut rewards: BTreeMap<Uint, Uint> = BTreeMap::new();
|
||||
rewards.insert(Uint(U256::from(0)), Uint(U256::from(5000000)));
|
||||
rewards.insert(Uint(U256::from(100)), Uint(U256::from(150)));
|
||||
assert_eq!(
|
||||
deserialized.params.block_reward,
|
||||
Some(BlockReward::Multi(rewards))
|
||||
);
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user