Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions core/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -313,6 +313,10 @@ impl<'x> OpenBlock<'x> {
self.block.header.set_seal(seal);
Ok(())
}

pub fn inner_mut(&mut self) -> &mut ExecutedBlock {
&mut self.block
}
}

/// Just like `OpenBlock`, except that we've applied `Engine::on_close_block`, finished up the non-seal header fields.
Expand Down Expand Up @@ -484,6 +488,7 @@ pub fn enact<C: ChainTimeInfo + EngineInfo + FindActionHandler + TermInfo>(
let mut b = OpenBlock::try_new(engine, db, parent, Address::default(), vec![])?;

b.populate_from(header);
engine.on_open_block(b.inner_mut())?;
b.push_transactions(transactions, client, parent.number(), parent.timestamp())?;

let term_common_params = client.term_common_params(BlockId::Hash(*header.parent_hash()));
Expand Down
10 changes: 5 additions & 5 deletions core/src/client/test_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ use crate::client::{
AccountData, BlockChainClient, BlockChainTrait, BlockProducer, BlockStatus, ConsensusClient, EngineInfo,
ImportBlock, ImportResult, MiningBlockChainClient, StateInfo, StateOrBlock, TermInfo,
};
use crate::consensus::stake::{Validator, Validators};
use crate::consensus::stake::{NextValidators, Validator};
use crate::consensus::EngineError;
use crate::db::{COL_STATE, NUM_COLUMNS};
use crate::encoded;
Expand Down Expand Up @@ -105,7 +105,7 @@ pub struct TestBlockChainClient {
/// Fixed validator keys
pub validator_keys: RwLock<HashMap<Public, Private>>,
/// Fixed validators
pub validators: Validators,
pub validators: NextValidators,
}

impl Default for TestBlockChainClient {
Expand Down Expand Up @@ -159,7 +159,7 @@ impl TestBlockChainClient {
history: RwLock::new(None),
term_id: Some(1),
validator_keys: RwLock::new(HashMap::new()),
validators: Validators::from_vector_to_test(vec![]),
validators: NextValidators::from_vector_to_test(vec![]),
};

// insert genesis hash.
Expand Down Expand Up @@ -324,14 +324,14 @@ impl TestBlockChainClient {
self.validator_keys.write().insert(*key_pair.public(), *key_pair.private());
pubkeys.push(*key_pair.public());
}
let fixed_validators: Validators = Validators::from_vector_to_test(
let fixed_validators: NextValidators = NextValidators::from_vector_to_test(
pubkeys.into_iter().map(|pubkey| Validator::new_for_test(0, 0, pubkey)).collect(),
);

self.validators = fixed_validators;
}

pub fn get_validators(&self) -> &Validators {
pub fn get_validators(&self) -> &NextValidators {
&self.validators
}
}
Expand Down
5 changes: 5 additions & 0 deletions core/src/consensus/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -196,6 +196,11 @@ pub trait ConsensusEngine: Sync + Send {
/// Stops any services that the may hold the Engine and makes it safe to drop.
fn stop(&self) {}

/// Block transformation functions, before the transactions.
fn on_open_block(&self, _block: &mut ExecutedBlock) -> Result<(), Error> {
Ok(())
}

/// Block transformation functions, after the transactions.
fn on_close_block(
&self,
Expand Down
2 changes: 1 addition & 1 deletion core/src/consensus/simple_poa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -149,7 +149,7 @@ impl ConsensusEngine for SimplePoA {
fn possible_authors(&self, _block_number: Option<u64>) -> Result<Option<Vec<Address>>, EngineError> {
// TODO: It works because the round robin validator doesn't use the parent hash.
let parent = H256::from(0).into();
Ok(Some(self.validators.addresses(&parent)))
Ok(Some(self.validators.next_addresses(&parent)))
}
}

Expand Down
15 changes: 12 additions & 3 deletions core/src/consensus/solo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ mod params;
use std::sync::{Arc, Weak};

use ckey::Address;
use cstate::{ActionHandler, HitHandler};
use cstate::{ActionHandler, HitHandler, TopStateView};
use ctypes::{CommonParams, Header};
use parking_lot::RwLock;

Expand Down Expand Up @@ -83,6 +83,16 @@ impl ConsensusEngine for Solo {
Seal::Solo
}

fn on_open_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
let block_number = block.header().number();
let metadata = block.state().metadata()?.expect("Metadata must exist");
if block_number == metadata.last_term_finished_block_num() + 1 {
let rewards = stake::drain_current_rewards(block.state_mut())?;
stake::update_calculated_rewards(block.state_mut(), rewards.into_iter().collect())?;
}
Ok(())
}

fn on_close_block(
&self,
block: &mut ExecutedBlock,
Expand Down Expand Up @@ -128,8 +138,7 @@ impl ConsensusEngine for Solo {
}
header.number()
};
stake::move_current_to_previous_intermediate_rewards(&mut block.state_mut())?;
let rewards = stake::drain_previous_rewards(&mut block.state_mut())?;
let rewards = stake::drain_calculated_rewards(&mut block.state_mut())?;
for (address, reward) in rewards {
self.machine.add_balance(block, &address, reward)?;
}
Expand Down
100 changes: 72 additions & 28 deletions core/src/consensus/stake/action_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,10 @@ lazy_static! {
pub static ref JAIL_KEY: H256 = ActionDataKeyBuilder::new(CUSTOM_ACTION_HANDLER_ID, 1).append(&"Jail").into_key();
pub static ref BANNED_KEY: H256 =
ActionDataKeyBuilder::new(CUSTOM_ACTION_HANDLER_ID, 1).append(&"Banned").into_key();
pub static ref VALIDATORS_KEY: H256 =
pub static ref NEXT_VALIDATORS_KEY: H256 =
ActionDataKeyBuilder::new(CUSTOM_ACTION_HANDLER_ID, 1).append(&"Validators").into_key();
pub static ref CURRENT_VALIDATORS_KEY: H256 =
ActionDataKeyBuilder::new(CUSTOM_ACTION_HANDLER_ID, 1).append(&"CurrentValidators").into_key();
}

pub fn get_delegation_key(address: &Address) -> H256 {
Expand Down Expand Up @@ -275,17 +277,17 @@ impl Validator {
}

#[derive(Debug)]
pub struct Validators(Vec<Validator>);
impl Validators {
pub struct NextValidators(Vec<Validator>);
impl NextValidators {
pub fn from_vector_to_test(vec: Vec<Validator>) -> Self {
Validators(vec)
Self(vec)
}

pub fn load_from_state(state: &TopLevelState) -> StateResult<Self> {
let key = &*VALIDATORS_KEY;
let key = &*NEXT_VALIDATORS_KEY;
let validators = state.action_data(&key)?.map(|data| decode_list(&data)).unwrap_or_default();

Ok(Validators(validators))
Ok(Self(validators))
}

pub fn elect(state: &TopLevelState) -> StateResult<Self> {
Expand Down Expand Up @@ -336,7 +338,7 @@ impl Validators {


pub fn save_to_state(&self, state: &mut TopLevelState) -> StateResult<()> {
let key = &*VALIDATORS_KEY;
let key = &*NEXT_VALIDATORS_KEY;
if !self.is_empty() {
state.update_action_data(&key, encode_list(&self.0).to_vec())?;
} else {
Expand Down Expand Up @@ -385,21 +387,21 @@ impl Validators {
}
}

impl Deref for Validators {
impl Deref for NextValidators {
type Target = Vec<Validator>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl From<Validators> for Vec<Validator> {
fn from(val: Validators) -> Self {
impl From<NextValidators> for Vec<Validator> {
fn from(val: NextValidators) -> Self {
val.0
}
}

impl IntoIterator for Validators {
impl IntoIterator for NextValidators {
type Item = Validator;
type IntoIter = vec::IntoIter<Self::Item>;

Expand All @@ -408,30 +410,69 @@ impl IntoIterator for Validators {
}
}

#[derive(Debug)]
pub struct CurrentValidators(Vec<Validator>);
impl CurrentValidators {
pub fn load_from_state(state: &TopLevelState) -> StateResult<Self> {
let key = &*CURRENT_VALIDATORS_KEY;
let validators = state.action_data(&key)?.map(|data| decode_list(&data)).unwrap_or_default();

Ok(Self(validators))
}

pub fn save_to_state(&self, state: &mut TopLevelState) -> StateResult<()> {
let key = &*CURRENT_VALIDATORS_KEY;
if !self.is_empty() {
state.update_action_data(&key, encode_list(&self.0).to_vec())?;
} else {
state.remove_action_data(&key);
}
Ok(())
}

pub fn update(&mut self, validators: Vec<Validator>) {
self.0 = validators;
}
}

impl Deref for CurrentValidators {
type Target = Vec<Validator>;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl From<CurrentValidators> for Vec<Validator> {
fn from(val: CurrentValidators) -> Self {
val.0
}
}

#[derive(Default, Debug, PartialEq)]
pub struct IntermediateRewards {
previous: BTreeMap<Address, u64>,
current: BTreeMap<Address, u64>,
calculated: BTreeMap<Address, u64>,
}

impl IntermediateRewards {
pub fn load_from_state(state: &TopLevelState) -> StateResult<Self> {
let key = get_intermediate_rewards_key();
let action_data = state.action_data(&key)?;
let (previous, current) = decode_map_tuple(action_data.as_ref());
let (current, calculated) = decode_map_tuple(action_data.as_ref());

Ok(Self {
previous,
current,
calculated,
})
}

pub fn save_to_state(&self, state: &mut TopLevelState) -> StateResult<()> {
let key = get_intermediate_rewards_key();
if self.previous.is_empty() && self.current.is_empty() {
if self.current.is_empty() && self.calculated.is_empty() {
state.remove_action_data(&key);
} else {
let encoded = encode_map_tuple(&self.previous, &self.current);
let encoded = encode_map_tuple(&self.current, &self.calculated);
state.update_action_data(&key, encoded)?;
}
Ok(())
Expand All @@ -444,15 +485,20 @@ impl IntermediateRewards {
*self.current.entry(address).or_insert(0) += quantity;
}

pub fn drain_previous(&mut self) -> BTreeMap<Address, u64> {
pub fn update_calculated(&mut self, rewards: BTreeMap<Address, u64>) {
self.calculated = rewards;
}

pub fn drain_current(&mut self) -> BTreeMap<Address, u64> {
let mut new = BTreeMap::new();
mem::swap(&mut new, &mut self.previous);
mem::swap(&mut new, &mut self.current);
new
}

pub fn move_current_to_previous(&mut self) {
assert!(self.previous.is_empty());
mem::swap(&mut self.previous, &mut self.current);
pub fn drain_calculated(&mut self) -> BTreeMap<Address, u64> {
let mut new = BTreeMap::new();
mem::swap(&mut new, &mut self.calculated);
new
}
}

Expand Down Expand Up @@ -539,7 +585,7 @@ impl Candidates {

pub fn renew_candidates(
&mut self,
validators: &Validators,
validators: &NextValidators,
nomination_ends_at: u64,
inactive_validators: &[Address],
banned: &Banned,
Expand Down Expand Up @@ -1159,14 +1205,12 @@ mod tests {
origin_rewards.save_to_state(&mut state).unwrap();
let mut recovered_rewards = IntermediateRewards::load_from_state(&state).unwrap();
assert_eq!(origin_rewards, recovered_rewards);
let _drained = recovered_rewards.drain_previous();
recovered_rewards.drain_current();
recovered_rewards.save_to_state(&mut state).unwrap();
let mut final_rewards = IntermediateRewards::load_from_state(&state).unwrap();
assert_eq!(BTreeMap::new(), final_rewards.previous);
let current = final_rewards.current.clone();
final_rewards.move_current_to_previous();
assert_eq!(BTreeMap::new(), final_rewards.current);
assert_eq!(current, final_rewards.previous);
final_rewards.drain_calculated();
assert_eq!(BTreeMap::new(), final_rewards.calculated);
}

#[test]
Expand Down Expand Up @@ -1751,7 +1795,7 @@ mod tests {
}
candidates.save_to_state(&mut state).unwrap();

let dummy_validators = Validators(
let dummy_validators = NextValidators(
pubkeys[0..5]
.iter()
.map(|pubkey| Validator {
Expand Down
Loading