Skip to content

Commit 4ad4a41

Browse files
committed
Precalculate the fee in era=1
1 parent b374d7e commit 4ad4a41

File tree

3 files changed

+212
-30
lines changed

3 files changed

+212
-30
lines changed

core/src/consensus/stake/action_data.rs

Lines changed: 103 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -409,12 +409,12 @@ impl IntoIterator for Validators {
409409
}
410410

411411
#[derive(Default, Debug, PartialEq)]
412-
pub struct IntermediateRewards {
412+
pub struct IntermediateRewardsV0 {
413413
previous: BTreeMap<Address, u64>,
414414
current: BTreeMap<Address, u64>,
415415
}
416416

417-
impl IntermediateRewards {
417+
impl IntermediateRewardsV0 {
418418
pub fn load_from_state(state: &TopLevelState) -> StateResult<Self> {
419419
let key = get_intermediate_rewards_key();
420420
let action_data = state.action_data(&key)?;
@@ -456,6 +456,59 @@ impl IntermediateRewards {
456456
}
457457
}
458458

459+
#[derive(Default, Debug, PartialEq)]
460+
pub struct IntermediateRewardsV1 {
461+
current: BTreeMap<Address, u64>,
462+
calculated: BTreeMap<Address, u64>,
463+
}
464+
465+
impl IntermediateRewardsV1 {
466+
pub fn load_from_state(state: &TopLevelState) -> StateResult<Self> {
467+
let key = get_intermediate_rewards_key();
468+
let action_data = state.action_data(&key)?;
469+
let (current, calculated) = decode_map_tuple(action_data.as_ref());
470+
471+
Ok(Self {
472+
current,
473+
calculated,
474+
})
475+
}
476+
477+
pub fn save_to_state(&self, state: &mut TopLevelState) -> StateResult<()> {
478+
let key = get_intermediate_rewards_key();
479+
if self.current.is_empty() && self.calculated.is_empty() {
480+
state.remove_action_data(&key);
481+
} else {
482+
let encoded = encode_map_tuple(&self.current, &self.calculated);
483+
state.update_action_data(&key, encoded)?;
484+
}
485+
Ok(())
486+
}
487+
488+
pub fn add_quantity(&mut self, address: Address, quantity: StakeQuantity) {
489+
if quantity == 0 {
490+
return
491+
}
492+
*self.current.entry(address).or_insert(0) += quantity;
493+
}
494+
495+
pub fn update_calculated(&mut self, rewards: BTreeMap<Address, u64>) {
496+
self.calculated = rewards;
497+
}
498+
499+
pub fn drain_current(&mut self) -> BTreeMap<Address, u64> {
500+
let mut new = BTreeMap::new();
501+
mem::swap(&mut new, &mut self.current);
502+
new
503+
}
504+
505+
pub fn drain_calculated(&mut self) -> BTreeMap<Address, u64> {
506+
let mut new = BTreeMap::new();
507+
mem::swap(&mut new, &mut self.calculated);
508+
new
509+
}
510+
}
511+
459512
pub struct Candidates(Vec<Candidate>);
460513
#[derive(Clone, Debug, Eq, PartialEq, RlpEncodable, RlpDecodable)]
461514
pub struct Candidate {
@@ -1129,46 +1182,85 @@ mod tests {
11291182
}
11301183

11311184
#[test]
1132-
fn load_and_save_intermediate_rewards() {
1185+
fn load_and_save_intermediate_rewards_v0() {
11331186
let mut state = helpers::get_temp_state();
1134-
let rewards = IntermediateRewards::load_from_state(&state).unwrap();
1187+
let rewards = IntermediateRewardsV0::load_from_state(&state).unwrap();
11351188
rewards.save_to_state(&mut state).unwrap();
11361189
}
11371190

11381191
#[test]
1139-
fn add_quantity() {
1192+
fn add_quantity_v0() {
11401193
let address1 = Address::random();
11411194
let address2 = Address::random();
11421195
let mut state = helpers::get_temp_state();
1143-
let mut origin_rewards = IntermediateRewards::load_from_state(&state).unwrap();
1196+
let mut origin_rewards = IntermediateRewardsV0::load_from_state(&state).unwrap();
11441197
origin_rewards.add_quantity(address1, 1);
11451198
origin_rewards.add_quantity(address2, 2);
11461199
origin_rewards.save_to_state(&mut state).unwrap();
1147-
let recovered_rewards = IntermediateRewards::load_from_state(&state).unwrap();
1200+
let recovered_rewards = IntermediateRewardsV0::load_from_state(&state).unwrap();
11481201
assert_eq!(origin_rewards, recovered_rewards);
11491202
}
11501203

11511204
#[test]
1152-
fn drain() {
1205+
fn drain_v0() {
11531206
let address1 = Address::random();
11541207
let address2 = Address::random();
11551208
let mut state = helpers::get_temp_state();
1156-
let mut origin_rewards = IntermediateRewards::load_from_state(&state).unwrap();
1209+
let mut origin_rewards = IntermediateRewardsV0::load_from_state(&state).unwrap();
11571210
origin_rewards.add_quantity(address1, 1);
11581211
origin_rewards.add_quantity(address2, 2);
11591212
origin_rewards.save_to_state(&mut state).unwrap();
1160-
let mut recovered_rewards = IntermediateRewards::load_from_state(&state).unwrap();
1213+
let mut recovered_rewards = IntermediateRewardsV0::load_from_state(&state).unwrap();
11611214
assert_eq!(origin_rewards, recovered_rewards);
11621215
let _drained = recovered_rewards.drain_previous();
11631216
recovered_rewards.save_to_state(&mut state).unwrap();
1164-
let mut final_rewards = IntermediateRewards::load_from_state(&state).unwrap();
1217+
let mut final_rewards = IntermediateRewardsV0::load_from_state(&state).unwrap();
11651218
assert_eq!(BTreeMap::new(), final_rewards.previous);
11661219
let current = final_rewards.current.clone();
11671220
final_rewards.move_current_to_previous();
11681221
assert_eq!(BTreeMap::new(), final_rewards.current);
11691222
assert_eq!(current, final_rewards.previous);
11701223
}
11711224

1225+
#[test]
1226+
fn load_and_save_intermediate_rewards_v1() {
1227+
let mut state = helpers::get_temp_state();
1228+
let rewards = IntermediateRewardsV1::load_from_state(&state).unwrap();
1229+
rewards.save_to_state(&mut state).unwrap();
1230+
}
1231+
1232+
#[test]
1233+
fn add_quantity_v1() {
1234+
let address1 = Address::random();
1235+
let address2 = Address::random();
1236+
let mut state = helpers::get_temp_state();
1237+
let mut origin_rewards = IntermediateRewardsV1::load_from_state(&state).unwrap();
1238+
origin_rewards.add_quantity(address1, 1);
1239+
origin_rewards.add_quantity(address2, 2);
1240+
origin_rewards.save_to_state(&mut state).unwrap();
1241+
let recovered_rewards = IntermediateRewardsV1::load_from_state(&state).unwrap();
1242+
assert_eq!(origin_rewards, recovered_rewards);
1243+
}
1244+
1245+
#[test]
1246+
fn drain_v1() {
1247+
let address1 = Address::random();
1248+
let address2 = Address::random();
1249+
let mut state = helpers::get_temp_state();
1250+
let mut origin_rewards = IntermediateRewardsV1::load_from_state(&state).unwrap();
1251+
origin_rewards.add_quantity(address1, 1);
1252+
origin_rewards.add_quantity(address2, 2);
1253+
origin_rewards.save_to_state(&mut state).unwrap();
1254+
let mut recovered_rewards = IntermediateRewardsV1::load_from_state(&state).unwrap();
1255+
assert_eq!(origin_rewards, recovered_rewards);
1256+
recovered_rewards.drain_current();
1257+
recovered_rewards.save_to_state(&mut state).unwrap();
1258+
let mut final_rewards = IntermediateRewardsV1::load_from_state(&state).unwrap();
1259+
assert_eq!(BTreeMap::new(), final_rewards.current);
1260+
final_rewards.drain_calculated();
1261+
assert_eq!(BTreeMap::new(), final_rewards.calculated);
1262+
}
1263+
11721264
#[test]
11731265
fn candidates_deposit_add() {
11741266
let mut state = helpers::get_temp_state();

core/src/consensus/stake/mod.rs

Lines changed: 41 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,10 @@ use primitives::{Bytes, H256};
3434
use rlp::{Decodable, Rlp};
3535

3636
pub use self::action_data::{Banned, Validator, Validators};
37-
use self::action_data::{Candidates, Delegation, IntermediateRewards, Jail, ReleaseResult, StakeAccount, Stakeholders};
37+
use self::action_data::{
38+
Candidates, Delegation, IntermediateRewardsV0, IntermediateRewardsV1, Jail, ReleaseResult, StakeAccount,
39+
Stakeholders,
40+
};
3841
pub use self::actions::Action;
3942
pub use self::distribute::fee_distribute;
4043
use super::ValidatorSet;
@@ -328,25 +331,57 @@ pub fn get_validators(state: &TopLevelState) -> StateResult<Validators> {
328331
}
329332

330333
pub fn add_intermediate_rewards(state: &mut TopLevelState, address: Address, reward: u64) -> StateResult<()> {
331-
let mut rewards = IntermediateRewards::load_from_state(state)?;
332-
rewards.add_quantity(address, reward);
333-
rewards.save_to_state(state)?;
334+
let metadata = state.metadata()?.expect("The metadata must exist");
335+
let era = metadata.term_params().map_or(0, |p| p.era());
336+
match era {
337+
0 => {
338+
let mut rewards = IntermediateRewardsV0::load_from_state(state)?;
339+
rewards.add_quantity(address, reward);
340+
rewards.save_to_state(state)?;
341+
}
342+
1 => {
343+
let mut rewards = IntermediateRewardsV1::load_from_state(state)?;
344+
rewards.add_quantity(address, reward);
345+
rewards.save_to_state(state)?;
346+
}
347+
_ => unimplemented!(),
348+
}
334349
Ok(())
335350
}
336351

337352
pub fn drain_previous_rewards(state: &mut TopLevelState) -> StateResult<BTreeMap<Address, u64>> {
338-
let mut rewards = IntermediateRewards::load_from_state(state)?;
353+
let mut rewards = IntermediateRewardsV0::load_from_state(state)?;
339354
let drained = rewards.drain_previous();
340355
rewards.save_to_state(state)?;
341356
Ok(drained)
342357
}
343358

344359
pub fn move_current_to_previous_intermediate_rewards(state: &mut TopLevelState) -> StateResult<()> {
345-
let mut rewards = IntermediateRewards::load_from_state(state)?;
360+
let mut rewards = IntermediateRewardsV0::load_from_state(state)?;
346361
rewards.move_current_to_previous();
347362
rewards.save_to_state(state)
348363
}
349364

365+
pub fn drain_current_rewards(state: &mut TopLevelState) -> StateResult<BTreeMap<Address, u64>> {
366+
let mut rewards = IntermediateRewardsV1::load_from_state(state)?;
367+
let drained = rewards.drain_current();
368+
rewards.save_to_state(state)?;
369+
Ok(drained)
370+
}
371+
372+
pub fn update_calculated_rewards(state: &mut TopLevelState, values: HashMap<Address, u64>) -> StateResult<()> {
373+
let mut rewards = IntermediateRewardsV1::load_from_state(state)?;
374+
rewards.update_calculated(values.into_iter().collect());
375+
rewards.save_to_state(state)
376+
}
377+
378+
pub fn drain_calculated_rewards(state: &mut TopLevelState) -> StateResult<BTreeMap<Address, u64>> {
379+
let mut rewards = IntermediateRewardsV1::load_from_state(state)?;
380+
let drained = rewards.drain_calculated();
381+
rewards.save_to_state(state)?;
382+
Ok(drained)
383+
}
384+
350385
pub fn update_validator_weights(state: &mut TopLevelState, block_author: &Address) -> StateResult<()> {
351386
let mut validators = Validators::load_from_state(state)?;
352387
validators.update_weight(block_author);

core/src/consensus/tendermint/engine.rs

Lines changed: 68 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -136,9 +136,49 @@ impl ConsensusEngine for Tendermint {
136136

137137
/// Block transformation functions, before the transactions.
138138
fn on_open_block(&self, block: &mut ExecutedBlock) -> Result<(), Error> {
139+
let client = self
140+
.client
141+
.read()
142+
.as_ref()
143+
.ok_or(EngineError::CannotOpenBlock)?
144+
.upgrade()
145+
.ok_or(EngineError::CannotOpenBlock)?;
146+
147+
let block_number = block.header().number();
148+
let era = client.term_common_params(block_number.into()).map_or(0, |p| p.era());
139149
let metadata = block.state().metadata()?.expect("Metadata must exist");
140-
if block.header().number() == metadata.last_term_finished_block_num() + 1 {
141-
// FIXME: on_term_open
150+
if block_number == metadata.last_term_finished_block_num() + 1 {
151+
match era {
152+
0 => {}
153+
1 => {
154+
let rewards = stake::drain_current_rewards(block.state_mut())?;
155+
let start_of_the_current_term = block_number;
156+
let start_of_the_previous_term = {
157+
let end_of_the_two_level_previous_term = client
158+
.last_term_finished_block_num((metadata.last_term_finished_block_num() - 1).into())
159+
.unwrap();
160+
161+
end_of_the_two_level_previous_term + 1
162+
};
163+
164+
let banned = stake::Banned::load_from_state(block.state())?;
165+
let start_of_the_current_term_header =
166+
encoded::Header::new(block.header().clone().rlp_bytes().to_vec());
167+
168+
let pending_rewards = calculate_pending_rewards_of_the_previous_term(
169+
&*client,
170+
&*self.validators,
171+
rewards,
172+
start_of_the_current_term,
173+
start_of_the_current_term_header,
174+
start_of_the_previous_term,
175+
&banned,
176+
)?;
177+
178+
stake::update_calculated_rewards(block.state_mut(), pending_rewards)?;
179+
}
180+
_ => unimplemented!(),
181+
}
142182
}
143183
Ok(())
144184
}
@@ -150,6 +190,14 @@ impl ConsensusEngine for Tendermint {
150190
parent_common_params: &CommonParams,
151191
term_common_params: Option<&CommonParams>,
152192
) -> Result<(), Error> {
193+
let client = self
194+
.client
195+
.read()
196+
.as_ref()
197+
.ok_or(EngineError::CannotOpenBlock)?
198+
.upgrade()
199+
.ok_or(EngineError::CannotOpenBlock)?;
200+
153201
let block_number = block.header().number();
154202
let author = *block.header().author();
155203
let (total_reward, total_min_fee) = {
@@ -170,6 +218,7 @@ impl ConsensusEngine for Tendermint {
170218

171219
let block_author_reward = total_reward - total_min_fee + distributor.remaining_fee();
172220

221+
let era = client.term_common_params(block_number.into()).map_or(0, |p| p.era());
173222
let metadata = block.state().metadata()?.expect("Metadata must exist");
174223
let term = metadata.current_term_id();
175224
let term_seconds = match term {
@@ -191,18 +240,11 @@ impl ConsensusEngine for Tendermint {
191240
return Ok(())
192241
}
193242

194-
let inactive_validators = match term {
195-
0 => Vec::new(),
196-
_ => {
243+
let inactive_validators = match (era, term) {
244+
(0, 0) => Vec::new(),
245+
(0, _) => {
197246
let rewards = stake::drain_previous_rewards(block.state_mut())?;
198247
let start_of_the_current_term = metadata.last_term_finished_block_num() + 1;
199-
let client = self
200-
.client
201-
.read()
202-
.as_ref()
203-
.ok_or(EngineError::CannotOpenBlock)?
204-
.upgrade()
205-
.ok_or(EngineError::CannotOpenBlock)?;
206248

207249
if term > 1 {
208250
let start_of_the_previous_term = {
@@ -243,13 +285,26 @@ impl ConsensusEngine for Tendermint {
243285
.collect();
244286
inactive_validators(&*client, start_of_the_current_term, block.header(), validators)
245287
}
288+
(1, _) => {
289+
for (address, reward) in stake::drain_calculated_rewards(block.state_mut())? {
290+
self.machine.add_balance(block, &address, reward)?;
291+
}
292+
293+
let start_of_the_current_term = metadata.last_term_finished_block_num() + 1;
294+
let validators = stake::Validators::load_from_state(block.state())?
295+
.into_iter()
296+
.map(|val| public_to_address(val.pubkey()))
297+
.collect();
298+
inactive_validators(&*client, start_of_the_current_term, block.header(), validators)
299+
}
300+
_ => unimplemented!(),
246301
};
247302

248303
stake::on_term_close(block.state_mut(), block_number, &inactive_validators)?;
249304

250305
match term {
251306
0 => {}
252-
_ => match term_common_params.expect("Term common params should exist").era() {
307+
_ => match era {
253308
0 => {}
254309
1 => block.state_mut().snapshot_term_params()?,
255310
_ => unimplemented!("It is not decided how we handle this"),

0 commit comments

Comments
 (0)