Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
20 commits
Select commit Hold shift + click to select a range
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
53 changes: 19 additions & 34 deletions core/src/block.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use crate::client::{EngineInfo, TermInfo};
use crate::consensus::CodeChainEngine;
use crate::error::{BlockError, Error};
use crate::transaction::{SignedTransaction, UnverifiedTransaction};
use crate::BlockId;

/// A block, encoded as it is on the block chain.
#[derive(Debug, Clone, PartialEq)]
Expand Down Expand Up @@ -220,25 +221,20 @@ impl<'x> OpenBlock<'x> {
pub fn close(
mut self,
parent_header: &Header,
parent_common_params: &CommonParams,
term_common_params: Option<&CommonParams>,
) -> Result<ClosedBlock, Error> {
let unclosed_state = self.block.state.clone();

if let Err(e) =
self.engine.on_close_block(&mut self.block, parent_header, parent_common_params, term_common_params)
{
if let Err(e) = self.engine.on_close_block(&mut self.block, term_common_params) {
warn!("Encountered error on closing the block: {}", e);
return Err(e)
}
let header = self.block.header().clone();
for handler in self.engine.action_handlers() {
handler.on_close_block(self.block.state_mut(), &header, parent_header, parent_common_params).map_err(
|e| {
warn!("Encountered error in {}::on_close_block", handler.name());
e
},
)?;
handler.on_close_block(self.block.state_mut(), &header).map_err(|e| {
warn!("Encountered error in {}::on_close_block", handler.name());
e
})?;
}

let state_root = self.block.state.commit().map_err(|e| {
Expand All @@ -262,23 +258,18 @@ impl<'x> OpenBlock<'x> {
pub fn close_and_lock(
mut self,
parent_header: &Header,
parent_common_params: &CommonParams,
term_common_params: Option<&CommonParams>,
) -> Result<LockedBlock, Error> {
if let Err(e) =
self.engine.on_close_block(&mut self.block, parent_header, parent_common_params, term_common_params)
{
if let Err(e) = self.engine.on_close_block(&mut self.block, term_common_params) {
warn!("Encountered error on closing the block: {}", e);
return Err(e)
}
let header = self.block.header().clone();
for handler in self.engine.action_handlers() {
handler.on_close_block(self.block.state_mut(), &header, parent_header, parent_common_params).map_err(
|e| {
warn!("Encountered error in {}::on_close_block", handler.name());
e
},
)?;
handler.on_close_block(self.block.state_mut(), &header).map_err(|e| {
warn!("Encountered error in {}::on_close_block", handler.name());
e
})?;
}

let state_root = self.block.state.commit().map_err(|e| {
Expand Down Expand Up @@ -322,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 @@ -501,20 +496,11 @@ 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 parent_common_params = client.common_params((*header.parent_hash()).into()).unwrap();
let term_common_params = {
let block_number = client
.last_term_finished_block_num((*header.parent_hash()).into())
.expect("The block of the parent hash should exist");
if block_number == 0 {
None
} else {
Some(client.common_params((block_number).into()).expect("Common params should exist"))
}
};
b.close_and_lock(parent, &parent_common_params, term_common_params.as_ref())
let term_common_params = client.term_common_params(BlockId::Hash(*header.parent_hash()));
b.close_and_lock(parent, term_common_params.as_ref())
}

#[cfg(test)]
Expand All @@ -532,9 +518,8 @@ mod tests {
let genesis_header = scheme.genesis_header();
let db = scheme.ensure_genesis_state(get_temp_state_db()).unwrap();
let b = OpenBlock::try_new(&*scheme.engine, db, &genesis_header, Address::default(), vec![]).unwrap();
let parent_common_params = CommonParams::default_for_test();
let term_common_params = CommonParams::default_for_test();
let b = b.close_and_lock(&genesis_header, &parent_common_params, Some(&term_common_params)).unwrap();
let b = b.close_and_lock(&genesis_header, Some(&term_common_params)).unwrap();
let _ = b.seal(&*scheme.engine, vec![]);
}
}
17 changes: 17 additions & 0 deletions core/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -826,6 +826,23 @@ impl TermInfo for Client {
.map(|state| state.metadata().unwrap().expect("Metadata always exist"))
.map(|metadata| metadata.current_term_id())
}

fn term_common_params(&self, id: BlockId) -> Option<CommonParams> {
let state = self.state_at(id)?;
let metadata = state.metadata().unwrap().expect("Metadata always exist");

if let Some(term_params) = metadata.term_params() {
Some(*term_params)
} else {
let block_number =
self.last_term_finished_block_num(id).expect("The block of the parent hash should exist");
if block_number == 0 {
None
} else {
Some(self.common_params((block_number).into()).expect("Common params should exist"))
}
}
}
}

impl AccountData for Client {
Expand Down
1 change: 1 addition & 0 deletions core/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,7 @@ pub trait ConsensusClient: BlockChainClient + EngineClient + EngineInfo + TermIn
pub trait TermInfo {
fn last_term_finished_block_num(&self, id: BlockId) -> Option<BlockNumber>;
fn current_term_id(&self, id: BlockId) -> Option<u64>;
fn term_common_params(&self, id: BlockId) -> Option<CommonParams>;
}

/// Provides methods to access account info
Expand Down
6 changes: 5 additions & 1 deletion core/src/client/test_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -645,7 +645,7 @@ impl super::EngineClient for TestBlockChainClient {

impl EngineInfo for TestBlockChainClient {
fn common_params(&self, _block_id: BlockId) -> Option<CommonParams> {
unimplemented!()
Some(*self.scheme.engine.machine().genesis_common_params())
}

fn metadata_seq(&self, _block_id: BlockId) -> Option<u64> {
Expand Down Expand Up @@ -679,6 +679,10 @@ impl TermInfo for TestBlockChainClient {
fn current_term_id(&self, _id: BlockId) -> Option<u64> {
self.term_id
}

fn term_common_params(&self, _id: BlockId) -> Option<CommonParams> {
None
}
}

impl StateInfo for TestBlockChainClient {
Expand Down
2 changes: 0 additions & 2 deletions core/src/consensus/blake_pow/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -163,8 +163,6 @@ impl ConsensusEngine for BlakePoW {
fn on_close_block(
&self,
block: &mut ExecutedBlock,
_parent_header: &Header,
_parent_common_params: &CommonParams,
_term_common_params: Option<&CommonParams>,
) -> Result<(), Error> {
let author = *block.header().author();
Expand Down
12 changes: 1 addition & 11 deletions core/src/consensus/cuckoo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -173,8 +173,6 @@ impl ConsensusEngine for Cuckoo {
fn on_close_block(
&self,
block: &mut ExecutedBlock,
_parent_header: &Header,
_parent_common_params: &CommonParams,
_term_common_params: Option<&CommonParams>,
) -> Result<(), Error> {
let author = *block.header().author();
Expand Down Expand Up @@ -261,21 +259,13 @@ mod tests {
#[test]
fn on_close_block() {
let scheme = Scheme::new_test_cuckoo();
let genesis_header = scheme.genesis_header();
let engine = &*scheme.engine;
let db = scheme.ensure_genesis_state(get_temp_state_db()).unwrap();
let header = Header::default();
let block = OpenBlock::try_new(engine, db, &header, Default::default(), vec![]).unwrap();
let mut executed_block = block.block().clone();

assert!(engine
.on_close_block(
&mut executed_block,
&genesis_header,
&CommonParams::default_for_test(),
Some(&CommonParams::default_for_test())
)
.is_ok());
assert!(engine.on_close_block(&mut executed_block, Some(&CommonParams::default_for_test())).is_ok());
assert_eq!(0xd, engine.machine().balance(&executed_block, header.author()).unwrap());
}

Expand Down
7 changes: 5 additions & 2 deletions core/src/consensus/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -221,12 +221,15 @@ 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,
_block: &mut ExecutedBlock,
_parent_header: &Header,
_parent_common_params: &CommonParams,
_term_common_params: Option<&CommonParams>,
) -> Result<(), Error> {
Ok(())
Expand Down
4 changes: 1 addition & 3 deletions core/src/consensus/null_engine/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
mod params;

use ckey::Address;
use ctypes::{CommonParams, Header};
use ctypes::CommonParams;

use self::params::NullEngineParams;
use super::ConsensusEngine;
Expand Down Expand Up @@ -58,8 +58,6 @@ impl ConsensusEngine for NullEngine {
fn on_close_block(
&self,
block: &mut ExecutedBlock,
_parent_header: &Header,
_parent_common_params: &CommonParams,
_term_common_params: Option<&CommonParams>,
) -> Result<(), Error> {
let (author, total_reward) = {
Expand Down
5 changes: 1 addition & 4 deletions core/src/consensus/simple_poa/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,6 @@ impl ConsensusEngine for SimplePoA {
fn on_close_block(
&self,
block: &mut ExecutedBlock,
_parent_header: &Header,
_parent_common_params: &CommonParams,
_term_common_params: Option<&CommonParams>,
) -> Result<(), Error> {
let author = *block.header().author();
Expand Down Expand Up @@ -186,9 +184,8 @@ mod tests {
let db = scheme.ensure_genesis_state(get_temp_state_db()).unwrap();
let genesis_header = scheme.genesis_header();
let b = OpenBlock::try_new(engine, db, &genesis_header, Default::default(), vec![]).unwrap();
let parent_common_params = CommonParams::default_for_test();
let term_common_params = CommonParams::default_for_test();
let b = b.close_and_lock(&genesis_header, &parent_common_params, Some(&term_common_params)).unwrap();
let b = b.close_and_lock(&genesis_header, Some(&term_common_params)).unwrap();
if let Some(seal) = engine.generate_seal(Some(b.block()), &genesis_header).seal_fields() {
assert!(b.try_seal(engine, seal).is_ok());
}
Expand Down
47 changes: 33 additions & 14 deletions core/src/consensus/solo/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,22 +16,25 @@

mod params;

use std::sync::Arc;
use std::sync::{Arc, Weak};

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

use self::params::SoloParams;
use super::stake;
use super::{ConsensusEngine, Seal};
use crate::block::{ExecutedBlock, IsBlock};
use crate::client::ConsensusClient;
use crate::codechain_machine::CodeChainMachine;
use crate::consensus::{EngineError, EngineType};
use crate::error::Error;

/// A consensus engine which does not provide any consensus mechanism.
pub struct Solo {
client: RwLock<Option<Weak<dyn ConsensusClient>>>,
params: SoloParams,
machine: CodeChainMachine,
action_handlers: Vec<Arc<dyn ActionHandler>>,
Expand All @@ -47,11 +50,16 @@ impl Solo {
action_handlers.push(Arc::new(stake::Stake::new(params.genesis_stakes.clone())));

Solo {
client: Default::default(),
params,
machine,
action_handlers,
}
}

fn client(&self) -> Option<Arc<dyn ConsensusClient>> {
self.client.read().as_ref()?.upgrade()
}
}

impl ConsensusEngine for Solo {
Expand All @@ -78,10 +86,13 @@ impl ConsensusEngine for Solo {
fn on_close_block(
&self,
block: &mut ExecutedBlock,
parent_header: &Header,
parent_common_params: &CommonParams,
_term_common_params: Option<&CommonParams>,
) -> Result<(), Error> {
let client = self.client().ok_or(EngineError::CannotOpenBlock)?;

let parent_hash = *block.header().parent_hash();
let parent = client.block_header(&parent_hash.into()).expect("Parent header must exist");
let parent_common_params = client.common_params(parent_hash.into()).expect("CommonParams of parent must exist");
let author = *block.header().author();
let (total_reward, total_min_fee) = {
let transactions = block.transactions();
Expand All @@ -107,18 +118,18 @@ impl ConsensusEngine for Solo {
self.machine.add_balance(block, &author, block_author_reward)?;
return Ok(())
}
stake::add_intermediate_rewards(block.state_mut(), author, block_author_reward)?;
stake::v0::add_intermediate_rewards(block.state_mut(), author, block_author_reward)?;
let last_term_finished_block_num = {
let header = block.header();
let current_term_period = header.timestamp() / term_seconds;
let parent_term_period = parent_header.timestamp() / term_seconds;
let parent_term_period = parent.timestamp() / term_seconds;
if current_term_period == parent_term_period {
return Ok(())
}
header.number()
};
stake::move_current_to_previous_intermediate_rewards(&mut block.state_mut())?;
let rewards = stake::drain_previous_rewards(&mut block.state_mut())?;
stake::v0::move_current_to_previous_intermediate_rewards(&mut block.state_mut())?;
let rewards = stake::v0::drain_previous_rewards(&mut block.state_mut())?;
for (address, reward) in rewards {
self.machine.add_balance(block, &address, reward)?;
}
Expand All @@ -127,6 +138,10 @@ impl ConsensusEngine for Solo {
Ok(())
}

fn register_client(&self, client: Weak<dyn ConsensusClient>) {
*self.client.write() = Some(Weak::clone(&client));
}

fn block_reward(&self, _block_number: u64) -> u64 {
self.params.block_reward
}
Expand All @@ -146,25 +161,29 @@ impl ConsensusEngine for Solo {

#[cfg(test)]
mod tests {
use std::sync::Arc;

use ctypes::{CommonParams, Header};
use primitives::H520;

use crate::block::{IsBlock, OpenBlock};
use crate::client::{ConsensusClient, TestBlockChainClient};
use crate::scheme::Scheme;
use crate::tests::helpers::get_temp_state_db;

#[test]
fn seal() {
let scheme = Scheme::new_test_solo();
let engine = &*scheme.engine;
let db = scheme.ensure_genesis_state(get_temp_state_db()).unwrap();
let genesis_header = scheme.genesis_header();
let b = OpenBlock::try_new(engine, db, &genesis_header, Default::default(), vec![]).unwrap();
let parent_common_params = CommonParams::default_for_test();
let client = Arc::new(TestBlockChainClient::new_with_scheme(scheme));
let engine = client.scheme.engine.clone();
engine.register_client(Arc::downgrade(&(client.clone() as Arc<dyn ConsensusClient>)));
let db = client.scheme.ensure_genesis_state(get_temp_state_db()).unwrap();
let genesis_header = client.scheme.genesis_header();
let b = OpenBlock::try_new(&*engine, db, &genesis_header, Default::default(), vec![]).unwrap();
let term_common_params = CommonParams::default_for_test();
let b = b.close_and_lock(&genesis_header, &parent_common_params, Some(&term_common_params)).unwrap();
let b = b.close_and_lock(&genesis_header, Some(&term_common_params)).unwrap();
if let Some(seal) = engine.generate_seal(Some(b.block()), &genesis_header).seal_fields() {
assert!(b.try_seal(engine, seal).is_ok());
assert!(b.try_seal(&*engine, seal).is_ok());
}
}

Expand Down
Loading