Compare commits
No commits in common. "8555ddceecc7e031aa1e5ce4297017bfff800bfc" and "7e9e6ac329cc58411cb2c7cbddb8384692f29f16" have entirely different histories.
8555ddceec
...
7e9e6ac329
@ -2,7 +2,7 @@
|
|||||||
name = "ghost-eye"
|
name = "ghost-eye"
|
||||||
authors = ["str3tch <stretch@ghostchain.io>"]
|
authors = ["str3tch <stretch@ghostchain.io>"]
|
||||||
description = "Application for interacting with Casper/Ghost nodes that are exposing RPC only to the localhost"
|
description = "Application for interacting with Casper/Ghost nodes that are exposing RPC only to the localhost"
|
||||||
version = "0.3.19"
|
version = "0.3.18"
|
||||||
edition = "2021"
|
edition = "2021"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
|
@ -49,13 +49,11 @@ pub enum Action {
|
|||||||
UpdateKnownValidator(String),
|
UpdateKnownValidator(String),
|
||||||
TransferTo(String),
|
TransferTo(String),
|
||||||
AccountDetailsOf(String, Option<SystemAccount>),
|
AccountDetailsOf(String, Option<SystemAccount>),
|
||||||
StoreRotatedKeys(String),
|
|
||||||
|
|
||||||
TransferBalance(String, [u8; 32], u128),
|
TransferBalance(String, [u8; 32], u128),
|
||||||
BondValidatorExtraFrom([u8; 32], u128),
|
BondValidatorExtraFrom([u8; 32], u128),
|
||||||
BondValidatorFrom([u8; 32], u128),
|
BondValidatorFrom([u8; 32], u128),
|
||||||
PayoutStakers([u8; 32], [u8; 32], u32),
|
PayoutStakers([u8; 32], [u8; 32], u32),
|
||||||
SetSessionKeys([u8; 32], String),
|
|
||||||
EventLog(String, ActionLevel, ActionTarget),
|
EventLog(String, ActionLevel, ActionTarget),
|
||||||
|
|
||||||
NewBestBlock(u32),
|
NewBestBlock(u32),
|
||||||
|
@ -10,11 +10,7 @@ use std::sync::mpsc::Sender;
|
|||||||
|
|
||||||
use super::{Component, PartialComponent, CurrentTab};
|
use super::{Component, PartialComponent, CurrentTab};
|
||||||
use crate::{
|
use crate::{
|
||||||
action::Action,
|
action::Action, config::Config, palette::StylePalette, types::{ActionLevel, ActionTarget}, widgets::{Input, InputRequest}
|
||||||
config::Config,
|
|
||||||
palette::StylePalette,
|
|
||||||
types::{ActionLevel, ActionTarget},
|
|
||||||
widgets::{Input, InputRequest},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
|
@ -2,11 +2,10 @@ use crossterm::event::{KeyCode, KeyEvent, KeyEventKind};
|
|||||||
use color_eyre::Result;
|
use color_eyre::Result;
|
||||||
use ratatui::{
|
use ratatui::{
|
||||||
layout::{Alignment, Constraint, Flex, Layout, Rect},
|
layout::{Alignment, Constraint, Flex, Layout, Rect},
|
||||||
text::Text,
|
widgets::{Block, Clear, Paragraph},
|
||||||
widgets::{Block, Cell, Clear, Row, Table},
|
Frame
|
||||||
Frame,
|
|
||||||
};
|
};
|
||||||
use tokio::sync::mpsc::UnboundedSender;
|
//use tokio::sync::mpsc::UnboundedSender;
|
||||||
use std::sync::mpsc::Sender;
|
use std::sync::mpsc::Sender;
|
||||||
|
|
||||||
use super::{Component, PartialComponent, CurrentTab};
|
use super::{Component, PartialComponent, CurrentTab};
|
||||||
@ -14,15 +13,14 @@ use crate::{
|
|||||||
action::Action,
|
action::Action,
|
||||||
config::Config,
|
config::Config,
|
||||||
palette::StylePalette,
|
palette::StylePalette,
|
||||||
|
//types::{ActionLevel, ActionTarget},
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub struct RotatePopup {
|
pub struct RotatePopup {
|
||||||
is_active: bool,
|
is_active: bool,
|
||||||
action_tx: Option<UnboundedSender<Action>>,
|
//action_tx: Option<UnboundedSender<Action>>,
|
||||||
network_tx: Option<Sender<Action>>,
|
network_tx: Option<Sender<Action>>,
|
||||||
cached_keys: String,
|
|
||||||
secret_seed: [u8; 32],
|
|
||||||
palette: StylePalette
|
palette: StylePalette
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -36,46 +34,17 @@ impl RotatePopup {
|
|||||||
pub fn new() -> Self {
|
pub fn new() -> Self {
|
||||||
Self {
|
Self {
|
||||||
is_active: false,
|
is_active: false,
|
||||||
action_tx: None,
|
//action_tx: None,
|
||||||
network_tx: None,
|
network_tx: None,
|
||||||
cached_keys: String::new(),
|
|
||||||
secret_seed: [0u8; 32],
|
|
||||||
palette: StylePalette::default(),
|
palette: StylePalette::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn rotate_keys(&mut self) {
|
fn rotate_keys(&mut self) {
|
||||||
if !self.cached_keys.is_empty() && self.cached_keys.len() == 258 {
|
todo!();
|
||||||
if let Some(network_tx) = &self.network_tx {
|
//if let Some(network_tx) = &self.network_tx {
|
||||||
let _ = network_tx.send(Action::SetSessionKeys(
|
// let _ = network_tx.send(Action::RotateSessionKeys);
|
||||||
self.secret_seed, self.cached_keys.clone()));
|
//}
|
||||||
}
|
|
||||||
if let Some(action_tx) = &self.action_tx {
|
|
||||||
let _ = action_tx.send(Action::ClosePopup);
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if let Some(network_tx) = &self.network_tx {
|
|
||||||
let _ = network_tx.send(Action::RotateSessionKeys);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fn parse_session_keys(&self) -> (String, String, String, String) {
|
|
||||||
if !self.cached_keys.is_empty() && self.cached_keys.len() == 258 {
|
|
||||||
let gran_key = format!("0x{}", &self.cached_keys[2..66]);
|
|
||||||
let babe_key = format!("0x{}", &self.cached_keys[66..130]);
|
|
||||||
let audi_key = format!("0x{}", &self.cached_keys[130..194]);
|
|
||||||
let slow_key = format!("0x{}", &self.cached_keys[194..258]);
|
|
||||||
|
|
||||||
(gran_key, babe_key, audi_key, slow_key)
|
|
||||||
} else {
|
|
||||||
(
|
|
||||||
String::from("not prepared"),
|
|
||||||
String::from("not prepared"),
|
|
||||||
String::from("not prepared"),
|
|
||||||
String::from("not prepared"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,16 +73,6 @@ impl Component for RotatePopup {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(&mut self, action: Action) -> Result<Option<Action>> {
|
|
||||||
match action {
|
|
||||||
Action::StoreRotatedKeys(cached_keys) => self.cached_keys = cached_keys,
|
|
||||||
Action::SetStashSecret(secret_seed) => self.secret_seed = secret_seed,
|
|
||||||
_ => {}
|
|
||||||
};
|
|
||||||
Ok(None)
|
|
||||||
}
|
|
||||||
|
|
||||||
fn handle_key_event(&mut self, key: KeyEvent) -> Result<Option<Action>> {
|
fn handle_key_event(&mut self, key: KeyEvent) -> Result<Option<Action>> {
|
||||||
if self.is_active && key.kind == KeyEventKind::Press {
|
if self.is_active && key.kind == KeyEventKind::Press {
|
||||||
match key.code {
|
match key.code {
|
||||||
@ -128,48 +87,20 @@ impl Component for RotatePopup {
|
|||||||
fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> {
|
fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> {
|
||||||
if self.is_active {
|
if self.is_active {
|
||||||
let (border_style, border_type) = self.palette.create_popup_style();
|
let (border_style, border_type) = self.palette.create_popup_style();
|
||||||
|
let popup = Paragraph::new(" Do you want to proceed key rotation?")
|
||||||
let (gran_key, babe_key, audi_key, slow_key) = self.parse_session_keys();
|
.block(Block::bordered()
|
||||||
let table = Table::new(
|
.border_style(border_style)
|
||||||
vec![
|
.border_type(border_type)
|
||||||
Row::new(vec![
|
.title_style(self.palette.create_popup_title_style())
|
||||||
Cell::from(Text::from("gran".to_string()).alignment(Alignment::Left)),
|
.title_alignment(Alignment::Right)
|
||||||
Cell::from(Text::from(gran_key).alignment(Alignment::Right)),
|
.title("Enter to proceed / Esc to close"));
|
||||||
]),
|
let v = Layout::vertical([Constraint::Max(3)]).flex(Flex::Center);
|
||||||
Row::new(vec![
|
let h = Layout::horizontal([Constraint::Max(50)]).flex(Flex::Center);
|
||||||
Cell::from(Text::from("babe".to_string()).alignment(Alignment::Left)),
|
|
||||||
Cell::from(Text::from(babe_key).alignment(Alignment::Right)),
|
|
||||||
]),
|
|
||||||
Row::new(vec![
|
|
||||||
Cell::from(Text::from("audi".to_string()).alignment(Alignment::Left)),
|
|
||||||
Cell::from(Text::from(audi_key).alignment(Alignment::Right)),
|
|
||||||
]),
|
|
||||||
Row::new(vec![
|
|
||||||
Cell::from(Text::from("slow".to_string()).alignment(Alignment::Left)),
|
|
||||||
Cell::from(Text::from(slow_key).alignment(Alignment::Right)),
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
[
|
|
||||||
Constraint::Min(4),
|
|
||||||
Constraint::Min(0),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.highlight_style(self.palette.create_highlight_style())
|
|
||||||
.column_spacing(1)
|
|
||||||
.block(Block::bordered()
|
|
||||||
.border_style(border_style)
|
|
||||||
.border_type(border_type)
|
|
||||||
.title_alignment(Alignment::Right)
|
|
||||||
.title_style(self.palette.create_title_style(false))
|
|
||||||
.title("Rotate session keys (Enter to proceed / Esc to close)"));
|
|
||||||
|
|
||||||
let v = Layout::vertical([Constraint::Max(6)]).flex(Flex::Center);
|
|
||||||
let h = Layout::horizontal([Constraint::Max(73)]).flex(Flex::Center);
|
|
||||||
let [area] = v.areas(area);
|
let [area] = v.areas(area);
|
||||||
let [area] = h.areas(area);
|
let [area] = h.areas(area);
|
||||||
|
|
||||||
frame.render_widget(Clear, area);
|
frame.render_widget(Clear, area);
|
||||||
frame.render_widget(table, area);
|
frame.render_widget(popup, area);
|
||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
@ -120,15 +120,3 @@ pub async fn get_local_identity(
|
|||||||
action_tx.send(Action::SetLocalIdentity(local_peer_id))?;
|
action_tx.send(Action::SetLocalIdentity(local_peer_id))?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn rotate_keys(
|
|
||||||
action_tx: &UnboundedSender<Action>,
|
|
||||||
rpc_client: &RpcClient,
|
|
||||||
) -> Result<()> {
|
|
||||||
let rotated_keys: String = rpc_client
|
|
||||||
.request("author_rotateKeys", rpc_params![])
|
|
||||||
.await
|
|
||||||
.unwrap_or_default();
|
|
||||||
action_tx.send(Action::StoreRotatedKeys(rotated_keys))?;
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
@ -166,7 +166,6 @@ impl Network {
|
|||||||
Action::GetConnectedPeers => legacy_rpc_calls::get_connected_peers(&self.action_tx, &self.rpc_client).await,
|
Action::GetConnectedPeers => legacy_rpc_calls::get_connected_peers(&self.action_tx, &self.rpc_client).await,
|
||||||
Action::GetListenAddresses => legacy_rpc_calls::get_listen_addresses(&self.action_tx, &self.rpc_client).await,
|
Action::GetListenAddresses => legacy_rpc_calls::get_listen_addresses(&self.action_tx, &self.rpc_client).await,
|
||||||
Action::GetLocalIdentity => legacy_rpc_calls::get_local_identity(&self.action_tx, &self.rpc_client).await,
|
Action::GetLocalIdentity => legacy_rpc_calls::get_local_identity(&self.action_tx, &self.rpc_client).await,
|
||||||
Action::RotateSessionKeys => legacy_rpc_calls::rotate_keys(&self.action_tx, &self.rpc_client).await,
|
|
||||||
|
|
||||||
Action::GetBlockAuthor(hash, logs) => predefined_calls::get_block_author(&self.action_tx, &self.online_client_api, &logs, &hash).await,
|
Action::GetBlockAuthor(hash, logs) => predefined_calls::get_block_author(&self.action_tx, &self.online_client_api, &logs, &hash).await,
|
||||||
Action::GetActiveEra => predefined_calls::get_active_era(&self.action_tx, &self.online_client_api).await,
|
Action::GetActiveEra => predefined_calls::get_active_era(&self.action_tx, &self.online_client_api).await,
|
||||||
@ -313,24 +312,6 @@ impl Network {
|
|||||||
}
|
}
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
Action::SetSessionKeys(sender, hashed_keys) => {
|
|
||||||
let sender_str = hex::encode(sender);
|
|
||||||
let maybe_nonce = self.senders.get_mut(&sender_str);
|
|
||||||
if let Ok(tx_progress) = predefined_txs::set_keys(
|
|
||||||
&self.action_tx,
|
|
||||||
&self.online_client_api,
|
|
||||||
&sender,
|
|
||||||
&hashed_keys,
|
|
||||||
maybe_nonce,
|
|
||||||
).await {
|
|
||||||
self.transactions_to_watch.push(TxToWatch {
|
|
||||||
tx_progress,
|
|
||||||
sender: sender_str,
|
|
||||||
target: ActionTarget::ValidatorLog,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
_ => Ok(())
|
_ => Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,10 @@ use subxt::{
|
|||||||
use tokio::sync::mpsc::UnboundedSender;
|
use tokio::sync::mpsc::UnboundedSender;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
action::Action, casper::{CasperConfig, CasperExtrinsicParamsBuilder}, casper_network::{self, runtime_types}, types::{ActionLevel, ActionTarget}
|
action::Action,
|
||||||
|
types::{ActionLevel, ActionTarget},
|
||||||
|
casper::{CasperExtrinsicParamsBuilder, CasperConfig},
|
||||||
|
casper_network,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub async fn transfer_balance(
|
pub async fn transfer_balance(
|
||||||
@ -200,68 +203,3 @@ pub async fn payout_stakers(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn set_keys(
|
|
||||||
action_tx: &UnboundedSender<Action>,
|
|
||||||
api: &OnlineClient<CasperConfig>,
|
|
||||||
sender: &[u8; 32],
|
|
||||||
hashed_keys_str: &String,
|
|
||||||
mut maybe_nonce: Option<&mut u32>,
|
|
||||||
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
|
|
||||||
let (gran_key, babe_key, audi_key, slow_key) = {
|
|
||||||
let s = hashed_keys_str.trim_start_matches("0x");
|
|
||||||
(
|
|
||||||
hex::decode(&s[0..64]).unwrap().as_slice().try_into().unwrap(),
|
|
||||||
hex::decode(&s[64..128]).unwrap().as_slice().try_into().unwrap(),
|
|
||||||
hex::decode(&s[128..192]).unwrap().as_slice().try_into().unwrap(),
|
|
||||||
hex::decode(&s[192..256]).unwrap().as_slice().try_into().unwrap(),
|
|
||||||
)
|
|
||||||
};
|
|
||||||
|
|
||||||
let session_keys = runtime_types::casper_runtime::opaque::SessionKeys {
|
|
||||||
grandpa: runtime_types::sp_consensus_grandpa::app::Public(gran_key),
|
|
||||||
babe: runtime_types::sp_consensus_babe::app::Public(babe_key),
|
|
||||||
authority_discovery: runtime_types::sp_authority_discovery::app::Public(audi_key),
|
|
||||||
slow_clap: runtime_types::ghost_slow_clap::sr25519::app_sr25519::Public(slow_key),
|
|
||||||
};
|
|
||||||
|
|
||||||
// it seems like there is no check for the second paramter, that's why
|
|
||||||
// we it can be anything.
|
|
||||||
// Not sure TBH
|
|
||||||
let transfer_tx = casper_network::tx()
|
|
||||||
.session()
|
|
||||||
.set_keys(session_keys, Vec::new());
|
|
||||||
|
|
||||||
let tx_params = match maybe_nonce {
|
|
||||||
Some(ref mut nonce) => {
|
|
||||||
**nonce = nonce.saturating_add(1);
|
|
||||||
CasperExtrinsicParamsBuilder::new()
|
|
||||||
.nonce(nonce.saturating_sub(1) as u64)
|
|
||||||
.build()
|
|
||||||
},
|
|
||||||
None => CasperExtrinsicParamsBuilder::new().build(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let pair = Pair::from_seed(sender);
|
|
||||||
let signer = PairSigner::<CasperConfig, Pair>::new(pair);
|
|
||||||
|
|
||||||
match api
|
|
||||||
.tx()
|
|
||||||
.sign_and_submit_then_watch(&transfer_tx, &signer, tx_params)
|
|
||||||
.await {
|
|
||||||
Ok(tx_progress) => {
|
|
||||||
action_tx.send(Action::EventLog(
|
|
||||||
format!("set keys {} sent", tx_progress.extrinsic_hash()),
|
|
||||||
ActionLevel::Info,
|
|
||||||
ActionTarget::ValidatorLog))?;
|
|
||||||
Ok(tx_progress)
|
|
||||||
},
|
|
||||||
Err(err) => {
|
|
||||||
action_tx.send(Action::EventLog(
|
|
||||||
format!("error during set keys: {err}"),
|
|
||||||
ActionLevel::Error,
|
|
||||||
ActionTarget::ValidatorLog))?;
|
|
||||||
Err(err.into())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
Loading…
Reference in New Issue
Block a user