adapt latest casper runtime changes

Signed-off-by: Uncle Stretch <uncle.stretch@ghostchain.io>
This commit is contained in:
Uncle Stretch 2026-09-13 11:05:16 +03:00
parent 47450a5c6e
commit 4d9e1cc95c
Signed by: str3tch
GPG Key ID: 84F3190747EE79AA
13 changed files with 98 additions and 107 deletions

View File

@ -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.92"
version = "0.4.0"
edition = "2021"
homepage = "https://git.ghostchain.io/ghostchain"
repository = "https://git.ghostchain.io/ghostchain/ghost-eye"

Binary file not shown.

View File

@ -77,7 +77,7 @@ impl Gatekeepers {
if let Some(index) = self.chain_ids.get(&network.chain_id) {
self.gatekeepers[*index] = NetworkDetails {
chain_id: network.chain_id,
chain_name: network.chain_name,
chain_name: network.chain_curve,
chain_type: network.chain_type,
};
} else {
@ -85,7 +85,7 @@ impl Gatekeepers {
self.chain_ids.insert(network.chain_id, position);
self.gatekeepers.push(NetworkDetails {
chain_id: network.chain_id,
chain_name: network.chain_name,
chain_name: network.chain_curve,
chain_type: network.chain_type,
});

View File

@ -151,7 +151,7 @@ impl Component for ListenAddresses {
}
fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> {
let [_, place, _] = super::validator_session_and_listen_layout(area);
let [_, place] = super::validator_session_and_listen_layout(area);
let (border_style, border_type) = self.palette.create_border_style(self.is_active);
let list = List::new(
self.listen_addresses

View File

@ -15,9 +15,6 @@ mod bond_popup;
mod change_blocks_popup;
mod chill_popup;
mod event_log;
mod gatekeeper_details;
mod gatekeeper_endpoints_popup;
mod gatekeepers;
mod history;
mod listen_addresses;
mod nominators;
@ -40,9 +37,6 @@ use bond_popup::BondPopup;
use change_blocks_popup::ChangeBlocksPopup;
use chill_popup::ChillPopup;
use event_log::EventLogs;
use gatekeeper_details::GatekeeperDetails;
use gatekeeper_endpoints_popup::GatekeeperEndpoints;
use gatekeepers::Gatekeepers;
use history::History;
use listen_addresses::ListenAddresses;
use nominators::NominatorsByValidator;
@ -65,7 +59,6 @@ use withdrawals::Withdrawals;
pub enum CurrentTab {
Nothing,
ListenAddresses,
Gatekeepers,
NominatorsByValidator,
History,
Withdrawals,
@ -82,7 +75,6 @@ pub enum CurrentTab {
WithdrawPopup,
PayeePopup,
ChangeBlocksPopup,
GatekeeperEndpoints,
}
pub trait PartialComponent: Component {
@ -108,12 +100,10 @@ impl Default for Validator {
Box::new(StashDetails::default()),
Box::new(StakingDetails::default()),
Box::new(RewardDetails::default()),
Box::new(GatekeeperDetails::default()),
Box::new(History::default()),
Box::new(Withdrawals::default()),
Box::new(Peers::default()),
Box::new(ListenAddresses::default()),
Box::new(Gatekeepers::default()),
Box::new(EventLogs::default()),
Box::new(BondPopup::default()),
Box::new(PayoutPopup::default()),
@ -126,7 +116,6 @@ impl Default for Validator {
Box::new(WithdrawPopup::default()),
Box::new(PayeePopup::default()),
Box::new(ChangeBlocksPopup::default()),
Box::new(GatekeeperEndpoints::default()),
],
}
}
@ -139,17 +128,12 @@ impl Validator {
CurrentTab::Peers => self.current_tab = CurrentTab::Withdrawals,
CurrentTab::Withdrawals => self.current_tab = CurrentTab::History,
CurrentTab::History => self.current_tab = CurrentTab::NominatorsByValidator,
CurrentTab::NominatorsByValidator => self.current_tab = CurrentTab::Gatekeepers,
CurrentTab::ListenAddresses => self.current_tab = CurrentTab::Gatekeepers,
_ => {}
}
}
fn move_right(&mut self) {
match self.current_tab {
CurrentTab::ListenAddresses => self.current_tab = CurrentTab::Gatekeepers,
CurrentTab::Gatekeepers => self.current_tab = CurrentTab::NominatorsByValidator,
CurrentTab::Nothing => self.current_tab = CurrentTab::NominatorsByValidator,
CurrentTab::NominatorsByValidator => self.current_tab = CurrentTab::History,
CurrentTab::History => self.current_tab = CurrentTab::Withdrawals,
CurrentTab::Withdrawals => self.current_tab = CurrentTab::Peers,
@ -197,8 +181,7 @@ impl Component for Validator {
| CurrentTab::WithdrawPopup
| CurrentTab::PayoutPopup
| CurrentTab::PayoutAllPopup
| CurrentTab::ChangeBlocksPopup
| CurrentTab::GatekeeperEndpoints => {
| CurrentTab::ChangeBlocksPopup => {
for component in self.components.iter_mut() {
component.handle_key_event(key)?;
}
@ -264,8 +247,7 @@ impl Component for Validator {
match action {
Action::SetActiveScreen(Mode::Validator) => {
self.is_active = true;
self.previous_tab = CurrentTab::Gatekeepers;
self.current_tab = CurrentTab::Gatekeepers;
self.previous_tab = CurrentTab::History;
}
Action::PayoutValidatorPopup(_) => {
self.previous_tab = self.current_tab;
@ -283,10 +265,6 @@ impl Component for Validator {
self.previous_tab = self.current_tab;
self.current_tab = CurrentTab::ChangeBlocksPopup;
}
Action::GatekeeperEndpoints => {
self.previous_tab = self.current_tab;
self.current_tab = CurrentTab::GatekeeperEndpoints;
}
Action::ClosePopup => self.current_tab = self.previous_tab,
_ => {}
}
@ -321,21 +299,15 @@ pub fn validator_details_layout(area: Rect) -> [Rect; 2] {
Layout::horizontal([Constraint::Length(31), Constraint::Fill(1)]).areas(place)
}
pub fn validator_session_and_listen_layout(area: Rect) -> [Rect; 3] {
pub fn validator_session_and_listen_layout(area: Rect) -> [Rect; 2] {
let [_, place] = validator_details_layout(area);
Layout::vertical([
Constraint::Length(6),
Constraint::Length(6),
Constraint::Length(7),
Constraint::Fill(1),
])
.areas(place)
}
pub fn validator_gatekeeped_networks_layout(area: Rect) -> [Rect; 2] {
let [_, _, place] = validator_session_and_listen_layout(area);
Layout::horizontal([Constraint::Fill(1), Constraint::Length(30)]).areas(place)
}
pub fn validator_statistics_layout(area: Rect) -> [Rect; 3] {
let [_, place, _, _] = validator_layout(area);
Layout::horizontal([
@ -349,7 +321,7 @@ pub fn validator_statistics_layout(area: Rect) -> [Rect; 3] {
pub fn validator_balance_layout(area: Rect) -> [Rect; 3] {
let [place, _] = validator_details_layout(area);
Layout::vertical([
Constraint::Length(6),
Constraint::Length(7),
Constraint::Length(6),
Constraint::Fill(1),
])

View File

@ -9,13 +9,10 @@ use ratatui::{
use super::{Component, CurrentTab, PartialComponent};
use crate::types::EraRewardPoints;
use crate::widgets::DotSpinner;
use crate::{action::Action, config::Config, palette::StylePalette};
pub struct RewardDetails {
palette: StylePalette,
commission: Option<u32>,
nominators_blocked: bool,
apy: String,
treasury_apy: String,
inflation: String,
@ -37,8 +34,6 @@ impl RewardDetails {
pub fn new() -> Self {
Self {
palette: StylePalette::default(),
commission: None,
nominators_blocked: false,
apy: String::from("0.0%"),
treasury_apy: String::from("0.0%"),
inflation: String::from("0.0%"),
@ -51,19 +46,6 @@ impl RewardDetails {
}
}
fn comission_to_string(&self) -> String {
match self.commission {
Some(commission) => {
if self.nominators_blocked {
"blocked".to_string()
} else {
format!("{:.2}%", commission as f64 / 10_000_000.0)
}
}
None => DotSpinner::default().to_string(),
}
}
fn update_individual(&mut self, individual: &Vec<EraRewardPoints>) {
let (is_disabled, in_rewards) = individual
.iter()
@ -108,13 +90,6 @@ impl Component for RewardDetails {
Action::SetCurrentValidatorEraRewards(_, _, individual) => {
self.update_individual(&individual)
}
Action::SetValidatorPrefs(commission, disabled, account_id)
if self.stash == account_id =>
{
self.commission = commission;
self.in_staking_validators = commission.is_some();
self.nominators_blocked = disabled;
}
Action::SetSessionKey(name, session_key_info) => {
if name.starts_with("q_") {
self.in_queued_keys = !session_key_info.key.is_empty();
@ -150,10 +125,6 @@ impl Component for RewardDetails {
let table = Table::new(
vec![
Row::new(vec![
Cell::from(Text::from("Nominators".to_string()).alignment(Alignment::Left)),
Cell::from(Text::from(self.comission_to_string()).alignment(Alignment::Right)),
]),
Row::new(vec![
Cell::from(Text::from("Validator APY".to_string()).alignment(Alignment::Left)),
Cell::from(Text::from(self.apy.clone()).alignment(Alignment::Right)),

View File

@ -65,20 +65,22 @@ impl RotatePopup {
}
}
fn parse_session_keys(&self) -> (String, String, String, String) {
if !self.cached_keys.is_empty() && self.cached_keys.len() == 258 {
fn parse_session_keys(&self) -> (String, String, String, String, String) {
if !self.cached_keys.is_empty() && self.cached_keys.len() == 322 {
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]);
let wevr_key = format!("0x{}", &self.cached_keys[194..258]);
let exds_key = format!("0x{}", &self.cached_keys[258..322]);
(gran_key, babe_key, audi_key, slow_key)
(gran_key, babe_key, audi_key, wevr_key, exds_key)
} else {
(
String::from("0x0000000000000000000000000000000000000000000000000000000000000000"),
String::from("0x0000000000000000000000000000000000000000000000000000000000000000"),
String::from("0x0000000000000000000000000000000000000000000000000000000000000000"),
String::from("0x0000000000000000000000000000000000000000000000000000000000000000"),
String::from("0x0000000000000000000000000000000000000000000000000000000000000000"),
)
}
}
@ -143,8 +145,8 @@ impl Component for RotatePopup {
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 (gran_key, babe_key, audi_key, wevr_key, exds_key) = self.parse_session_keys();
let (gran_key, babe_key, audi_key, slow_key) = self.parse_session_keys();
let table = Table::new(
vec![
Row::new(vec![
@ -160,8 +162,12 @@ impl Component for RotatePopup {
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)),
Cell::from(Text::from("wevr".to_string()).alignment(Alignment::Left)),
Cell::from(Text::from(wevr_key).alignment(Alignment::Right)),
]),
Row::new(vec![
Cell::from(Text::from("exds".to_string()).alignment(Alignment::Left)),
Cell::from(Text::from(exds_key).alignment(Alignment::Right)),
]),
],
[Constraint::Length(4), Constraint::Min(0)],
@ -177,7 +183,7 @@ impl Component for RotatePopup {
.title("Rotate session keys (Enter to proceed / Esc to close)"),
);
let v = Layout::vertical([Constraint::Max(6)]).flex(Flex::Center);
let v = Layout::vertical([Constraint::Max(7)]).flex(Flex::Center);
let h = Layout::horizontal([Constraint::Max(73)]).flex(Flex::Center);
let [area] = v.areas(area);
let [area] = h.areas(area);

View File

@ -15,6 +15,8 @@ use crate::{action::Action, config::Config, palette::StylePalette};
pub struct StashDetails {
palette: StylePalette,
network_tx: Option<Sender<Action>>,
commission: Option<u32>,
nominators_blocked: bool,
is_bonded: bool,
free_balance: Option<u128>,
staked_total: Option<u128>,
@ -37,6 +39,8 @@ impl StashDetails {
Self {
palette: StylePalette::default(),
network_tx: None,
nominators_blocked: false,
commission: None,
is_bonded: false,
free_balance: None,
staked_total: None,
@ -46,6 +50,19 @@ impl StashDetails {
}
}
fn commission_to_string(&self) -> String {
match self.commission {
Some(commission) => {
if self.nominators_blocked {
"disabled".to_string()
} else {
format!("{:.2}%", commission as f64 / 10_000_000.0)
}
}
None => DotSpinner::default().to_string(),
}
}
fn prepare_u128(&self, maybe_value: Option<u128>) -> String {
match maybe_value {
Some(value) => {
@ -102,6 +119,10 @@ impl Component for StashDetails {
match action {
Action::SetStashSecret(secret) => self.stash_secret = secret,
Action::SetStashAccount(account_id) => self.stash_account_id = account_id,
Action::SetValidatorPrefs(commission, disabled, account_id) if self.stash_account_id == account_id => {
self.commission = commission;
self.nominators_blocked = disabled;
}
Action::SetIsBonded(is_bonded, account_id) if self.stash_account_id == account_id => {
self.is_bonded = is_bonded
}
@ -139,7 +160,7 @@ impl Component for StashDetails {
let table = Table::new(
vec![
Row::new(vec![
Cell::from(Text::from("Bond ready".to_string()).alignment(Alignment::Left)),
Cell::from(Text::from("Bond status".to_string()).alignment(Alignment::Left)),
Cell::from(Text::from(self.is_bonded_to_string()).alignment(Alignment::Right)),
]),
Row::new(vec![
@ -163,6 +184,10 @@ impl Component for StashDetails {
.alignment(Alignment::Right),
),
]),
Row::new(vec![
Cell::from(Text::from("Nomination fee".to_string()).alignment(Alignment::Left)),
Cell::from(Text::from(self.commission_to_string()).alignment(Alignment::Right))
]),
],
[Constraint::Min(14), Constraint::Min(0)],
)

View File

@ -56,7 +56,7 @@ impl StashInfo {
stash_address: String::new(),
stash_pair: None,
session_keys: Default::default(),
key_names: &["gran", "babe", "audi", "slow"],
key_names: &["gran", "babe", "audi", "wevr", "exds"],
stash_filepath: PathBuf::from("/etc/ghost/stash-key"),
}
}
@ -232,7 +232,7 @@ impl Component for StashInfo {
}
fn draw(&mut self, frame: &mut Frame, area: Rect) -> Result<()> {
let [place, _, _] = super::validator_session_and_listen_layout(area);
let [place, _] = super::validator_session_and_listen_layout(area);
let (border_style, border_type) = self.palette.create_border_style(self.is_active);
let table = Table::new(
self.key_names.iter().map(|name| {

View File

@ -14,7 +14,8 @@ use tokio::sync::mpsc::UnboundedSender;
use crate::{
action::Action,
casper_network::runtime_types::{
ghost_networks::NetworkType, pallet_staking::RewardDestination, sp_consensus_slots,
ghost_helpers::networks::{NetworkCurve, NetworkType},
pallet_staking::RewardDestination, sp_consensus_slots,
},
types::{
EraInfo, EraRewardPoints, Gatekeeper, Nominations, Nominator, SessionKeyInfo,
@ -201,8 +202,8 @@ pub async fn get_inflation(
.await?
.map(|imbalance| {
total_issuance
.saturating_add(imbalance.bridged_out)
.saturating_sub(imbalance.bridged_in)
.saturating_add(imbalance.1)
.saturating_sub(imbalance.0)
})
.unwrap_or_default();
@ -237,22 +238,24 @@ pub async fn get_session_keys(
account_id: &[u8; 32],
) -> Result<()> {
let maybe_session_keys = super::raw_calls::session::next_keys(api, None, account_id).await?;
let (gran_key, babe_key, audi_key, slow_key) = match maybe_session_keys {
let (gran_key, babe_key, audi_key, wevr_key, exds_key) = match maybe_session_keys {
Some(session_keys) => {
let gran_key = format!("0x{}", hex::encode(session_keys.grandpa.0));
let babe_key = format!("0x{}", hex::encode(session_keys.babe.0));
let audi_key = format!("0x{}", hex::encode(session_keys.authority_discovery.0));
let slow_key = format!("0x{}", hex::encode(session_keys.slow_clap.0));
let wevr_key = format!("0x{}", hex::encode(session_keys.weaver.0));
let exds_key = format!("0x{}", hex::encode(session_keys.exodus.0));
(gran_key, babe_key, audi_key, slow_key)
(gran_key, babe_key, audi_key, wevr_key, exds_key)
}
None => (String::new(), String::new(), String::new(), String::new()),
None => (String::new(), String::new(), String::new(), String::new(), String::new()),
};
check_author_has_key(rpc_client, action_tx, &gran_key, "gran").await?;
check_author_has_key(rpc_client, action_tx, &babe_key, "babe").await?;
check_author_has_key(rpc_client, action_tx, &audi_key, "audi").await?;
check_author_has_key(rpc_client, action_tx, &slow_key, "slow").await?;
check_author_has_key(rpc_client, action_tx, &wevr_key, "wevr").await?;
check_author_has_key(rpc_client, action_tx, &exds_key, "exds").await?;
Ok(())
}
@ -266,26 +269,28 @@ pub async fn get_queued_session_keys(
let account = super::raw_calls::convert_array_to_account_id(account_id);
let maybe_queued_keys = super::raw_calls::session::queued_keys(api, None).await?;
let (gran_key, babe_key, audi_key, slow_key) = match maybe_queued_keys {
let (gran_key, babe_key, audi_key, wevr_key, exds_key) = match maybe_queued_keys {
Some(session_keys) => match session_keys.iter().find(|tuple| tuple.0 == account) {
Some(keys) => {
let session_keys = &keys.1;
let gran_key = format!("0x{}", hex::encode(session_keys.grandpa.0));
let babe_key = format!("0x{}", hex::encode(session_keys.babe.0));
let audi_key = format!("0x{}", hex::encode(session_keys.authority_discovery.0));
let slow_key = format!("0x{}", hex::encode(session_keys.slow_clap.0));
let wevr_key = format!("0x{}", hex::encode(session_keys.weaver.0));
let exds_key = format!("0x{}", hex::encode(session_keys.exodus.0));
(gran_key, babe_key, audi_key, slow_key)
(gran_key, babe_key, audi_key, wevr_key, exds_key)
}
None => (String::new(), String::new(), String::new(), String::new()),
None => (String::new(), String::new(), String::new(), String::new(), String::new()),
},
None => (String::new(), String::new(), String::new(), String::new()),
None => (String::new(), String::new(), String::new(), String::new(), String::new()),
};
check_author_has_key(rpc_client, action_tx, &gran_key, "q_gran").await?;
check_author_has_key(rpc_client, action_tx, &babe_key, "q_babe").await?;
check_author_has_key(rpc_client, action_tx, &audi_key, "q_audi").await?;
check_author_has_key(rpc_client, action_tx, &slow_key, "q_slow").await?;
check_author_has_key(rpc_client, action_tx, &wevr_key, "q_wevr").await?;
check_author_has_key(rpc_client, action_tx, &exds_key, "q_exds").await?;
Ok(())
}
@ -712,20 +717,24 @@ pub async fn get_gatekeeped_network(
.await?
.map(|network| Gatekeeper {
chain_id,
chain_name: String::from_utf8_lossy(&network.chain_name).to_string(),
chain_type: match network.network_type {
chain_curve: match network.curve {
NetworkCurve::Secp256k1 => String::from("Secp256k1"),
NetworkCurve::Ed25519 => String::from("Ed25519"),
},
chain_type: match network.r#type {
NetworkType::Evm => String::from("EVM"),
NetworkType::Utxo => String::from("UTXO"),
NetworkType::Undefined => String::from("???"),
_ => String::from("???"),
},
default_endpoints: network
.default_endpoints
.0
.iter()
.map(|endpoint| String::from_utf8_lossy(&endpoint).to_string())
.map(|endpoint| String::from_utf8_lossy(endpoint.0.as_slice()).to_string())
.collect(),
gatekeeper: String::from_utf8_lossy(&network.gatekeeper).to_string(),
incoming_fee: network.incoming_fee,
outgoing_fee: network.outgoing_fee,
gatekeeper: String::from_utf8_lossy(network.gatekeeper.0.as_slice()).to_string(),
incoming_fee: network.incoming_share,
outgoing_fee: network.outgoing_share,
})
.unwrap_or_default();
action_tx.send(Action::SetGatekeepedNetwork(gatekeeped_network))?;

View File

@ -115,7 +115,7 @@ pub async fn set_keys(
hashed_keys_str: &String,
maybe_nonce: Option<&mut u32>,
) -> Result<TxProgress<CasperConfig, OnlineClient<CasperConfig>>> {
let (gran_key, babe_key, audi_key, slow_key) = {
let (gran_key, babe_key, audi_key, wevr_key, exds_key) = {
let s = hashed_keys_str.trim_start_matches("0x");
(
hex::decode(&s[0..64])
@ -138,13 +138,19 @@ pub async fn set_keys(
.as_slice()
.try_into()
.unwrap(),
hex::decode(&s[256..320])
.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),
weaver: runtime_types::ghost_weaver::sr25519::app_sr25519::Public(wevr_key),
exodus: runtime_types::ghost_exodus::sr25519::app_sr25519::Public(exds_key),
};
// it seems like there is no check for the second paramter, that's why
// we it can be anything. For example empty vector.

View File

@ -4,7 +4,7 @@ use subxt::{client::OnlineClient, utils::H256};
use crate::{
casper_network::{
self,
runtime_types::ghost_networks::{BridgeAdjustment, NetworkData},
runtime_types::ghost_helpers::networks::NetworkData,
},
CasperConfig,
};
@ -12,12 +12,13 @@ use crate::{
pub async fn bridged_imbalance(
online_client: &OnlineClient<CasperConfig>,
at_hash: Option<&H256>,
) -> Result<Option<BridgeAdjustment<u128>>> {
) -> Result<Option<(u128, u128)>> {
let storage_key = casper_network::storage()
.ghost_networks()
.bridged_imbalance();
let maybe_bridged_imbalance =
.network_imbalance();
let maybe_network_imbalance =
super::do_storage_call(online_client, &storage_key, at_hash).await?;
let maybe_bridged_imbalance = maybe_network_imbalance.map(|n| (n.incoming, n.outgoing));
Ok(maybe_bridged_imbalance)
}
@ -27,9 +28,10 @@ pub async fn accumulated_commission(
) -> Result<Option<u128>> {
let storage_key = casper_network::storage()
.ghost_networks()
.accumulated_commission();
let maybe_accumulated_commission =
.network_imbalance();
let maybe_network_imbalance =
super::do_storage_call(online_client, &storage_key, at_hash).await?;
let maybe_accumulated_commission = maybe_network_imbalance.map(|n| n.curve_share);
Ok(maybe_accumulated_commission)
}

View File

@ -4,8 +4,8 @@ use serde::{Deserialize, Serialize};
#[derive(Debug, Default, Clone, PartialEq, Eq, Serialize, Deserialize, Decode)]
pub struct Gatekeeper {
pub chain_id: u64,
pub chain_name: String,
pub chain_type: String,
pub chain_curve: String,
pub gatekeeper: String,
pub incoming_fee: u32,
pub outgoing_fee: u32,