config + ui: add p2p config and ui, fix input fields size, update translations
This commit is contained in:
parent
6cfc6ae0b5
commit
bab8c49f26
14 changed files with 1431 additions and 298 deletions
|
@ -111,6 +111,24 @@ network_settings:
|
||||||
aggregation_period: Aggregation period (in seconds)
|
aggregation_period: Aggregation period (in seconds)
|
||||||
stem_probability: Stem phase probability
|
stem_probability: Stem phase probability
|
||||||
stem_txs: Stem transactions
|
stem_txs: Stem transactions
|
||||||
|
p2p_server: P2P server
|
||||||
|
p2p_port: P2P port
|
||||||
|
add_seed: Add DNS Seed
|
||||||
|
add_peer: Add peer
|
||||||
|
peer_address_error: 'Enter IP address or DNS name (make sure specified host is available) in correct format, e.g.: 192.168.0.1:1234 or example.com:5678'
|
||||||
|
default: Default
|
||||||
|
allow_list: Allow list
|
||||||
|
allow_list_desc: Connect only to peers in this list.
|
||||||
|
deny_list: Deny list
|
||||||
|
deny_list_desc: Never connect to peers in this list.
|
||||||
|
favourites: Favourites
|
||||||
|
favourites_desc: A list of preferred peers to connect to.
|
||||||
|
ban_window: How long a banned peer should stay banned (in seconds)
|
||||||
|
ban_window_desc: The decision to ban is made by node, based on the correctness of the data received from the peer.
|
||||||
|
max_inbound_count: Maximum number of inbound peer connections
|
||||||
|
max_outbound_count: Maximum number of outbound peer connections
|
||||||
|
min_outbound_count: Minimum number of outbound peer connections
|
||||||
|
min_outbound_desc: Node server will actively keep trying to add peers until it will get to at least this number.
|
||||||
modal:
|
modal:
|
||||||
cancel: Cancel
|
cancel: Cancel
|
||||||
save: Save
|
save: Save
|
||||||
|
|
|
@ -111,6 +111,24 @@ network_settings:
|
||||||
aggregation_period: Период агрегации (в секундах)
|
aggregation_period: Период агрегации (в секундах)
|
||||||
stem_probability: Вероятность фазы Stem
|
stem_probability: Вероятность фазы Stem
|
||||||
stem_txs: Stem транзакций
|
stem_txs: Stem транзакций
|
||||||
|
p2p_server: P2P сервер
|
||||||
|
p2p_port: P2P порт
|
||||||
|
add_seed: Добавить DNS Seed
|
||||||
|
add_peer: Добавить пир
|
||||||
|
peer_address_error: 'Введите IP адрес или DNS имя (убедитесь, что указанный хост доступен) в правильном формате, например: 192.168.0.1:1234 или example.com:5678'
|
||||||
|
default: По умолчанию
|
||||||
|
allow_list: Белый список
|
||||||
|
allow_list_desc: Подключаться только к пирам в данном списке.
|
||||||
|
deny_list: Чёрный список
|
||||||
|
deny_list_desc: Никогда не подключаться к пирам в данном списке.
|
||||||
|
favourites: Избранное
|
||||||
|
favourites_desc: Список предпочтительных пиров для подключения.
|
||||||
|
ban_window: Как долго забаненый пир должен оставаться забаненым (в секундах)
|
||||||
|
ban_window_desc: Решение о запрете принимается нодой, основываясь на корректности данных полученных от пира.
|
||||||
|
max_inbound_count: Максимальное количество входящих подключений пиров
|
||||||
|
max_outbound_count: Максимальное количество исходящих подключений к пирам
|
||||||
|
min_outbound_count: Минимальное количество исходящих подключений к пирам
|
||||||
|
min_outbound_desc: Сервер узла будет активно пытаться добавить пиры, пока не дойдёт хотя бы до этого числа.
|
||||||
modal:
|
modal:
|
||||||
cancel: Отмена
|
cancel: Отмена
|
||||||
save: Сохранить
|
save: Сохранить
|
||||||
|
|
|
@ -15,7 +15,7 @@
|
||||||
use egui::{Id, RichText, TextStyle, Ui, Widget};
|
use egui::{Id, RichText, TextStyle, Ui, Widget};
|
||||||
|
|
||||||
use crate::gui::{Colors, Navigator};
|
use crate::gui::{Colors, Navigator};
|
||||||
use crate::gui::icons::{CLOCK_COUNTDOWN, LINE_SEGMENTS, TIMER, WATCH};
|
use crate::gui::icons::{CLOCK_COUNTDOWN, GRAPH, TIMER, WATCH};
|
||||||
use crate::gui::platform::PlatformCallbacks;
|
use crate::gui::platform::PlatformCallbacks;
|
||||||
use crate::gui::views::{Modal, ModalPosition, View};
|
use crate::gui::views::{Modal, ModalPosition, View};
|
||||||
use crate::gui::views::network::settings::NetworkSettings;
|
use crate::gui::views::network::settings::NetworkSettings;
|
||||||
|
@ -58,7 +58,7 @@ impl DandelionSetup {
|
||||||
pub const STEM_PROBABILITY_MODAL: &'static str = "stem_probability";
|
pub const STEM_PROBABILITY_MODAL: &'static str = "stem_probability";
|
||||||
|
|
||||||
pub fn ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
pub fn ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||||
View::sub_title(ui, format!("{} {}", LINE_SEGMENTS, "Dandelion"));
|
View::sub_title(ui, format!("{} {}", GRAPH, "Dandelion"));
|
||||||
View::horizontal_line(ui, Colors::STROKE);
|
View::horizontal_line(ui, Colors::STROKE);
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
@ -135,7 +135,7 @@ impl DandelionSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.epoch_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.epoch_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(46.0)
|
.desired_width(52.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
@ -220,7 +220,7 @@ impl DandelionSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.embargo_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.embargo_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(46.0)
|
.desired_width(52.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
@ -305,7 +305,7 @@ impl DandelionSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.aggregation_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.aggregation_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(36.0)
|
.desired_width(42.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
@ -390,7 +390,7 @@ impl DandelionSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.stem_prob_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.stem_prob_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(36.0)
|
.desired_width(42.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
|
|
@ -35,13 +35,10 @@ pub struct NodeSetup {
|
||||||
api_port_available_edit: bool,
|
api_port_available_edit: bool,
|
||||||
|
|
||||||
/// Flag to check if API port from saved config value is available.
|
/// Flag to check if API port from saved config value is available.
|
||||||
pub(crate) is_api_port_available: bool,
|
is_api_port_available: bool,
|
||||||
|
|
||||||
/// Rest API and v2 Owner API secret value.
|
/// Secret edit value for modal.
|
||||||
api_secret_edit: String,
|
secret_edit: String,
|
||||||
|
|
||||||
/// Foreign API secret value.
|
|
||||||
foreign_api_secret_edit: String,
|
|
||||||
|
|
||||||
/// Future Time Limit value.
|
/// Future Time Limit value.
|
||||||
ftl_edit: String,
|
ftl_edit: String,
|
||||||
|
@ -56,8 +53,7 @@ impl Default for NodeSetup {
|
||||||
api_port_edit: api_port,
|
api_port_edit: api_port,
|
||||||
api_port_available_edit: is_api_port_available,
|
api_port_available_edit: is_api_port_available,
|
||||||
is_api_port_available,
|
is_api_port_available,
|
||||||
api_secret_edit: "".to_string(),
|
secret_edit: "".to_string(),
|
||||||
foreign_api_secret_edit: "".to_string(),
|
|
||||||
ftl_edit: NodeConfig::get_ftl(),
|
ftl_edit: NodeConfig::get_ftl(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -253,7 +249,7 @@ impl NodeSetup {
|
||||||
// Draw API port text edit.
|
// Draw API port text edit.
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.api_port_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.api_port_edit)
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(58.0)
|
.desired_width(64.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
@ -335,14 +331,7 @@ impl NodeSetup {
|
||||||
|
|
||||||
View::button(ui, secret_text, Colors::BUTTON, || {
|
View::button(ui, secret_text, Colors::BUTTON, || {
|
||||||
// Setup values for modal.
|
// Setup values for modal.
|
||||||
match modal_id {
|
self.secret_edit = secret_value.unwrap_or("".to_string());
|
||||||
Self::API_SECRET_MODAL => {
|
|
||||||
self.api_secret_edit = secret_value.unwrap_or("".to_string());
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
self.foreign_api_secret_edit = secret_value.unwrap_or("".to_string());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Show secret edit modal.
|
// Show secret edit modal.
|
||||||
let port_modal = Modal::new(modal_id)
|
let port_modal = Modal::new(modal_id)
|
||||||
.position(ModalPosition::CenterTop)
|
.position(ModalPosition::CenterTop)
|
||||||
|
@ -367,11 +356,7 @@ impl NodeSetup {
|
||||||
ui.add_space(8.0);
|
ui.add_space(8.0);
|
||||||
|
|
||||||
// Draw API port text edit.
|
// Draw API port text edit.
|
||||||
let edit_text = match modal.id {
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.secret_edit)
|
||||||
Self::API_SECRET_MODAL => &mut self.api_secret_edit,
|
|
||||||
_ => &mut self.foreign_api_secret_edit
|
|
||||||
};
|
|
||||||
let text_edit_resp = egui::TextEdit::singleline(edit_text)
|
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
|
@ -396,25 +381,15 @@ impl NodeSetup {
|
||||||
columns[0].with_layout(Layout::right_to_left(Align::Center), |ui| {
|
columns[0].with_layout(Layout::right_to_left(Align::Center), |ui| {
|
||||||
let copy_title = format!("{} {}", COPY, t!("network_settings.copy"));
|
let copy_title = format!("{} {}", COPY, t!("network_settings.copy"));
|
||||||
View::button(ui, copy_title, Colors::WHITE, || {
|
View::button(ui, copy_title, Colors::WHITE, || {
|
||||||
match modal.id {
|
cb.copy_string_to_buffer(self.secret_edit.clone());
|
||||||
Self::API_SECRET_MODAL => {
|
|
||||||
cb.copy_string_to_buffer(self.api_secret_edit.clone());
|
|
||||||
},
|
|
||||||
_ => {
|
|
||||||
cb.copy_string_to_buffer(self.foreign_api_secret_edit.clone());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
columns[1].with_layout(Layout::left_to_right(Align::Center), |ui| {
|
columns[1].with_layout(Layout::left_to_right(Align::Center), |ui| {
|
||||||
let paste_title = format!("{} {}", CLIPBOARD_TEXT, t!("network_settings.paste"));
|
let paste_title = format!("{} {}",
|
||||||
|
CLIPBOARD_TEXT,
|
||||||
|
t!("network_settings.paste"));
|
||||||
View::button(ui, paste_title, Colors::WHITE, || {
|
View::button(ui, paste_title, Colors::WHITE, || {
|
||||||
let text = cb.get_string_from_buffer();
|
self.secret_edit = cb.get_string_from_buffer();
|
||||||
match modal.id {
|
|
||||||
Self::API_SECRET_MODAL => self.api_secret_edit = text,
|
|
||||||
_ => self.foreign_api_secret_edit = text
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -435,14 +410,13 @@ impl NodeSetup {
|
||||||
|
|
||||||
// Save button callback.
|
// Save button callback.
|
||||||
let on_save = || {
|
let on_save = || {
|
||||||
|
let secret = self.secret_edit.clone();
|
||||||
match modal.id {
|
match modal.id {
|
||||||
Self::API_SECRET_MODAL => {
|
Self::API_SECRET_MODAL => {
|
||||||
let api_secret = &self.api_secret_edit.clone();
|
NodeConfig::save_api_secret(&secret);
|
||||||
NodeConfig::save_api_secret(api_secret);
|
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
let foreign_api_secret = &self.foreign_api_secret_edit.clone();
|
NodeConfig::save_foreign_api_secret(&secret);
|
||||||
NodeConfig::save_foreign_api_secret(foreign_api_secret);
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
cb.hide_keyboard();
|
cb.hide_keyboard();
|
||||||
|
@ -504,7 +478,7 @@ impl NodeSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.ftl_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.ftl_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(46.0)
|
.desired_width(52.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
|
|
@ -10,4 +10,892 @@
|
||||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||||
// See the License for the specific language governing permissions and
|
// See the License for the specific language governing permissions and
|
||||||
// limitations under the License.
|
// limitations under the License.
|
||||||
|
|
||||||
|
use std::fmt::format;
|
||||||
|
use egui::{Direction, Id, Layout, RichText, Rounding, Stroke, TextStyle, Ui, Widget};
|
||||||
|
use egui_extras::{Size, StripBuilder};
|
||||||
|
use grin_core::global::ChainTypes;
|
||||||
|
|
||||||
|
use crate::AppConfig;
|
||||||
|
use crate::gui::{Colors, Navigator};
|
||||||
|
use crate::gui::icons::{HANDSHAKE, PLUG, TRASH, GLOBE_SIMPLE, PLUS_CIRCLE, ARROW_FAT_LINES_UP, ARROW_FAT_LINES_DOWN, ARROW_FAT_LINE_UP, PROHIBIT_INSET};
|
||||||
|
use crate::gui::platform::PlatformCallbacks;
|
||||||
|
use crate::gui::views::{Modal, ModalPosition, View};
|
||||||
|
use crate::gui::views::network::settings::NetworkSettings;
|
||||||
|
use crate::node::{NodeConfig, PeersConfig};
|
||||||
|
|
||||||
|
/// Type of peer.
|
||||||
|
#[derive(Eq, PartialEq)]
|
||||||
|
enum PeerType {
|
||||||
|
DefaultSeed,
|
||||||
|
CustomSeed,
|
||||||
|
Allowed,
|
||||||
|
Denied,
|
||||||
|
Preferred
|
||||||
|
}
|
||||||
|
|
||||||
|
/// P2P server setup ui section.
|
||||||
|
pub struct P2PSetup {
|
||||||
|
/// P2P port value.
|
||||||
|
port_edit: String,
|
||||||
|
/// Flag to check if p2p port is available.
|
||||||
|
port_available_edit: bool,
|
||||||
|
|
||||||
|
/// Flag to check if p2p port from saved config value is available.
|
||||||
|
is_port_available: bool,
|
||||||
|
|
||||||
|
/// Flag to check if entered peer address is correct and/or available.
|
||||||
|
is_correct_address_edit: bool,
|
||||||
|
|
||||||
|
/// Peer edit value for modal.
|
||||||
|
peer_edit: String,
|
||||||
|
/// Default main network seeds.
|
||||||
|
default_main_seeds: Vec<String>,
|
||||||
|
/// Default test network seeds.
|
||||||
|
default_test_seeds: Vec<String>,
|
||||||
|
|
||||||
|
/// How long banned peer should stay banned.
|
||||||
|
ban_window_edit: String,
|
||||||
|
|
||||||
|
/// Maximum number of inbound peer connections.
|
||||||
|
max_inbound_count: String,
|
||||||
|
|
||||||
|
/// Maximum number of outbound peer connections.
|
||||||
|
max_outbound_count: String,
|
||||||
|
|
||||||
|
/// Preferred minimum number of outbound peers.
|
||||||
|
min_outbound_count: String
|
||||||
|
}
|
||||||
|
|
||||||
|
impl Default for P2PSetup {
|
||||||
|
fn default() -> Self {
|
||||||
|
let port = NodeConfig::get_p2p_port();
|
||||||
|
let is_port_available = NodeConfig::is_p2p_port_available(&port);
|
||||||
|
let default_main_seeds = grin_servers::MAINNET_DNS_SEEDS
|
||||||
|
.iter()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect();
|
||||||
|
let default_test_seeds = grin_servers::TESTNET_DNS_SEEDS
|
||||||
|
.into_iter()
|
||||||
|
.map(|s| s.to_string())
|
||||||
|
.collect();
|
||||||
|
Self {
|
||||||
|
port_edit: port,
|
||||||
|
port_available_edit: is_port_available,
|
||||||
|
is_correct_address_edit: true,
|
||||||
|
is_port_available,
|
||||||
|
peer_edit: "".to_string(),
|
||||||
|
default_main_seeds,
|
||||||
|
default_test_seeds,
|
||||||
|
ban_window_edit: NodeConfig::get_p2p_ban_window(),
|
||||||
|
max_inbound_count: NodeConfig::get_max_inbound_peers(),
|
||||||
|
max_outbound_count: NodeConfig::get_max_outbound_peers(),
|
||||||
|
min_outbound_count: NodeConfig::get_min_outbound_peers(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl P2PSetup {
|
||||||
|
/// Identifier for port value [`Modal`].
|
||||||
|
pub const PORT_MODAL: &'static str = "p2p_port";
|
||||||
|
/// Identifier for custom seed [`Modal`].
|
||||||
|
pub const CUSTOM_SEED_MODAL: &'static str = "p2p_custom_seed";
|
||||||
|
/// Identifier for allowed peer [`Modal`].
|
||||||
|
pub const ALLOW_PEER_MODAL: &'static str = "p2p_allow_peer";
|
||||||
|
/// Identifier for denied peer [`Modal`].
|
||||||
|
pub const DENY_PEER_MODAL: &'static str = "p2p_deny_peer";
|
||||||
|
/// Identifier for preferred peer [`Modal`].
|
||||||
|
pub const PREFER_PEER_MODAL: &'static str = "p2p_prefer_peer";
|
||||||
|
/// Identifier for ban window [`Modal`].
|
||||||
|
pub const BAN_WINDOW_MODAL: &'static str = "p2p_ban_window";
|
||||||
|
/// Identifier for maximum number of inbound peers [`Modal`].
|
||||||
|
pub const MAX_INBOUND_MODAL: &'static str = "p2p_max_inbound";
|
||||||
|
/// Identifier for maximum number of outbound peers [`Modal`].
|
||||||
|
pub const MAX_OUTBOUND_MODAL: &'static str = "p2p_max_outbound";
|
||||||
|
/// Identifier for minimum number of outbound peers [`Modal`].
|
||||||
|
pub const MIN_OUTBOUND_MODAL: &'static str = "p2p_min_outbound";
|
||||||
|
|
||||||
|
/// Title for custom DNS Seeds setup section.
|
||||||
|
const DNS_SEEDS_TITLE: &'static str = "DNS Seeds";
|
||||||
|
|
||||||
|
pub fn ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||||
|
View::sub_title(ui, format!("{} {}", HANDSHAKE, t!("network_settings.p2p_server")));
|
||||||
|
View::horizontal_line(ui, Colors::STROKE);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
// Show p2p port setup.
|
||||||
|
self.port_ui(ui, cb);
|
||||||
|
|
||||||
|
ui.add_space(6.0);
|
||||||
|
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
// Show seeding type setup.
|
||||||
|
self.seeding_type_ui(ui, cb);
|
||||||
|
|
||||||
|
ui.add_space(6.0);
|
||||||
|
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
ui.label(RichText::new(t!("network_settings.allow_list"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::GRAY));
|
||||||
|
ui.add_space(6.0);
|
||||||
|
// Show allowed peers setup.
|
||||||
|
self.peer_list_ui(ui, &PeerType::Allowed, cb);
|
||||||
|
|
||||||
|
ui.add_space(6.0);
|
||||||
|
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
ui.label(RichText::new(t!("network_settings.deny_list"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::GRAY));
|
||||||
|
ui.add_space(6.0);
|
||||||
|
// Show denied peers setup.
|
||||||
|
self.peer_list_ui(ui, &PeerType::Denied, cb);
|
||||||
|
|
||||||
|
ui.add_space(6.0);
|
||||||
|
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
ui.label(RichText::new(t!("network_settings.favourites"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::GRAY));
|
||||||
|
ui.add_space(6.0);
|
||||||
|
// Show preferred peers setup.
|
||||||
|
self.peer_list_ui(ui, &PeerType::Preferred, cb);
|
||||||
|
|
||||||
|
|
||||||
|
ui.add_space(6.0);
|
||||||
|
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
// Show ban window setup.
|
||||||
|
self.ban_window_ui(ui, cb);
|
||||||
|
|
||||||
|
ui.add_space(6.0);
|
||||||
|
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
// Show maximum inbound peers value setup.
|
||||||
|
self.max_inbound_ui(ui, cb);
|
||||||
|
|
||||||
|
ui.add_space(6.0);
|
||||||
|
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
// Show maximum outbound peers value setup.
|
||||||
|
self.max_outbound_ui(ui, cb);
|
||||||
|
|
||||||
|
ui.add_space(6.0);
|
||||||
|
View::horizontal_line(ui, Colors::ITEM_STROKE);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
// Show minimum outbound peers value setup.
|
||||||
|
self.min_outbound_ui(ui, cb);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw p2p port setup content.
|
||||||
|
fn port_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||||
|
ui.label(RichText::new(t!("network_settings.p2p_port"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::GRAY)
|
||||||
|
);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
let port = NodeConfig::get_p2p_port();
|
||||||
|
View::button(ui, format!("{} {}", PLUG, port.clone()), Colors::BUTTON, || {
|
||||||
|
// Setup values for modal.
|
||||||
|
self.port_edit = port;
|
||||||
|
self.port_available_edit = self.is_port_available;
|
||||||
|
// Show p2p port modal.
|
||||||
|
let port_modal = Modal::new(Self::PORT_MODAL)
|
||||||
|
.position(ModalPosition::CenterTop)
|
||||||
|
.title(t!("network_settings.change_value"));
|
||||||
|
Navigator::show_modal(port_modal);
|
||||||
|
cb.show_keyboard();
|
||||||
|
});
|
||||||
|
ui.add_space(12.0);
|
||||||
|
|
||||||
|
// Show error when stratum server port is unavailable.
|
||||||
|
if !self.is_port_available {
|
||||||
|
ui.add_space(6.0);
|
||||||
|
ui.label(RichText::new(t!("network_settings.port_unavailable"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::RED));
|
||||||
|
ui.add_space(12.0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw p2p port [`Modal`] content.
|
||||||
|
pub fn port_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||||
|
ui.add_space(6.0);
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.label(RichText::new(t!("network_settings.p2p_port"))
|
||||||
|
.size(18.0)
|
||||||
|
.color(Colors::GRAY));
|
||||||
|
ui.add_space(8.0);
|
||||||
|
|
||||||
|
// Draw p2p port text edit.
|
||||||
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.port_edit)
|
||||||
|
.id(Id::from(modal.id))
|
||||||
|
.font(TextStyle::Heading)
|
||||||
|
.desired_width(58.0)
|
||||||
|
.cursor_at_end(true)
|
||||||
|
.ui(ui);
|
||||||
|
text_edit_resp.request_focus();
|
||||||
|
if text_edit_resp.clicked() {
|
||||||
|
cb.show_keyboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show error when specified port is unavailable.
|
||||||
|
if !self.port_available_edit {
|
||||||
|
ui.add_space(12.0);
|
||||||
|
ui.label(RichText::new(t!("network_settings.port_unavailable"))
|
||||||
|
.size(18.0)
|
||||||
|
.color(Colors::RED));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.add_space(12.0);
|
||||||
|
|
||||||
|
// Show modal buttons.
|
||||||
|
ui.scope(|ui| {
|
||||||
|
// Setup spacing between buttons.
|
||||||
|
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||||
|
|
||||||
|
// Save button callback.
|
||||||
|
let on_save = || {
|
||||||
|
// Check if port is available.
|
||||||
|
let available = NodeConfig::is_p2p_port_available(&self.port_edit);
|
||||||
|
self.port_available_edit = available;
|
||||||
|
|
||||||
|
// Save port at config if it's available.
|
||||||
|
if available {
|
||||||
|
NodeConfig::save_p2p_port(self.port_edit.parse::<u16>().unwrap());
|
||||||
|
|
||||||
|
self.is_port_available = true;
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ui.columns(2, |columns| {
|
||||||
|
columns[0].vertical_centered_justified(|ui| {
|
||||||
|
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||||
|
// Close modal.
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
columns[1].vertical_centered_justified(|ui| {
|
||||||
|
View::button(ui, t!("modal.save"), Colors::WHITE, on_save);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ui.add_space(6.0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw peer list content based on provided [`PeerType`].
|
||||||
|
fn peer_list_ui(&mut self, ui: &mut Ui, peer_type: &PeerType, cb: &dyn PlatformCallbacks) {
|
||||||
|
let peer_list = match peer_type {
|
||||||
|
PeerType::DefaultSeed => {
|
||||||
|
if AppConfig::chain_type() == ChainTypes::Testnet {
|
||||||
|
self.default_test_seeds.clone()
|
||||||
|
} else {
|
||||||
|
self.default_main_seeds.clone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
PeerType::CustomSeed => NodeConfig::get_custom_seeds(),
|
||||||
|
PeerType::Allowed => NodeConfig::get_allowed_peers(),
|
||||||
|
PeerType::Denied => NodeConfig::get_denied_peers(),
|
||||||
|
PeerType::Preferred => NodeConfig::get_preferred_peers()
|
||||||
|
};
|
||||||
|
for (index, peer) in peer_list.iter().enumerate() {
|
||||||
|
let rounding = if peer_list.len() == 1 {
|
||||||
|
[true, true]
|
||||||
|
} else if index == 0 {
|
||||||
|
[true, false]
|
||||||
|
} else if index == peer_list.len() - 1 {
|
||||||
|
[false, true]
|
||||||
|
} else {
|
||||||
|
[false, false]
|
||||||
|
};
|
||||||
|
ui.horizontal_wrapped(|ui| {
|
||||||
|
// Draw peer list item.
|
||||||
|
Self::peer_item_ui(ui, peer, peer_type, rounding);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if peer_type != &PeerType::DefaultSeed {
|
||||||
|
// Draw description.
|
||||||
|
if peer_type != &PeerType::CustomSeed {
|
||||||
|
if !peer_list.is_empty() {
|
||||||
|
ui.add_space(12.0);
|
||||||
|
}
|
||||||
|
let desc = match peer_type {
|
||||||
|
PeerType::Allowed => t!("network_settings.allow_list_desc"),
|
||||||
|
PeerType::Denied => t!("network_settings.deny_list_desc"),
|
||||||
|
&_ => t!("network_settings.favourites_desc"),
|
||||||
|
};
|
||||||
|
ui.label(RichText::new(desc)
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::INACTIVE_TEXT));
|
||||||
|
ui.add_space(12.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
let add_text = if peer_type == &PeerType::CustomSeed {
|
||||||
|
format!("{} {}", PLUS_CIRCLE, t!("network_settings.add_seed"))
|
||||||
|
} else {
|
||||||
|
format!("{} {}", PLUS_CIRCLE, t!("network_settings.add_peer"))
|
||||||
|
|
||||||
|
};
|
||||||
|
View::button(ui, add_text, Colors::GOLD, || {
|
||||||
|
// Setup values for modal.
|
||||||
|
self.peer_edit = "".to_string();
|
||||||
|
// Select modal id.
|
||||||
|
let modal_id = match peer_type {
|
||||||
|
PeerType::Allowed => Self::ALLOW_PEER_MODAL,
|
||||||
|
PeerType::Denied => Self::DENY_PEER_MODAL,
|
||||||
|
PeerType::Preferred => Self::PREFER_PEER_MODAL,
|
||||||
|
_ => Self::CUSTOM_SEED_MODAL
|
||||||
|
};
|
||||||
|
// Select modal title.
|
||||||
|
let modal_title = match peer_type {
|
||||||
|
PeerType::Allowed => t!("network_settings.allow_list"),
|
||||||
|
PeerType::Denied => t!("network_settings.deny_list"),
|
||||||
|
PeerType::Preferred => t!("network_settings.favourites"),
|
||||||
|
_ => Self::DNS_SEEDS_TITLE.to_string()
|
||||||
|
};
|
||||||
|
// Show modal to add peer.
|
||||||
|
let peer_modal = Modal::new(modal_id)
|
||||||
|
.position(ModalPosition::CenterTop)
|
||||||
|
.title(modal_title);
|
||||||
|
Navigator::show_modal(peer_modal);
|
||||||
|
cb.show_keyboard();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
ui.add_space(6.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw peer creation [`Modal`] content.
|
||||||
|
pub fn peer_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||||
|
ui.add_space(6.0);
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
let label_text = match modal.id {
|
||||||
|
Self::CUSTOM_SEED_MODAL => t!("network_settings.add_seed"),
|
||||||
|
&_ => t!("network_settings.add_peer")
|
||||||
|
};
|
||||||
|
ui.label(RichText::new(label_text).size(18.0).color(Colors::GRAY));
|
||||||
|
ui.add_space(8.0);
|
||||||
|
|
||||||
|
// Draw peer address text edit.
|
||||||
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.peer_edit)
|
||||||
|
.id(Id::from(modal.id))
|
||||||
|
.font(TextStyle::Heading)
|
||||||
|
.desired_width(ui.available_width())
|
||||||
|
.cursor_at_end(true)
|
||||||
|
.ui(ui);
|
||||||
|
text_edit_resp.request_focus();
|
||||||
|
if text_edit_resp.clicked() {
|
||||||
|
cb.show_keyboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show error when specified address is incorrect.
|
||||||
|
if !self.is_correct_address_edit {
|
||||||
|
ui.add_space(12.0);
|
||||||
|
ui.label(RichText::new(t!("network_settings.peer_address_error"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::RED));
|
||||||
|
}
|
||||||
|
|
||||||
|
ui.add_space(12.0);
|
||||||
|
|
||||||
|
// Show modal buttons.
|
||||||
|
ui.scope(|ui| {
|
||||||
|
// Setup spacing between buttons.
|
||||||
|
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||||
|
|
||||||
|
// Save button callback.
|
||||||
|
let on_save = || {
|
||||||
|
// Check if peer is correct and/or available.
|
||||||
|
let peer = self.peer_edit.clone();
|
||||||
|
let is_correct_address = PeersConfig::peer_to_addr(peer.clone()).is_some();
|
||||||
|
self.is_correct_address_edit = is_correct_address;
|
||||||
|
|
||||||
|
// Save peer at config.
|
||||||
|
if is_correct_address {
|
||||||
|
match modal.id {
|
||||||
|
Self::CUSTOM_SEED_MODAL => NodeConfig::save_custom_seed(peer),
|
||||||
|
Self::ALLOW_PEER_MODAL => NodeConfig::allow_peer(peer),
|
||||||
|
Self::DENY_PEER_MODAL => NodeConfig::deny_peer(peer),
|
||||||
|
Self::PREFER_PEER_MODAL => NodeConfig::prefer_peer(peer),
|
||||||
|
&_ => {}
|
||||||
|
}
|
||||||
|
|
||||||
|
self.is_port_available = true;
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ui.columns(2, |columns| {
|
||||||
|
columns[0].vertical_centered_justified(|ui| {
|
||||||
|
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||||
|
// Close modal.
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
columns[1].vertical_centered_justified(|ui| {
|
||||||
|
View::button(ui, t!("modal.save"), Colors::WHITE, on_save);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ui.add_space(6.0);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw peer list item.
|
||||||
|
fn peer_item_ui(ui: &mut Ui, peer_addr: &String, peer_type: &PeerType, rounding: [bool; 2]) {
|
||||||
|
// Draw round background.
|
||||||
|
let mut rect = ui.available_rect_before_wrap();
|
||||||
|
rect.min += egui::emath::vec2(6.0, 0.0);
|
||||||
|
rect.set_height(42.0);
|
||||||
|
ui.painter().rect(
|
||||||
|
rect,
|
||||||
|
Rounding {
|
||||||
|
nw: if rounding[0] { 6.0 } else { 0.0 },
|
||||||
|
ne: if rounding[0] { 6.0 } else { 0.0 },
|
||||||
|
sw: if rounding[1] { 6.0 } else { 0.0 },
|
||||||
|
se: if rounding[1] { 6.0 } else { 0.0 },
|
||||||
|
},
|
||||||
|
Colors::WHITE,
|
||||||
|
Stroke { width: 1.0, color: Colors::ITEM_STROKE }
|
||||||
|
);
|
||||||
|
|
||||||
|
StripBuilder::new(ui)
|
||||||
|
.size(Size::exact(42.0))
|
||||||
|
.vertical(|mut strip| {
|
||||||
|
strip.strip(|builder| {
|
||||||
|
builder
|
||||||
|
.size(Size::exact(13.0))
|
||||||
|
.size(Size::remainder())
|
||||||
|
.size(Size::exact(46.0))
|
||||||
|
.horizontal(|mut strip| {
|
||||||
|
strip.empty();
|
||||||
|
strip.cell(|ui| {
|
||||||
|
ui.horizontal_centered(|ui| {
|
||||||
|
// Draw peer address.
|
||||||
|
let peer_text = format!("{} {}", GLOBE_SIMPLE, &peer_addr);
|
||||||
|
ui.label(RichText::new(peer_text)
|
||||||
|
.color(Colors::TEXT_BUTTON)
|
||||||
|
.size(17.0));
|
||||||
|
});
|
||||||
|
});
|
||||||
|
if peer_type != &PeerType::DefaultSeed {
|
||||||
|
strip.cell(|ui| {
|
||||||
|
// Draw delete button for non-default seed peers.
|
||||||
|
View::button(ui, TRASH.to_string(), Colors::BUTTON, || {
|
||||||
|
match peer_type {
|
||||||
|
PeerType::CustomSeed => {
|
||||||
|
NodeConfig::remove_custom_seed(peer_addr);
|
||||||
|
}
|
||||||
|
PeerType::Allowed => {
|
||||||
|
NodeConfig::remove_allowed_peer(peer_addr);
|
||||||
|
}
|
||||||
|
PeerType::Denied => {
|
||||||
|
NodeConfig::remove_denied_peer(peer_addr);
|
||||||
|
}
|
||||||
|
PeerType::Preferred => {
|
||||||
|
NodeConfig::remove_preferred_peer(peer_addr);
|
||||||
|
}
|
||||||
|
PeerType::DefaultSeed => {}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
strip.empty();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw seeding type setup content.
|
||||||
|
fn seeding_type_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||||
|
let title = Self::DNS_SEEDS_TITLE;
|
||||||
|
ui.label(RichText::new(title).size(16.0).color(Colors::GRAY));
|
||||||
|
ui.add_space(2.0);
|
||||||
|
|
||||||
|
let default_seeding = NodeConfig::is_default_seeding_type();
|
||||||
|
View::checkbox(ui, default_seeding, t!("network_settings.default"), || {
|
||||||
|
NodeConfig::toggle_seeding_type();
|
||||||
|
});
|
||||||
|
ui.add_space(8.0);
|
||||||
|
|
||||||
|
let peers_type = if default_seeding {
|
||||||
|
PeerType::DefaultSeed
|
||||||
|
} else {
|
||||||
|
PeerType::CustomSeed
|
||||||
|
};
|
||||||
|
self.peer_list_ui(ui, &peers_type, cb);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw ban window setup content.
|
||||||
|
fn ban_window_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||||
|
ui.label(RichText::new(t!("network_settings.ban_window"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::GRAY)
|
||||||
|
);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
let ban_window = NodeConfig::get_p2p_ban_window();
|
||||||
|
View::button(ui, format!("{} {}", PROHIBIT_INSET, ban_window.clone()), Colors::BUTTON, || {
|
||||||
|
// Setup values for modal.
|
||||||
|
self.ban_window_edit = ban_window;
|
||||||
|
// Show ban window period setup modal.
|
||||||
|
let ban_modal = Modal::new(Self::BAN_WINDOW_MODAL)
|
||||||
|
.position(ModalPosition::CenterTop)
|
||||||
|
.title(t!("network_settings.change_value"));
|
||||||
|
Navigator::show_modal(ban_modal);
|
||||||
|
cb.show_keyboard();
|
||||||
|
});
|
||||||
|
ui.add_space(6.0);
|
||||||
|
ui.label(RichText::new(t!("network_settings.ban_window_desc"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::INACTIVE_TEXT)
|
||||||
|
);
|
||||||
|
ui.add_space(2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw ban window [`Modal`] content.
|
||||||
|
pub fn ban_window_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||||
|
ui.add_space(6.0);
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.label(RichText::new(t!("network_settings.ban_window"))
|
||||||
|
.size(18.0)
|
||||||
|
.color(Colors::GRAY));
|
||||||
|
ui.add_space(8.0);
|
||||||
|
|
||||||
|
// Draw ban window text edit.
|
||||||
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.ban_window_edit)
|
||||||
|
.id(Id::from(modal.id))
|
||||||
|
.font(TextStyle::Heading)
|
||||||
|
.desired_width(84.0)
|
||||||
|
.cursor_at_end(true)
|
||||||
|
.ui(ui);
|
||||||
|
text_edit_resp.request_focus();
|
||||||
|
if text_edit_resp.clicked() {
|
||||||
|
cb.show_keyboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show error when specified value is not valid or reminder to restart enabled node.
|
||||||
|
if self.ban_window_edit.parse::<i64>().is_err() {
|
||||||
|
ui.add_space(12.0);
|
||||||
|
ui.label(RichText::new(t!("network_settings.not_valid_value"))
|
||||||
|
.size(18.0)
|
||||||
|
.color(Colors::RED));
|
||||||
|
} else {
|
||||||
|
NetworkSettings::node_restart_required_ui(ui);
|
||||||
|
}
|
||||||
|
ui.add_space(12.0);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show modal buttons.
|
||||||
|
ui.scope(|ui| {
|
||||||
|
// Setup spacing between buttons.
|
||||||
|
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||||
|
|
||||||
|
// Save button callback.
|
||||||
|
let on_save = || {
|
||||||
|
if let Ok(ban_window) = self.ban_window_edit.parse::<i64>() {
|
||||||
|
NodeConfig::save_p2p_ban_window(ban_window);
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ui.columns(2, |columns| {
|
||||||
|
columns[0].vertical_centered_justified(|ui| {
|
||||||
|
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||||
|
// Close modal.
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
columns[1].vertical_centered_justified(|ui| {
|
||||||
|
View::button(ui, t!("modal.save"), Colors::WHITE, on_save);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ui.add_space(6.0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw maximum number of inbound peers setup content.
|
||||||
|
fn max_inbound_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||||
|
ui.label(RichText::new(t!("network_settings.max_inbound_count"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::GRAY)
|
||||||
|
);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
let max_inbound = NodeConfig::get_max_inbound_peers();
|
||||||
|
let button_text = format!("{} {}", ARROW_FAT_LINES_DOWN, max_inbound.clone());
|
||||||
|
View::button(ui, button_text, Colors::BUTTON, || {
|
||||||
|
// Setup values for modal.
|
||||||
|
self.max_inbound_count = max_inbound;
|
||||||
|
// Show maximum number of inbound peers setup modal.
|
||||||
|
let max_inbound_modal = Modal::new(Self::MAX_INBOUND_MODAL)
|
||||||
|
.position(ModalPosition::CenterTop)
|
||||||
|
.title(t!("network_settings.change_value"));
|
||||||
|
Navigator::show_modal(max_inbound_modal);
|
||||||
|
cb.show_keyboard();
|
||||||
|
});
|
||||||
|
ui.add_space(6.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw maximum number of inbound peers [`Modal`] content.
|
||||||
|
pub fn max_inbound_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||||
|
ui.add_space(6.0);
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.label(RichText::new(t!("network_settings.max_inbound_count"))
|
||||||
|
.size(18.0)
|
||||||
|
.color(Colors::GRAY));
|
||||||
|
ui.add_space(8.0);
|
||||||
|
|
||||||
|
// Draw maximum number of inbound peers text edit.
|
||||||
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.max_inbound_count)
|
||||||
|
.id(Id::from(modal.id))
|
||||||
|
.font(TextStyle::Heading)
|
||||||
|
.desired_width(42.0)
|
||||||
|
.cursor_at_end(true)
|
||||||
|
.ui(ui);
|
||||||
|
text_edit_resp.request_focus();
|
||||||
|
if text_edit_resp.clicked() {
|
||||||
|
cb.show_keyboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show error when specified value is not valid or reminder to restart enabled node.
|
||||||
|
if self.max_inbound_count.parse::<u32>().is_err() {
|
||||||
|
ui.add_space(12.0);
|
||||||
|
ui.label(RichText::new(t!("network_settings.not_valid_value"))
|
||||||
|
.size(18.0)
|
||||||
|
.color(Colors::RED));
|
||||||
|
} else {
|
||||||
|
NetworkSettings::node_restart_required_ui(ui);
|
||||||
|
}
|
||||||
|
ui.add_space(12.0);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show modal buttons.
|
||||||
|
ui.scope(|ui| {
|
||||||
|
// Setup spacing between buttons.
|
||||||
|
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||||
|
|
||||||
|
// Save button callback.
|
||||||
|
let on_save = || {
|
||||||
|
if let Ok(max_inbound) = self.max_inbound_count.parse::<u32>() {
|
||||||
|
NodeConfig::save_max_inbound_peers(max_inbound);
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ui.columns(2, |columns| {
|
||||||
|
columns[0].vertical_centered_justified(|ui| {
|
||||||
|
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||||
|
// Close modal.
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
columns[1].vertical_centered_justified(|ui| {
|
||||||
|
View::button(ui, t!("modal.save"), Colors::WHITE, on_save);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ui.add_space(6.0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw maximum number of outbound peers setup content.
|
||||||
|
fn max_outbound_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||||
|
ui.label(RichText::new(t!("network_settings.max_outbound_count"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::GRAY)
|
||||||
|
);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
let max_outbound = NodeConfig::get_max_outbound_peers();
|
||||||
|
let button_text = format!("{} {}", ARROW_FAT_LINES_UP, max_outbound.clone());
|
||||||
|
View::button(ui, button_text, Colors::BUTTON, || {
|
||||||
|
// Setup values for modal.
|
||||||
|
self.max_outbound_count = max_outbound;
|
||||||
|
// Show maximum number of outbound peers setup modal.
|
||||||
|
let max_outbound = Modal::new(Self::MAX_OUTBOUND_MODAL)
|
||||||
|
.position(ModalPosition::CenterTop)
|
||||||
|
.title(t!("network_settings.change_value"));
|
||||||
|
Navigator::show_modal(max_outbound);
|
||||||
|
cb.show_keyboard();
|
||||||
|
});
|
||||||
|
ui.add_space(2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw maximum number of outbound peers [`Modal`] content.
|
||||||
|
pub fn max_outbound_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||||
|
ui.add_space(6.0);
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.label(RichText::new(t!("network_settings.max_outbound_count"))
|
||||||
|
.size(18.0)
|
||||||
|
.color(Colors::GRAY));
|
||||||
|
ui.add_space(8.0);
|
||||||
|
|
||||||
|
// Draw maximum number of outbound peers text edit.
|
||||||
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.max_outbound_count)
|
||||||
|
.id(Id::from(modal.id))
|
||||||
|
.font(TextStyle::Heading)
|
||||||
|
.desired_width(42.0)
|
||||||
|
.cursor_at_end(true)
|
||||||
|
.ui(ui);
|
||||||
|
text_edit_resp.request_focus();
|
||||||
|
if text_edit_resp.clicked() {
|
||||||
|
cb.show_keyboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show error when specified value is not valid or reminder to restart enabled node.
|
||||||
|
if self.max_outbound_count.parse::<u32>().is_err() {
|
||||||
|
ui.add_space(12.0);
|
||||||
|
ui.label(RichText::new(t!("network_settings.not_valid_value"))
|
||||||
|
.size(18.0)
|
||||||
|
.color(Colors::RED));
|
||||||
|
} else {
|
||||||
|
NetworkSettings::node_restart_required_ui(ui);
|
||||||
|
}
|
||||||
|
ui.add_space(12.0);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show modal buttons.
|
||||||
|
ui.scope(|ui| {
|
||||||
|
// Setup spacing between buttons.
|
||||||
|
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||||
|
|
||||||
|
// Save button callback.
|
||||||
|
let on_save = || {
|
||||||
|
if let Ok(max_outbound) = self.max_outbound_count.parse::<u32>() {
|
||||||
|
NodeConfig::save_max_outbound_peers(max_outbound);
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ui.columns(2, |columns| {
|
||||||
|
columns[0].vertical_centered_justified(|ui| {
|
||||||
|
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||||
|
// Close modal.
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
columns[1].vertical_centered_justified(|ui| {
|
||||||
|
View::button(ui, t!("modal.save"), Colors::WHITE, on_save);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ui.add_space(6.0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw minimum number of outbound peers setup content.
|
||||||
|
fn min_outbound_ui(&mut self, ui: &mut Ui, cb: &dyn PlatformCallbacks) {
|
||||||
|
ui.label(RichText::new(t!("network_settings.min_outbound_count"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::GRAY)
|
||||||
|
);
|
||||||
|
ui.add_space(6.0);
|
||||||
|
|
||||||
|
let min_outbound = NodeConfig::get_min_outbound_peers();
|
||||||
|
let button_text = format!("{} {}", ARROW_FAT_LINE_UP, min_outbound.clone());
|
||||||
|
View::button(ui, button_text, Colors::BUTTON, || {
|
||||||
|
// Setup values for modal.
|
||||||
|
self.min_outbound_count = min_outbound;
|
||||||
|
// Show maximum number of outbound peers setup modal.
|
||||||
|
let min_outbound = Modal::new(Self::MIN_OUTBOUND_MODAL)
|
||||||
|
.position(ModalPosition::CenterTop)
|
||||||
|
.title(t!("network_settings.change_value"));
|
||||||
|
Navigator::show_modal(min_outbound);
|
||||||
|
cb.show_keyboard();
|
||||||
|
});
|
||||||
|
ui.add_space(6.0);
|
||||||
|
ui.label(RichText::new(t!("network_settings.min_outbound_desc"))
|
||||||
|
.size(16.0)
|
||||||
|
.color(Colors::INACTIVE_TEXT)
|
||||||
|
);
|
||||||
|
ui.add_space(2.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Draw minimum number of outbound peers [`Modal`] content.
|
||||||
|
pub fn min_outbound_modal(&mut self, ui: &mut Ui, modal: &Modal, cb: &dyn PlatformCallbacks) {
|
||||||
|
ui.add_space(6.0);
|
||||||
|
ui.vertical_centered(|ui| {
|
||||||
|
ui.label(RichText::new(t!("network_settings.min_outbound_count"))
|
||||||
|
.size(18.0)
|
||||||
|
.color(Colors::GRAY));
|
||||||
|
ui.add_space(8.0);
|
||||||
|
|
||||||
|
// Draw maximum number of outbound peers text edit.
|
||||||
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.min_outbound_count)
|
||||||
|
.id(Id::from(modal.id))
|
||||||
|
.font(TextStyle::Heading)
|
||||||
|
.desired_width(42.0)
|
||||||
|
.cursor_at_end(true)
|
||||||
|
.ui(ui);
|
||||||
|
text_edit_resp.request_focus();
|
||||||
|
if text_edit_resp.clicked() {
|
||||||
|
cb.show_keyboard();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Show error when specified value is not valid or reminder to restart enabled node.
|
||||||
|
if self.min_outbound_count.parse::<u32>().is_err() {
|
||||||
|
ui.add_space(12.0);
|
||||||
|
ui.label(RichText::new(t!("network_settings.not_valid_value"))
|
||||||
|
.size(18.0)
|
||||||
|
.color(Colors::RED));
|
||||||
|
} else {
|
||||||
|
NetworkSettings::node_restart_required_ui(ui);
|
||||||
|
}
|
||||||
|
ui.add_space(12.0);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Show modal buttons.
|
||||||
|
ui.scope(|ui| {
|
||||||
|
// Setup spacing between buttons.
|
||||||
|
ui.spacing_mut().item_spacing = egui::Vec2::new(8.0, 0.0);
|
||||||
|
|
||||||
|
// Save button callback.
|
||||||
|
let on_save = || {
|
||||||
|
if let Ok(max_outbound) = self.min_outbound_count.parse::<u32>() {
|
||||||
|
NodeConfig::save_min_outbound_peers(max_outbound);
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
ui.columns(2, |columns| {
|
||||||
|
columns[0].vertical_centered_justified(|ui| {
|
||||||
|
View::button(ui, t!("modal.cancel"), Colors::WHITE, || {
|
||||||
|
// Close modal.
|
||||||
|
cb.hide_keyboard();
|
||||||
|
modal.close();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
columns[1].vertical_centered_justified(|ui| {
|
||||||
|
View::button(ui, t!("modal.save"), Colors::WHITE, on_save);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
ui.add_space(6.0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -137,7 +137,7 @@ impl PoolSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.fee_base_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.fee_base_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(70.0)
|
.desired_width(76.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
@ -222,7 +222,7 @@ impl PoolSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.reorg_period_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.reorg_period_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(36.0)
|
.desired_width(42.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
@ -307,7 +307,7 @@ impl PoolSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.pool_size_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.pool_size_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(58.0)
|
.desired_width(64.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
@ -392,7 +392,7 @@ impl PoolSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.stempool_size_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.stempool_size_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(58.0)
|
.desired_width(64.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
@ -477,7 +477,7 @@ impl PoolSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.max_weight_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.max_weight_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(58.0)
|
.desired_width(64.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
|
|
@ -32,7 +32,7 @@ pub struct StratumSetup {
|
||||||
stratum_port_available_edit: bool,
|
stratum_port_available_edit: bool,
|
||||||
|
|
||||||
/// Flag to check if stratum port from saved config value is available.
|
/// Flag to check if stratum port from saved config value is available.
|
||||||
pub(crate) is_port_available: bool,
|
is_port_available: bool,
|
||||||
|
|
||||||
/// Attempt time value in seconds to mine on a particular header.
|
/// Attempt time value in seconds to mine on a particular header.
|
||||||
attempt_time_edit: String,
|
attempt_time_edit: String,
|
||||||
|
@ -192,7 +192,7 @@ impl StratumSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.stratum_port_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.stratum_port_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(58.0)
|
.desired_width(64.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
@ -288,7 +288,7 @@ impl StratumSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.attempt_time_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.attempt_time_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(36.0)
|
.desired_width(42.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
@ -374,7 +374,7 @@ impl StratumSetup {
|
||||||
let text_edit_resp = egui::TextEdit::singleline(&mut self.min_share_diff_edit)
|
let text_edit_resp = egui::TextEdit::singleline(&mut self.min_share_diff_edit)
|
||||||
.id(Id::from(modal.id))
|
.id(Id::from(modal.id))
|
||||||
.font(TextStyle::Heading)
|
.font(TextStyle::Heading)
|
||||||
.desired_width(36.0)
|
.desired_width(42.0)
|
||||||
.cursor_at_end(true)
|
.cursor_at_end(true)
|
||||||
.ui(ui);
|
.ui(ui);
|
||||||
text_edit_resp.request_focus();
|
text_edit_resp.request_focus();
|
||||||
|
|
|
@ -21,11 +21,12 @@ use grin_chain::SyncStatus;
|
||||||
|
|
||||||
use crate::AppConfig;
|
use crate::AppConfig;
|
||||||
use crate::gui::{Colors, Navigator};
|
use crate::gui::{Colors, Navigator};
|
||||||
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE};
|
use crate::gui::icons::{CARDHOLDER, DATABASE, DOTS_THREE_OUTLINE_VERTICAL, FACTORY, FADERS, GAUGE, POWER};
|
||||||
use crate::gui::platform::PlatformCallbacks;
|
use crate::gui::platform::PlatformCallbacks;
|
||||||
use crate::gui::views::{Modal, ModalContainer, TitlePanel, View};
|
use crate::gui::views::{Modal, ModalContainer, TitlePanel, View};
|
||||||
use crate::gui::views::network::configs::dandelion::DandelionSetup;
|
use crate::gui::views::network::configs::dandelion::DandelionSetup;
|
||||||
use crate::gui::views::network::configs::node::NodeSetup;
|
use crate::gui::views::network::configs::node::NodeSetup;
|
||||||
|
use crate::gui::views::network::configs::p2p::P2PSetup;
|
||||||
use crate::gui::views::network::configs::pool::PoolSetup;
|
use crate::gui::views::network::configs::pool::PoolSetup;
|
||||||
use crate::gui::views::network::configs::stratum::StratumSetup;
|
use crate::gui::views::network::configs::stratum::StratumSetup;
|
||||||
use crate::gui::views::network::metrics::NetworkMetrics;
|
use crate::gui::views::network::metrics::NetworkMetrics;
|
||||||
|
@ -77,6 +78,16 @@ impl Default for NetworkContainer {
|
||||||
NodeSetup::API_SECRET_MODAL,
|
NodeSetup::API_SECRET_MODAL,
|
||||||
NodeSetup::FOREIGN_API_SECRET_MODAL,
|
NodeSetup::FOREIGN_API_SECRET_MODAL,
|
||||||
NodeSetup::FTL_MODAL,
|
NodeSetup::FTL_MODAL,
|
||||||
|
// P2P setup modals.
|
||||||
|
P2PSetup::PORT_MODAL,
|
||||||
|
P2PSetup::CUSTOM_SEED_MODAL,
|
||||||
|
P2PSetup::ALLOW_PEER_MODAL,
|
||||||
|
P2PSetup::DENY_PEER_MODAL,
|
||||||
|
P2PSetup::PREFER_PEER_MODAL,
|
||||||
|
P2PSetup::BAN_WINDOW_MODAL,
|
||||||
|
P2PSetup::MAX_INBOUND_MODAL,
|
||||||
|
P2PSetup::MAX_OUTBOUND_MODAL,
|
||||||
|
P2PSetup::MIN_OUTBOUND_MODAL,
|
||||||
// Stratum setup modals.
|
// Stratum setup modals.
|
||||||
StratumSetup::STRATUM_PORT_MODAL,
|
StratumSetup::STRATUM_PORT_MODAL,
|
||||||
StratumSetup::ATTEMPT_TIME_MODAL,
|
StratumSetup::ATTEMPT_TIME_MODAL,
|
||||||
|
@ -114,6 +125,7 @@ impl NetworkContainer {
|
||||||
}
|
}
|
||||||
|
|
||||||
egui::TopBottomPanel::top("network_title")
|
egui::TopBottomPanel::top("network_title")
|
||||||
|
.exact_height(TitlePanel::DEFAULT_HEIGHT)
|
||||||
.resizable(false)
|
.resizable(false)
|
||||||
.frame(egui::Frame {
|
.frame(egui::Frame {
|
||||||
fill: Colors::YELLOW,
|
fill: Colors::YELLOW,
|
||||||
|
@ -187,34 +199,28 @@ impl NetworkContainer {
|
||||||
/// Draw title content.
|
/// Draw title content.
|
||||||
fn title_ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) {
|
fn title_ui(&mut self, ui: &mut egui::Ui, frame: &mut eframe::Frame) {
|
||||||
StripBuilder::new(ui)
|
StripBuilder::new(ui)
|
||||||
.size(Size::exact(TitlePanel::DEFAULT_HEIGHT))
|
.size(Size::exact(52.0))
|
||||||
.vertical(|mut strip| {
|
.size(Size::remainder())
|
||||||
|
.size(Size::exact(52.0))
|
||||||
|
.horizontal(|mut strip| {
|
||||||
|
strip.cell(|ui| {
|
||||||
|
ui.centered_and_justified(|ui| {
|
||||||
|
View::title_button(ui, DOTS_THREE_OUTLINE_VERTICAL, || {
|
||||||
|
//TODO: Show connections
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
strip.strip(|builder| {
|
strip.strip(|builder| {
|
||||||
builder
|
self.title_text_ui(builder);
|
||||||
.size(Size::exact(52.0))
|
});
|
||||||
.size(Size::remainder())
|
strip.cell(|ui| {
|
||||||
.size(Size::exact(52.0))
|
if !View::is_dual_panel_mode(frame) {
|
||||||
.horizontal(|mut strip| {
|
ui.centered_and_justified(|ui| {
|
||||||
strip.cell(|ui| {
|
View::title_button(ui, CARDHOLDER, || {
|
||||||
ui.centered_and_justified(|ui| {
|
Navigator::toggle_side_panel();
|
||||||
View::title_button(ui, DOTS_THREE_OUTLINE_VERTICAL, || {
|
|
||||||
//TODO: Actions for node
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
|
||||||
strip.strip(|builder| {
|
|
||||||
self.title_text_ui(builder);
|
|
||||||
});
|
|
||||||
strip.cell(|ui| {
|
|
||||||
if !View::is_dual_panel_mode(frame) {
|
|
||||||
ui.centered_and_justified(|ui| {
|
|
||||||
View::title_button(ui, CARDHOLDER, || {
|
|
||||||
Navigator::toggle_side_panel();
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -249,14 +255,14 @@ impl NetworkContainer {
|
||||||
bright as f32
|
bright as f32
|
||||||
};
|
};
|
||||||
|
|
||||||
// Draw sync text
|
// Draw sync status text.
|
||||||
let status_color_rgba = Rgba::from(Colors::TEXT) * color_factor;
|
let status_color_rgba = Rgba::from(Colors::TEXT) * color_factor;
|
||||||
let status_color = Color32::from(status_color_rgba);
|
let status_color = Color32::from(status_color_rgba);
|
||||||
View::ellipsize_text(ui, Node::get_sync_status_text(), 15.0, status_color);
|
View::ellipsize_text(ui, Node::get_sync_status_text(), 15.0, status_color);
|
||||||
|
|
||||||
// Repaint based on sync status
|
// Repaint delay based on sync status.
|
||||||
if idle {
|
if idle {
|
||||||
ui.ctx().request_repaint_after(Duration::from_millis(250));
|
ui.ctx().request_repaint_after(Node::STATS_UPDATE_DELAY);
|
||||||
} else {
|
} else {
|
||||||
ui.ctx().request_repaint();
|
ui.ctx().request_repaint();
|
||||||
}
|
}
|
||||||
|
@ -274,7 +280,7 @@ impl NetworkContainer {
|
||||||
.color(Colors::INACTIVE_TEXT)
|
.color(Colors::INACTIVE_TEXT)
|
||||||
);
|
);
|
||||||
ui.add_space(10.0);
|
ui.add_space(10.0);
|
||||||
View::button(ui, t!("network.enable_node"), Colors::GOLD, || {
|
View::button(ui, format!("{} {}", POWER, t!("network.enable_node")), Colors::GOLD, || {
|
||||||
Node::start();
|
Node::start();
|
||||||
});
|
});
|
||||||
ui.add_space(2.0);
|
ui.add_space(2.0);
|
||||||
|
|
|
@ -164,8 +164,7 @@ impl NetworkTab for NetworkNode {
|
||||||
// Show peer stats when available.
|
// Show peer stats when available.
|
||||||
if stats.peer_count > 0 {
|
if stats.peer_count > 0 {
|
||||||
View::sub_title(ui, format!("{} {}", HANDSHAKE, t!("network_node.peers")));
|
View::sub_title(ui, format!("{} {}", HANDSHAKE, t!("network_node.peers")));
|
||||||
for index in 0..stats.peer_stats.len() {
|
for (index, ps) in stats.peer_stats.iter().enumerate() {
|
||||||
let ps = stats.peer_stats.get(index).unwrap();
|
|
||||||
let rounding = if stats.peer_count == 1 {
|
let rounding = if stats.peer_count == 1 {
|
||||||
[true, true]
|
[true, true]
|
||||||
} else if index == 0 {
|
} else if index == 0 {
|
||||||
|
@ -188,9 +187,9 @@ impl NetworkTab for NetworkNode {
|
||||||
|
|
||||||
fn draw_peer_stats(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
|
fn draw_peer_stats(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
|
||||||
ui.vertical(|ui| {
|
ui.vertical(|ui| {
|
||||||
|
// Draw round background.
|
||||||
let mut rect = ui.available_rect_before_wrap();
|
let mut rect = ui.available_rect_before_wrap();
|
||||||
rect.set_height(78.3);
|
rect.set_height(78.3);
|
||||||
|
|
||||||
ui.painter().rect(
|
ui.painter().rect(
|
||||||
rect,
|
rect,
|
||||||
Rounding {
|
Rounding {
|
||||||
|
@ -204,39 +203,29 @@ fn draw_peer_stats(ui: &mut egui::Ui, peer: &PeerStats, rounding: [bool; 2]) {
|
||||||
);
|
);
|
||||||
|
|
||||||
ui.add_space(2.0);
|
ui.add_space(2.0);
|
||||||
|
|
||||||
|
// Draw peer address
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.add_space(5.0);
|
ui.add_space(5.0);
|
||||||
// Draw peer address
|
let addr_text = format!("{} {}", PLUGS_CONNECTED, &peer.addr);
|
||||||
ui.heading(RichText::new(format!("{} {}", PLUGS_CONNECTED, &peer.addr))
|
ui.label(RichText::new(addr_text).color(Colors::BLACK).size(18.0));
|
||||||
.color(Colors::BLACK)
|
|
||||||
.size(18.0));
|
|
||||||
});
|
});
|
||||||
|
// Draw peer difficulty and height
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
// Draw peer difficulty and height
|
let diff_text = format!("{} {}", PACKAGE, peer.total_difficulty);
|
||||||
ui.heading(RichText::new(format!("{} {}", PACKAGE, peer.total_difficulty))
|
ui.label(RichText::new(diff_text).color(Colors::TITLE).size(16.0));
|
||||||
.color(Colors::TITLE)
|
|
||||||
.size(16.0));
|
|
||||||
ui.add_space(2.0);
|
ui.add_space(2.0);
|
||||||
ui.heading(RichText::new(AT).color(Colors::TITLE).size(16.0));
|
ui.label(RichText::new(AT).color(Colors::TITLE).size(16.0));
|
||||||
ui.add_space(2.0);
|
ui.add_space(2.0);
|
||||||
ui.heading(RichText::new(peer.height.to_string())
|
ui.label(RichText::new(peer.height.to_string()).color(Colors::TITLE).size(16.0));
|
||||||
.color(Colors::TITLE)
|
|
||||||
.size(16.0));
|
|
||||||
});
|
});
|
||||||
|
// Draw peer user-agent
|
||||||
ui.horizontal(|ui| {
|
ui.horizontal(|ui| {
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
// Draw peer user-agent
|
let agent_text = format!("{} {}", DEVICES, &peer.user_agent);
|
||||||
ui.heading(RichText::new(format!("{} {}", DEVICES, &peer.user_agent))
|
ui.label(RichText::new(agent_text).color(Colors::GRAY).size(16.0));
|
||||||
.color(Colors::GRAY)
|
|
||||||
.size(16.0));
|
|
||||||
});
|
});
|
||||||
ui.add_space(4.0);
|
ui.add_space(4.0);
|
||||||
});
|
});
|
||||||
|
|
||||||
// Add space after last item
|
|
||||||
// if rounding[1] {
|
|
||||||
// ui.add_space(2.0);
|
|
||||||
// }
|
|
||||||
}
|
}
|
|
@ -21,13 +21,16 @@ use crate::gui::views::{Modal, ModalPosition, View};
|
||||||
use crate::gui::views::network::{NetworkTab, NetworkTabType};
|
use crate::gui::views::network::{NetworkTab, NetworkTabType};
|
||||||
use crate::gui::views::network::configs::dandelion::DandelionSetup;
|
use crate::gui::views::network::configs::dandelion::DandelionSetup;
|
||||||
use crate::gui::views::network::configs::node::NodeSetup;
|
use crate::gui::views::network::configs::node::NodeSetup;
|
||||||
|
use crate::gui::views::network::configs::p2p::P2PSetup;
|
||||||
use crate::gui::views::network::configs::pool::PoolSetup;
|
use crate::gui::views::network::configs::pool::PoolSetup;
|
||||||
use crate::gui::views::network::configs::stratum::StratumSetup;
|
use crate::gui::views::network::configs::stratum::StratumSetup;
|
||||||
use crate::node::{Node, NodeConfig};
|
use crate::node::{Node, NodeConfig};
|
||||||
|
|
||||||
|
/// Integrated node settings tab content.
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct NetworkSettings {
|
pub struct NetworkSettings {
|
||||||
node: NodeSetup,
|
node: NodeSetup,
|
||||||
|
p2p: P2PSetup,
|
||||||
stratum: StratumSetup,
|
stratum: StratumSetup,
|
||||||
pool: PoolSetup,
|
pool: PoolSetup,
|
||||||
dandelion: DandelionSetup
|
dandelion: DandelionSetup
|
||||||
|
@ -49,6 +52,12 @@ impl NetworkTab for NetworkSettings {
|
||||||
View::horizontal_line(ui, Colors::STROKE);
|
View::horizontal_line(ui, Colors::STROKE);
|
||||||
ui.add_space(4.0);
|
ui.add_space(4.0);
|
||||||
|
|
||||||
|
self.p2p.ui(ui, cb);
|
||||||
|
|
||||||
|
ui.add_space(6.0);
|
||||||
|
View::horizontal_line(ui, Colors::STROKE);
|
||||||
|
ui.add_space(4.0);
|
||||||
|
|
||||||
self.stratum.ui(ui, cb);
|
self.stratum.ui(ui, cb);
|
||||||
|
|
||||||
ui.add_space(6.0);
|
ui.add_space(6.0);
|
||||||
|
@ -81,6 +90,16 @@ impl NetworkTab for NetworkSettings {
|
||||||
NodeSetup::API_SECRET_MODAL => self.node.secret_modal(ui, modal, cb),
|
NodeSetup::API_SECRET_MODAL => self.node.secret_modal(ui, modal, cb),
|
||||||
NodeSetup::FOREIGN_API_SECRET_MODAL => self.node.secret_modal(ui, modal, cb),
|
NodeSetup::FOREIGN_API_SECRET_MODAL => self.node.secret_modal(ui, modal, cb),
|
||||||
NodeSetup::FTL_MODAL => self.node.ftl_modal(ui, modal, cb),
|
NodeSetup::FTL_MODAL => self.node.ftl_modal(ui, modal, cb),
|
||||||
|
// P2P setup modals.
|
||||||
|
P2PSetup::PORT_MODAL => self.p2p.port_modal(ui, modal, cb),
|
||||||
|
P2PSetup::CUSTOM_SEED_MODAL => self.p2p.peer_modal(ui, modal, cb),
|
||||||
|
P2PSetup::ALLOW_PEER_MODAL => self.p2p.peer_modal(ui, modal, cb),
|
||||||
|
P2PSetup::DENY_PEER_MODAL => self.p2p.peer_modal(ui, modal, cb),
|
||||||
|
P2PSetup::PREFER_PEER_MODAL => self.p2p.peer_modal(ui, modal, cb),
|
||||||
|
P2PSetup::BAN_WINDOW_MODAL => self.p2p.ban_window_modal(ui, modal, cb),
|
||||||
|
P2PSetup::MAX_INBOUND_MODAL => self.p2p.max_inbound_modal(ui, modal, cb),
|
||||||
|
P2PSetup::MAX_OUTBOUND_MODAL => self.p2p.max_outbound_modal(ui, modal, cb),
|
||||||
|
P2PSetup::MIN_OUTBOUND_MODAL => self.p2p.min_outbound_modal(ui, modal, cb),
|
||||||
// Stratum server setup modals.
|
// Stratum server setup modals.
|
||||||
StratumSetup::STRATUM_PORT_MODAL => self.stratum.port_modal(ui, modal, cb),
|
StratumSetup::STRATUM_PORT_MODAL => self.stratum.port_modal(ui, modal, cb),
|
||||||
StratumSetup::ATTEMPT_TIME_MODAL => self.stratum.attempt_modal(ui, modal, cb),
|
StratumSetup::ATTEMPT_TIME_MODAL => self.stratum.attempt_modal(ui, modal, cb),
|
||||||
|
|
|
@ -14,9 +14,10 @@
|
||||||
|
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
use std::io::{BufRead, BufReader, Write};
|
use std::io::{BufRead, BufReader, Write};
|
||||||
use std::net::{IpAddr, Ipv4Addr, SocketAddrV4, TcpListener};
|
use std::net::{IpAddr, Ipv4Addr, SocketAddr, SocketAddrV4, TcpListener, ToSocketAddrs};
|
||||||
use std::path::PathBuf;
|
use std::path::PathBuf;
|
||||||
use std::str::FromStr;
|
use std::str::FromStr;
|
||||||
|
use egui::Key::P;
|
||||||
|
|
||||||
use grin_config::{config, ConfigError, ConfigMembers, GlobalConfig};
|
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_config::config::{API_SECRET_FILE_NAME, FOREIGN_API_SECRET_FILE_NAME, SERVER_CONFIG_FILE_NAME};
|
||||||
|
@ -29,39 +30,171 @@ use crate::node::Node;
|
||||||
|
|
||||||
use crate::{AppConfig, Settings};
|
use crate::{AppConfig, Settings};
|
||||||
|
|
||||||
/// Wrapped node config to be used by [`grin_servers::Server`].
|
/// Peers config to save peers DNS names into the file.
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize, Default)]
|
||||||
pub struct NodeConfig {
|
pub struct PeersConfig {
|
||||||
pub members: ConfigMembers
|
seeds: Vec<String>,
|
||||||
|
allowed: Vec<String>,
|
||||||
|
denied: Vec<String>,
|
||||||
|
preferred: Vec<String>
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NodeConfig {
|
impl PeersConfig {
|
||||||
/// Initialize integrated node config.
|
/// File name for peers config.
|
||||||
pub fn init(chain_type: &ChainTypes) -> Self {
|
pub const FILE_NAME: &'static str = "peers.toml";
|
||||||
let config_members = Self::for_chain_type(chain_type);
|
|
||||||
Self {
|
/// Save peers config to the file.
|
||||||
members: config_members
|
pub fn save(&self) {
|
||||||
|
let chain_type = AppConfig::chain_type();
|
||||||
|
let config_path = Settings::get_config_path(Self::FILE_NAME, Some(&chain_type));
|
||||||
|
Settings::write_to_file(self, config_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save seed peer.
|
||||||
|
pub fn save_seed(&mut self, peer: String) {
|
||||||
|
self.seeds.insert(self.seeds.len(), peer);
|
||||||
|
self.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save allowed peer.
|
||||||
|
pub fn save_allowed(&mut self, peer: String) {
|
||||||
|
self.allowed.insert(self.allowed.len(), peer);
|
||||||
|
self.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save denied peer.
|
||||||
|
pub fn save_denied(&mut self, peer: String) {
|
||||||
|
self.denied.insert(self.denied.len(), peer);
|
||||||
|
self.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save preferred peer.
|
||||||
|
pub fn save_preferred(&mut self, peer: String) {
|
||||||
|
self.preferred.insert(self.preferred.len(), peer);
|
||||||
|
self.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Convert string to [`PeerAddr`] if address is in correct format (`host:port`) and available.
|
||||||
|
pub fn peer_to_addr(peer: String) -> Option<PeerAddr> {
|
||||||
|
match SocketAddr::from_str(peer.as_str()) {
|
||||||
|
// Try to parse IP address first.
|
||||||
|
Ok(ip) => Some(PeerAddr(ip)),
|
||||||
|
// If that fails it's probably a DNS record.
|
||||||
|
Err(_) => {
|
||||||
|
if let Ok(mut socket_addr_list) = peer.to_socket_addrs() {
|
||||||
|
if let Some(addr) = socket_addr_list.next() {
|
||||||
|
return Some(PeerAddr(addr));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
None
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Initialize config with provided [`ChainTypes`].
|
/// Load saved peers to node server [`ConfigMembers`] config.
|
||||||
pub fn for_chain_type(chain_type: &ChainTypes) -> ConfigMembers {
|
fn load_to_server_config() {
|
||||||
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
|
// Load seeds.
|
||||||
|
for seed in w_node_config.peers.seeds.clone() {
|
||||||
|
if let Some(p) = Self::peer_to_addr(seed.to_string()) {
|
||||||
|
let mut seeds = w_node_config
|
||||||
|
.node
|
||||||
|
.server
|
||||||
|
.p2p_config
|
||||||
|
.seeds
|
||||||
|
.clone()
|
||||||
|
.unwrap_or(PeerAddrs::default());
|
||||||
|
seeds.peers.insert(seeds.peers.len(), p);
|
||||||
|
w_node_config.node.server.p2p_config.seeds = Some(seeds);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Load allowed peers.
|
||||||
|
for peer in w_node_config.peers.allowed.clone() {
|
||||||
|
if let Some(p) = Self::peer_to_addr(peer.clone()) {
|
||||||
|
let mut allowed = w_node_config
|
||||||
|
.node
|
||||||
|
.server
|
||||||
|
.p2p_config
|
||||||
|
.peers_allow
|
||||||
|
.clone()
|
||||||
|
.unwrap_or(PeerAddrs::default());
|
||||||
|
allowed.peers.insert(allowed.peers.len(), p);
|
||||||
|
w_node_config.node.server.p2p_config.peers_allow = Some(allowed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Load denied peers.
|
||||||
|
for peer in w_node_config.peers.denied.clone() {
|
||||||
|
if let Some(p) = Self::peer_to_addr(peer.clone()) {
|
||||||
|
let mut denied = w_node_config
|
||||||
|
.node
|
||||||
|
.server
|
||||||
|
.p2p_config
|
||||||
|
.peers_deny
|
||||||
|
.clone()
|
||||||
|
.unwrap_or(PeerAddrs::default());
|
||||||
|
denied.peers.insert(denied.peers.len(), p);
|
||||||
|
w_node_config.node.server.p2p_config.peers_deny = Some(denied);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
// Load preferred peers.
|
||||||
|
for peer in &w_node_config.peers.preferred.clone() {
|
||||||
|
if let Some(p) = Self::peer_to_addr(peer.clone()) {
|
||||||
|
let mut preferred = w_node_config
|
||||||
|
.node
|
||||||
|
.server
|
||||||
|
.p2p_config
|
||||||
|
.peers_preferred
|
||||||
|
.clone()
|
||||||
|
.unwrap_or(PeerAddrs::default());
|
||||||
|
preferred.peers.insert(preferred.peers.len(), p);
|
||||||
|
w_node_config.node.server.p2p_config.peers_preferred = Some(preferred);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Wrapped node config to be used by [`grin_servers::Server`].
|
||||||
|
#[derive(Serialize, Deserialize)]
|
||||||
|
pub struct NodeConfig {
|
||||||
|
pub(crate) node: ConfigMembers,
|
||||||
|
pub(crate) peers: PeersConfig
|
||||||
|
}
|
||||||
|
|
||||||
|
impl NodeConfig {
|
||||||
|
/// Initialize config fields from provided [`ChainTypes`].
|
||||||
|
pub fn for_chain_type(chain_type: &ChainTypes) -> Self {
|
||||||
// Check secret files for current chain type.
|
// Check secret files for current chain type.
|
||||||
let _ = Self::check_api_secret_files(chain_type, API_SECRET_FILE_NAME);
|
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 _ = Self::check_api_secret_files(chain_type, FOREIGN_API_SECRET_FILE_NAME);
|
||||||
|
|
||||||
// Create config.
|
// Initialize peers config.
|
||||||
let path = Settings::get_config_path(SERVER_CONFIG_FILE_NAME, Some(chain_type));
|
let peers_config = {
|
||||||
let parsed = Settings::read_from_file::<ConfigMembers>(path.clone());
|
let path = Settings::get_config_path(PeersConfig::FILE_NAME, Some(chain_type));
|
||||||
if !path.exists() || parsed.is_err() {
|
let config = Settings::read_from_file::<PeersConfig>(path.clone());
|
||||||
Self::save_default_config(chain_type)
|
if !path.exists() || config.is_err() {
|
||||||
} else {
|
Self::save_default_peers_config(chain_type)
|
||||||
parsed.unwrap()
|
} else {
|
||||||
}
|
config.unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// Initialize node config.
|
||||||
|
let node_config = {
|
||||||
|
let path = Settings::get_config_path(SERVER_CONFIG_FILE_NAME, Some(chain_type));
|
||||||
|
let config = Settings::read_from_file::<ConfigMembers>(path.clone());
|
||||||
|
if !path.exists() || config.is_err() {
|
||||||
|
Self::save_default_node_server_config(chain_type)
|
||||||
|
} else {
|
||||||
|
config.unwrap()
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Self { node: node_config, peers: peers_config }
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Generate and save default node config for specified [`ChainTypes`].
|
/// Save default node config for specified [`ChainTypes`].
|
||||||
fn save_default_config(chain_type: &ChainTypes) -> ConfigMembers {
|
fn save_default_node_server_config(chain_type: &ChainTypes) -> ConfigMembers {
|
||||||
let path = Settings::get_config_path(SERVER_CONFIG_FILE_NAME, Some(chain_type));
|
let path = Settings::get_config_path(SERVER_CONFIG_FILE_NAME, Some(chain_type));
|
||||||
let mut default_config = GlobalConfig::for_chain(chain_type);
|
let mut default_config = GlobalConfig::for_chain(chain_type);
|
||||||
default_config.update_paths(&Settings::get_working_path(Some(chain_type)));
|
default_config.update_paths(&Settings::get_working_path(Some(chain_type)));
|
||||||
|
@ -70,32 +203,42 @@ impl NodeConfig {
|
||||||
config
|
config
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save node config to disk.
|
/// Save default peers config for specified [`ChainTypes`].
|
||||||
pub fn save(&mut self) {
|
fn save_default_peers_config(chain_type: &ChainTypes) -> PeersConfig {
|
||||||
let config_path = Settings::get_config_path(
|
let path = Settings::get_config_path(PeersConfig::FILE_NAME, Some(chain_type));
|
||||||
SERVER_CONFIG_FILE_NAME,
|
let config = PeersConfig::default();
|
||||||
Some(&self.members.server.chain_type)
|
Settings::write_to_file(&config, path);
|
||||||
);
|
config
|
||||||
Settings::write_to_file(&self.members, config_path);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get node config values.
|
/// Save node config to the file.
|
||||||
pub fn get_members() -> ConfigMembers {
|
pub fn save(&self) {
|
||||||
|
let config_path = Settings::get_config_path(
|
||||||
|
SERVER_CONFIG_FILE_NAME,
|
||||||
|
Some(&self.node.server.chain_type)
|
||||||
|
);
|
||||||
|
Settings::write_to_file(&self.node, config_path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Get server config to use for node server before start.
|
||||||
|
pub fn node_server_config() -> ConfigMembers {
|
||||||
|
PeersConfig::load_to_server_config();
|
||||||
let r_config = Settings::node_config_to_read();
|
let r_config = Settings::node_config_to_read();
|
||||||
r_config.members.clone()
|
r_config.node.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reset node config to default values.
|
/// Reset node config to default values.
|
||||||
pub fn reset_to_default() {
|
pub fn reset_to_default() {
|
||||||
let chain_type = {
|
let chain_type = {
|
||||||
let r_config = Settings::node_config_to_read();
|
let r_config = Settings::node_config_to_read();
|
||||||
r_config.members.server.chain_type
|
r_config.node.server.chain_type
|
||||||
};
|
};
|
||||||
let members = Self::save_default_config(&chain_type);
|
let node_server_config = Self::save_default_node_server_config(&chain_type);
|
||||||
|
let peers_config = Self::save_default_peers_config(&chain_type);
|
||||||
{
|
{
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members = members;
|
w_node_config.node = node_server_config;
|
||||||
w_node_config.save();
|
w_node_config.peers = peers_config;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +277,7 @@ impl NodeConfig {
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check whether a port is available on the provided host.
|
/// Check whether a port is available on the provided host.
|
||||||
fn is_port_available(host: &String, port: &String) -> bool {
|
fn is_host_port_available(host: &String, port: &String) -> bool {
|
||||||
if let Ok(p) = port.parse::<u16>() {
|
if let Ok(p) = port.parse::<u16>() {
|
||||||
let ip_addr = Ipv4Addr::from_str(host.as_str()).unwrap();
|
let ip_addr = Ipv4Addr::from_str(host.as_str()).unwrap();
|
||||||
let ipv4 = SocketAddrV4::new(ip_addr, p);
|
let ipv4 = SocketAddrV4::new(ip_addr, p);
|
||||||
|
@ -143,11 +286,27 @@ impl NodeConfig {
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Check whether a port is available across the system at all hosts.
|
||||||
|
fn is_port_available(port: &String) -> bool {
|
||||||
|
if let Ok(p) = port.parse::<u16>() {
|
||||||
|
for ip in Self::get_ip_addrs() {
|
||||||
|
let ip_addr = Ipv4Addr::from_str(ip.as_str()).unwrap();
|
||||||
|
let ipv4 = SocketAddrV4::new(ip_addr, p);
|
||||||
|
if TcpListener::bind(ipv4).is_err() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
true
|
||||||
|
}
|
||||||
|
|
||||||
/// Get stratum server IP address and port.
|
/// Get stratum server IP address and port.
|
||||||
pub fn get_stratum_address() -> (String, String) {
|
pub fn get_stratum_address() -> (String, String) {
|
||||||
let r_config = Settings::node_config_to_read();
|
let r_config = Settings::node_config_to_read();
|
||||||
let saved_stratum_addr = r_config
|
let saved_stratum_addr = r_config
|
||||||
.members
|
.node
|
||||||
.server
|
.server
|
||||||
.stratum_mining_config
|
.stratum_mining_config
|
||||||
.as_ref()
|
.as_ref()
|
||||||
|
@ -164,7 +323,7 @@ impl NodeConfig {
|
||||||
let addr_to_save = format!("{}:{}", addr, port);
|
let addr_to_save = format!("{}:{}", addr, port);
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config
|
w_node_config
|
||||||
.members
|
.node
|
||||||
.server
|
.server
|
||||||
.stratum_mining_config
|
.stratum_mining_config
|
||||||
.as_mut()
|
.as_mut()
|
||||||
|
@ -186,14 +345,14 @@ impl NodeConfig {
|
||||||
|
|
||||||
/// Check if stratum port is available when server is not running.
|
/// Check if stratum port is available when server is not running.
|
||||||
fn is_not_running_stratum_port_available(ip: &String, port: &String) -> bool {
|
fn is_not_running_stratum_port_available(ip: &String, port: &String) -> bool {
|
||||||
if Self::is_port_available(&ip, &port) {
|
if Self::is_host_port_available(&ip, &port) {
|
||||||
if &Self::get_p2p_port().to_string() != port {
|
if &Self::get_p2p_port() != port {
|
||||||
let (api_ip, api_port) = Self::get_api_address();
|
let (api_ip, api_port) = Self::get_api_address();
|
||||||
return if &api_ip == ip {
|
return if &api_ip == ip {
|
||||||
&api_port != port
|
&api_port != port
|
||||||
} else {
|
} else {
|
||||||
true
|
true
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
|
@ -202,13 +361,13 @@ impl NodeConfig {
|
||||||
/// Get stratum mining server wallet address to get rewards.
|
/// Get stratum mining server wallet address to get rewards.
|
||||||
pub fn get_stratum_wallet_addr() -> String {
|
pub fn get_stratum_wallet_addr() -> String {
|
||||||
let r_config = Settings::node_config_to_read();
|
let r_config = Settings::node_config_to_read();
|
||||||
r_config.members.clone().server.stratum_mining_config.unwrap().wallet_listener_url
|
r_config.node.clone().server.stratum_mining_config.unwrap().wallet_listener_url
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get the amount of time in seconds to attempt to mine on a particular header.
|
/// Get the amount of time in seconds to attempt to mine on a particular header.
|
||||||
pub fn get_stratum_attempt_time() -> String {
|
pub fn get_stratum_attempt_time() -> String {
|
||||||
let r_config = Settings::node_config_to_read();
|
let r_config = Settings::node_config_to_read();
|
||||||
r_config.members
|
r_config.node
|
||||||
.clone()
|
.clone()
|
||||||
.server
|
.server
|
||||||
.stratum_mining_config
|
.stratum_mining_config
|
||||||
|
@ -219,8 +378,8 @@ impl NodeConfig {
|
||||||
|
|
||||||
/// Save stratum attempt time value in seconds.
|
/// Save stratum attempt time value in seconds.
|
||||||
pub fn save_stratum_attempt_time(time: u32) {
|
pub fn save_stratum_attempt_time(time: u32) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members
|
w_node_config.node
|
||||||
.clone()
|
.clone()
|
||||||
.server
|
.server
|
||||||
.stratum_mining_config
|
.stratum_mining_config
|
||||||
|
@ -232,7 +391,7 @@ impl NodeConfig {
|
||||||
/// Get minimum acceptable share difficulty to request from miners.
|
/// Get minimum acceptable share difficulty to request from miners.
|
||||||
pub fn get_stratum_min_share_diff() -> String {
|
pub fn get_stratum_min_share_diff() -> String {
|
||||||
let r_config = Settings::node_config_to_read();
|
let r_config = Settings::node_config_to_read();
|
||||||
r_config.members
|
r_config.node
|
||||||
.clone()
|
.clone()
|
||||||
.server
|
.server
|
||||||
.stratum_mining_config
|
.stratum_mining_config
|
||||||
|
@ -243,8 +402,8 @@ impl NodeConfig {
|
||||||
|
|
||||||
/// Save minimum acceptable share difficulty.
|
/// Save minimum acceptable share difficulty.
|
||||||
pub fn save_stratum_min_share_diff(diff: u64) {
|
pub fn save_stratum_min_share_diff(diff: u64) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members
|
w_node_config.node
|
||||||
.clone()
|
.clone()
|
||||||
.server
|
.server
|
||||||
.stratum_mining_config
|
.stratum_mining_config
|
||||||
|
@ -256,7 +415,7 @@ impl NodeConfig {
|
||||||
/// Check if stratum mining server autorun is enabled.
|
/// Check if stratum mining server autorun is enabled.
|
||||||
pub fn is_stratum_autorun_enabled() -> bool {
|
pub fn is_stratum_autorun_enabled() -> bool {
|
||||||
let stratum_config = Settings::node_config_to_read()
|
let stratum_config = Settings::node_config_to_read()
|
||||||
.members
|
.node
|
||||||
.clone()
|
.clone()
|
||||||
.server
|
.server
|
||||||
.stratum_mining_config
|
.stratum_mining_config
|
||||||
|
@ -271,7 +430,7 @@ impl NodeConfig {
|
||||||
pub fn toggle_stratum_autorun() {
|
pub fn toggle_stratum_autorun() {
|
||||||
let autorun = Self::is_stratum_autorun_enabled();
|
let autorun = Self::is_stratum_autorun_enabled();
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members
|
w_node_config.node
|
||||||
.server
|
.server
|
||||||
.stratum_mining_config
|
.stratum_mining_config
|
||||||
.as_mut()
|
.as_mut()
|
||||||
|
@ -284,7 +443,7 @@ impl NodeConfig {
|
||||||
pub fn get_api_address() -> (String, String) {
|
pub fn get_api_address() -> (String, String) {
|
||||||
let r_config = Settings::node_config_to_read();
|
let r_config = Settings::node_config_to_read();
|
||||||
let saved_api_addr = r_config
|
let saved_api_addr = r_config
|
||||||
.members
|
.node
|
||||||
.server
|
.server
|
||||||
.api_http_addr
|
.api_http_addr
|
||||||
.as_str();
|
.as_str();
|
||||||
|
@ -296,7 +455,7 @@ impl NodeConfig {
|
||||||
pub fn save_api_address(addr: &String, port: &String) {
|
pub fn save_api_address(addr: &String, port: &String) {
|
||||||
let addr_to_save = format!("{}:{}", addr, port);
|
let addr_to_save = format!("{}:{}", addr, port);
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.api_http_addr = addr_to_save;
|
w_node_config.node.server.api_http_addr = addr_to_save;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -309,12 +468,12 @@ impl NodeConfig {
|
||||||
} else {
|
} else {
|
||||||
false
|
false
|
||||||
};
|
};
|
||||||
if same_running || Self::is_port_available(&ip, &port) {
|
if same_running || Self::is_host_port_available(ip, port) {
|
||||||
return &Self::get_p2p_port().to_string() != port;
|
return &Self::get_p2p_port() != port;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
} else if Self::is_port_available(&ip, &port) {
|
} else if Self::is_host_port_available(ip, port) {
|
||||||
return &Self::get_p2p_port().to_string() != port;
|
return &Self::get_p2p_port() != port;
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
}
|
}
|
||||||
|
@ -323,7 +482,7 @@ impl NodeConfig {
|
||||||
pub fn get_api_secret() -> Option<String> {
|
pub fn get_api_secret() -> Option<String> {
|
||||||
let r_config = Settings::node_config_to_read();
|
let r_config = Settings::node_config_to_read();
|
||||||
let api_secret_path = r_config
|
let api_secret_path = r_config
|
||||||
.members
|
.node
|
||||||
.server
|
.server
|
||||||
.api_secret_path
|
.api_secret_path
|
||||||
.clone();
|
.clone();
|
||||||
|
@ -335,7 +494,7 @@ impl NodeConfig {
|
||||||
Some(first_line.unwrap())
|
Some(first_line.unwrap())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save API secret text.
|
/// Save API secret text.
|
||||||
|
@ -347,7 +506,7 @@ impl NodeConfig {
|
||||||
pub fn get_foreign_api_secret() -> Option<String> {
|
pub fn get_foreign_api_secret() -> Option<String> {
|
||||||
let r_config = Settings::node_config_to_read();
|
let r_config = Settings::node_config_to_read();
|
||||||
let foreign_secret_path = r_config
|
let foreign_secret_path = r_config
|
||||||
.members
|
.node
|
||||||
.server
|
.server
|
||||||
.foreign_api_secret_path
|
.foreign_api_secret_path
|
||||||
.clone();
|
.clone();
|
||||||
|
@ -359,7 +518,7 @@ impl NodeConfig {
|
||||||
Some(first_line.unwrap())
|
Some(first_line.unwrap())
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
}
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Update Foreign API secret.
|
/// Update Foreign API secret.
|
||||||
|
@ -373,8 +532,8 @@ impl NodeConfig {
|
||||||
if value.is_empty() {
|
if value.is_empty() {
|
||||||
let mut w_config = Settings::node_config_to_update();
|
let mut w_config = Settings::node_config_to_update();
|
||||||
match file_name {
|
match file_name {
|
||||||
API_SECRET_FILE_NAME => w_config.members.server.api_secret_path = None,
|
API_SECRET_FILE_NAME => w_config.node.server.api_secret_path = None,
|
||||||
_ => w_config.members.server.foreign_api_secret_path = None
|
_ => w_config.node.server.foreign_api_secret_path = None
|
||||||
}
|
}
|
||||||
w_config.save();
|
w_config.save();
|
||||||
return;
|
return;
|
||||||
|
@ -385,8 +544,8 @@ impl NodeConfig {
|
||||||
let secret_path = {
|
let secret_path = {
|
||||||
let r_config = Settings::node_config_to_read();
|
let r_config = Settings::node_config_to_read();
|
||||||
let path = match file_name {
|
let path = match file_name {
|
||||||
API_SECRET_FILE_NAME => r_config.members.server.api_secret_path.clone(),
|
API_SECRET_FILE_NAME => r_config.node.server.api_secret_path.clone(),
|
||||||
_ => r_config.members.server.foreign_api_secret_path.clone()
|
_ => r_config.node.server.foreign_api_secret_path.clone()
|
||||||
};
|
};
|
||||||
path.unwrap_or_else(|| {
|
path.unwrap_or_else(|| {
|
||||||
secret_enabled = false;
|
secret_enabled = false;
|
||||||
|
@ -400,10 +559,10 @@ impl NodeConfig {
|
||||||
let mut w_config = Settings::node_config_to_update();
|
let mut w_config = Settings::node_config_to_update();
|
||||||
match file_name {
|
match file_name {
|
||||||
API_SECRET_FILE_NAME => w_config
|
API_SECRET_FILE_NAME => w_config
|
||||||
.members
|
.node
|
||||||
.server
|
.server
|
||||||
.api_secret_path = Some(secret_path.clone()),
|
.api_secret_path = Some(secret_path.clone()),
|
||||||
_ => w_config.members.server.foreign_api_secret_path = Some(secret_path.clone())
|
_ => w_config.node.server.foreign_api_secret_path = Some(secret_path.clone())
|
||||||
};
|
};
|
||||||
|
|
||||||
w_config.save();
|
w_config.save();
|
||||||
|
@ -415,19 +574,19 @@ impl NodeConfig {
|
||||||
|
|
||||||
/// Get Future Time Limit.
|
/// Get Future Time Limit.
|
||||||
pub fn get_ftl() -> String {
|
pub fn get_ftl() -> String {
|
||||||
Settings::node_config_to_read().members.server.future_time_limit.to_string()
|
Settings::node_config_to_read().node.server.future_time_limit.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save Future Time Limit.
|
/// Save Future Time Limit.
|
||||||
pub fn save_ftl(ftl: u64) {
|
pub fn save_ftl(ftl: u64) {
|
||||||
let mut w_config = Settings::node_config_to_update();
|
let mut w_config = Settings::node_config_to_update();
|
||||||
w_config.members.server.future_time_limit = ftl;
|
w_config.node.server.future_time_limit = ftl;
|
||||||
w_config.save();
|
w_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if full chain validation mode is enabled.
|
/// Check if full chain validation mode is enabled.
|
||||||
pub fn is_full_chain_validation() -> bool {
|
pub fn is_full_chain_validation() -> bool {
|
||||||
let mode = Settings::node_config_to_read().members.clone().server.chain_validation_mode;
|
let mode = Settings::node_config_to_read().node.clone().server.chain_validation_mode;
|
||||||
mode == ChainValidationMode::EveryBlock
|
mode == ChainValidationMode::EveryBlock
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -440,13 +599,13 @@ impl NodeConfig {
|
||||||
ChainValidationMode::EveryBlock
|
ChainValidationMode::EveryBlock
|
||||||
};
|
};
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.chain_validation_mode = new_mode;
|
w_node_config.node.server.chain_validation_mode = new_mode;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Check if node is running in archive mode.
|
/// Check if node is running in archive mode.
|
||||||
pub fn is_archive_mode() -> bool {
|
pub fn is_archive_mode() -> bool {
|
||||||
let archive_mode = Settings::node_config_to_read().members.clone().server.archive_mode;
|
let archive_mode = Settings::node_config_to_read().node.clone().server.archive_mode;
|
||||||
archive_mode.is_some() && archive_mode.unwrap()
|
archive_mode.is_some() && archive_mode.unwrap()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -454,159 +613,219 @@ impl NodeConfig {
|
||||||
pub fn toggle_archive_mode() {
|
pub fn toggle_archive_mode() {
|
||||||
let archive_mode = Self::is_archive_mode();
|
let archive_mode = Self::is_archive_mode();
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.archive_mode = Some(!archive_mode);
|
w_node_config.node.server.archive_mode = Some(!archive_mode);
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
// P2P settings
|
// P2P settings
|
||||||
|
|
||||||
/// Get P2P server port.
|
/// Get P2P server port.
|
||||||
pub fn get_p2p_port() -> u16 {
|
pub fn get_p2p_port() -> String {
|
||||||
Settings::node_config_to_read().members.server.p2p_config.port
|
Settings::node_config_to_read().node.server.p2p_config.port.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get P2P server port.
|
/// Check if P2P server port is available across the system and config.
|
||||||
|
pub fn is_p2p_port_available(port: &String) -> bool {
|
||||||
|
if port.parse::<u16>().is_err() {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
let (_, api_port) = Self::get_api_address();
|
||||||
|
if Node::is_running() {
|
||||||
|
// Check if P2P server with same port is running.
|
||||||
|
let same_running = if let Some(running_port) = Node::get_p2p_port() {
|
||||||
|
&running_port.to_string() == port
|
||||||
|
} else {
|
||||||
|
false
|
||||||
|
};
|
||||||
|
if same_running || Self::is_port_available(port) {
|
||||||
|
return &api_port != port;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
} else if Self::is_port_available(port) {
|
||||||
|
return &api_port != port;
|
||||||
|
}
|
||||||
|
false
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save P2P server port.
|
||||||
pub fn save_p2p_port(port: u16) {
|
pub fn save_p2p_port(port: u16) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.p2p_config.port = port;
|
w_node_config.node.server.p2p_config.port = port;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get peers seeding type.
|
/// Check if default seed list is used.
|
||||||
pub fn get_peers_seeding_type() -> Seeding {
|
pub fn is_default_seeding_type() -> bool {
|
||||||
Settings::node_config_to_read().members.server.p2p_config.seeding_type
|
Settings::node_config_to_read().node.server.p2p_config.seeding_type == Seeding::DNSSeed
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get seeds for [`Seeding::List`] type.
|
/// Toggle seeding type to use default or custom seed list.
|
||||||
pub fn get_seeds() -> PeerAddrs {
|
pub fn toggle_seeding_type() {
|
||||||
let r_config = Settings::node_config_to_read();
|
let seeding_type = if Self::is_default_seeding_type() {
|
||||||
r_config.members.server.p2p_config.seeds.clone().unwrap_or(PeerAddrs::default())
|
Seeding::List
|
||||||
}
|
} else {
|
||||||
|
Seeding::DNSSeed
|
||||||
/// Save peers seeding type, with list of peers for [`Seeding::List`] type.
|
};
|
||||||
pub fn save_peers_seeding_type(seeding_type: Seeding, peers: Option<PeerAddrs>) {
|
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.p2p_config.seeding_type = seeding_type;
|
w_node_config.node.server.p2p_config.seeding_type = seeding_type;
|
||||||
if seeding_type == Seeding::List {
|
|
||||||
w_node_config.members.server.p2p_config.seeds = peers;
|
|
||||||
}
|
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Get custom seed peers.
|
||||||
|
pub fn get_custom_seeds() -> Vec<String> {
|
||||||
|
Settings::node_config_to_read().peers.seeds.clone()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Save custom seed peer.
|
||||||
|
pub fn save_custom_seed(peer: String) {
|
||||||
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
|
let size = w_node_config.peers.seeds.len();
|
||||||
|
w_node_config.peers.seeds.insert(size, peer);
|
||||||
|
w_node_config.peers.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove custom seed peer.
|
||||||
|
pub fn remove_custom_seed(peer: &String) {
|
||||||
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
|
let mut seeds = w_node_config.peers.seeds.clone();
|
||||||
|
if let Some(index) = seeds.iter().position(|x| x == peer) {
|
||||||
|
seeds.remove(index);
|
||||||
|
}
|
||||||
|
w_node_config.peers.seeds = seeds;
|
||||||
|
w_node_config.peers.save();
|
||||||
|
}
|
||||||
|
|
||||||
/// Get denied peer list.
|
/// Get denied peer list.
|
||||||
pub fn get_denied_peers() -> PeerAddrs {
|
pub fn get_denied_peers() -> Vec<String> {
|
||||||
let r_config = Settings::node_config_to_read();
|
Settings::node_config_to_read().peers.denied.clone()
|
||||||
r_config.members.server.p2p_config.peers_deny.clone().unwrap_or(PeerAddrs::default())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add peer at denied list.
|
/// Save peer to denied list.
|
||||||
pub fn deny_peer(peer: String) {
|
pub fn deny_peer(peer: String) {
|
||||||
let ip_addr = IpAddr::from_str(peer.as_str()).unwrap();
|
|
||||||
let peer_addr = PeerAddr::from_ip(ip_addr);
|
|
||||||
|
|
||||||
let mut deny_peers = Self::get_denied_peers();
|
|
||||||
deny_peers.peers.insert(0, peer_addr);
|
|
||||||
|
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.p2p_config.peers_deny = Some(deny_peers);
|
let size = w_node_config.peers.denied.len();
|
||||||
w_node_config.save();
|
w_node_config.peers.denied.insert(size, peer);
|
||||||
|
w_node_config.peers.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save denied peer list.
|
/// Remove denied peer.
|
||||||
pub fn save_denied_peers(peers: Option<PeerAddrs>) {
|
pub fn remove_denied_peer(peer: &String) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.p2p_config.peers_deny = peers;
|
let mut denied = w_node_config.peers.denied.clone();
|
||||||
w_node_config.save();
|
if let Some(index) = denied.iter().position(|x| x == peer) {
|
||||||
|
denied.remove(index);
|
||||||
|
}
|
||||||
|
w_node_config.peers.denied = denied;
|
||||||
|
w_node_config.peers.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get allowed peer list.
|
/// Get allowed peer list.
|
||||||
pub fn get_allowed_peers() -> PeerAddrs {
|
pub fn get_allowed_peers() -> Vec<String> {
|
||||||
let r_config = Settings::node_config_to_read();
|
Settings::node_config_to_read().peers.allowed.clone()
|
||||||
r_config.members.server.p2p_config.peers_allow.clone().unwrap_or(PeerAddrs::default())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save allowed peer list.
|
/// Save peer to allowed list.
|
||||||
pub fn save_allowed_peers(peers: Option<PeerAddrs>) {
|
pub fn allow_peer(peer: String) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.p2p_config.peers_allow = peers;
|
let size = w_node_config.peers.allowed.len();
|
||||||
w_node_config.save();
|
w_node_config.peers.allowed.insert(size, peer);
|
||||||
|
w_node_config.peers.save();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Remove allowed peer.
|
||||||
|
pub fn remove_allowed_peer(peer: &String) {
|
||||||
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
|
let mut allowed = w_node_config.peers.allowed.clone();
|
||||||
|
if let Some(index) = allowed.iter().position(|x| x == peer) {
|
||||||
|
allowed.remove(index);
|
||||||
|
}
|
||||||
|
w_node_config.peers.allowed = allowed;
|
||||||
|
w_node_config.peers.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Get preferred peer list.
|
/// Get preferred peer list.
|
||||||
pub fn get_preferred_peers() -> PeerAddrs {
|
pub fn get_preferred_peers() -> Vec<String> {
|
||||||
let r_config = Settings::node_config_to_read();
|
Settings::node_config_to_read().peers.preferred.clone()
|
||||||
r_config.members.server.p2p_config.peers_preferred.clone().unwrap_or(PeerAddrs::default())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Add peer at preferred list.
|
/// Add peer at preferred list.
|
||||||
pub fn prefer_peer(peer: String) {
|
pub fn prefer_peer(peer: String) {
|
||||||
let ip_addr = IpAddr::from_str(peer.as_str()).unwrap();
|
|
||||||
let peer_addr = PeerAddr::from_ip(ip_addr);
|
|
||||||
|
|
||||||
let mut prefer_peers = Self::get_preferred_peers();
|
|
||||||
prefer_peers.peers.insert(0, peer_addr);
|
|
||||||
|
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.p2p_config.peers_preferred = Some(prefer_peers);
|
let size = w_node_config.peers.preferred.len();
|
||||||
w_node_config.save();
|
w_node_config.peers.preferred.insert(size, peer);
|
||||||
|
w_node_config.peers.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save preferred peer list.
|
/// Remove preferred peer.
|
||||||
pub fn save_preferred_peers(peers: Option<PeerAddrs>) {
|
pub fn remove_preferred_peer(peer: &String) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.p2p_config.peers_preferred = peers;
|
let mut preferred = w_node_config.peers.preferred.clone();
|
||||||
w_node_config.save();
|
if let Some(index) = preferred.iter().position(|x| x == peer) {
|
||||||
|
preferred.remove(index);
|
||||||
|
}
|
||||||
|
w_node_config.peers.preferred = preferred;
|
||||||
|
w_node_config.peers.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// How long a banned peer should stay banned in ms.
|
/// How long a banned peer should stay banned in ms.
|
||||||
pub fn get_ban_window() -> i64 {
|
pub fn get_p2p_ban_window() -> String {
|
||||||
Settings::node_config_to_read().members.server.p2p_config.ban_window()
|
Settings::node_config_to_read().node.server.p2p_config.ban_window().to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save for how long a banned peer should stay banned in ms.
|
/// Save for how long a banned peer should stay banned in ms.
|
||||||
pub fn save_ban_window(time: i64) {
|
pub fn save_p2p_ban_window(time: i64) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.p2p_config.ban_window = Some(time);
|
w_node_config.node.server.p2p_config.ban_window = Some(time);
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maximum number of inbound peer connections.
|
/// Maximum number of inbound peer connections.
|
||||||
pub fn get_max_inbound_count() -> u32 {
|
pub fn get_max_inbound_peers() -> String {
|
||||||
Settings::node_config_to_read().members.server.p2p_config.peer_max_inbound_count()
|
Settings::node_config_to_read()
|
||||||
|
.node.server
|
||||||
|
.p2p_config
|
||||||
|
.peer_max_inbound_count()
|
||||||
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save maximum number of inbound peer connections.
|
/// Save maximum number of inbound peer connections.
|
||||||
pub fn save_max_inbound_count(count: u32) {
|
pub fn save_max_inbound_peers(count: u32) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.p2p_config.peer_max_inbound_count = Some(count);
|
w_node_config.node.server.p2p_config.peer_max_inbound_count = Some(count);
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Maximum number of outbound peer connections.
|
/// Maximum number of outbound peer connections.
|
||||||
pub fn get_max_outbound_count() -> u32 {
|
pub fn get_max_outbound_peers() -> String {
|
||||||
Settings::node_config_to_read().members.server.p2p_config.peer_max_outbound_count()
|
Settings::node_config_to_read()
|
||||||
|
.node
|
||||||
|
.server
|
||||||
|
.p2p_config
|
||||||
|
.peer_max_outbound_count()
|
||||||
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save maximum number of outbound peer connections.
|
/// Save maximum number of outbound peer connections.
|
||||||
pub fn save_max_outbound_count(count: u32) {
|
pub fn save_max_outbound_peers(count: u32) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.p2p_config.peer_max_outbound_count = Some(count);
|
w_node_config.node.server.p2p_config.peer_max_outbound_count = Some(count);
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Minimum number of outbound peer connections.
|
/// Minimum number of outbound peer connections.
|
||||||
pub fn get_min_outbound_count() -> u32 {
|
pub fn get_min_outbound_peers() -> String {
|
||||||
Settings::node_config_to_read()
|
Settings::node_config_to_read()
|
||||||
.members
|
.node
|
||||||
.server
|
.server
|
||||||
.p2p_config
|
.p2p_config
|
||||||
.peer_min_preferred_outbound_count()
|
.peer_min_preferred_outbound_count()
|
||||||
|
.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save minimum number of outbound peer connections.
|
/// Save minimum number of outbound peer connections.
|
||||||
pub fn save_min_outbound_count(count: u32) {
|
pub fn save_min_outbound_peers(count: u32) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.p2p_config.peer_min_preferred_outbound_count = Some(count);
|
w_node_config.node.server.p2p_config.peer_min_preferred_outbound_count = Some(count);
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -614,61 +833,61 @@ impl NodeConfig {
|
||||||
|
|
||||||
/// Base fee that's accepted into the pool.
|
/// Base fee that's accepted into the pool.
|
||||||
pub fn get_base_fee() -> String {
|
pub fn get_base_fee() -> String {
|
||||||
Settings::node_config_to_read().members.server.pool_config.accept_fee_base.to_string()
|
Settings::node_config_to_read().node.server.pool_config.accept_fee_base.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save base fee that's accepted into the pool.
|
/// Save base fee that's accepted into the pool.
|
||||||
pub fn save_base_fee(fee: u64) {
|
pub fn save_base_fee(fee: u64) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.pool_config.accept_fee_base = fee;
|
w_node_config.node.server.pool_config.accept_fee_base = fee;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Reorg cache retention period in minutes.
|
/// Reorg cache retention period in minutes.
|
||||||
pub fn get_reorg_cache_period() -> String {
|
pub fn get_reorg_cache_period() -> String {
|
||||||
Settings::node_config_to_read().members.server.pool_config.reorg_cache_period.to_string()
|
Settings::node_config_to_read().node.server.pool_config.reorg_cache_period.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save reorg cache retention period in minutes.
|
/// Save reorg cache retention period in minutes.
|
||||||
pub fn save_reorg_cache_period(period: u32) {
|
pub fn save_reorg_cache_period(period: u32) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.pool_config.reorg_cache_period = period;
|
w_node_config.node.server.pool_config.reorg_cache_period = period;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Max amount of transactions at pool.
|
/// Max amount of transactions at pool.
|
||||||
pub fn get_max_pool_size() -> String {
|
pub fn get_max_pool_size() -> String {
|
||||||
Settings::node_config_to_read().members.server.pool_config.max_pool_size.to_string()
|
Settings::node_config_to_read().node.server.pool_config.max_pool_size.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save max amount of transactions at pool.
|
/// Save max amount of transactions at pool.
|
||||||
pub fn save_max_pool_size(amount: usize) {
|
pub fn save_max_pool_size(amount: usize) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.pool_config.max_pool_size = amount;
|
w_node_config.node.server.pool_config.max_pool_size = amount;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Max amount of transactions at stem pool.
|
/// Max amount of transactions at stem pool.
|
||||||
pub fn get_max_stempool_size() -> String {
|
pub fn get_max_stempool_size() -> String {
|
||||||
Settings::node_config_to_read().members.server.pool_config.max_stempool_size.to_string()
|
Settings::node_config_to_read().node.server.pool_config.max_stempool_size.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save max amount of transactions at stem pool.
|
/// Save max amount of transactions at stem pool.
|
||||||
pub fn save_max_stempool_size(amount: usize) {
|
pub fn save_max_stempool_size(amount: usize) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.pool_config.max_stempool_size = amount;
|
w_node_config.node.server.pool_config.max_stempool_size = amount;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Max total weight of transactions that can get selected to build a block.
|
/// Max total weight of transactions that can get selected to build a block.
|
||||||
pub fn get_mineable_max_weight() -> String {
|
pub fn get_mineable_max_weight() -> String {
|
||||||
Settings::node_config_to_read().members.server.pool_config.mineable_max_weight.to_string()
|
Settings::node_config_to_read().node.server.pool_config.mineable_max_weight.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Set max total weight of transactions that can get selected to build a block.
|
/// Set max total weight of transactions that can get selected to build a block.
|
||||||
pub fn save_mineable_max_weight(weight: u64) {
|
pub fn save_mineable_max_weight(weight: u64) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.pool_config.mineable_max_weight = weight;
|
w_node_config.node.server.pool_config.mineable_max_weight = weight;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -676,63 +895,63 @@ impl NodeConfig {
|
||||||
|
|
||||||
/// Dandelion epoch duration in seconds.
|
/// Dandelion epoch duration in seconds.
|
||||||
pub fn get_dandelion_epoch() -> String {
|
pub fn get_dandelion_epoch() -> String {
|
||||||
Settings::node_config_to_read().members.server.dandelion_config.epoch_secs.to_string()
|
Settings::node_config_to_read().node.server.dandelion_config.epoch_secs.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save Dandelion epoch duration in seconds.
|
/// Save Dandelion epoch duration in seconds.
|
||||||
pub fn save_dandelion_epoch(secs: u16) {
|
pub fn save_dandelion_epoch(secs: u16) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.dandelion_config.epoch_secs = secs;
|
w_node_config.node.server.dandelion_config.epoch_secs = secs;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dandelion embargo timer in seconds.
|
/// Dandelion embargo timer in seconds.
|
||||||
/// Fluff and broadcast after embargo expires if tx not seen on network.
|
/// Fluff and broadcast after embargo expires if tx not seen on network.
|
||||||
pub fn get_dandelion_embargo() -> String {
|
pub fn get_dandelion_embargo() -> String {
|
||||||
Settings::node_config_to_read().members.server.dandelion_config.embargo_secs.to_string()
|
Settings::node_config_to_read().node.server.dandelion_config.embargo_secs.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save Dandelion embargo timer in seconds.
|
/// Save Dandelion embargo timer in seconds.
|
||||||
pub fn save_dandelion_embargo(secs: u16) {
|
pub fn save_dandelion_embargo(secs: u16) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.dandelion_config.embargo_secs = secs;
|
w_node_config.node.server.dandelion_config.embargo_secs = secs;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dandelion aggregation period in seconds.
|
/// Dandelion aggregation period in seconds.
|
||||||
pub fn get_dandelion_aggregation() -> String {
|
pub fn get_dandelion_aggregation() -> String {
|
||||||
Settings::node_config_to_read().members.server.dandelion_config.aggregation_secs.to_string()
|
Settings::node_config_to_read().node.server.dandelion_config.aggregation_secs.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save Dandelion aggregation period in seconds.
|
/// Save Dandelion aggregation period in seconds.
|
||||||
pub fn save_dandelion_aggregation(secs: u16) {
|
pub fn save_dandelion_aggregation(secs: u16) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.dandelion_config.aggregation_secs = secs;
|
w_node_config.node.server.dandelion_config.aggregation_secs = secs;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Dandelion stem probability (default: stem 90% of the time, fluff 10% of the time).
|
/// Dandelion stem probability (default: stem 90% of the time, fluff 10% of the time).
|
||||||
pub fn get_stem_probability() -> String {
|
pub fn get_stem_probability() -> String {
|
||||||
Settings::node_config_to_read().members.server.dandelion_config.stem_probability.to_string()
|
Settings::node_config_to_read().node.server.dandelion_config.stem_probability.to_string()
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Save Dandelion stem probability.
|
/// Save Dandelion stem probability.
|
||||||
pub fn save_stem_probability(percent: u8) {
|
pub fn save_stem_probability(percent: u8) {
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.dandelion_config.stem_probability = percent;
|
w_node_config.node.server.dandelion_config.stem_probability = percent;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Default to always stem our txs as described in Dandelion++ paper.
|
/// Default to always stem our txs as described in Dandelion++ paper.
|
||||||
pub fn always_stem_our_txs() -> bool {
|
pub fn always_stem_our_txs() -> bool {
|
||||||
Settings::node_config_to_read().members.server.dandelion_config.always_stem_our_txs
|
Settings::node_config_to_read().node.server.dandelion_config.always_stem_our_txs
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Toggle stem of our txs.
|
/// Toggle stem of our txs.
|
||||||
pub fn toggle_always_stem_our_txs() {
|
pub fn toggle_always_stem_our_txs() {
|
||||||
let stem_txs = Self::always_stem_our_txs();
|
let stem_txs = Self::always_stem_our_txs();
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members.server.dandelion_config.always_stem_our_txs = !stem_txs;
|
w_node_config.node.server.dandelion_config.always_stem_our_txs = !stem_txs;
|
||||||
w_node_config.save();
|
w_node_config.save();
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -20,4 +20,4 @@ mod config;
|
||||||
mod stratum;
|
mod stratum;
|
||||||
mod mine_block;
|
mod mine_block;
|
||||||
|
|
||||||
pub use config::NodeConfig;
|
pub use config::{NodeConfig, PeersConfig};
|
|
@ -79,6 +79,9 @@ impl Default for Node {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Node {
|
impl Node {
|
||||||
|
/// Delay for server thread to update the stats.
|
||||||
|
pub const STATS_UPDATE_DELAY: Duration = Duration::from_millis(250);
|
||||||
|
|
||||||
/// Stop the [`Server`] and setup exit flag after if needed.
|
/// Stop the [`Server`] and setup exit flag after if needed.
|
||||||
pub fn stop(exit_after_stop: bool) {
|
pub fn stop(exit_after_stop: bool) {
|
||||||
NODE_STATE.stop_needed.store(true, Ordering::Relaxed);
|
NODE_STATE.stop_needed.store(true, Ordering::Relaxed);
|
||||||
|
@ -262,7 +265,7 @@ impl Node {
|
||||||
NODE_STATE.start_stratum_needed.store(false, Ordering::Relaxed);
|
NODE_STATE.start_stratum_needed.store(false, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
thread::sleep(Duration::from_millis(250));
|
thread::sleep(Self::STATS_UPDATE_DELAY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
|
@ -495,11 +498,11 @@ impl Node {
|
||||||
|
|
||||||
/// Start the node [`Server`].
|
/// Start the node [`Server`].
|
||||||
fn start_node_server() -> Result<Server, Error> {
|
fn start_node_server() -> Result<Server, Error> {
|
||||||
// Get current global config
|
// Get saved server config.
|
||||||
let config = NodeConfig::get_members();
|
let config = NodeConfig::node_server_config();
|
||||||
let server_config = config.server.clone();
|
let server_config = config.server.clone();
|
||||||
|
|
||||||
// Remove temporary file dir
|
// Remove temporary file dir.
|
||||||
{
|
{
|
||||||
let mut tmp_dir = PathBuf::from(&server_config.db_root);
|
let mut tmp_dir = PathBuf::from(&server_config.db_root);
|
||||||
tmp_dir = tmp_dir.parent().unwrap().to_path_buf();
|
tmp_dir = tmp_dir.parent().unwrap().to_path_buf();
|
||||||
|
@ -511,6 +514,7 @@ fn start_node_server() -> Result<Server, Error> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Initialize our global chain_type, feature flags (NRD kernel support currently),
|
// Initialize our global chain_type, feature flags (NRD kernel support currently),
|
||||||
// accept_fee_base, and future_time_limit.
|
// accept_fee_base, and future_time_limit.
|
||||||
// These are read via global and not read from config beyond this point.
|
// These are read via global and not read from config beyond this point.
|
||||||
|
@ -524,22 +528,18 @@ fn start_node_server() -> Result<Server, Error> {
|
||||||
if !global::GLOBAL_NRD_FEATURE_ENABLED.is_init() {
|
if !global::GLOBAL_NRD_FEATURE_ENABLED.is_init() {
|
||||||
match global::get_chain_type() {
|
match global::get_chain_type() {
|
||||||
ChainTypes::Mainnet => {
|
ChainTypes::Mainnet => {
|
||||||
// Set various mainnet specific feature flags.
|
|
||||||
global::init_global_nrd_enabled(false);
|
global::init_global_nrd_enabled(false);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Set various non-mainnet feature flags.
|
|
||||||
global::init_global_nrd_enabled(true);
|
global::init_global_nrd_enabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
match global::get_chain_type() {
|
match global::get_chain_type() {
|
||||||
ChainTypes::Mainnet => {
|
ChainTypes::Mainnet => {
|
||||||
// Set various mainnet specific feature flags.
|
|
||||||
global::set_global_nrd_enabled(false);
|
global::set_global_nrd_enabled(false);
|
||||||
}
|
}
|
||||||
_ => {
|
_ => {
|
||||||
// Set various non-mainnet feature flags.
|
|
||||||
global::set_global_nrd_enabled(true);
|
global::set_global_nrd_enabled(true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -562,13 +562,13 @@ fn start_node_server() -> Result<Server, Error> {
|
||||||
let api_chan: &'static mut (oneshot::Sender<()>, oneshot::Receiver<()>) =
|
let api_chan: &'static mut (oneshot::Sender<()>, oneshot::Receiver<()>) =
|
||||||
Box::leak(Box::new(oneshot::channel::<()>()));
|
Box::leak(Box::new(oneshot::channel::<()>()));
|
||||||
|
|
||||||
// Write launching API server address.
|
// Set launching API server address from config to state.
|
||||||
{
|
{
|
||||||
let mut w_api_addr = NODE_STATE.api_addr.write().unwrap();
|
let mut w_api_addr = NODE_STATE.api_addr.write().unwrap();
|
||||||
*w_api_addr = Some(config.server.api_http_addr);
|
*w_api_addr = Some(config.server.api_http_addr);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write launching P2P server port.
|
// Set launching P2P server port from config to state.
|
||||||
{
|
{
|
||||||
let mut w_p2p_port = NODE_STATE.p2p_port.write().unwrap();
|
let mut w_p2p_port = NODE_STATE.p2p_port.write().unwrap();
|
||||||
*w_p2p_port = Some(config.server.p2p_config.port);
|
*w_p2p_port = Some(config.server.p2p_config.port);
|
||||||
|
@ -579,7 +579,7 @@ fn start_node_server() -> Result<Server, Error> {
|
||||||
NODE_STATE.start_stratum_needed.store(true, Ordering::Relaxed);
|
NODE_STATE.start_stratum_needed.store(true, Ordering::Relaxed);
|
||||||
}
|
}
|
||||||
|
|
||||||
let server_result = Server::new(server_config.clone(), None, api_chan);
|
let server_result = Server::new(server_config, None, api_chan);
|
||||||
server_result
|
server_result
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -32,7 +32,7 @@ lazy_static! {
|
||||||
|
|
||||||
const APP_CONFIG_FILE_NAME: &'static str = "app.toml";
|
const APP_CONFIG_FILE_NAME: &'static str = "app.toml";
|
||||||
|
|
||||||
/// Application settings config.
|
/// Common application settings.
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct AppConfig {
|
pub struct AppConfig {
|
||||||
/// Run node server on startup.
|
/// Run node server on startup.
|
||||||
|
@ -69,17 +69,19 @@ impl AppConfig {
|
||||||
Settings::write_to_file(self, Settings::get_config_path(APP_CONFIG_FILE_NAME, None));
|
Settings::write_to_file(self, Settings::get_config_path(APP_CONFIG_FILE_NAME, None));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Change chain type and load new [`NodeConfig`] accordingly.
|
/// Change chain type and load new [`NodeConfig`].
|
||||||
pub fn change_chain_type(chain_type: &ChainTypes) {
|
pub fn change_chain_type(chain_type: &ChainTypes) {
|
||||||
let current_chain_type = Self::chain_type();
|
let current_chain_type = Self::chain_type();
|
||||||
if current_chain_type != *chain_type {
|
if current_chain_type != *chain_type {
|
||||||
let mut w_app_config = Settings::app_config_to_update();
|
let mut w_app_config = Settings::app_config_to_update();
|
||||||
w_app_config.chain_type = *chain_type;
|
w_app_config.chain_type = *chain_type;
|
||||||
w_app_config.save();
|
w_app_config.save();
|
||||||
// Load config for selected chain type.
|
|
||||||
|
// Load node config for selected chain type.
|
||||||
let mut w_node_config = Settings::node_config_to_update();
|
let mut w_node_config = Settings::node_config_to_update();
|
||||||
w_node_config.members = NodeConfig::for_chain_type(chain_type);
|
let node_config = NodeConfig::for_chain_type(chain_type);
|
||||||
w_node_config.save();
|
w_node_config.node = node_config.node;
|
||||||
|
w_node_config.peers = node_config.peers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +119,7 @@ impl Settings {
|
||||||
fn init() -> Self {
|
fn init() -> Self {
|
||||||
let app_config = AppConfig::init();
|
let app_config = AppConfig::init();
|
||||||
Self {
|
Self {
|
||||||
node_config: Arc::new(RwLock::new(NodeConfig::init(&app_config.chain_type))),
|
node_config: Arc::new(RwLock::new(NodeConfig::for_chain_type(&app_config.chain_type))),
|
||||||
app_config: Arc::new(RwLock::new(app_config))
|
app_config: Arc::new(RwLock::new(app_config))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue