Add ability to force feature activation without code modification (#14783)

(cherry picked from commit c3548f790c)

Co-authored-by: Michael Vines <mvines@gmail.com>
This commit is contained in:
mergify[bot]
2021-01-22 22:39:56 +00:00
committed by GitHub
parent 952a5b11c1
commit 2d246581ed

View File

@ -19,10 +19,22 @@ use solana_sdk::{
}; };
use std::{collections::HashMap, fmt, sync::Arc}; use std::{collections::HashMap, fmt, sync::Arc};
#[derive(Copy, Clone, Debug, PartialEq)]
pub enum ForceActivation {
No,
Almost,
Yes,
}
#[derive(Debug, PartialEq)] #[derive(Debug, PartialEq)]
pub enum FeatureCliCommand { pub enum FeatureCliCommand {
Status { features: Vec<Pubkey> }, Status {
Activate { feature: Pubkey }, features: Vec<Pubkey>,
},
Activate {
feature: Pubkey,
force: ForceActivation,
},
} }
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
@ -126,6 +138,13 @@ impl FeatureSubCommands for App<'_, '_> {
.index(1) .index(1)
.required(true) .required(true)
.help("The signer for the feature to activate"), .help("The signer for the feature to activate"),
)
.arg(
Arg::with_name("force")
.long("yolo")
.hidden(true)
.multiple(true)
.help("Override activation sanity checks. Don't use this flag"),
), ),
), ),
) )
@ -152,13 +171,20 @@ pub fn parse_feature_subcommand(
("activate", Some(matches)) => { ("activate", Some(matches)) => {
let (feature_signer, feature) = signer_of(matches, "feature", wallet_manager)?; let (feature_signer, feature) = signer_of(matches, "feature", wallet_manager)?;
let mut signers = vec![default_signer.signer_from_path(matches, wallet_manager)?]; let mut signers = vec![default_signer.signer_from_path(matches, wallet_manager)?];
let force = match matches.occurrences_of("force") {
2 => ForceActivation::Yes,
1 => ForceActivation::Almost,
_ => ForceActivation::No,
};
signers.push(feature_signer.unwrap()); signers.push(feature_signer.unwrap());
let feature = feature.unwrap(); let feature = feature.unwrap();
known_feature(&feature)?; known_feature(&feature)?;
CliCommandInfo { CliCommandInfo {
command: CliCommand::Feature(FeatureCliCommand::Activate { feature }), command: CliCommand::Feature(FeatureCliCommand::Activate { feature, force }),
signers, signers,
} }
} }
@ -189,7 +215,9 @@ pub fn process_feature_subcommand(
) -> ProcessResult { ) -> ProcessResult {
match feature_subcommand { match feature_subcommand {
FeatureCliCommand::Status { features } => process_status(rpc_client, config, features), FeatureCliCommand::Status { features } => process_status(rpc_client, config, features),
FeatureCliCommand::Activate { feature } => process_activate(rpc_client, config, *feature), FeatureCliCommand::Activate { feature, force } => {
process_activate(rpc_client, config, *feature, *force)
}
} }
} }
@ -329,12 +357,14 @@ fn process_activate(
rpc_client: &RpcClient, rpc_client: &RpcClient,
config: &CliConfig, config: &CliConfig,
feature_id: Pubkey, feature_id: Pubkey,
force: ForceActivation,
) -> ProcessResult { ) -> ProcessResult {
let account = rpc_client let account = rpc_client
.get_multiple_accounts(&[feature_id])? .get_multiple_accounts(&[feature_id])?
.into_iter() .into_iter()
.next() .next()
.unwrap(); .unwrap();
if let Some(account) = account { if let Some(account) = account {
if feature::from_account(&account).is_some() { if feature::from_account(&account).is_some() {
return Err(format!("{} has already been activated", feature_id).into()); return Err(format!("{} has already been activated", feature_id).into());
@ -342,7 +372,13 @@ fn process_activate(
} }
if !feature_activation_allowed(rpc_client, false)? { if !feature_activation_allowed(rpc_client, false)? {
return Err("Feature activation is not allowed at this time".into()); match force {
ForceActivation::Almost =>
return Err("Add force argument once more to override the sanity check to force feature activation ".into()),
ForceActivation::Yes => println!("FEATURE ACTIVATION FORCED"),
ForceActivation::No =>
return Err("Feature activation is not allowed at this time".into()),
}
} }
let rent = rpc_client.get_minimum_balance_for_rent_exemption(Feature::size_of())?; let rent = rpc_client.get_minimum_balance_for_rent_exemption(Feature::size_of())?;