config + ui: config refactoring, stratum server launch, mining ui (without worker list yet)
This commit is contained in:
parent
d34889a801
commit
94a598a923
12 changed files with 352 additions and 146 deletions
|
@ -1,15 +1,16 @@
|
|||
screen_accounts:
|
||||
title: Accounts
|
||||
network:
|
||||
self: Network
|
||||
node: Integrated node
|
||||
metrics: Metrics
|
||||
metrics: Network metrics
|
||||
mining: Mining
|
||||
settings: Server settings
|
||||
enable: Enable
|
||||
settings: Node settings
|
||||
enable_node: Enable node
|
||||
disable: Disable
|
||||
restart: Restart
|
||||
autorun: Autorun
|
||||
disabled_server: 'Enable server or choose another connection method by pressing %{dots} on top left corner of the screen.'
|
||||
disabled_server: 'Enable integrated node or choose another connection method by pressing %{dots} in the top-left corner of the screen.'
|
||||
sync_status:
|
||||
server_restarting: Server is restarting
|
||||
server_down: Server is down
|
||||
|
@ -51,7 +52,20 @@ network_metrics:
|
|||
supply: Supply
|
||||
block_time: Block time
|
||||
reward: Reward
|
||||
difficulty_window: 'Difficulty at window %{size}'
|
||||
difficulty_window: 'Difficulty window %{size}'
|
||||
network_mining:
|
||||
loading: Mining will be available after the synchronization
|
||||
enable_server: Enable server
|
||||
disabled_server: 'Enable stratum server at %{address} or change settings by selecting %{settings} at the bottom of the screen.'
|
||||
starting: Stratum server is starting
|
||||
info: 'Mining server is enabled, you can change settings by selecting %{settings} at the bottom of the screen. Data is updating when devices are connected.'
|
||||
address: IP Address
|
||||
wallet: Wallet Address
|
||||
server: Stratum server
|
||||
miners: Miners
|
||||
devices: Devices
|
||||
blocks_found: Blocks found
|
||||
hashrate: Hashrate
|
||||
modal:
|
||||
cancel: Cancel
|
||||
modal_exit:
|
||||
|
|
|
@ -1,15 +1,16 @@
|
|||
screen_accounts:
|
||||
title: Аккаунты
|
||||
network:
|
||||
self: Сеть
|
||||
node: Встроенный узел
|
||||
metrics: Метрики
|
||||
metrics: Показатели сети
|
||||
mining: Майнинг
|
||||
settings: Настройки сервера
|
||||
enable: Включить
|
||||
settings: Настройки узла
|
||||
enable_node: Включить узел
|
||||
disable: Выключить
|
||||
restart: Перезапустить
|
||||
autorun: Автозапуск
|
||||
disabled_server: 'Включите сервер или выберите другой способ подключения, нажав %{dots} в левом верхнем углу экрана.'
|
||||
disabled_server: 'Включите встроенный узел или выберите другой способ подключения, нажав %{dots} в левом-верхнем углу экрана.'
|
||||
sync_status:
|
||||
server_restarting: Сервер перезапускается
|
||||
server_down: Сервер выключен
|
||||
|
@ -51,7 +52,20 @@ network_metrics:
|
|||
supply: Предложение
|
||||
block_time: Время блока
|
||||
reward: Награда
|
||||
difficulty_window: 'Сложность в окне %{size}'
|
||||
difficulty_window: 'Окно сложности %{size}'
|
||||
network_mining:
|
||||
loading: Майнинг будет доступен после синхронизации
|
||||
enable_server: Включить сервер
|
||||
disabled_server: 'Включите stratum-сервер по адресу %{address} или измените настройки, выбрав %{settings} внизу экрана.'
|
||||
starting: Stratum-сервер запускается
|
||||
info: 'Сервер майнинга запущен, вы можете изменить настройки, выбрав %{settings} внизу экрана. Данные обновляются, когда устройства подключены.'
|
||||
address: IP Адрес
|
||||
wallet: Адрес кошелька
|
||||
server: Stratum-сервер
|
||||
miners: Майнеры
|
||||
devices: Устройства
|
||||
found: Найдено
|
||||
hashrate: Хешрэйт
|
||||
modal:
|
||||
cancel: Отмена
|
||||
modal_exit:
|
||||
|
|
|
@ -74,7 +74,7 @@ fn start(mut options: NativeOptions, app_creator: AppCreator) {
|
|||
|
||||
setup_i18n();
|
||||
|
||||
if Settings::get_app_config().auto_start_node {
|
||||
if Settings::app_config_to_read().auto_start_node {
|
||||
Node::start();
|
||||
}
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ use egui_extras::{Size, StripBuilder};
|
|||
use grin_chain::SyncStatus;
|
||||
|
||||
use crate::gui::{Colors, Navigator};
|
||||
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE, POWER};
|
||||
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE};
|
||||
use crate::gui::platform::PlatformCallbacks;
|
||||
use crate::gui::views::network_metrics::NetworkMetrics;
|
||||
use crate::gui::views::network_mining::NetworkMining;
|
||||
|
@ -32,7 +32,6 @@ use crate::Settings;
|
|||
|
||||
pub trait NetworkTab {
|
||||
fn get_type(&self) -> NetworkTabType;
|
||||
fn name(&self) -> String;
|
||||
fn ui(&mut self, ui: &mut egui::Ui);
|
||||
}
|
||||
|
||||
|
@ -44,6 +43,17 @@ pub enum NetworkTabType {
|
|||
Settings
|
||||
}
|
||||
|
||||
impl NetworkTabType {
|
||||
pub fn name(&self) -> String {
|
||||
match *self {
|
||||
NetworkTabType::Node => { t!("network.node") }
|
||||
NetworkTabType::Metrics => { t!("network.metrics") }
|
||||
NetworkTabType::Mining => { t!("network.mining") }
|
||||
NetworkTabType::Settings => { t!("network.settings") }
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub struct Network {
|
||||
current_tab: Box<dyn NetworkTab>,
|
||||
}
|
||||
|
@ -101,26 +111,22 @@ impl Network {
|
|||
|
||||
ui.columns(4, |columns| {
|
||||
columns[0].vertical_centered_justified(|ui| {
|
||||
View::tab_button(ui, DATABASE,
|
||||
self.current_tab.get_type() == NetworkTabType::Node, || {
|
||||
View::tab_button(ui, DATABASE, self.is_current_tab(NetworkTabType::Node), || {
|
||||
self.current_tab = Box::new(NetworkNode::default());
|
||||
});
|
||||
});
|
||||
columns[1].vertical_centered_justified(|ui| {
|
||||
View::tab_button(ui, GAUGE,
|
||||
self.current_tab.get_type() == NetworkTabType::Metrics, || {
|
||||
View::tab_button(ui, GAUGE, self.is_current_tab(NetworkTabType::Metrics), || {
|
||||
self.current_tab = Box::new(NetworkMetrics::default());
|
||||
});
|
||||
});
|
||||
columns[2].vertical_centered_justified(|ui| {
|
||||
View::tab_button(ui, FACTORY,
|
||||
self.current_tab.get_type() == NetworkTabType::Mining, || {
|
||||
View::tab_button(ui, FACTORY, self.is_current_tab(NetworkTabType::Mining), || {
|
||||
self.current_tab = Box::new(NetworkMining::default());
|
||||
});
|
||||
});
|
||||
columns[3].vertical_centered_justified(|ui| {
|
||||
View::tab_button(ui, FADERS,
|
||||
self.current_tab.get_type() == NetworkTabType::Settings, || {
|
||||
View::tab_button(ui, FADERS, self.is_current_tab(NetworkTabType::Settings), || {
|
||||
self.current_tab = Box::new(NetworkSettings::default());
|
||||
});
|
||||
});
|
||||
|
@ -128,6 +134,10 @@ impl Network {
|
|||
});
|
||||
}
|
||||
|
||||
fn is_current_tab(&self, tab_type: NetworkTabType) -> bool {
|
||||
self.current_tab.get_type() == tab_type
|
||||
}
|
||||
|
||||
fn draw_title(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) {
|
||||
StripBuilder::new(ui)
|
||||
.size(Size::exact(52.0))
|
||||
|
@ -170,7 +180,7 @@ impl Network {
|
|||
strip.cell(|ui| {
|
||||
ui.add_space(2.0);
|
||||
ui.vertical_centered(|ui| {
|
||||
ui.label(RichText::new(self.current_tab.name().to_uppercase())
|
||||
ui.label(RichText::new(self.current_tab.get_type().name().to_uppercase())
|
||||
.size(18.0)
|
||||
.color(Colors::TITLE));
|
||||
});
|
||||
|
@ -217,15 +227,15 @@ impl Network {
|
|||
|
||||
ui.add_space(10.0);
|
||||
|
||||
View::button(ui, format!("{} {}", POWER, t!("network.enable")), Colors::GOLD, || {
|
||||
View::button(ui, t!("network.enable_node"), Colors::GOLD, || {
|
||||
Node::start();
|
||||
});
|
||||
|
||||
ui.add_space(4.0);
|
||||
ui.add_space(2.0);
|
||||
|
||||
let autostart: bool = Settings::get_app_config().auto_start_node;
|
||||
let autostart: bool = Settings::app_config_to_read().auto_start_node;
|
||||
View::checkbox(ui, autostart, t!("network.autorun"), || {
|
||||
let mut w_app_config = Settings::get_app_config_to_update();
|
||||
let mut w_app_config = Settings::app_config_to_update();
|
||||
w_app_config.auto_start_node = !autostart;
|
||||
w_app_config.save();
|
||||
});
|
||||
|
|
|
@ -34,23 +34,19 @@ impl NetworkTab for NetworkMetrics {
|
|||
NetworkTabType::Metrics
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
t!("network.metrics")
|
||||
}
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
let server_stats = Node::get_stats();
|
||||
// Show loading spinner when stats are not available or message when server is not enabled.
|
||||
// Show message when node is not running or loading spinner when metrics are not available.
|
||||
if server_stats.is_none() || server_stats.as_ref().unwrap().diff_stats.height == 0 {
|
||||
if !Node::is_running() {
|
||||
Network::disabled_server_content(ui);
|
||||
} else {
|
||||
View::center_content(ui, 160.0, |ui| {
|
||||
View::center_content(ui, 162.0, |ui| {
|
||||
View::big_loading_spinner(ui);
|
||||
ui.add_space(18.0);
|
||||
ui.label(RichText::new(t!("network_metrics.loading"))
|
||||
.size(16.0)
|
||||
.color(Colors::TEXT)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
});
|
||||
}
|
||||
|
@ -88,7 +84,7 @@ impl NetworkTab for NetworkMetrics {
|
|||
[false, true, false, true]);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
ui.add_space(4.0);
|
||||
|
||||
// Show difficulty adjustment window info
|
||||
ui.vertical_centered_justified(|ui| {
|
||||
|
@ -119,7 +115,7 @@ impl NetworkTab for NetworkMetrics {
|
|||
[false, true, false, true]);
|
||||
});
|
||||
});
|
||||
ui.add_space(6.0);
|
||||
ui.add_space(4.0);
|
||||
|
||||
// Show difficulty adjustment window blocks
|
||||
let blocks_size = stats.diff_stats.last_blocks.len();
|
||||
|
|
|
@ -12,9 +12,14 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use egui::RichText;
|
||||
use grin_chain::SyncStatus;
|
||||
|
||||
use crate::gui::Colors;
|
||||
use crate::gui::icons::{COMPUTER_TOWER, CPU, FADERS, POLYGON};
|
||||
use crate::gui::views::{Network, NetworkTab, NetworkTabType, View};
|
||||
use crate::node::Node;
|
||||
use crate::Settings;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NetworkMining;
|
||||
|
@ -24,25 +29,184 @@ impl NetworkTab for NetworkMining {
|
|||
NetworkTabType::Mining
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
t!("network.mining")
|
||||
}
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
let server_stats = Node::get_stats();
|
||||
// Show loading spinner when stats are not available or message when server is not enabled.
|
||||
if !server_stats.is_some() {
|
||||
// Show message when node is not running or loading spinner when mining are not available.
|
||||
if !server_stats.is_some() || Node::get_sync_status().unwrap() != SyncStatus::NoSync {
|
||||
if !Node::is_running() {
|
||||
Network::disabled_server_content(ui);
|
||||
} else {
|
||||
ui.centered_and_justified(|ui| {
|
||||
View::center_content(ui, 162.0, |ui| {
|
||||
View::big_loading_spinner(ui);
|
||||
ui.add_space(18.0);
|
||||
ui.label(RichText::new(t!("network_mining.loading"))
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
let stats = server_stats.as_ref().unwrap();
|
||||
// Stratum mining server address.
|
||||
let stratum_address = Settings::node_config_to_read()
|
||||
.members.clone()
|
||||
.server.stratum_mining_config.unwrap()
|
||||
.stratum_server_addr.unwrap();
|
||||
|
||||
let stratum_stats = &server_stats.as_ref().unwrap().stratum_stats;
|
||||
if !stratum_stats.is_running && !Node::is_stratum_server_starting() {
|
||||
// Show Stratum setup when mining server is not enabled.
|
||||
View::center_content(ui, 162.0, |ui| {
|
||||
let text = t!(
|
||||
"network_mining.disabled_server",
|
||||
"address" => stratum_address,
|
||||
"settings" => FADERS
|
||||
);
|
||||
ui.label(RichText::new(text)
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
|
||||
ui.add_space(10.0);
|
||||
|
||||
View::button(ui, t!("network_mining.enable_server"), Colors::GOLD, || {
|
||||
Node::start_stratum_server();
|
||||
});
|
||||
|
||||
ui.add_space(2.0);
|
||||
|
||||
// Check if stratum server is enabled at config
|
||||
let stratum_enabled = Settings::node_config_to_read()
|
||||
.members.clone()
|
||||
.server.stratum_mining_config.unwrap()
|
||||
.enable_stratum_server.unwrap();
|
||||
|
||||
View::checkbox(ui, stratum_enabled, t!("network.autorun"), || {
|
||||
let mut w_node_config = Settings::node_config_to_update();
|
||||
w_node_config.members
|
||||
.server.stratum_mining_config.as_mut().unwrap()
|
||||
.enable_stratum_server = Some(!stratum_enabled);
|
||||
w_node_config.save();
|
||||
});
|
||||
});
|
||||
return;
|
||||
} else if Node::is_stratum_server_starting() {
|
||||
// Show loading spinner when mining server is starting.
|
||||
View::center_content(ui, 162.0, |ui| {
|
||||
View::big_loading_spinner(ui);
|
||||
ui.add_space(18.0);
|
||||
ui.label(RichText::new(t!("network_mining.starting"))
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
// Show stratum mining server info.
|
||||
ui.vertical_centered_justified(|ui| {
|
||||
View::sub_header(ui, format!("{} {}", COMPUTER_TOWER, t!("network_mining.server")));
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered(|ui| {
|
||||
View::rounded_box(ui,
|
||||
stratum_address,
|
||||
t!("network_mining.address"),
|
||||
[true, false, true, false]);
|
||||
});
|
||||
columns[1].vertical_centered(|ui| {
|
||||
// Stratum mining wallet address.
|
||||
let wallet_address = Settings::node_config_to_read()
|
||||
.members.clone()
|
||||
.server.stratum_mining_config.unwrap()
|
||||
.wallet_listener_url;
|
||||
View::rounded_box(ui,
|
||||
wallet_address,
|
||||
t!("network_mining.wallet"),
|
||||
[false, true, false, true]);
|
||||
});
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
|
||||
// Show network info.
|
||||
ui.vertical_centered_justified(|ui| {
|
||||
View::sub_header(ui, format!("{} {}", POLYGON, t!("network.self")));
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
|
||||
ui.columns(3, |columns| {
|
||||
columns[0].vertical_centered(|ui| {
|
||||
let difficulty = if stratum_stats.network_difficulty > 0 {
|
||||
stratum_stats.network_difficulty.to_string()
|
||||
} else {
|
||||
"-".into()
|
||||
};
|
||||
View::rounded_box(ui,
|
||||
difficulty,
|
||||
t!("network_node.difficulty"),
|
||||
[true, false, true, false]);
|
||||
});
|
||||
columns[1].vertical_centered(|ui| {
|
||||
let block_height = if stratum_stats.block_height > 0 {
|
||||
stratum_stats.block_height.to_string()
|
||||
} else {
|
||||
"-".into()
|
||||
};
|
||||
View::rounded_box(ui,
|
||||
block_height,
|
||||
t!("network_node.header"),
|
||||
[false, false, false, false]);
|
||||
});
|
||||
columns[2].vertical_centered(|ui| {
|
||||
let hashrate = if stratum_stats.network_hashrate > 0.0 {
|
||||
stratum_stats.network_hashrate.to_string()
|
||||
} else {
|
||||
"-".into()
|
||||
};
|
||||
View::rounded_box(ui,
|
||||
hashrate,
|
||||
t!("network_mining.hashrate"),
|
||||
[false, true, false, true]);
|
||||
});
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
|
||||
// Show mining info.
|
||||
ui.vertical_centered_justified(|ui| {
|
||||
View::sub_header(ui, format!("{} {}", CPU, t!("network_mining.miners")));
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
|
||||
ui.columns(2, |columns| {
|
||||
columns[0].vertical_centered(|ui| {
|
||||
View::rounded_box(ui,
|
||||
stratum_stats.num_workers.to_string(),
|
||||
t!("network_mining.devices"),
|
||||
[true, false, true, false]);
|
||||
});
|
||||
|
||||
columns[1].vertical_centered(|ui| {
|
||||
View::rounded_box(ui,
|
||||
stratum_stats.blocks_found.to_string(),
|
||||
t!("network_mining.blocks_found"),
|
||||
[false, true, false, true]);
|
||||
});
|
||||
});
|
||||
ui.add_space(4.0);
|
||||
|
||||
// Show miners info.
|
||||
if !stratum_stats.worker_stats.is_empty() {
|
||||
//TODO: miners workers
|
||||
} else if ui.available_height() > 142.0 {
|
||||
View::center_content(ui, 142.0, |ui| {
|
||||
ui.label(RichText::new(t!("network_mining.info", "settings" => FADERS))
|
||||
.size(16.0)
|
||||
.color(Colors::INACTIVE_TEXT)
|
||||
);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
|
@ -26,16 +26,12 @@ pub struct NetworkNode;
|
|||
|
||||
impl NetworkTab for NetworkNode {
|
||||
fn get_type(&self) -> NetworkTabType {
|
||||
NetworkTabType::Metrics
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
t!("network.node")
|
||||
NetworkTabType::Node
|
||||
}
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
let server_stats = Node::get_stats();
|
||||
// Show loading spinner when stats are not available or message when server is not enabled.
|
||||
// Show message when node is not running or loading spinner when stats are not available.
|
||||
if !server_stats.is_some() {
|
||||
if !Node::is_running() {
|
||||
Network::disabled_server_content(ui);
|
||||
|
|
|
@ -12,7 +12,9 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use grin_core::global::ChainTypes;
|
||||
use crate::gui::views::{NetworkTab, NetworkTabType};
|
||||
use crate::Settings;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct NetworkSettings;
|
||||
|
@ -22,11 +24,6 @@ impl NetworkTab for NetworkSettings {
|
|||
NetworkTabType::Settings
|
||||
}
|
||||
|
||||
fn name(&self) -> String {
|
||||
t!("network.settings")
|
||||
}
|
||||
|
||||
fn ui(&mut self, ui: &mut egui::Ui) {
|
||||
|
||||
}
|
||||
}
|
|
@ -196,27 +196,19 @@ impl View {
|
|||
Spinner::new().size(48.0).color(Colors::GOLD).ui(ui);
|
||||
}
|
||||
|
||||
// let wt = RichText::new(text.to_uppercase()).size(18.0).color(Colors::BUTTON);
|
||||
// let br = Button::new(wt)
|
||||
// .stroke(Self::DEFAULT_STROKE)
|
||||
// .fill(fill_color)
|
||||
// .ui(ui).interact(Sense::click_and_drag());
|
||||
//
|
||||
// Self::on_button_click(ui, br, action);
|
||||
|
||||
/// Draw button that looks like checkbox with callback to change value.
|
||||
pub fn checkbox(ui: &mut egui::Ui, value: bool, text: String, cb: impl FnOnce()) {
|
||||
let text_value = match value {
|
||||
/// Draw the button that looks like checkbox with callback after change.
|
||||
pub fn checkbox(ui: &mut egui::Ui, checked: bool, text: String, callback: impl FnOnce()) {
|
||||
let text_value = match checked {
|
||||
true => { format!("{} {}", CHECK_SQUARE, text)}
|
||||
false => { format!("{} {}", SQUARE, text)}
|
||||
};
|
||||
let wt = RichText::new(text_value).size(18.0).color(Colors::BUTTON);
|
||||
let wt = RichText::new(text_value).size(19.0).color(Colors::BUTTON);
|
||||
let br = Button::new(wt)
|
||||
.frame(false)
|
||||
.stroke(Stroke::NONE)
|
||||
.fill(Colors::TRANSPARENT)
|
||||
.ui(ui).interact(Sense::click_and_drag());
|
||||
|
||||
Self::on_button_click(ui, br, cb);
|
||||
Self::on_button_click(ui, br, callback);
|
||||
}
|
||||
}
|
|
@ -12,11 +12,6 @@
|
|||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
use std::{fs, thread};
|
||||
use std::fs::File;
|
||||
use std::io::Write;
|
||||
use std::sync::atomic::{AtomicBool, Ordering};
|
||||
|
||||
use grin_config::{config, ConfigError, ConfigMembers, GlobalConfig};
|
||||
use grin_config::config::{API_SECRET_FILE_NAME, FOREIGN_API_SECRET_FILE_NAME, SERVER_CONFIG_FILE_NAME};
|
||||
use grin_core::global::ChainTypes;
|
||||
|
@ -24,70 +19,49 @@ use serde::{Deserialize, Serialize};
|
|||
|
||||
use crate::Settings;
|
||||
|
||||
/// Node config that contains [`GlobalConfig`] to be used by [`grin_servers::Server`].
|
||||
/// Wrapped node config to be used by [`grin_servers::Server`].
|
||||
#[derive(Serialize, Deserialize)]
|
||||
pub struct NodeConfig {
|
||||
pub global_config: GlobalConfig,
|
||||
update_needed: AtomicBool,
|
||||
updating: AtomicBool
|
||||
pub members: ConfigMembers
|
||||
}
|
||||
|
||||
impl NodeConfig {
|
||||
/// Initialize node config with provided chain type from the disk.
|
||||
pub fn init(chain_type: &ChainTypes) -> Self {
|
||||
/// Initialize integrated node config.
|
||||
pub fn init(chain_type: ChainTypes) -> Self {
|
||||
let _ = Self::check_api_secret_files(chain_type, API_SECRET_FILE_NAME);
|
||||
let _ = Self::check_api_secret_files(chain_type, FOREIGN_API_SECRET_FILE_NAME);
|
||||
|
||||
let config_path = Settings::get_config_path(SERVER_CONFIG_FILE_NAME, Some(chain_type));
|
||||
|
||||
// Create default config if it doesn't exist or has wrong format.
|
||||
if !config_path.exists() || toml::from_str::<ConfigMembers>(
|
||||
fs::read_to_string(config_path.clone()).unwrap().as_str()
|
||||
).is_err() {
|
||||
let mut default_config = GlobalConfig::for_chain(chain_type);
|
||||
default_config.update_paths(&Settings::get_working_path(Some(chain_type)));
|
||||
let _ = default_config.write_to_file(config_path.to_str().unwrap());
|
||||
}
|
||||
|
||||
let config = GlobalConfig::new(config_path.to_str().unwrap());
|
||||
|
||||
let config_members = Self::for_chain_type(chain_type);
|
||||
Self {
|
||||
global_config: config.unwrap(),
|
||||
update_needed: AtomicBool::new(false),
|
||||
updating: AtomicBool::new(false)
|
||||
members: config_members
|
||||
}
|
||||
}
|
||||
|
||||
/// Write node config on disk.
|
||||
pub fn save_config(&self) {
|
||||
if self.updating.load(Ordering::Relaxed) {
|
||||
self.update_needed.store(true, Ordering::Relaxed);
|
||||
return;
|
||||
/// Initialize config with provided [`ChainTypes`].
|
||||
pub fn for_chain_type(chain_type: ChainTypes) -> ConfigMembers {
|
||||
let path = Settings::get_config_path(SERVER_CONFIG_FILE_NAME, Some(chain_type));
|
||||
let parsed = Settings::read_from_file::<ConfigMembers>(path.clone());
|
||||
if !path.exists() || parsed.is_err() {
|
||||
let mut default_config = GlobalConfig::for_chain(&chain_type);
|
||||
default_config.update_paths(&Settings::get_working_path(Some(chain_type)));
|
||||
let config = default_config.members.unwrap();
|
||||
Settings::write_to_file(&config, path);
|
||||
config
|
||||
} else {
|
||||
parsed.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
thread::spawn(move || loop {
|
||||
let config = Settings::get_node_config();
|
||||
config.update_needed.store(false, Ordering::Relaxed);
|
||||
config.updating.store(true, Ordering::Relaxed);
|
||||
|
||||
let chain_type = &config.global_config.members.clone().unwrap().server.chain_type;
|
||||
let config_path = Settings::get_config_path(SERVER_CONFIG_FILE_NAME, Some(chain_type));
|
||||
|
||||
// Write config to file.
|
||||
let conf_out = toml::to_string(&config.global_config.members).unwrap();
|
||||
let mut file = File::create(config_path.to_str().unwrap()).unwrap();
|
||||
file.write_all(conf_out.as_bytes()).unwrap();
|
||||
|
||||
if !config.update_needed.load(Ordering::Relaxed) {
|
||||
config.updating.store(false, Ordering::Relaxed);
|
||||
break;
|
||||
}
|
||||
});
|
||||
/// Save node config to disk.
|
||||
pub fn save(&mut self) {
|
||||
let chain_type = self.members.server.chain_type;
|
||||
let config_path = Settings::get_config_path(SERVER_CONFIG_FILE_NAME, Some(chain_type));
|
||||
Settings::write_to_file(&self.members, config_path);
|
||||
}
|
||||
|
||||
/// Check that the api secret files exist and are valid.
|
||||
fn check_api_secret_files(
|
||||
chain_type: &ChainTypes,
|
||||
chain_type: ChainTypes,
|
||||
secret_file_name: &str,
|
||||
) -> Result<(), ConfigError> {
|
||||
let grin_path = Settings::get_working_path(Some(chain_type));
|
||||
|
|
|
@ -45,7 +45,9 @@ pub struct Node {
|
|||
/// Thread flag to stop the server.
|
||||
stop_needed: AtomicBool,
|
||||
/// Flag to check if app exit is needed after server stop.
|
||||
exit_after_stop: AtomicBool
|
||||
exit_after_stop: AtomicBool,
|
||||
/// Thread flag to start stratum server at separate.
|
||||
start_stratum_server: AtomicBool
|
||||
}
|
||||
|
||||
impl Default for Node {
|
||||
|
@ -55,7 +57,8 @@ impl Default for Node {
|
|||
starting: AtomicBool::new(false),
|
||||
restart_needed: AtomicBool::new(false),
|
||||
stop_needed: AtomicBool::new(false),
|
||||
exit_after_stop: AtomicBool::new(false)
|
||||
exit_after_stop: AtomicBool::new(false),
|
||||
start_stratum_server: AtomicBool::new(false)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -83,6 +86,16 @@ impl Node {
|
|||
}
|
||||
}
|
||||
|
||||
/// Start stratum server.
|
||||
pub fn start_stratum_server() {
|
||||
NODE_STATE.start_stratum_server.store(true, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
/// Check if stratum server is starting.
|
||||
pub fn is_stratum_server_starting() -> bool {
|
||||
NODE_STATE.start_stratum_server.load(Ordering::Relaxed)
|
||||
}
|
||||
|
||||
/// Check if node is starting.
|
||||
pub fn is_starting() -> bool {
|
||||
NODE_STATE.starting.load(Ordering::Relaxed)
|
||||
|
@ -164,8 +177,20 @@ impl Node {
|
|||
|
||||
NODE_STATE.starting.store(false, Ordering::Relaxed);
|
||||
NODE_STATE.stop_needed.store(false, Ordering::Relaxed);
|
||||
NODE_STATE.start_stratum_server.store(false, Ordering::Relaxed);
|
||||
break;
|
||||
} else {
|
||||
if Self::is_stratum_server_starting() {
|
||||
// Start mining server.
|
||||
let stratum_config = server.config.stratum_mining_config.clone().unwrap();
|
||||
server.start_stratum_server(stratum_config);
|
||||
|
||||
// Wait for mining server to start and update status.
|
||||
thread::sleep(Duration::from_millis(1000));
|
||||
|
||||
NODE_STATE.start_stratum_server.store(false, Ordering::Relaxed);
|
||||
}
|
||||
|
||||
let stats = server.get_server_stats();
|
||||
if stats.is_ok() {
|
||||
// Update server stats.
|
||||
|
@ -308,8 +333,8 @@ impl Node {
|
|||
/// Start the node [`Server`].
|
||||
fn start_server() -> Server {
|
||||
// Get current global config
|
||||
let config = &Settings::get_node_config().global_config;
|
||||
let server_config = config.members.as_ref().unwrap().server.clone();
|
||||
let config = &Settings::node_config_to_read().members;
|
||||
let server_config = config.server.clone();
|
||||
|
||||
// Remove temporary file dir
|
||||
{
|
||||
|
@ -328,7 +353,7 @@ fn start_server() -> Server {
|
|||
// accept_fee_base, and future_time_limit.
|
||||
// These are read via global and not read from config beyond this point.
|
||||
if !global::GLOBAL_CHAIN_TYPE.is_init() {
|
||||
global::init_global_chain_type(config.members.as_ref().unwrap().server.chain_type);
|
||||
global::init_global_chain_type(config.server.chain_type);
|
||||
}
|
||||
info!("Chain: {:?}", global::get_chain_type());
|
||||
|
||||
|
@ -345,12 +370,12 @@ fn start_server() -> Server {
|
|||
}
|
||||
}
|
||||
if !global::GLOBAL_ACCEPT_FEE_BASE.is_init() {
|
||||
let afb = config.members.as_ref().unwrap().server.pool_config.accept_fee_base;
|
||||
let afb = config.server.pool_config.accept_fee_base;
|
||||
global::init_global_accept_fee_base(afb);
|
||||
info!("Accept Fee Base: {:?}", global::get_accept_fee_base());
|
||||
}
|
||||
if !global::GLOBAL_FUTURE_TIME_LIMIT.is_init() {
|
||||
let future_time_limit = config.members.as_ref().unwrap().server.future_time_limit;
|
||||
let future_time_limit = config.server.future_time_limit;
|
||||
global::init_global_future_time_limit(future_time_limit);
|
||||
info!("Future Time Limit: {:?}", global::get_future_time_limit());
|
||||
}
|
||||
|
@ -417,13 +442,12 @@ pub extern "C" fn Java_mw_gri_android_BackgroundService_getSyncTitle(
|
|||
#[cfg(target_os = "android")]
|
||||
#[allow(non_snake_case)]
|
||||
#[no_mangle]
|
||||
/// Check if app exit is needed after node stop.
|
||||
/// Check if app exit is needed after node stop to finish Android app at background.
|
||||
pub extern "C" fn Java_mw_gri_android_BackgroundService_exitAppAfterNodeStop(
|
||||
_env: jni::JNIEnv,
|
||||
_class: jni::objects::JObject,
|
||||
_activity: jni::objects::JObject,
|
||||
) -> jboolean {
|
||||
let exit_after_stop = NODE_STATE.exit_after_stop.load(Ordering::Relaxed);
|
||||
let is_app_exit_needed = !Node::is_running() && exit_after_stop;
|
||||
return is_app_exit_needed as jboolean;
|
||||
let exit_needed = !Node::is_running() && NODE_STATE.exit_after_stop.load(Ordering::Relaxed);
|
||||
return exit_needed as jboolean;
|
||||
}
|
|
@ -38,7 +38,7 @@ pub struct AppConfig {
|
|||
/// Run node server on startup.
|
||||
pub auto_start_node: bool,
|
||||
/// Chain type for node server.
|
||||
pub node_chain_type: ChainTypes
|
||||
node_chain_type: ChainTypes
|
||||
}
|
||||
|
||||
impl Default for AppConfig {
|
||||
|
@ -53,62 +53,87 @@ impl Default for AppConfig {
|
|||
impl AppConfig {
|
||||
/// Initialize application config from the disk.
|
||||
pub fn init() -> Self {
|
||||
let config_path = Settings::get_config_path(APP_CONFIG_FILE_NAME, None);
|
||||
let parsed = Settings::read_from_file::<AppConfig>(config_path.clone());
|
||||
if !config_path.exists() || parsed.is_err() {
|
||||
let path = Settings::get_config_path(APP_CONFIG_FILE_NAME, None);
|
||||
let parsed = Settings::read_from_file::<AppConfig>(path.clone());
|
||||
if !path.exists() || parsed.is_err() {
|
||||
let default_config = AppConfig::default();
|
||||
Settings::write_to_file(&default_config, config_path);
|
||||
Settings::write_to_file(&default_config, path);
|
||||
default_config
|
||||
} else {
|
||||
parsed.unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
/// Change chain type and load new [`NodeConfig`] accordingly.
|
||||
pub fn change_chain_type(&mut self, chain_type: ChainTypes) {
|
||||
if self.node_chain_type == chain_type {
|
||||
return;
|
||||
} else {
|
||||
self.node_chain_type = chain_type;
|
||||
self.save();
|
||||
|
||||
// Load config for selected chain type.
|
||||
Settings::node_config_to_update().members = NodeConfig::for_chain_type(chain_type);
|
||||
}
|
||||
}
|
||||
|
||||
/// Save app config to disk.
|
||||
pub fn save(&self) {
|
||||
Settings::write_to_file(self, Settings::get_config_path(APP_CONFIG_FILE_NAME, None));
|
||||
}
|
||||
}
|
||||
|
||||
const WORKING_DIRECTORY_NAME: &'static str = ".grim";
|
||||
|
||||
/// Provides access to app and node configs.
|
||||
pub struct Settings {
|
||||
app_config: Arc<RwLock<AppConfig>>,
|
||||
node_config: Arc<RwLock<NodeConfig>>
|
||||
}
|
||||
|
||||
impl Settings {
|
||||
/// Initialize settings with app and node configs from the disk.
|
||||
/// Initialize settings with app and node configs.
|
||||
fn init() -> Self {
|
||||
let app_config = AppConfig::init();
|
||||
let chain_type = app_config.node_chain_type;
|
||||
Self {
|
||||
app_config: Arc::new(RwLock::new(app_config)),
|
||||
node_config: Arc::new(RwLock::new(NodeConfig::init(&chain_type)))
|
||||
node_config: Arc::new(RwLock::new(NodeConfig::init(chain_type)))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_node_config() -> RwLockReadGuard<'static, NodeConfig> {
|
||||
/// Get node config to read values.
|
||||
pub fn node_config_to_read() -> RwLockReadGuard<'static, NodeConfig> {
|
||||
SETTINGS_STATE.node_config.read().unwrap()
|
||||
}
|
||||
|
||||
pub fn get_app_config() -> RwLockReadGuard<'static, AppConfig> {
|
||||
/// Get node config to update values.
|
||||
pub fn node_config_to_update() -> RwLockWriteGuard<'static, NodeConfig> {
|
||||
SETTINGS_STATE.node_config.write().unwrap()
|
||||
}
|
||||
|
||||
/// Get app config to read values.
|
||||
pub fn app_config_to_read() -> RwLockReadGuard<'static, AppConfig> {
|
||||
SETTINGS_STATE.app_config.read().unwrap()
|
||||
}
|
||||
|
||||
pub fn get_app_config_to_update() -> RwLockWriteGuard<'static, AppConfig> {
|
||||
/// Get app config to update values.
|
||||
pub fn app_config_to_update() -> RwLockWriteGuard<'static, AppConfig> {
|
||||
SETTINGS_STATE.app_config.write().unwrap()
|
||||
}
|
||||
|
||||
/// Get working directory path for application.
|
||||
pub fn get_working_path(chain_type: Option<&ChainTypes>) -> PathBuf {
|
||||
// Check if dir exists
|
||||
/// Get working directory path for the application.
|
||||
pub fn get_working_path(chain_type: Option<ChainTypes>) -> PathBuf {
|
||||
// Check if dir exists.
|
||||
let mut path = match dirs::home_dir() {
|
||||
Some(p) => p,
|
||||
None => PathBuf::new(),
|
||||
};
|
||||
path.push(".grim");
|
||||
path.push(WORKING_DIRECTORY_NAME);
|
||||
if chain_type.is_some() {
|
||||
path.push(chain_type.unwrap().shortname());
|
||||
}
|
||||
// Create if the default path doesn't exist
|
||||
// Create if the default path doesn't exist.
|
||||
if !path.exists() {
|
||||
let _ = fs::create_dir_all(path.clone());
|
||||
}
|
||||
|
@ -116,14 +141,14 @@ impl Settings {
|
|||
}
|
||||
|
||||
/// Get config file path from provided name and [`ChainTypes`] if needed.
|
||||
pub fn get_config_path(config_name: &str, chain_type: Option<&ChainTypes>) -> PathBuf {
|
||||
pub fn get_config_path(config_name: &str, chain_type: Option<ChainTypes>) -> PathBuf {
|
||||
let main_path = Self::get_working_path(chain_type);
|
||||
let mut settings_path = main_path.clone();
|
||||
settings_path.push(config_name);
|
||||
settings_path
|
||||
}
|
||||
|
||||
/// Read config from file
|
||||
/// Read config from a file
|
||||
pub fn read_from_file<T: DeserializeOwned>(config_path: PathBuf) -> Result<T, ConfigError> {
|
||||
let file_content = fs::read_to_string(config_path.clone())?;
|
||||
let parsed = toml::from_str::<T>(file_content.as_str());
|
||||
|
|
Loading…
Reference in a new issue