Compare commits

..

No commits in common. "92e82ceeee960bd9a836fc4feb58fdb2bdbca0fc" and "7f246d9a4eb42f12e7389d1158e5e0b4cb391b2a" have entirely different histories.

7 changed files with 134 additions and 22 deletions

View File

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

View File

@ -133,8 +133,10 @@ pub enum Action {
SetChoosenGatekeeper(u64), SetChoosenGatekeeper(u64),
SetSlashingSpansLength(usize, [u8; 32]), SetSlashingSpansLength(usize, [u8; 32]),
SetStoredRpcEndpoints(Vec<String>), SetStoredRpcEndpoints(Vec<String>),
SetLastUpdated(u64, u64),
SetRateLimitDelay(u64, u64), SetRateLimitDelay(u64, u64),
UpdateStoredRpcEndpoints(u64, Vec<String>), UpdateStoredRpcEndpoints(u64, Vec<String>),
NullifyLastTimestamp(u64),
BestBlockInformation(H256, u32), BestBlockInformation(H256, u32),
FinalizedBlockInformation(H256, u32), FinalizedBlockInformation(H256, u32),

View File

@ -30,6 +30,7 @@ pub struct GatekeeperEndpoints {
is_active: bool, is_active: bool,
selected: Selected, selected: Selected,
rate_limit_delay: u64, rate_limit_delay: u64,
last_updated: u64,
chain_id: u64, chain_id: u64,
rpc_input: Input, rpc_input: Input,
action_tx: Option<UnboundedSender<Action>>, action_tx: Option<UnboundedSender<Action>>,
@ -89,6 +90,11 @@ impl GatekeeperEndpoints {
} }
} }
} }
Selected::StoredRpcs if new_char == 'T' => {
if let Some(network_tx) = &self.network_tx {
let _ = network_tx.send(Action::NullifyLastTimestamp(self.chain_id));
}
}
_ => match new_char { _ => match new_char {
'j' => self.move_cursor_down(), 'j' => self.move_cursor_down(),
'k' => self.move_cursor_up(), 'k' => self.move_cursor_up(),
@ -232,7 +238,31 @@ impl GatekeeperEndpoints {
} }
fn prepare_rate_limits(&self) -> String { fn prepare_rate_limits(&self) -> String {
format!("RPC call cooldown: {}s", self.rate_limit_delay) format!("Rate limit: {}", self.rate_limit_delay / 1_000)
}
fn prepare_datetime_string(&self) -> String {
let now = std::time::SystemTime::now()
.duration_since(std::time::UNIX_EPOCH)
.expect("Time went backwards")
.as_millis();
let diff = now as i64 - self.last_updated as i64;
let abs_diff = diff.abs();
if abs_diff < 60_000 {
let secs = abs_diff / 1_000;
format!("{}secs {}", secs, if diff >= 0 { "ago" } else { "left" })
} else if abs_diff < 3_600_000 {
let mins = abs_diff / 60_000;
format!("{}mins {}", mins, if diff >= 0 { "ago" } else { "left" })
} else if abs_diff < 86_400_000 {
let hours = abs_diff / 3_600_000;
format!("{}hour {}", hours, if diff >= 0 { "ago" } else { "left" })
} else {
let days = abs_diff / 86_400_000;
format!("{}days {}", days, if diff >= 0 { "ago" } else { "left" })
}
} }
} }
@ -305,9 +335,14 @@ impl Component for GatekeeperEndpoints {
fn update(&mut self, action: Action) -> Result<Option<Action>> { fn update(&mut self, action: Action) -> Result<Option<Action>> {
match action { match action {
Action::SetChoosenGatekeeper(chain_id) => self.set_chain_id(chain_id), Action::SetChoosenGatekeeper(chain_id) => self.set_chain_id(chain_id),
Action::SetLastUpdated(chain_id, last_updated) => {
if chain_id == self.chain_id {
self.last_updated = last_updated;
}
}
Action::SetRateLimitDelay(chain_id, rate_limit_delay) => { Action::SetRateLimitDelay(chain_id, rate_limit_delay) => {
if chain_id == self.chain_id { if chain_id == self.chain_id {
self.rate_limit_delay = rate_limit_delay / 1_000; self.rate_limit_delay = rate_limit_delay;
} }
} }
Action::SetGatekeepedNetwork(network) => { Action::SetGatekeepedNetwork(network) => {
@ -365,7 +400,8 @@ impl Component for GatekeeperEndpoints {
.title_style(self.palette.create_popup_title_style()) .title_style(self.palette.create_popup_title_style())
.title_alignment(Alignment::Right) .title_alignment(Alignment::Right)
.title("Input new RPC") .title("Input new RPC")
.title_top(Line::from(self.prepare_rate_limits()).left_aligned()), .title_bottom(Line::from(self.prepare_datetime_string()).left_aligned())
.title_bottom(Line::from(self.prepare_rate_limits()).right_aligned()),
); );
let v = Layout::vertical([Constraint::Max(14)]).flex(Flex::Center); let v = Layout::vertical([Constraint::Max(14)]).flex(Flex::Center);

View File

@ -264,8 +264,8 @@ impl Component for Validator {
match action { match action {
Action::SetActiveScreen(Mode::Validator) => { Action::SetActiveScreen(Mode::Validator) => {
self.is_active = true; self.is_active = true;
self.previous_tab = CurrentTab::Gatekeepers; self.previous_tab = CurrentTab::NominatorsByValidator;
self.current_tab = CurrentTab::Gatekeepers; self.current_tab = CurrentTab::NominatorsByValidator;
} }
Action::PayoutValidatorPopup(_) => { Action::PayoutValidatorPopup(_) => {
self.previous_tab = self.current_tab; self.previous_tab = self.current_tab;

View File

@ -169,6 +169,36 @@ pub async fn get_block_range(
Ok(()) Ok(())
} }
pub async fn get_last_updated(
action_tx: &UnboundedSender<Action>,
rpc_client: &RpcClient,
chain_id: u64,
) -> Result<()> {
let chain_id_encoded = chain_id.encode();
let block_range_key_raw = get_slow_clap_storage_key(b"last-timestamp-", &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 last_timestamp: u64 = rpc_client
.request(
"offchain_localStorageGet",
rpc_params!["PERSISTENT", block_range_key],
)
.await
.ok()
.map(|hex_string: String| {
let bytes = hex::decode(&hex_string[2..]).expect("Invalid hex string");
u64::decode(&mut bytes.as_slice())
.ok()
.unwrap_or_default()
})
.unwrap_or_default();
action_tx.send(Action::SetLastUpdated(chain_id, last_timestamp))?;
Ok(())
}
pub async fn get_rate_limit_delay( pub async fn get_rate_limit_delay(
action_tx: &UnboundedSender<Action>, action_tx: &UnboundedSender<Action>,
rpc_client: &RpcClient, rpc_client: &RpcClient,
@ -189,7 +219,9 @@ pub async fn get_rate_limit_delay(
.ok() .ok()
.map(|hex_string: String| { .map(|hex_string: String| {
let bytes = hex::decode(&hex_string[2..]).expect("Invalid hex string"); let bytes = hex::decode(&hex_string[2..]).expect("Invalid hex string");
u64::decode(&mut bytes.as_slice()).ok().unwrap_or(5_000u64) u64::decode(&mut bytes.as_slice())
.ok()
.unwrap_or(5_000u64)
}) })
.unwrap_or(5_000u64); .unwrap_or(5_000u64);
@ -314,3 +346,40 @@ pub async fn set_stored_rpc_endpoints(
Ok(()) Ok(())
} }
pub async fn set_last_timestamp(
action_tx: &UnboundedSender<Action>,
rpc_client: &RpcClient,
chain_id: u64,
) -> Result<()> {
let chain_id_encoded = chain_id.encode();
let endpoint_key_raw = get_slow_clap_storage_key(b"last-timestamp-", &chain_id_encoded);
let mut endpoint_key = String::from("0x");
for byte in endpoint_key_raw {
endpoint_key.push_str(&format!("{:02x}", byte));
}
let encoded_zero = String::from("0x0000000000000000");
match rpc_client
.request::<()>(
"offchain_localStorageSet",
rpc_params!["PERSISTENT", endpoint_key, encoded_zero],
)
.await
{
Ok(_) => {
action_tx.send(Action::EventLog(
format!("Last timestamp nullified for network #{:?}", chain_id),
ActionLevel::Info,
ActionTarget::ValidatorLog,
))?;
get_stored_rpc_endpoints(action_tx, rpc_client, chain_id).await?;
}
Err(err) => action_tx.send(Action::EventLog(
format!("Last timestamp nullification failed: {:?}", err),
ActionLevel::Error,
ActionTarget::ValidatorLog,
))?,
};
Ok(())
}

View File

@ -277,8 +277,8 @@ impl Network {
} }
TxStatus::InBestBlock(b) => self.action_tx.send(Action::EventLog( TxStatus::InBestBlock(b) => self.action_tx.send(Action::EventLog(
format!( format!(
"transaction {:?} included in the block header {}", "transaction {} included in the block header {}",
b, b.extrinsic_hash(),
b.block_hash() b.block_hash()
), ),
ActionLevel::Info, ActionLevel::Info,
@ -378,12 +378,10 @@ impl Network {
for chain_id in GATEKEEPED_CHAIN_IDS { for chain_id in GATEKEEPED_CHAIN_IDS {
legacy_rpc_calls::get_block_range(&self.action_tx, &self.rpc_client, chain_id) legacy_rpc_calls::get_block_range(&self.action_tx, &self.rpc_client, chain_id)
.await?; .await?;
legacy_rpc_calls::get_rate_limit_delay( legacy_rpc_calls::get_last_updated(&self.action_tx, &self.rpc_client, chain_id)
&self.action_tx, .await?;
&self.rpc_client, legacy_rpc_calls::get_rate_limit_delay(&self.action_tx, &self.rpc_client, chain_id)
chain_id, .await?;
)
.await?;
} }
Ok(()) Ok(())
} }
@ -717,7 +715,7 @@ impl Network {
Action::ChillFrom(sender) => { Action::ChillFrom(sender) => {
let sender_str = hex::encode(sender); let sender_str = hex::encode(sender);
let maybe_nonce = self.senders.get_mut(&sender_str); let maybe_nonce = self.senders.get_mut(&sender_str);
if let Ok(_) = predefined_txs::chill( if let Ok(tx_progress) = predefined_txs::chill(
&self.action_tx, &self.action_tx,
&self.online_client_api, &self.online_client_api,
&sender, &sender,
@ -725,11 +723,11 @@ impl Network {
) )
.await .await
{ {
self.action_tx.send(Action::EventLog( self.transactions_to_watch.push(TxToWatch {
format!("the chill state will be applied at the start of new era."), tx_progress,
ActionLevel::Info, sender: sender_str,
ActionTarget::ValidatorLog, target: ActionTarget::ValidatorLog,
))? });
} }
Ok(()) Ok(())
} }
@ -852,6 +850,14 @@ impl Network {
) )
.await .await
} }
Action::NullifyLastTimestamp(chain_id) => {
legacy_rpc_calls::set_last_timestamp(
&self.action_tx,
&self.rpc_client,
chain_id,
)
.await
}
_ => Ok(()), _ => Ok(()),
} }
} }

View File

@ -1 +0,0 @@