Add cli command to query upgradeable account authorities (#14491)

This commit is contained in:
Jack May
2021-01-08 14:43:36 -08:00
committed by GitHub
parent 9d53eca6e3
commit 638f225dc4
2 changed files with 191 additions and 11 deletions

View File

@ -80,6 +80,9 @@ pub enum ProgramCliCommand {
upgrade_authority_index: Option<SignerIndex>, upgrade_authority_index: Option<SignerIndex>,
new_upgrade_authority: Option<Pubkey>, new_upgrade_authority: Option<Pubkey>,
}, },
GetAuthority {
account_pubkey: Option<Pubkey>,
},
} }
pub trait ProgramSubCommands { pub trait ProgramSubCommands {
@ -222,7 +225,6 @@ impl ProgramSubCommands for App<'_, '_> {
.conflicts_with("new_buffer_authority") .conflicts_with("new_buffer_authority")
.help("The buffer will be immutable") .help("The buffer will be immutable")
) )
.arg(commitment_arg_with_default("singleGossip")),
) )
.subcommand( .subcommand(
SubCommand::with_name("set-upgrade-authority") SubCommand::with_name("set-upgrade-authority")
@ -256,7 +258,18 @@ impl ProgramSubCommands for App<'_, '_> {
.conflicts_with("new_upgrade_authority") .conflicts_with("new_upgrade_authority")
.help("The program will not be upgradeable") .help("The program will not be upgradeable")
) )
.arg(commitment_arg_with_default("singleGossip")), )
.subcommand(
SubCommand::with_name("get-authority")
.about("Gets a buffer or program account's authority")
.arg(
Arg::with_name("account")
.index(1)
.value_name("ACCOUNT_ADDRESS")
.takes_value(true)
.required(true)
.help("Public key of the account to query")
)
) )
) )
} }
@ -462,6 +475,12 @@ pub fn parse_program_subcommand(
signers: signer_info.signers, signers: signer_info.signers,
} }
} }
("get-authority", Some(matches)) => CliCommandInfo {
command: CliCommand::Program(ProgramCliCommand::GetAuthority {
account_pubkey: pubkey_of(matches, "account"),
}),
signers: vec![],
},
_ => unreachable!(), _ => unreachable!(),
}; };
Ok(response) Ok(response)
@ -539,6 +558,9 @@ pub fn process_program_subcommand(
*upgrade_authority_index, *upgrade_authority_index,
*new_upgrade_authority, *new_upgrade_authority,
), ),
ProgramCliCommand::GetAuthority { account_pubkey } => {
process_get_authority(&rpc_client, config, *account_pubkey)
}
} }
} }
@ -872,15 +894,59 @@ fn process_set_authority(
) )
.map_err(|e| format!("Setting authority failed: {}", e))?; .map_err(|e| format!("Setting authority failed: {}", e))?;
match new_authority { Ok(option_pubkey_to_string("Authority", new_authority))
Some(pubkey) => Ok(json!({ }
"Authority": format!("{:?}", pubkey),
}) fn process_get_authority(
.to_string()), rpc_client: &RpcClient,
None => Ok(json!({ config: &CliConfig,
"Authority": "None", account_pubkey: Option<Pubkey>,
}) ) -> ProcessResult {
.to_string()), if let Some(account_pubkey) = account_pubkey {
if let Some(account) = rpc_client
.get_account_with_commitment(&account_pubkey, config.commitment)?
.value
{
if let Ok(UpgradeableLoaderState::Program {
programdata_address,
}) = account.state()
{
if let Some(account) = rpc_client
.get_account_with_commitment(&programdata_address, config.commitment)?
.value
{
if let Ok(UpgradeableLoaderState::ProgramData {
upgrade_authority_address,
..
}) = account.state()
{
Ok(option_pubkey_to_string(
"Program upgrade authority",
upgrade_authority_address,
))
} else {
Err("Invalid associated ProgramData account found for the program".into())
}
} else {
Err(
"Failed to find associated ProgramData account for the provided program"
.into(),
)
}
} else if let Ok(UpgradeableLoaderState::Buffer { authority_address }) = account.state()
{
Ok(option_pubkey_to_string(
"Buffer authority",
authority_address,
))
} else {
Err("Not a buffer or program account".into())
}
} else {
Err("Unable to find the account".into())
}
} else {
Err("No account specified".into())
} }
} }
@ -1415,6 +1481,19 @@ fn report_ephemeral_mnemonic(words: usize, mnemonic: bip39::Mnemonic) {
); );
} }
fn option_pubkey_to_string(tag: &str, option: Option<Pubkey>) -> String {
match option {
Some(pubkey) => json!({
tag: format!("{:?}", pubkey),
})
.to_string(),
None => json!({
tag: "None",
})
.to_string(),
}
}
fn send_and_confirm_transactions_with_spinner<T: Signers>( fn send_and_confirm_transactions_with_spinner<T: Signers>(
rpc_client: &RpcClient, rpc_client: &RpcClient,
mut transactions: Vec<Transaction>, mut transactions: Vec<Transaction>,
@ -2248,6 +2327,37 @@ mod tests {
); );
} }
#[test]
#[allow(clippy::cognitive_complexity)]
fn test_cli_parse_get_authority() {
let test_commands = app("test", "desc", "version");
let default_keypair = Keypair::new();
let keypair_file = make_tmp_path("keypair_file");
write_keypair_file(&default_keypair, &keypair_file).unwrap();
let default_signer = DefaultSigner {
path: keypair_file,
arg_name: "".to_string(),
};
let buffer_pubkey = Pubkey::new_unique();
let test_deploy = test_commands.clone().get_matches_from(vec![
"test",
"program",
"get-authority",
&buffer_pubkey.to_string(),
]);
assert_eq!(
parse_command(&test_deploy, &default_signer, &mut None).unwrap(),
CliCommandInfo {
command: CliCommand::Program(ProgramCliCommand::GetAuthority {
account_pubkey: Some(buffer_pubkey)
}),
signers: vec![],
}
);
}
#[test] #[test]
fn test_cli_keypair_file() { fn test_cli_keypair_file() {
solana_logger::setup(); solana_logger::setup();

View File

@ -486,6 +486,25 @@ fn test_cli_program_deploy_with_authority() {
program_data[..] program_data[..]
); );
// Get upgrade authority
config.signers = vec![&keypair];
config.command = CliCommand::Program(ProgramCliCommand::GetAuthority {
account_pubkey: Some(program_pubkey),
});
let response = process_command(&config);
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
let authority_pubkey_str = json
.as_object()
.unwrap()
.get("Program upgrade authority")
.unwrap()
.as_str()
.unwrap();
assert_eq!(
new_upgrade_authority.pubkey(),
Pubkey::from_str(&authority_pubkey_str).unwrap()
);
// Set no authority // Set no authority
config.signers = vec![&keypair, &new_upgrade_authority]; config.signers = vec![&keypair, &new_upgrade_authority];
config.command = CliCommand::Program(ProgramCliCommand::SetUpgradeAuthority { config.command = CliCommand::Program(ProgramCliCommand::SetUpgradeAuthority {
@ -560,6 +579,22 @@ fn test_cli_program_deploy_with_authority() {
} else { } else {
panic!("not a buffer account"); panic!("not a buffer account");
} }
// Get buffer authority
config.signers = vec![&keypair];
config.command = CliCommand::Program(ProgramCliCommand::GetAuthority {
account_pubkey: Some(program_pubkey),
});
let response = process_command(&config);
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
let authority_pubkey_str = json
.as_object()
.unwrap()
.get("Program upgrade authority")
.unwrap()
.as_str()
.unwrap();
assert_eq!("None", authority_pubkey_str);
} }
#[test] #[test]
@ -686,6 +721,25 @@ fn test_cli_program_write_buffer() {
program_data[..] program_data[..]
); );
// Get buffer authority
config.signers = vec![&keypair];
config.command = CliCommand::Program(ProgramCliCommand::GetAuthority {
account_pubkey: Some(buffer_keypair.pubkey()),
});
let response = process_command(&config);
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
let authority_pubkey_str = json
.as_object()
.unwrap()
.get("Buffer authority")
.unwrap()
.as_str()
.unwrap();
assert_eq!(
keypair.pubkey(),
Pubkey::from_str(&authority_pubkey_str).unwrap()
);
// Specify buffer authority // Specify buffer authority
let buffer_keypair = Keypair::new(); let buffer_keypair = Keypair::new();
let authority_keypair = Keypair::new(); let authority_keypair = Keypair::new();
@ -799,6 +853,22 @@ fn test_cli_program_write_buffer() {
} else { } else {
panic!("not a buffer account"); panic!("not a buffer account");
} }
// Get buffer authority
config.signers = vec![&keypair];
config.command = CliCommand::Program(ProgramCliCommand::GetAuthority {
account_pubkey: Some(buffer_pubkey),
});
let response = process_command(&config);
let json: Value = serde_json::from_str(&response.unwrap()).unwrap();
let authority_pubkey_str = json
.as_object()
.unwrap()
.get("Buffer authority")
.unwrap()
.as_str()
.unwrap();
assert_eq!("None", authority_pubkey_str);
} }
#[test] #[test]