Compare commits
2 Commits
e91dc51ff7
...
718ae51dee
| Author | SHA1 | Date | |
|---|---|---|---|
| 718ae51dee | |||
| abf2388761 |
@ -2,7 +2,7 @@
|
||||
name = "ghost-eye"
|
||||
authors = ["str3tch <stretch@ghostchain.io>"]
|
||||
description = "Application for interacting with Casper/Ghost nodes that are exposing RPC only to the localhost"
|
||||
version = "0.3.71"
|
||||
version = "0.3.73"
|
||||
edition = "2021"
|
||||
homepage = "https://git.ghostchain.io/ghostchain"
|
||||
repository = "https://git.ghostchain.io/ghostchain/ghost-eye"
|
||||
|
||||
@ -38,6 +38,7 @@ pub enum Action {
|
||||
PayoutValidatorPopup(u32),
|
||||
PayoutAllValidatorPopup(Vec<u32>),
|
||||
WithdrawValidatorPopup,
|
||||
ChangeBlocksPopup,
|
||||
|
||||
BalanceRequest([u8; 32], bool),
|
||||
BalanceResponse([u8; 32], Option<SystemAccount>),
|
||||
@ -62,6 +63,7 @@ pub enum Action {
|
||||
SetSessionKeys([u8; 32], String),
|
||||
ValidateFrom([u8; 32], u32),
|
||||
ChillFrom([u8; 32]),
|
||||
ChangeBlocks(u64, u64),
|
||||
UnbondFrom([u8; 32], u128),
|
||||
RebondFrom([u8; 32], u128),
|
||||
WithdrawUnbondedFrom([u8; 32], u32),
|
||||
|
||||
@ -26,7 +26,7 @@ impl Activatable for Empty {
|
||||
}
|
||||
|
||||
impl Empty {
|
||||
fn prepare_inactive_text(&self) -> Vec<Line> {
|
||||
fn prepare_inactive_text(&self) -> Vec<Line<'_>> {
|
||||
vec![
|
||||
Line::from(" ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢐⣤⣼⣿⣿⣿⣿⣿⣿⣷⣶⣦⣀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀"),
|
||||
Line::from("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣢⣾⣿⣿⣿⣿⣿⣿⣿⣿⣯⣿⣿⣿⣿⣿⣦⡀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀"),
|
||||
@ -61,7 +61,7 @@ impl Empty {
|
||||
]
|
||||
}
|
||||
|
||||
fn prepare_active_text(&self) -> Vec<Line> {
|
||||
fn prepare_active_text(&self) -> Vec<Line<'_>> {
|
||||
vec![
|
||||
Line::from(" ⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⢀⣀⣀"),
|
||||
Line::from("⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⠀⣠⠴⠊⠁⠀⠀⠀⠀⠀⠉⠒⠤⡀⠀⠀⠀⠀⠀"),
|
||||
|
||||
@ -24,7 +24,7 @@ impl ExtrinsicsChart {
|
||||
const BAR_WIDTH: usize = 6;
|
||||
const BAR_GAP: usize = 1;
|
||||
|
||||
fn extrinsics_bar_chart(&self, width: u16) -> BarChart {
|
||||
fn extrinsics_bar_chart(&self, width: u16) -> BarChart<'_> {
|
||||
let (border_style, border_type) = self.palette.create_border_style(false);
|
||||
let length = (width as usize) / (Self::BAR_WIDTH + Self::BAR_GAP);
|
||||
|
||||
@ -47,7 +47,7 @@ impl ExtrinsicsChart {
|
||||
.bar_gap(1)
|
||||
}
|
||||
|
||||
fn extrinsic_vertical_bar(&self, block_number: &u32, ext_len: &usize) -> Bar {
|
||||
fn extrinsic_vertical_bar(&self, block_number: &u32, ext_len: &usize) -> Bar<'_> {
|
||||
Bar::default()
|
||||
.value(*ext_len as u64)
|
||||
.label(Line::from(format!("..{}", block_number % 100)))
|
||||
|
||||
157
src/components/validator/change_blocks_popup.rs
Normal file
157
src/components/validator/change_blocks_popup.rs
Normal file
@ -0,0 +1,157 @@
|
||||
use crossterm::event::{KeyCode, KeyEvent, KeyEventKind};
|
||||
use color_eyre::Result;
|
||||
use ratatui::{
|
||||
layout::{Position, Alignment, Constraint, Flex, Layout, Rect},
|
||||
widgets::{Block, Clear, Paragraph},
|
||||
Frame
|
||||
};
|
||||
use std::sync::mpsc::Sender;
|
||||
use tokio::sync::mpsc::UnboundedSender;
|
||||
|
||||
use super::{Component, PartialComponent, CurrentTab};
|
||||
use crate::{
|
||||
action::Action,
|
||||
config::Config,
|
||||
palette::StylePalette,
|
||||
types::{ActionTarget, ActionLevel},
|
||||
widgets::{Input, InputRequest},
|
||||
};
|
||||
|
||||
#[derive(Debug, Default)]
|
||||
pub struct ChangeBlocksPopup {
|
||||
is_active: bool,
|
||||
action_tx: Option<UnboundedSender<Action>>,
|
||||
network_tx: Option<Sender<Action>>,
|
||||
chain_id: u64,
|
||||
block_number: Input,
|
||||
palette: StylePalette
|
||||
}
|
||||
|
||||
impl ChangeBlocksPopup {
|
||||
fn close_popup(&mut self) {
|
||||
self.is_active = false;
|
||||
if let Some(action_tx) = &self.action_tx {
|
||||
let _ = action_tx.send(Action::ClosePopup);
|
||||
}
|
||||
}
|
||||
|
||||
fn submit_new_block(&mut self) {
|
||||
if let Some(network_tx) = &self.network_tx {
|
||||
if let Some(action_tx) = &self.action_tx {
|
||||
let _ = match self.block_number.value().parse::<u64>() {
|
||||
Ok(new_block) => {
|
||||
let _ = network_tx.send(Action::ChangeBlocks(self.chain_id, new_block));
|
||||
action_tx.send(Action::ClosePopup)
|
||||
}
|
||||
Err(_) => action_tx.send(Action::EventLog(
|
||||
"Incorrect block number format".to_string(),
|
||||
ActionLevel::Error,
|
||||
ActionTarget::ValidatorLog,
|
||||
)),
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn enter_char(&mut self, new_char: char) {
|
||||
let is_separator_needed = !self.block_number.value().contains('.') && new_char == '.';
|
||||
if new_char.is_digit(10) || is_separator_needed {
|
||||
let _ = self.block_number.handle(InputRequest::InsertChar(new_char));
|
||||
}
|
||||
}
|
||||
|
||||
fn delete_char(&mut self) {
|
||||
let _ = self.block_number.handle(InputRequest::DeletePrevChar);
|
||||
}
|
||||
|
||||
fn move_cursor_right(&mut self) {
|
||||
let _ = self.block_number.handle(InputRequest::GoToNextChar);
|
||||
}
|
||||
|
||||
fn move_cursor_left(&mut self) {
|
||||
let _ = self.block_number.handle(InputRequest::GoToPrevChar);
|
||||
}
|
||||
}
|
||||
|
||||
impl PartialComponent for ChangeBlocksPopup {
|
||||
fn set_active(&mut self, current_tab: CurrentTab) {
|
||||
match current_tab {
|
||||
CurrentTab::ChangeBlocksPopup => self.is_active = true,
|
||||
_ => {
|
||||
self.is_active = false;
|
||||
self.block_number = Input::new(String::new());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl Component for ChangeBlocksPopup {
|
||||
fn register_network_handler(&mut self, tx: Sender<Action>) -> Result<()> {
|
||||
self.network_tx = Some(tx);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn register_action_handler(&mut self, tx: UnboundedSender<Action>) -> Result<()> {
|
||||
self.action_tx = Some(tx);
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn register_config_handler(&mut self, config: Config) -> Result<()> {
|
||||
if let Some(style) = config.styles.get(&crate::app::Mode::Wallet) {
|
||||
self.palette.with_normal_style(style.get("normal_style").copied());
|
||||
self.palette.with_normal_border_style(style.get("normal_border_style").copied());
|
||||
self.palette.with_normal_title_style(style.get("normal_title_style").copied());
|
||||
self.palette.with_popup_style(style.get("popup_style").copied());
|
||||
self.palette.with_popup_title_style(style.get("popup_title_style").copied());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn handle_key_event(&mut self, key: KeyEvent) -> Result<Option<Action>> {
|
||||
if self.is_active && key.kind == KeyEventKind::Press {
|
||||
match key.code {
|
||||
KeyCode::Enter => self.submit_new_block(),
|
||||
KeyCode::Esc => self.close_popup(),
|
||||
KeyCode::Char(to_insert) => self.enter_char(to_insert),
|
||||
KeyCode::Backspace => self.delete_char(),
|
||||
KeyCode::Left => self.move_cursor_left(),
|
||||
KeyCode::Right => self.move_cursor_right(),
|
||||
_ => {},
|
||||
};
|
||||
}
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn update(&mut self, action: Action) -> Result<Option<Action>> {
|
||||
match action {
|
||||
Action::SetChoosenGatekeeper(chain_id) => self.chain_id = chain_id,
|
||||
_ => {}
|
||||
};
|
||||
Ok(None)
|
||||
}
|
||||
|
||||
fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> {
|
||||
if self.is_active {
|
||||
let (border_style, border_type) = self.palette.create_popup_style();
|
||||
let input = Paragraph::new(self.block_number.value())
|
||||
.block(Block::bordered()
|
||||
.border_style(border_style)
|
||||
.border_type(border_type)
|
||||
.title_style(self.palette.create_popup_title_style())
|
||||
.title_alignment(Alignment::Right)
|
||||
.title(format!("Bump blocks for #{:?}", self.chain_id)));
|
||||
let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center);
|
||||
let h = Layout::horizontal([Constraint::Max(57)]).flex(Flex::Center);
|
||||
let [area] = v.areas(area);
|
||||
let [area] = h.areas(area);
|
||||
|
||||
frame.render_widget(Clear, area);
|
||||
frame.render_widget(input, area);
|
||||
frame.set_cursor_position(Position::new(
|
||||
area.x + self.block_number.cursor() as u16 + 1,
|
||||
area.y + 1
|
||||
));
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
@ -55,6 +55,12 @@ impl Gatekeepers {
|
||||
}
|
||||
}
|
||||
|
||||
fn nullify_evm_blocks(&mut self) {
|
||||
if let Some(action_tx) = &self.action_tx {
|
||||
let _ = action_tx.send(Action::ChangeBlocksPopup);
|
||||
}
|
||||
}
|
||||
|
||||
fn change_choosen_gatekeeper(&mut self) {
|
||||
if let Some(action_tx) = &self.action_tx {
|
||||
if let Some(chain_id) = self.list_state
|
||||
@ -191,6 +197,7 @@ impl Component for Gatekeepers {
|
||||
KeyCode::Down | KeyCode::Char('j') => self.next_row(),
|
||||
KeyCode::Char('g') => self.first_row(),
|
||||
KeyCode::Char('G') => self.last_row(),
|
||||
KeyCode::Char('O') => self.nullify_evm_blocks(),
|
||||
_ => {},
|
||||
};
|
||||
}
|
||||
|
||||
@ -33,6 +33,7 @@ mod unbond_popup;
|
||||
mod rebond_popup;
|
||||
mod withdraw_popup;
|
||||
mod payee_popup;
|
||||
mod change_blocks_popup;
|
||||
|
||||
use stash_details::StashDetails;
|
||||
use staking_details::StakingDetails;
|
||||
@ -56,6 +57,7 @@ use unbond_popup::UnbondPopup;
|
||||
use rebond_popup::RebondPopup;
|
||||
use withdraw_popup::WithdrawPopup;
|
||||
use payee_popup::PayeePopup;
|
||||
use change_blocks_popup::ChangeBlocksPopup;
|
||||
|
||||
#[derive(Debug, Copy, Clone, PartialEq)]
|
||||
pub enum CurrentTab {
|
||||
@ -77,6 +79,7 @@ pub enum CurrentTab {
|
||||
RebondPopup,
|
||||
WithdrawPopup,
|
||||
PayeePopup,
|
||||
ChangeBlocksPopup,
|
||||
}
|
||||
|
||||
pub trait PartialComponent: Component {
|
||||
@ -119,6 +122,7 @@ impl Default for Validator {
|
||||
Box::new(RebondPopup::default()),
|
||||
Box::new(WithdrawPopup::default()),
|
||||
Box::new(PayeePopup::default()),
|
||||
Box::new(ChangeBlocksPopup::default()),
|
||||
],
|
||||
}
|
||||
}
|
||||
@ -185,7 +189,8 @@ impl Component for Validator {
|
||||
CurrentTab::RebondPopup |
|
||||
CurrentTab::WithdrawPopup |
|
||||
CurrentTab::PayoutPopup |
|
||||
CurrentTab::PayoutAllPopup => {
|
||||
CurrentTab::PayoutAllPopup |
|
||||
CurrentTab::ChangeBlocksPopup => {
|
||||
for component in self.components.iter_mut() {
|
||||
component.handle_key_event(key)?;
|
||||
}
|
||||
@ -266,6 +271,10 @@ impl Component for Validator {
|
||||
self.previous_tab = self.current_tab;
|
||||
self.current_tab = CurrentTab::WithdrawPopup;
|
||||
},
|
||||
Action::ChangeBlocksPopup => {
|
||||
self.previous_tab = self.current_tab;
|
||||
self.current_tab = CurrentTab::ChangeBlocksPopup;
|
||||
},
|
||||
Action::ClosePopup => self.current_tab = self.previous_tab,
|
||||
_ => {},
|
||||
}
|
||||
|
||||
@ -3,7 +3,7 @@ use color_eyre::Result;
|
||||
use subxt::{backend::{legacy::rpc_methods::SystemHealth, rpc::RpcClient}, rpc_params};
|
||||
use codec::{Encode, Decode};
|
||||
|
||||
use crate::{action::Action, network::miscellaneous::get_slow_clap_storage_key, types::{BlockRange, PeerInformation}};
|
||||
use crate::{action::Action, network::miscellaneous::get_slow_clap_storage_key, types::{ActionLevel, ActionTarget, BlockRange, PeerInformation}};
|
||||
|
||||
pub async fn get_node_name(
|
||||
action_tx: &UnboundedSender<Action>,
|
||||
@ -161,3 +161,41 @@ pub async fn get_block_range(
|
||||
action_tx.send(Action::SetBlockRange(chain_id, block_range))?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub async fn nullify_blocks(
|
||||
action_tx: &UnboundedSender<Action>,
|
||||
rpc_client: &RpcClient,
|
||||
chain_id: u64,
|
||||
new_block: u64
|
||||
) -> Result<()> {
|
||||
let chain_id_encoded = chain_id.encode();
|
||||
let block_range_key_raw = get_slow_clap_storage_key(b"block-", &chain_id_encoded);
|
||||
let mut block_range_key = String::from("0x");
|
||||
for byte in block_range_key_raw {
|
||||
block_range_key.push_str(&format!("{:02x}", byte));
|
||||
}
|
||||
|
||||
let zeroes = (new_block, new_block).encode();
|
||||
let mut zeroes_bytes = String::from("0x");
|
||||
for byte in &zeroes {
|
||||
zeroes_bytes.push_str(&format!("{:02x}", byte));
|
||||
}
|
||||
|
||||
match rpc_client
|
||||
.request::<()>("offchain_localStorageSet", rpc_params!["PERSISTENT", block_range_key, zeroes_bytes])
|
||||
.await
|
||||
{
|
||||
Ok(_) => action_tx.send(Action::EventLog(
|
||||
format!("Blocks changed for chain id #{:?}", chain_id),
|
||||
ActionLevel::Info,
|
||||
ActionTarget::ValidatorLog,
|
||||
))?,
|
||||
Err(err) => action_tx.send(Action::EventLog(
|
||||
format!("Block changing failed: {:?}", err),
|
||||
ActionLevel::Error,
|
||||
ActionTarget::ValidatorLog,
|
||||
))?,
|
||||
};
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
@ -507,6 +507,14 @@ impl Network {
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
Action::ChangeBlocks(chain_id, new_block) => {
|
||||
legacy_rpc_calls::nullify_blocks(
|
||||
&self.action_tx,
|
||||
&self.rpc_client,
|
||||
chain_id,
|
||||
new_block,
|
||||
).await
|
||||
}
|
||||
_ => Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user