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
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 6 additions & 0 deletions codechain/codechain.yml
Original file line number Diff line number Diff line change
Expand Up @@ -192,6 +192,12 @@ args:
takes_value: true
conflicts_with:
- no-miner
- no-reseal-timer:
long: no-reseal-timer
help: Do not use reseal timer.
takes_value: false
conflicts_with:
- no-miner
- work-queue-size:
long: work-queue-size
value_name: ITEMS
Expand Down
8 changes: 8 additions & 0 deletions codechain/config/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,7 @@ impl Config {
reseal_on_external_parcel,
reseal_min_period: Duration::from_millis(self.mining.reseal_min_period.unwrap()),
reseal_max_period: Duration::from_millis(self.mining.reseal_max_period.unwrap()),
no_reseal_timer: self.mining.no_reseal_timer.unwrap(),
work_queue_size: self.mining.work_queue_size.unwrap(),
})
}
Expand Down Expand Up @@ -218,6 +219,7 @@ pub struct Mining {
pub reseal_on_txs: Option<String>,
pub reseal_min_period: Option<u64>,
pub reseal_max_period: Option<u64>,
pub no_reseal_timer: Option<bool>,
pub work_queue_size: Option<usize>,
}

Expand Down Expand Up @@ -375,6 +377,9 @@ impl Mining {
if other.reseal_max_period.is_some() {
self.reseal_max_period = other.reseal_max_period;
}
if other.no_reseal_timer.is_some() {
self.no_reseal_timer = other.no_reseal_timer;
}
if other.work_queue_size.is_some() {
self.work_queue_size = other.work_queue_size;
}
Expand Down Expand Up @@ -412,6 +417,9 @@ impl Mining {
if let Some(reseal_max_period) = matches.value_of("reseal-max-period") {
self.reseal_max_period = Some(reseal_max_period.parse().map_err(|_| "Invalid period")?);
}
if matches.is_present("no-reseal-timer") {
self.no_reseal_timer = Some(true);
}
if let Some(work_queue_size) = matches.value_of("work-queue-size") {
self.work_queue_size = Some(work_queue_size.parse().map_err(|_| "Invalid size")?);
}
Expand Down
1 change: 1 addition & 0 deletions codechain/config/presets/config.dev.toml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ force_sealing = false
reseal_on_txs = "all"
reseal_min_period = 0
reseal_max_period = 120000
no_reseal_timer = false
work_queue_size = 20

[network]
Expand Down
1 change: 1 addition & 0 deletions codechain/config/presets/config.prod.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ force_sealing = true
reseal_on_txs = "all"
reseal_min_period = 4000
reseal_max_period = 120000
no_reseal_timer = false
work_queue_size = 20

[network]
Expand Down
12 changes: 10 additions & 2 deletions codechain/run_node.rs
Original file line number Diff line number Diff line change
Expand Up @@ -86,14 +86,22 @@ fn discovery_start(service: &NetworkService, cfg: &config::Network) -> Result<()
Ok(())
}

fn client_start(cfg: &config::Operating, scheme: &Scheme, miner: Arc<Miner>) -> Result<ClientService, String> {
fn client_start(
timer_loop: &TimerLoop,
cfg: &config::Operating,
scheme: &Scheme,
miner: Arc<Miner>,
) -> Result<ClientService, String> {
cinfo!(CLIENT, "Starting client");
let db_path = cfg.db_path.as_ref().map(|s| s.as_str()).unwrap();
let client_path = Path::new(db_path);
let client_config = Default::default();
let service = ClientService::start(&client_config, &scheme, &client_path, miner)
.map_err(|e| format!("Client service error: {}", e))?;

let reseal_timer = timer_loop.new_timer("Client reseal timer", service.client());
service.client().register_reseal_timer(reseal_timer);

Ok(service)
}

Expand Down Expand Up @@ -229,7 +237,7 @@ pub fn run_node(matches: &ArgMatches) -> Result<(), String> {
unlock_accounts(&*ap, &pf)?;

let miner = new_miner(&config, &scheme, ap.clone())?;
let client = client_start(&config.operating, &scheme, miner.clone())?;
let client = client_start(&timer_loop, &config.operating, &scheme, miner.clone())?;
let sync = BlockSyncExtension::new(client.client());

scheme.engine.register_chain_notify(client.client().as_ref());
Expand Down
1 change: 1 addition & 0 deletions core/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ codechain-logger = { path = "../util/logger" }
codechain-merkle = { path = "../util/merkle" }
codechain-network = { path = "../network" }
codechain-state = { path = "../state" }
codechain-timer = { path = "../util/timer" }
codechain-types = { path = "../types" }
codechain-stratum = { path = "../stratum" }
codechain-vm = { path = "../vm" }
Expand Down
63 changes: 60 additions & 3 deletions core/src/client/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@ use cnetwork::NodeId;
use cstate::{
ActionHandler, AssetScheme, AssetSchemeAddress, OwnedAsset, OwnedAssetAddress, StateDB, TopLevelState, TopStateView,
};
use ctimer::{TimeoutHandler, TimerApi, TimerToken};
use ctypes::invoice::Invoice;
use ctypes::transaction::Transaction;
use ctypes::{BlockNumber, ShardId};
Expand All @@ -41,7 +42,8 @@ use super::{
AccountData, AssetClient, Balance, BlockChain as BlockChainTrait, BlockChainClient, BlockChainInfo, BlockInfo,
BlockProducer, ChainInfo, ChainNotify, ClientConfig, DatabaseClient, EngineClient, EngineInfo,
Error as ClientError, ExecuteClient, ImportBlock, ImportResult, ImportSealedBlock, MiningBlockChainClient,
ParcelInfo, PrepareOpenBlock, RegularKey, RegularKeyOwner, ReopenBlock, Seq, Shard, StateOrBlock, TransactionInfo,
ParcelInfo, PrepareOpenBlock, RegularKey, RegularKeyOwner, ReopenBlock, ResealTimer, Seq, Shard, StateOrBlock,
TransactionInfo,
};
use crate::block::{ClosedBlock, IsBlock, OpenBlock, SealedBlock};
use crate::blockchain::{
Expand Down Expand Up @@ -79,6 +81,9 @@ pub struct Client {
genesis_accounts: Vec<Address>,

importer: Importer,

/// Timer for reseal_min_period/reseal_max_period on miner client
reseal_timer: RwLock<Option<TimerApi>>,
}

impl Client {
Expand Down Expand Up @@ -121,13 +126,18 @@ impl Client {
queue_parcels: AtomicUsize::new(0),
genesis_accounts,
importer,
reseal_timer: RwLock::new(None),
});

// ensure buffered changes are flushed.
client.db.flush().map_err(ClientError::Database)?;
Ok(client)
}

pub fn register_reseal_timer(&self, timer: TimerApi) {
self.register_timer(timer);
}

/// Returns engine reference.
pub fn engine(&self) -> &CodeChainEngine {
&*self.engine
Expand Down Expand Up @@ -260,6 +270,53 @@ impl Client {
}
}

const RESEAL_MAX_TIMER_TOKEN: TimerToken = 0;
const RESEAL_MIN_TIMER_TOKEN: TimerToken = 1;

impl TimeoutHandler for Client {
fn on_timeout(&self, token: TimerToken) {
match token {
RESEAL_MAX_TIMER_TOKEN => {
// Working in PoW only
if self.engine().seals_internally().is_none() && !self.importer.miner.prepare_work_sealing(self) {
self.update_sealing(true);
}
}
RESEAL_MIN_TIMER_TOKEN => {
// Checking self.ready_parcels() for efficiency
if !self.ready_parcels().is_empty() {
self.update_sealing(false);
}
}
_ => unreachable!(),
}
}
}

impl ResealTimer for Client {
fn register_timer(&self, timer: TimerApi) {
*self.reseal_timer.write() = Some(timer);
}

fn set_max_timer(&self) {
if let Some(reseal_timer) = self.reseal_timer.read().as_ref() {
reseal_timer.cancel(RESEAL_MAX_TIMER_TOKEN).expect("Reseal max timer clear succeeds");
reseal_timer
.schedule_once(self.importer.miner.get_options().reseal_max_period, RESEAL_MAX_TIMER_TOKEN)
.expect("Reseal max timer set succeeds");
};
}

fn set_min_timer(&self) {
if let Some(reseal_timer) = self.reseal_timer.read().as_ref() {
reseal_timer.cancel(RESEAL_MIN_TIMER_TOKEN).expect("Reseal min timer clear succeeds");
reseal_timer
.schedule_once(self.importer.miner.get_options().reseal_min_period, RESEAL_MIN_TIMER_TOKEN)
.expect("Reseal min timer set succeeds");
};
}
}

impl DatabaseClient for Client {
fn database(&self) -> Arc<KeyValueDB> {
Arc::clone(&self.db())
Expand Down Expand Up @@ -367,8 +424,8 @@ impl EngineInfo for Client {

impl EngineClient for Client {
/// Make a new block and seal it.
fn update_sealing(&self) {
self.importer.miner.update_sealing(self)
fn update_sealing(&self, allow_empty_block: bool) {
self.importer.miner.update_sealing(self, allow_empty_block)
}

/// Submit a seal for a block in the mining queue.
Expand Down
15 changes: 13 additions & 2 deletions core/src/client/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,7 @@ use ckey::{Address, PlatformAddress, Public};
use cmerkle::Result as TrieResult;
use cnetwork::NodeId;
use cstate::{ActionHandler, AssetScheme, AssetSchemeAddress, OwnedAsset, TopStateView};
use ctimer::TimerApi;
use ctypes::invoice::Invoice;
use ctypes::transaction::Transaction;
use ctypes::{BlockNumber, ShardId};
Expand Down Expand Up @@ -101,7 +102,7 @@ pub trait EngineInfo: Send + Sync {
/// Client facilities used by internally sealing Engines.
pub trait EngineClient: Sync + Send + ChainInfo + ImportBlock + BlockInfo {
/// Make a new block and seal it.
fn update_sealing(&self);
fn update_sealing(&self, allow_empty_block: bool);

/// Submit a seal for a block in the mining queue.
fn submit_seal(&self, block_hash: H256, seal: Vec<Bytes>);
Expand Down Expand Up @@ -183,6 +184,16 @@ pub trait Shard {
fn shard_root(&self, shard_id: ShardId, state: StateOrBlock) -> Option<H256>;
}

/// Provides a timer API for reseal_min_period/reseal_max_period on miner client
pub trait ResealTimer {
/// Register timer API
fn register_timer(&self, timer: TimerApi);
/// Set reseal min timer as reseal_min_period, for creating blocks with parcels which are pending because of reseal_min_period
fn set_min_timer(&self);
/// Set reseal max timer as reseal_max_period, for creating empty blocks every reseal_max_period
fn set_max_timer(&self);
}

/// Provides methods to access account info
pub trait AccountData: Seq + Balance {}

Expand All @@ -200,7 +211,7 @@ pub trait BlockChain: ChainInfo + BlockInfo + ParcelInfo + TransactionInfo {}

/// Blockchain database client. Owns and manages a blockchain and a block queue.
pub trait BlockChainClient:
Sync + Send + AccountData + BlockChain + ImportBlock + RegularKeyOwner + ChainTimeInfo {
Sync + Send + AccountData + BlockChain + ImportBlock + RegularKeyOwner + ChainTimeInfo + ResealTimer {
/// Get block queue information.
fn queue_info(&self) -> BlockQueueInfo;

Expand Down
21 changes: 17 additions & 4 deletions core/src/client/test_client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ use ckey::{public_to_address, Address, Generator, NetworkId, PlatformAddress, Ra
use cmerkle::skewed_merkle_root;
use cnetwork::NodeId;
use cstate::{ActionHandler, StateDB};
use ctimer::{TimeoutHandler, TimerApi, TimerToken};
use ctypes::invoice::Invoice;
use ctypes::parcel::{Action, Parcel};
use ctypes::transaction::Transaction;
Expand All @@ -55,8 +56,8 @@ use crate::blockchain_info::BlockChainInfo;
use crate::client::ImportResult;
use crate::client::{
AccountData, Balance, BlockChain, BlockChainClient, BlockInfo, BlockProducer, BlockStatus, ChainInfo, ImportBlock,
ImportSealedBlock, MiningBlockChainClient, ParcelInfo, PrepareOpenBlock, RegularKeyOwner, ReopenBlock, Seq,
StateOrBlock, TransactionInfo,
ImportSealedBlock, MiningBlockChainClient, ParcelInfo, PrepareOpenBlock, RegularKeyOwner, ReopenBlock, ResealTimer,
Seq, StateOrBlock, TransactionInfo,
};
use crate::db::{COL_STATE, NUM_COLUMNS};
use crate::encoded;
Expand Down Expand Up @@ -529,6 +530,18 @@ impl BlockChainClient for TestBlockChainClient {
}
}

impl TimeoutHandler for TestBlockChainClient {
fn on_timeout(&self, _token: TimerToken) {}
}

impl ResealTimer for TestBlockChainClient {
fn register_timer(&self, _timer: TimerApi) {}

fn set_max_timer(&self) {}

fn set_min_timer(&self) {}
}

impl ChainTimeInfo for TestBlockChainClient {
fn best_block_number(&self) -> u64 {
0
Expand All @@ -548,8 +561,8 @@ impl ChainTimeInfo for TestBlockChainClient {
}

impl super::EngineClient for TestBlockChainClient {
fn update_sealing(&self) {
self.miner.update_sealing(self)
fn update_sealing(&self, allow_empty_block: bool) {
self.miner.update_sealing(self, allow_empty_block)
}

fn submit_seal(&self, block_hash: H256, seal: Vec<Bytes>) {
Expand Down
5 changes: 3 additions & 2 deletions core/src/consensus/tendermint/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ use std::sync::{Arc, Weak};

use ccrypto::blake256;
use ckey::{public_to_address, recover, Address, Message, Password, Signature};
use cnetwork::{Api, NetworkExtension, NetworkService, NodeId, TimeoutHandler, TimerToken};
use cnetwork::{Api, NetworkExtension, NetworkService, NodeId};
use ctimer::{TimeoutHandler, TimerToken};
use ctypes::machine::WithBalances;
use ctypes::util::unexpected::{Mismatch, OutOfBounds};
use ctypes::BlockNumber;
Expand Down Expand Up @@ -257,7 +258,7 @@ impl Tendermint {
fn update_sealing(&self) {
if let Some(ref weak) = *self.client.read() {
if let Some(c) = weak.upgrade() {
c.update_sealing();
c.update_sealing(true);
}
}
}
Expand Down
1 change: 1 addition & 0 deletions core/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@ extern crate codechain_merkle as cmerkle;
extern crate codechain_network as cnetwork;
extern crate codechain_state as cstate;
extern crate codechain_stratum as cstratum;
extern crate codechain_timer as ctimer;
extern crate codechain_types as ctypes;
extern crate codechain_vm as cvm;
extern crate cuckoo;
Expand Down
Loading