Add deploy err if program-account balance is too high (#13091)

* Add deploy err if program-account balance is too high

* Review comments

* Add system-program check

* Rename and unhide flag
This commit is contained in:
Tyera Eulberg 2020-10-22 22:42:35 -06:00 committed by GitHub
parent 368aeb2cee
commit 4669fa0f98
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 71 additions and 5 deletions

View File

@ -49,6 +49,7 @@ use solana_sdk::{
instruction::{Instruction, InstructionError},
loader_instruction,
message::Message,
native_token::Sol,
pubkey::{Pubkey, MAX_SEED_LEN},
signature::{keypair_from_seed, Keypair, Signature, Signer, SignerError},
signers::Signers,
@ -178,6 +179,7 @@ pub enum CliCommand {
program_location: String,
address: Option<SignerIndex>,
use_deprecated_loader: bool,
allow_excessive_balance: bool,
},
// Stake Commands
CreateStakeAccount {
@ -609,13 +611,13 @@ pub fn parse_command(
signers.push(signer);
1
});
let use_deprecated_loader = matches.is_present("use_deprecated_loader");
Ok(CliCommandInfo {
command: CliCommand::Deploy {
program_location: matches.value_of("program_location").unwrap().to_string(),
address,
use_deprecated_loader,
use_deprecated_loader: matches.is_present("use_deprecated_loader"),
allow_excessive_balance: matches.is_present("allow_excessive_balance"),
},
signers,
})
@ -1132,6 +1134,7 @@ fn process_deploy(
program_location: &str,
address: Option<SignerIndex>,
use_deprecated_loader: bool,
allow_excessive_balance: bool,
) -> ProcessResult {
const WORDS: usize = 12;
// Create ephemeral keypair to use for program address, if not provided
@ -1145,6 +1148,7 @@ fn process_deploy(
program_location,
address,
use_deprecated_loader,
allow_excessive_balance,
new_keypair,
);
@ -1160,7 +1164,7 @@ fn process_deploy(
WORDS
);
eprintln!(
"then pass it as the [ADDRESS_SIGNER] argument to `solana deploy ...`\n{}\n{}\n{}",
"then pass it as the [PROGRAM_ADDRESS_SIGNER] argument to `solana deploy ...`\n{}\n{}\n{}",
divider, phrase, divider
);
}
@ -1173,6 +1177,7 @@ fn do_process_deploy(
program_location: &str,
address: Option<SignerIndex>,
use_deprecated_loader: bool,
allow_excessive_balance: bool,
new_keypair: Keypair,
) -> ProcessResult {
let program_id = if let Some(i) = address {
@ -1237,6 +1242,15 @@ fn do_process_deploy(
balance,
));
balance_needed = balance;
} else if account.lamports > minimum_balance
&& system_program::check_id(&account.owner)
&& !allow_excessive_balance
{
return Err(CliError::DynamicProgramError(format!(
"Program account has a balance: {:?}; it may already be in use",
Sol(account.lamports)
))
.into());
}
(instructions, balance_needed)
} else {
@ -1619,12 +1633,14 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
program_location,
address,
use_deprecated_loader,
allow_excessive_balance,
} => process_deploy(
&rpc_client,
config,
program_location,
*address,
*use_deprecated_loader,
*allow_excessive_balance,
),
// Stake Commands
@ -2241,7 +2257,7 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
.arg(
Arg::with_name("address_signer")
.index(2)
.value_name("ADDRESS_SIGNER")
.value_name("PROGRAM_ADDRESS_SIGNER")
.takes_value(true)
.validator(is_valid_signer)
.help("The signer for the desired address of the program [default: new random address]")
@ -2253,6 +2269,12 @@ pub fn app<'ab, 'v>(name: &str, about: &'ab str, version: &'v str) -> App<'ab, '
.hidden(true) // Don't document this argument to discourage its use
.help("Use the deprecated BPF loader")
)
.arg(
Arg::with_name("allow_excessive_balance")
.long("allow-excessive-deploy-account-balance")
.takes_value(false)
.help("Use the designated program id, even if the account already holds a large balance of SOL")
)
.arg(commitment_arg_with_default("max")),
)
.subcommand(
@ -2621,6 +2643,7 @@ mod tests {
program_location: "/Users/test/program.o".to_string(),
address: None,
use_deprecated_loader: false,
allow_excessive_balance: false,
},
signers: vec![read_keypair_file(&keypair_file).unwrap().into()],
}
@ -2642,6 +2665,7 @@ mod tests {
program_location: "/Users/test/program.o".to_string(),
address: Some(1),
use_deprecated_loader: false,
allow_excessive_balance: false,
},
signers: vec![
read_keypair_file(&keypair_file).unwrap().into(),
@ -2955,6 +2979,7 @@ mod tests {
program_location: pathbuf.to_str().unwrap().to_string(),
address: None,
use_deprecated_loader: false,
allow_excessive_balance: false,
};
let result = process_command(&config);
let json: Value = serde_json::from_str(&result.unwrap()).unwrap();
@ -2973,6 +2998,7 @@ mod tests {
program_location: "bad/file/location.so".to_string(),
address: None,
use_deprecated_loader: false,
allow_excessive_balance: false,
};
assert!(process_command(&config).is_err());
}

