cli: Feature status improvements (#24745)
* cli: Display feature activation epoch instead of slot * cli: Always display feature statuses for specific queries * cli: Add epoch column and show epoch for pending features * cli: Remove epoch column and clarify statuses * skip serializing bookkeeping fields * Add activation slot to feature status table
This commit is contained in:
parent
aee17f3b50
commit
2d7e29477a
|
@ -13,6 +13,7 @@ use {
|
||||||
solana_sdk::{
|
solana_sdk::{
|
||||||
account::Account,
|
account::Account,
|
||||||
clock::Slot,
|
clock::Slot,
|
||||||
|
epoch_schedule::EpochSchedule,
|
||||||
feature::{self, Feature},
|
feature::{self, Feature},
|
||||||
feature_set::FEATURE_NAMES,
|
feature_set::FEATURE_NAMES,
|
||||||
message::Message,
|
message::Message,
|
||||||
|
@ -107,6 +108,10 @@ impl Ord for CliFeature {
|
||||||
#[serde(rename_all = "camelCase")]
|
#[serde(rename_all = "camelCase")]
|
||||||
pub struct CliFeatures {
|
pub struct CliFeatures {
|
||||||
pub features: Vec<CliFeature>,
|
pub features: Vec<CliFeature>,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub epoch_schedule: EpochSchedule,
|
||||||
|
#[serde(skip)]
|
||||||
|
pub current_slot: Slot,
|
||||||
pub feature_activation_allowed: bool,
|
pub feature_activation_allowed: bool,
|
||||||
#[serde(skip_serializing_if = "Option::is_none")]
|
#[serde(skip_serializing_if = "Option::is_none")]
|
||||||
pub cluster_feature_sets: Option<CliClusterFeatureSets>,
|
pub cluster_feature_sets: Option<CliClusterFeatureSets>,
|
||||||
|
@ -116,13 +121,13 @@ pub struct CliFeatures {
|
||||||
|
|
||||||
impl fmt::Display for CliFeatures {
|
impl fmt::Display for CliFeatures {
|
||||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||||
if self.features.len() > 1 {
|
if !self.features.is_empty() {
|
||||||
writeln!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
"{}",
|
"{}",
|
||||||
style(format!(
|
style(format!(
|
||||||
"{:<44} | {:<27} | {}",
|
"{:<44} | {:<23} | {} | {}",
|
||||||
"Feature", "Status", "Description"
|
"Feature", "Status", "Activation Slot", "Description"
|
||||||
))
|
))
|
||||||
.bold()
|
.bold()
|
||||||
)?;
|
)?;
|
||||||
|
@ -130,13 +135,22 @@ impl fmt::Display for CliFeatures {
|
||||||
for feature in &self.features {
|
for feature in &self.features {
|
||||||
writeln!(
|
writeln!(
|
||||||
f,
|
f,
|
||||||
"{:<44} | {:<27} | {}",
|
"{:<44} | {:<23} | {:<15} | {}",
|
||||||
feature.id,
|
feature.id,
|
||||||
match feature.status {
|
match feature.status {
|
||||||
CliFeatureStatus::Inactive => style("inactive".to_string()).red(),
|
CliFeatureStatus::Inactive => style("inactive".to_string()).red(),
|
||||||
CliFeatureStatus::Pending => style("activation pending".to_string()).yellow(),
|
CliFeatureStatus::Pending => {
|
||||||
CliFeatureStatus::Active(activation_slot) =>
|
let current_epoch = self.epoch_schedule.get_epoch(self.current_slot);
|
||||||
style(format!("active since slot {:>9}", activation_slot)).green(),
|
style(format!("pending until epoch {}", current_epoch + 1)).yellow()
|
||||||
|
}
|
||||||
|
CliFeatureStatus::Active(activation_slot) => {
|
||||||
|
let activation_epoch = self.epoch_schedule.get_epoch(activation_slot);
|
||||||
|
style(format!("active since epoch {}", activation_epoch)).green()
|
||||||
|
}
|
||||||
|
},
|
||||||
|
match feature.status {
|
||||||
|
CliFeatureStatus::Active(activation_slot) => activation_slot.to_string(),
|
||||||
|
_ => "NA".to_string(),
|
||||||
},
|
},
|
||||||
feature.description,
|
feature.description,
|
||||||
)?;
|
)?;
|
||||||
|
@ -443,7 +457,8 @@ pub fn parse_feature_subcommand(
|
||||||
} else {
|
} else {
|
||||||
FEATURE_NAMES.keys().cloned().collect()
|
FEATURE_NAMES.keys().cloned().collect()
|
||||||
};
|
};
|
||||||
let display_all = matches.is_present("display_all");
|
let display_all =
|
||||||
|
matches.is_present("display_all") || features.len() < FEATURE_NAMES.len();
|
||||||
features.sort();
|
features.sort();
|
||||||
CliCommandInfo {
|
CliCommandInfo {
|
||||||
command: CliCommand::Feature(FeatureCliCommand::Status {
|
command: CliCommand::Feature(FeatureCliCommand::Status {
|
||||||
|
@ -680,9 +695,9 @@ fn process_status(
|
||||||
feature_ids: &[Pubkey],
|
feature_ids: &[Pubkey],
|
||||||
display_all: bool,
|
display_all: bool,
|
||||||
) -> ProcessResult {
|
) -> ProcessResult {
|
||||||
|
let current_slot = rpc_client.get_slot()?;
|
||||||
let filter = if !display_all {
|
let filter = if !display_all {
|
||||||
let now = rpc_client.get_slot()?;
|
current_slot.checked_sub(DEFAULT_MAX_ACTIVE_DISPLAY_AGE_SLOTS)
|
||||||
now.checked_sub(DEFAULT_MAX_ACTIVE_DISPLAY_AGE_SLOTS)
|
|
||||||
} else {
|
} else {
|
||||||
None
|
None
|
||||||
};
|
};
|
||||||
|
@ -721,8 +736,11 @@ fn process_status(
|
||||||
|
|
||||||
let (feature_activation_allowed, cluster_feature_sets) =
|
let (feature_activation_allowed, cluster_feature_sets) =
|
||||||
feature_activation_allowed(rpc_client, features.len() <= 1)?;
|
feature_activation_allowed(rpc_client, features.len() <= 1)?;
|
||||||
|
let epoch_schedule = rpc_client.get_epoch_schedule()?;
|
||||||
let feature_set = CliFeatures {
|
let feature_set = CliFeatures {
|
||||||
features,
|
features,
|
||||||
|
current_slot,
|
||||||
|
epoch_schedule,
|
||||||
feature_activation_allowed,
|
feature_activation_allowed,
|
||||||
cluster_feature_sets,
|
cluster_feature_sets,
|
||||||
inactive,
|
inactive,
|
||||||
|
|
Loading…
Reference in New Issue