use crate::util::RwLock;
use std::convert::From;
use std::sync::Arc;
use crate::api;
use crate::chain;
use crate::core::global::ChainTypes;
use crate::core::{core, pow};
use crate::p2p;
use crate::pool;
use crate::store;
use crate::wallet;
use chrono::prelude::{DateTime, Utc};
#[derive(Debug)]
pub enum Error {
Core(core::block::Error),
Store(store::Error),
Chain(chain::Error),
P2P(p2p::Error),
API(api::Error),
Wallet(wallet::Error),
Cuckoo(pow::Error),
Pool(pool::PoolError),
ArgumentError(String),
IOError(std::io::Error),
}
impl From<core::block::Error> for Error {
fn from(e: core::block::Error) -> Error {
Error::Core(e)
}
}
impl From<chain::Error> for Error {
fn from(e: chain::Error) -> Error {
Error::Chain(e)
}
}
impl From<std::io::Error> for Error {
fn from(e: std::io::Error) -> Error {
Error::IOError(e)
}
}
impl From<p2p::Error> for Error {
fn from(e: p2p::Error) -> Error {
Error::P2P(e)
}
}
impl From<pow::Error> for Error {
fn from(e: pow::Error) -> Error {
Error::Cuckoo(e)
}
}
impl From<store::Error> for Error {
fn from(e: store::Error) -> Error {
Error::Store(e)
}
}
impl From<api::Error> for Error {
fn from(e: api::Error) -> Error {
Error::API(e)
}
}
impl From<wallet::Error> for Error {
fn from(e: wallet::Error) -> Error {
Error::Wallet(e)
}
}
impl From<pool::PoolError> for Error {
fn from(e: pool::PoolError) -> Error {
Error::Pool(e)
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub enum ChainValidationMode {
EveryBlock,
Disabled,
}
impl Default for ChainValidationMode {
fn default() -> ChainValidationMode {
ChainValidationMode::Disabled
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct ServerConfig {
pub db_root: String,
pub api_http_addr: String,
pub api_secret_path: Option<String>,
pub tls_certificate_file: Option<String>,
pub tls_certificate_key: Option<String>,
#[serde(default)]
pub chain_type: ChainTypes,
#[serde(default)]
pub chain_validation_mode: ChainValidationMode,
pub archive_mode: Option<bool>,
pub skip_sync_wait: Option<bool>,
pub run_tui: Option<bool>,
pub use_db_wallet: Option<bool>,
pub run_test_miner: Option<bool>,
pub test_miner_wallet_url: Option<String>,
pub p2p_config: p2p::P2PConfig,
#[serde(default)]
pub pool_config: pool::PoolConfig,
#[serde(default)]
pub dandelion_config: pool::DandelionConfig,
#[serde(default)]
pub stratum_mining_config: Option<StratumServerConfig>,
}
impl Default for ServerConfig {
fn default() -> ServerConfig {
ServerConfig {
db_root: "grin_chain".to_string(),
api_http_addr: "127.0.0.1:3413".to_string(),
api_secret_path: Some(".api_secret".to_string()),
tls_certificate_file: None,
tls_certificate_key: None,
p2p_config: p2p::P2PConfig::default(),
dandelion_config: pool::DandelionConfig::default(),
stratum_mining_config: Some(StratumServerConfig::default()),
chain_type: ChainTypes::default(),
archive_mode: Some(false),
chain_validation_mode: ChainValidationMode::default(),
pool_config: pool::PoolConfig::default(),
skip_sync_wait: Some(false),
run_tui: Some(true),
use_db_wallet: None,
run_test_miner: Some(false),
test_miner_wallet_url: None,
}
}
}
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq)]
pub struct StratumServerConfig {
pub enable_stratum_server: Option<bool>,
pub stratum_server_addr: Option<String>,
pub attempt_time_per_block: u32,
pub minimum_share_difficulty: u64,
pub wallet_listener_url: String,
pub burn_reward: bool,
}
impl Default for StratumServerConfig {
fn default() -> StratumServerConfig {
StratumServerConfig {
wallet_listener_url: "http://127.0.0.1:3415".to_string(),
burn_reward: false,
attempt_time_per_block: 15,
minimum_share_difficulty: 1,
enable_stratum_server: Some(false),
stratum_server_addr: Some("127.0.0.1:3416".to_string()),
}
}
}
#[derive(Debug, Clone, Copy, Eq, PartialEq)]
#[allow(missing_docs)]
pub enum SyncStatus {
Initial,
NoSync,
AwaitingPeers(bool),
HeaderSync {
current_height: u64,
highest_height: u64,
},
TxHashsetDownload {
start_time: DateTime<Utc>,
downloaded_size: u64,
total_size: u64,
},
TxHashsetSetup,
TxHashsetValidation {
kernels: u64,
kernel_total: u64,
rproofs: u64,
rproof_total: u64,
},
TxHashsetSave,
TxHashsetDone,
BodySync {
current_height: u64,
highest_height: u64,
},
}
pub struct SyncState {
current: RwLock<SyncStatus>,
sync_error: Arc<RwLock<Option<Error>>>,
}
impl SyncState {
pub fn new() -> SyncState {
SyncState {
current: RwLock::new(SyncStatus::Initial),
sync_error: Arc::new(RwLock::new(None)),
}
}
pub fn is_syncing(&self) -> bool {
*self.current.read() != SyncStatus::NoSync
}
pub fn status(&self) -> SyncStatus {
*self.current.read()
}
pub fn update(&self, new_status: SyncStatus) {
if self.status() == new_status {
return;
}
let mut status = self.current.write();
debug!("sync_state: sync_status: {:?} -> {:?}", *status, new_status,);
*status = new_status;
}
pub fn update_txhashset_download(&self, new_status: SyncStatus) -> bool {
if let SyncStatus::TxHashsetDownload { .. } = new_status {
let mut status = self.current.write();
*status = new_status;
true
} else {
false
}
}
pub fn set_sync_error(&self, error: Error) {
*self.sync_error.write() = Some(error);
}
pub fn sync_error(&self) -> Arc<RwLock<Option<Error>>> {
Arc::clone(&self.sync_error)
}
pub fn clear_sync_error(&self) {
*self.sync_error.write() = None;
}
}
impl chain::TxHashsetWriteStatus for SyncState {
fn on_setup(&self) {
self.update(SyncStatus::TxHashsetSetup);
}
fn on_validation(&self, vkernels: u64, vkernel_total: u64, vrproofs: u64, vrproof_total: u64) {
let mut status = self.current.write();
match *status {
SyncStatus::TxHashsetValidation {
kernels,
kernel_total,
rproofs,
rproof_total,
} => {
let ks = if vkernels > 0 { vkernels } else { kernels };
let kt = if vkernel_total > 0 {
vkernel_total
} else {
kernel_total
};
let rps = if vrproofs > 0 { vrproofs } else { rproofs };
let rpt = if vrproof_total > 0 {
vrproof_total
} else {
rproof_total
};
*status = SyncStatus::TxHashsetValidation {
kernels: ks,
kernel_total: kt,
rproofs: rps,
rproof_total: rpt,
};
}
_ => {
*status = SyncStatus::TxHashsetValidation {
kernels: 0,
kernel_total: 0,
rproofs: 0,
rproof_total: 0,
}
}
}
}
fn on_save(&self) {
self.update(SyncStatus::TxHashsetSave);
}
fn on_done(&self) {
self.update(SyncStatus::TxHashsetDone);
}
}