View File

@ -55,7 +55,7 @@ fn test_cli_deploy_program() {
faucet_host: None,
faucet_port: faucet_addr.port(),
pubkey: None,
lamports: 3 * minimum_balance_for_rent_exemption, // min balance for rent exemption for two programs + leftover for tx processing
lamports: 4 * minimum_balance_for_rent_exemption, // min balance for rent exemption for three programs + leftover for tx processing
};
config.signers = vec![&keypair];
process_command(&config).unwrap();
@ -64,6 +64,7 @@ fn test_cli_deploy_program() {
program_location: pathbuf.to_str().unwrap().to_string(),
address: None,
use_deprecated_loader: false,
allow_excessive_balance: false,
};
let response = process_command(&config);
@ -98,6 +99,7 @@ fn test_cli_deploy_program() {
program_location: pathbuf.to_str().unwrap().to_string(),
address: Some(1),
use_deprecated_loader: false,
allow_excessive_balance: false,
};
process_command(&config).unwrap();
let account1 = rpc_client
@ -113,6 +115,44 @@ fn test_cli_deploy_program() {
// Attempt to redeploy to the same address
process_command(&config).unwrap_err();
// Attempt to deploy to account with excess balance
let custom_address_keypair = Keypair::new();
config.command = CliCommand::Airdrop {
faucet_host: None,
faucet_port: faucet_addr.port(),
pubkey: None,
lamports: 2 * minimum_balance_for_rent_exemption, // Anything over minimum_balance_for_rent_exemption should trigger err
};
config.signers = vec![&custom_address_keypair];
process_command(&config).unwrap();
config.signers = vec![&keypair, &custom_address_keypair];
config.command = CliCommand::Deploy {
program_location: pathbuf.to_str().unwrap().to_string(),
address: Some(1),
use_deprecated_loader: false,
allow_excessive_balance: false,
};
process_command(&config).unwrap_err();
// Use forcing parameter to deploy to account with excess balance
config.command = CliCommand::Deploy {
program_location: pathbuf.to_str().unwrap().to_string(),
address: Some(1),
use_deprecated_loader: false,
allow_excessive_balance: true,
};
process_command(&config).unwrap();
let account2 = rpc_client
.get_account_with_commitment(&custom_address_keypair.pubkey(), CommitmentConfig::recent())
.unwrap()
.value
.unwrap();
assert_eq!(account2.lamports, 2 * minimum_balance_for_rent_exemption);
assert_eq!(account2.owner, bpf_loader::id());
assert_eq!(account2.executable, true);
assert_eq!(account0.data, account2.data);
server.close().unwrap();
remove_dir_all(ledger_path).unwrap();
}