This repository has been archived by the owner on Jan 22, 2025. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 4.5k
"solana program set-upgrade-authority" uses SetAuthorityChecked instruction by default #29190
Merged
Merged
Changes from 4 commits
Commits
Show all changes
6 commits
Select commit
Hold shift + click to select a range
ddf00b2
set-upgrade-authority uses checked instruction by default
0xripleys 7b7892b
remove print statements
0xripleys 14ffe23
Merge remote-tracking branch 'upstream/master'
0xripleys 62cbd67
PR fixes
0xripleys fef4293
Merge remote-tracking branch 'upstream/master'
0xripleys f23891c
Merge branch 'master' into master
0xripleys File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -99,6 +99,11 @@ pub enum ProgramCliCommand { | |
upgrade_authority_index: Option<SignerIndex>, | ||
new_upgrade_authority: Option<Pubkey>, | ||
}, | ||
SetUpgradeAuthorityChecked { | ||
program_pubkey: Pubkey, | ||
upgrade_authority_index: SignerIndex, | ||
new_upgrade_authority_index: SignerIndex, | ||
}, | ||
Show { | ||
account_pubkey: Option<Pubkey>, | ||
authority_pubkey: Pubkey, | ||
|
@@ -276,18 +281,27 @@ impl ProgramSubCommands for App<'_, '_> { | |
.help("Upgrade authority [default: the default configured keypair]") | ||
) | ||
.arg( | ||
pubkey!(Arg::with_name("new_upgrade_authority") | ||
Arg::with_name("new_upgrade_authority") | ||
.long("new-upgrade-authority") | ||
.value_name("NEW_UPGRADE_AUTHORITY") | ||
.required_unless("final") | ||
.value_name("NEW_UPGRADE_AUTHORITY"), | ||
"Address of the new upgrade authority"), | ||
.takes_value(true) | ||
.help("New upgrade authority (keypair or pubkey). It is strongly recommended to pass in a keypair to prevent mistakes in setting the upgrade authority. You can opt out of this behavior by passing --skip-new-upgrade-authority-signer-check if you are really confident that you are setting the correct authority. Alternatively, If you wish to make the program immutable, you should ignore this arg and pass the --final flag." | ||
) | ||
) | ||
.arg( | ||
Arg::with_name("final") | ||
.long("final") | ||
.conflicts_with("new_upgrade_authority") | ||
.help("The program will not be upgradeable") | ||
) | ||
.arg( | ||
Arg::with_name("skip_new_upgrade_authority_signer_check") | ||
.long("skip-new-upgrade-authority-signer-check") | ||
.requires("new_upgrade_authority") | ||
.takes_value(false) | ||
.help("Set this flag if you don't want the new authority to sign the set-upgrade-authority transaction."), | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Can you explain more that the default behavior requires the new authority to sign to prevent mistakes in setting the upgrade authority? You can also warn that by opting out of this default behavior, users must be confident that they are setting the correct authority. Furthermore, if they intentionally are setting a new authority that can never sign, they should be instructed to use |
||
), | ||
) | ||
.subcommand( | ||
SubCommand::with_name("show") | ||
|
@@ -564,28 +578,49 @@ pub fn parse_program_subcommand( | |
let (upgrade_authority_signer, upgrade_authority_pubkey) = | ||
signer_of(matches, "upgrade_authority", wallet_manager)?; | ||
let program_pubkey = pubkey_of(matches, "program_id").unwrap(); | ||
let new_upgrade_authority = if matches.is_present("final") { | ||
let is_final = matches.is_present("final"); | ||
let new_upgrade_authority = if is_final { | ||
None | ||
} else { | ||
pubkey_of_signer(matches, "new_upgrade_authority", wallet_manager)? | ||
}; | ||
|
||
let signer_info = default_signer.generate_unique_signers( | ||
vec![ | ||
Some(default_signer.signer_from_path(matches, wallet_manager)?), | ||
upgrade_authority_signer, | ||
], | ||
matches, | ||
wallet_manager, | ||
)?; | ||
let mut signers = vec![ | ||
Some(default_signer.signer_from_path(matches, wallet_manager)?), | ||
upgrade_authority_signer, | ||
]; | ||
|
||
CliCommandInfo { | ||
command: CliCommand::Program(ProgramCliCommand::SetUpgradeAuthority { | ||
program_pubkey, | ||
upgrade_authority_index: signer_info.index_of(upgrade_authority_pubkey), | ||
new_upgrade_authority, | ||
}), | ||
signers: signer_info.signers, | ||
if !is_final && !matches.is_present("skip_new_upgrade_authority_signer_check") { | ||
let (new_upgrade_authority_signer, _) = | ||
signer_of(matches, "new_upgrade_authority", wallet_manager)?; | ||
signers.push(new_upgrade_authority_signer); | ||
} | ||
|
||
let signer_info = | ||
default_signer.generate_unique_signers(signers, matches, wallet_manager)?; | ||
|
||
if matches.is_present("skip_new_upgrade_authority_signer_check") || is_final { | ||
CliCommandInfo { | ||
command: CliCommand::Program(ProgramCliCommand::SetUpgradeAuthority { | ||
program_pubkey, | ||
upgrade_authority_index: signer_info.index_of(upgrade_authority_pubkey), | ||
new_upgrade_authority, | ||
}), | ||
signers: signer_info.signers, | ||
} | ||
} else { | ||
CliCommandInfo { | ||
command: CliCommand::Program(ProgramCliCommand::SetUpgradeAuthorityChecked { | ||
program_pubkey, | ||
upgrade_authority_index: signer_info | ||
.index_of(upgrade_authority_pubkey) | ||
.expect("upgrade authority is missing from signers"), | ||
new_upgrade_authority_index: signer_info | ||
.index_of(new_upgrade_authority) | ||
.expect("new upgrade authority is missing from signers"), | ||
}), | ||
signers: signer_info.signers, | ||
} | ||
} | ||
} | ||
("show", Some(matches)) => { | ||
|
@@ -735,6 +770,17 @@ pub fn process_program_subcommand( | |
*upgrade_authority_index, | ||
*new_upgrade_authority, | ||
), | ||
ProgramCliCommand::SetUpgradeAuthorityChecked { | ||
program_pubkey, | ||
upgrade_authority_index, | ||
new_upgrade_authority_index, | ||
} => process_set_authority_checked( | ||
&rpc_client, | ||
config, | ||
*program_pubkey, | ||
*upgrade_authority_index, | ||
*new_upgrade_authority_index, | ||
), | ||
ProgramCliCommand::Show { | ||
account_pubkey, | ||
authority_pubkey, | ||
|
@@ -1171,6 +1217,51 @@ fn process_set_authority( | |
Ok(config.output_format.formatted_string(&authority)) | ||
} | ||
|
||
fn process_set_authority_checked( | ||
rpc_client: &RpcClient, | ||
config: &CliConfig, | ||
program_pubkey: Pubkey, | ||
authority_index: SignerIndex, | ||
new_authority_index: SignerIndex, | ||
) -> ProcessResult { | ||
let authority_signer = config.signers[authority_index]; | ||
let new_authority_signer = config.signers[new_authority_index]; | ||
|
||
trace!("Set a new (checked) authority"); | ||
let blockhash = rpc_client.get_latest_blockhash()?; | ||
|
||
let mut tx = Transaction::new_unsigned(Message::new( | ||
&[bpf_loader_upgradeable::set_upgrade_authority_checked( | ||
&program_pubkey, | ||
&authority_signer.pubkey(), | ||
&new_authority_signer.pubkey(), | ||
)], | ||
Some(&config.signers[0].pubkey()), | ||
)); | ||
|
||
tx.try_sign( | ||
&[config.signers[0], authority_signer, new_authority_signer], | ||
blockhash, | ||
)?; | ||
rpc_client | ||
.send_and_confirm_transaction_with_spinner_and_config( | ||
&tx, | ||
config.commitment, | ||
RpcSendTransactionConfig { | ||
skip_preflight: false, | ||
preflight_commitment: Some(config.commitment.commitment), | ||
..RpcSendTransactionConfig::default() | ||
}, | ||
) | ||
.map_err(|e| format!("Setting authority failed: {e}"))?; | ||
|
||
let authority = CliProgramAuthority { | ||
authority: new_authority_signer.pubkey().to_string(), | ||
account_type: CliProgramAccountType::Program, | ||
}; | ||
Ok(config.output_format.formatted_string(&authority)) | ||
} | ||
|
||
const ACCOUNT_TYPE_SIZE: usize = 4; | ||
const SLOT_SIZE: usize = size_of::<u64>(); | ||
const OPTION_SIZE: usize = 1; | ||
|
@@ -2625,6 +2716,7 @@ mod tests { | |
&program_pubkey.to_string(), | ||
"--new-upgrade-authority", | ||
&new_authority_pubkey.to_string(), | ||
"--skip-new-upgrade-authority-signer-check", | ||
]); | ||
assert_eq!( | ||
parse_command(&test_command, &default_signer, &mut None).unwrap(), | ||
|
@@ -2649,6 +2741,7 @@ mod tests { | |
&program_pubkey.to_string(), | ||
"--new-upgrade-authority", | ||
&new_authority_pubkey_file, | ||
"--skip-new-upgrade-authority-signer-check", | ||
]); | ||
assert_eq!( | ||
parse_command(&test_command, &default_signer, &mut None).unwrap(), | ||
|
@@ -2662,6 +2755,35 @@ mod tests { | |
} | ||
); | ||
|
||
let program_pubkey = Pubkey::new_unique(); | ||
let new_authority_pubkey = Keypair::new(); | ||
let new_authority_pubkey_file = make_tmp_path("authority_keypair_file"); | ||
write_keypair_file(&new_authority_pubkey, &new_authority_pubkey_file).unwrap(); | ||
let test_command = test_commands.clone().get_matches_from(vec![ | ||
"test", | ||
"program", | ||
"set-upgrade-authority", | ||
&program_pubkey.to_string(), | ||
"--new-upgrade-authority", | ||
&new_authority_pubkey_file, | ||
]); | ||
assert_eq!( | ||
parse_command(&test_command, &default_signer, &mut None).unwrap(), | ||
CliCommandInfo { | ||
command: CliCommand::Program(ProgramCliCommand::SetUpgradeAuthorityChecked { | ||
program_pubkey, | ||
upgrade_authority_index: 0, | ||
new_upgrade_authority_index: 1, | ||
}), | ||
signers: vec![ | ||
read_keypair_file(&keypair_file).unwrap().into(), | ||
read_keypair_file(&new_authority_pubkey_file) | ||
.unwrap() | ||
.into(), | ||
], | ||
} | ||
); | ||
|
||
let program_pubkey = Pubkey::new_unique(); | ||
let new_authority_pubkey = Keypair::new(); | ||
let new_authority_pubkey_file = make_tmp_path("authority_keypair_file"); | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The
new_upgrade_authority
arg above (can't comment directly) should be updated to match how theupgrade_authority
arg is defined