CLI: Disallow blockhash/fee-calc lookups when offline (#7981)

* CLI: Add BlockhashSpec to tighten control over --blockhash

* Use BlockhashSpec

* Add a matches-free constructor

* More descriptive naming
This commit is contained in:
Trent Nelson 2020-01-30 09:21:32 -07:00 committed by GitHub
parent 400412d76c
commit 966d077431
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 284 additions and 87 deletions

View File

@ -161,7 +161,7 @@ pub struct PayCommand {
pub cancelable: bool,
pub sign_only: bool,
pub signers: Option<Vec<(Pubkey, Signature)>>,
pub blockhash: Option<Hash>,
pub blockhash_query: BlockhashQuery,
pub nonce_account: Option<Pubkey>,
pub nonce_authority: Option<SigningAuthority>,
}
@ -256,7 +256,7 @@ pub enum CliCommand {
stake_authority: Option<SigningAuthority>,
sign_only: bool,
signers: Option<Vec<(Pubkey, Signature)>>,
blockhash: Option<Hash>,
blockhash_query: BlockhashQuery,
nonce_account: Option<Pubkey>,
nonce_authority: Option<SigningAuthority>,
},
@ -267,7 +267,7 @@ pub enum CliCommand {
force: bool,
sign_only: bool,
signers: Option<Vec<(Pubkey, Signature)>>,
blockhash: Option<Hash>,
blockhash_query: BlockhashQuery,
nonce_account: Option<Pubkey>,
nonce_authority: Option<SigningAuthority>,
},
@ -285,7 +285,7 @@ pub enum CliCommand {
authority: Option<SigningAuthority>,
sign_only: bool,
signers: Option<Vec<(Pubkey, Signature)>>,
blockhash: Option<Hash>,
blockhash_query: BlockhashQuery,
nonce_account: Option<Pubkey>,
nonce_authority: Option<SigningAuthority>,
},
@ -607,7 +607,7 @@ pub fn parse_command(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, Box<dyn
let cancelable = matches.is_present("cancelable");
let sign_only = matches.is_present(SIGN_ONLY_ARG.name);
let signers = pubkeys_sigs_of(&matches, SIGNER_ARG.name);
let blockhash = value_of(&matches, BLOCKHASH_ARG.name);
let blockhash_query = BlockhashQuery::new_from_matches(&matches);
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
let nonce_authority = if matches.is_present(NONCE_AUTHORITY_ARG.name) {
Some(SigningAuthority::new_from_matches(
@ -629,7 +629,7 @@ pub fn parse_command(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, Box<dyn
cancelable,
sign_only,
signers,
blockhash,
blockhash_query,
nonce_account,
nonce_authority,
}),
@ -1008,7 +1008,7 @@ fn process_pay(
cancelable: bool,
sign_only: bool,
signers: &Option<Vec<(Pubkey, Signature)>>,
blockhash: Option<Hash>,
blockhash_query: &BlockhashQuery,
nonce_account: Option<Pubkey>,
nonce_authority: Option<&SigningAuthority>,
) -> ProcessResult {
@ -1017,8 +1017,7 @@ fn process_pay(
(to, "to".to_string()),
)?;
let (blockhash, fee_calculator) =
get_blockhash_fee_calculator(rpc_client, sign_only, blockhash)?;
let (blockhash, fee_calculator) = blockhash_query.get_blockhash_fee_calculator(rpc_client)?;
let cancelable = if cancelable {
Some(config.keypair.pubkey())
@ -1388,7 +1387,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
ref stake_authority,
sign_only,
ref signers,
blockhash,
blockhash_query,
nonce_account,
ref nonce_authority,
} => process_deactivate_stake_account(
@ -1398,7 +1397,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
stake_authority.as_ref(),
*sign_only,
signers,
*blockhash,
blockhash_query,
*nonce_account,
nonce_authority.as_ref(),
),
@ -1409,7 +1408,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
force,
sign_only,
ref signers,
blockhash,
blockhash_query,
nonce_account,
ref nonce_authority,
} => process_delegate_stake(
@ -1421,7 +1420,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
*force,
*sign_only,
signers,
*blockhash,
blockhash_query,
*nonce_account,
nonce_authority.as_ref(),
),
@ -1444,7 +1443,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
ref authority,
sign_only,
ref signers,
blockhash,
blockhash_query,
nonce_account,
ref nonce_authority,
} => process_stake_authorize(
@ -1456,7 +1455,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
authority.as_ref(),
*sign_only,
signers,
*blockhash,
blockhash_query,
*nonce_account,
nonce_authority.as_ref(),
),
@ -1628,7 +1627,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
cancelable,
sign_only,
ref signers,
blockhash,
blockhash_query,
nonce_account,
ref nonce_authority,
}) => process_pay(
@ -1642,7 +1641,7 @@ pub fn process_command(config: &CliConfig) -> ProcessResult {
*cancelable,
*sign_only,
signers,
*blockhash,
blockhash_query,
*nonce_account,
nonce_authority.as_ref(),
),
@ -2386,7 +2385,7 @@ mod tests {
command: CliCommand::Pay(PayCommand {
lamports: 50,
to: pubkey,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
sign_only: true,
..PayCommand::default()
}),
@ -2415,7 +2414,7 @@ mod tests {
command: CliCommand::Pay(PayCommand {
lamports: 50,
to: pubkey,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
signers: Some(vec![(key1, sig1)]),
..PayCommand::default()
}),
@ -2446,7 +2445,7 @@ mod tests {
command: CliCommand::Pay(PayCommand {
lamports: 50,
to: pubkey,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
signers: Some(vec![(key1, sig1), (key2, sig2)]),
..PayCommand::default()
}),
@ -2470,7 +2469,7 @@ mod tests {
command: CliCommand::Pay(PayCommand {
lamports: 50,
to: pubkey,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
..PayCommand::default()
}),
require_keypair: true
@ -2497,7 +2496,7 @@ mod tests {
command: CliCommand::Pay(PayCommand {
lamports: 50,
to: pubkey,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: Some(pubkey),
..PayCommand::default()
}),
@ -2528,7 +2527,7 @@ mod tests {
command: CliCommand::Pay(PayCommand {
lamports: 50,
to: pubkey,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: Some(pubkey),
nonce_authority: Some(keypair.into()),
..PayCommand::default()
@ -2564,7 +2563,7 @@ mod tests {
command: CliCommand::Pay(PayCommand {
lamports: 50,
to: pubkey,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: Some(pubkey),
nonce_authority: Some(authority_pubkey.into()),
signers: Some(vec![(authority_pubkey, sig)]),
@ -2768,7 +2767,7 @@ mod tests {
stake_authority: None,
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
};
@ -2854,7 +2853,7 @@ mod tests {
lamports: 10,
to: bob_pubkey,
nonce_account: Some(bob_pubkey),
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
..PayCommand::default()
});
let signature = process_command(&config);
@ -2881,7 +2880,7 @@ mod tests {
config.command = CliCommand::Pay(PayCommand {
lamports: 10,
to: bob_pubkey,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: Some(bob_pubkey),
nonce_authority: Some(bob_keypair.into()),
..PayCommand::default()

View File

@ -1,8 +1,11 @@
use clap::{App, Arg};
use clap::{App, Arg, ArgMatches};
use solana_clap_utils::{
input_parsers::value_of,
input_validators::{is_hash, is_pubkey_sig},
ArgConstant,
};
use solana_client::rpc_client::RpcClient;
use solana_sdk::{fee_calculator::FeeCalculator, hash::Hash};
pub const BLOCKHASH_ARG: ArgConstant<'static> = ArgConstant {
name: "blockhash",
@ -22,6 +25,53 @@ pub const SIGNER_ARG: ArgConstant<'static> = ArgConstant {
help: "Provid a public-key/signature pair for the transaction",
};
#[derive(Clone, Debug, PartialEq)]
pub enum BlockhashQuery {
None(Hash, FeeCalculator),
FeeCalculator(Hash),
All,
}
impl BlockhashQuery {
pub fn new(blockhash: Option<Hash>, sign_only: bool) -> Self {
match blockhash {
Some(hash) if sign_only => Self::None(hash, FeeCalculator::default()),
Some(hash) if !sign_only => Self::FeeCalculator(hash),
None if !sign_only => Self::All,
_ => panic!("Cannot resolve blockhash"),
}
}
pub fn new_from_matches(matches: &ArgMatches<'_>) -> Self {
let blockhash = value_of(matches, BLOCKHASH_ARG.name);
let sign_only = matches.is_present(SIGN_ONLY_ARG.name);
BlockhashQuery::new(blockhash, sign_only)
}
pub fn get_blockhash_fee_calculator(
&self,
rpc_client: &RpcClient,
) -> Result<(Hash, FeeCalculator), Box<dyn std::error::Error>> {
let (hash, fee_calc) = match self {
BlockhashQuery::None(hash, fee_calc) => (Some(hash), Some(fee_calc)),
BlockhashQuery::FeeCalculator(hash) => (Some(hash), None),
BlockhashQuery::All => (None, None),
};
if None == fee_calc {
let (cluster_hash, fee_calc) = rpc_client.get_recent_blockhash()?;
Ok((*hash.unwrap_or(&cluster_hash), fee_calc))
} else {
Ok((*hash.unwrap(), fee_calc.unwrap().clone()))
}
}
}
impl Default for BlockhashQuery {
fn default() -> Self {
BlockhashQuery::All
}
}
fn blockhash_arg<'a, 'b>() -> Arg<'a, 'b> {
Arg::with_name(BLOCKHASH_ARG.name)
.long(BLOCKHASH_ARG.long)
@ -61,3 +111,142 @@ impl OfflineArgs for App<'_, '_> {
.arg(signer_arg())
}
}
#[cfg(test)]
mod tests {
use super::*;
use clap::App;
use serde_json::{self, json, Value};
use solana_client::{
rpc_request::RpcRequest,
rpc_response::{Response, RpcResponseContext},
};
use solana_sdk::{fee_calculator::FeeCalculator, hash::hash};
use std::collections::HashMap;
#[test]
fn test_blockhashspec_new_ok() {
let blockhash = hash(&[1u8]);
assert_eq!(
BlockhashQuery::new(Some(blockhash), true),
BlockhashQuery::None(blockhash, FeeCalculator::default()),
);
assert_eq!(
BlockhashQuery::new(Some(blockhash), false),
BlockhashQuery::FeeCalculator(blockhash),
);
assert_eq!(BlockhashQuery::new(None, false), BlockhashQuery::All,);
}
#[test]
#[should_panic]
fn test_blockhashspec_new_fail() {
BlockhashQuery::new(None, true);
}
#[test]
fn test_blockhashspec_new_from_matches_ok() {
let test_commands = App::new("blockhashspec_test").offline_args();
let blockhash = hash(&[1u8]);
let blockhash_string = blockhash.to_string();
let matches = test_commands.clone().get_matches_from(vec![
"blockhashspec_test",
"--blockhash",
&blockhash_string,
"--sign-only",
]);
assert_eq!(
BlockhashQuery::new_from_matches(&matches),
BlockhashQuery::None(blockhash, FeeCalculator::default()),
);
let matches = test_commands.clone().get_matches_from(vec![
"blockhashspec_test",
"--blockhash",
&blockhash_string,
]);
assert_eq!(
BlockhashQuery::new_from_matches(&matches),
BlockhashQuery::FeeCalculator(blockhash),
);
let matches = test_commands
.clone()
.get_matches_from(vec!["blockhashspec_test"]);
assert_eq!(
BlockhashQuery::new_from_matches(&matches),
BlockhashQuery::All,
);
}
#[test]
#[should_panic]
fn test_blockhashspec_new_from_matches_fail() {
let test_commands = App::new("blockhashspec_test")
.arg(blockhash_arg())
// We can really only hit this case unless the arg requirements
// are broken, so unset the requires() to recreate that condition
.arg(sign_only_arg().requires(""));
let matches = test_commands
.clone()
.get_matches_from(vec!["blockhashspec_test", "--sign-only"]);
BlockhashQuery::new_from_matches(&matches);
}
#[test]
fn test_blockhashspec_get_blockhash_fee_calc() {
let test_blockhash = hash(&[0u8]);
let rpc_blockhash = hash(&[1u8]);
let rpc_fee_calc = FeeCalculator::new(42, 42);
let get_recent_blockhash_response = json!(Response {
context: RpcResponseContext { slot: 1 },
value: json!((
Value::String(rpc_blockhash.to_string()),
serde_json::to_value(rpc_fee_calc.clone()).unwrap()
)),
});
let mut mocks = HashMap::new();
mocks.insert(
RpcRequest::GetRecentBlockhash,
get_recent_blockhash_response.clone(),
);
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!(
BlockhashQuery::All
.get_blockhash_fee_calculator(&rpc_client)
.unwrap(),
(rpc_blockhash, rpc_fee_calc.clone()),
);
let mut mocks = HashMap::new();
mocks.insert(
RpcRequest::GetRecentBlockhash,
get_recent_blockhash_response.clone(),
);
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!(
BlockhashQuery::FeeCalculator(test_blockhash)
.get_blockhash_fee_calculator(&rpc_client)
.unwrap(),
(test_blockhash, rpc_fee_calc.clone()),
);
let mut mocks = HashMap::new();
mocks.insert(
RpcRequest::GetRecentBlockhash,
get_recent_blockhash_response.clone(),
);
let rpc_client = RpcClient::new_mock_with_mocks("".to_string(), mocks);
assert_eq!(
BlockhashQuery::None(test_blockhash, FeeCalculator::default())
.get_blockhash_fee_calculator(&rpc_client)
.unwrap(),
(test_blockhash, FeeCalculator::default()),
);
let rpc_client = RpcClient::new_mock("fails".to_string());
assert!(BlockhashQuery::All
.get_blockhash_fee_calculator(&rpc_client)
.is_err());
}
}

View File

@ -1,9 +1,9 @@
use crate::{
cli::{
build_balance_message, check_account_for_fee, check_unique_pubkeys,
get_blockhash_fee_calculator, log_instruction_custom_error, nonce_authority_arg,
replace_signatures, required_lamports_from, return_signers, CliCommand, CliCommandInfo,
CliConfig, CliError, ProcessResult, SigningAuthority,
log_instruction_custom_error, nonce_authority_arg, replace_signatures,
required_lamports_from, return_signers, CliCommand, CliCommandInfo, CliConfig, CliError,
ProcessResult, SigningAuthority,
},
nonce::{check_nonce_account, nonce_arg, NONCE_ARG, NONCE_AUTHORITY_ARG},
offline::*,
@ -15,7 +15,6 @@ use solana_client::rpc_client::RpcClient;
use solana_sdk::signature::{Keypair, Signature};
use solana_sdk::{
account_utils::StateMut,
hash::Hash,
pubkey::Pubkey,
signature::KeypairUtil,
system_instruction::{create_address_with_seed, SystemError},
@ -352,7 +351,7 @@ pub fn parse_stake_delegate_stake(matches: &ArgMatches<'_>) -> Result<CliCommand
let force = matches.is_present("force");
let sign_only = matches.is_present(SIGN_ONLY_ARG.name);
let signers = pubkeys_sigs_of(&matches, SIGNER_ARG.name);
let blockhash = value_of(matches, BLOCKHASH_ARG.name);
let blockhash_query = BlockhashQuery::new_from_matches(matches);
let require_keypair = signers.is_none();
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
let stake_authority = if matches.is_present(STAKE_AUTHORITY_ARG.name) {
@ -382,7 +381,7 @@ pub fn parse_stake_delegate_stake(matches: &ArgMatches<'_>) -> Result<CliCommand
force,
sign_only,
signers,
blockhash,
blockhash_query,
nonce_account,
nonce_authority,
},
@ -411,7 +410,7 @@ pub fn parse_stake_authorize(
} else {
None
};
let blockhash = value_of(matches, BLOCKHASH_ARG.name);
let blockhash_query = BlockhashQuery::new_from_matches(matches);
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
let nonce_authority = if matches.is_present(NONCE_AUTHORITY_ARG.name) {
Some(SigningAuthority::new_from_matches(
@ -431,7 +430,7 @@ pub fn parse_stake_authorize(
authority,
sign_only,
signers,
blockhash,
blockhash_query,
nonce_account,
nonce_authority,
},
@ -443,7 +442,7 @@ pub fn parse_stake_deactivate_stake(matches: &ArgMatches<'_>) -> Result<CliComma
let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap();
let sign_only = matches.is_present(SIGN_ONLY_ARG.name);
let signers = pubkeys_sigs_of(&matches, SIGNER_ARG.name);
let blockhash = value_of(matches, BLOCKHASH_ARG.name);
let blockhash_query = BlockhashQuery::new_from_matches(matches);
let require_keypair = signers.is_none();
let nonce_account = pubkey_of(&matches, NONCE_ARG.name);
let stake_authority = if matches.is_present(STAKE_AUTHORITY_ARG.name) {
@ -471,7 +470,7 @@ pub fn parse_stake_deactivate_stake(matches: &ArgMatches<'_>) -> Result<CliComma
stake_authority,
sign_only,
signers,
blockhash,
blockhash_query,
nonce_account,
nonce_authority,
},
@ -626,7 +625,7 @@ pub fn process_stake_authorize(
authority: Option<&SigningAuthority>,
sign_only: bool,
signers: &Option<Vec<(Pubkey, Signature)>>,
blockhash: Option<Hash>,
blockhash_query: &BlockhashQuery,
nonce_account: Option<Pubkey>,
nonce_authority: Option<&SigningAuthority>,
) -> ProcessResult {
@ -636,7 +635,7 @@ pub fn process_stake_authorize(
)?;
let authority = authority.map(|a| a.keypair()).unwrap_or(&config.keypair);
let (recent_blockhash, fee_calculator) =
get_blockhash_fee_calculator(rpc_client, sign_only, blockhash)?;
blockhash_query.get_blockhash_fee_calculator(rpc_client)?;
let ixs = vec![stake_instruction::authorize(
stake_account_pubkey, // stake account to update
&authority.pubkey(), // currently authorized
@ -692,12 +691,12 @@ pub fn process_deactivate_stake_account(
stake_authority: Option<&SigningAuthority>,
sign_only: bool,
signers: &Option<Vec<(Pubkey, Signature)>>,
blockhash: Option<Hash>,
blockhash_query: &BlockhashQuery,
nonce_account: Option<Pubkey>,
nonce_authority: Option<&SigningAuthority>,
) -> ProcessResult {
let (recent_blockhash, fee_calculator) =
get_blockhash_fee_calculator(rpc_client, sign_only, blockhash)?;
blockhash_query.get_blockhash_fee_calculator(rpc_client)?;
let stake_authority = stake_authority
.map(|a| a.keypair())
.unwrap_or(&config.keypair);
@ -913,7 +912,7 @@ pub fn process_delegate_stake(
force: bool,
sign_only: bool,
signers: &Option<Vec<(Pubkey, Signature)>>,
blockhash: Option<Hash>,
blockhash_query: &BlockhashQuery,
nonce_account: Option<Pubkey>,
nonce_authority: Option<&SigningAuthority>,
) -> ProcessResult {
@ -966,7 +965,7 @@ pub fn process_delegate_stake(
}
let (recent_blockhash, fee_calculator) =
get_blockhash_fee_calculator(rpc_client, sign_only, blockhash)?;
blockhash_query.get_blockhash_fee_calculator(rpc_client)?;
let ixs = vec![stake_instruction::delegate_stake(
stake_account_pubkey,
@ -1018,7 +1017,11 @@ pub fn process_delegate_stake(
mod tests {
use super::*;
use crate::cli::{app, parse_command};
use solana_sdk::signature::{read_keypair_file, write_keypair};
use solana_sdk::{
fee_calculator::FeeCalculator,
hash::Hash,
signature::{read_keypair_file, write_keypair},
};
use tempfile::NamedTempFile;
fn make_tmp_file() -> (String, NamedTempFile) {
@ -1056,7 +1059,7 @@ mod tests {
authority: None,
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
},
@ -1082,7 +1085,7 @@ mod tests {
authority: Some(read_keypair_file(&authority_keypair_file).unwrap().into()),
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
},
@ -1111,7 +1114,7 @@ mod tests {
authority: None,
sign_only: true,
signers: None,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
nonce_account: None,
nonce_authority: None,
},
@ -1142,7 +1145,7 @@ mod tests {
authority: None,
sign_only: false,
signers: Some(vec![(keypair.pubkey(), sig)]),
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: None,
nonce_authority: None,
},
@ -1175,7 +1178,7 @@ mod tests {
authority: None,
sign_only: false,
signers: Some(vec![(keypair.pubkey(), sig), (keypair2.pubkey(), sig2),]),
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: None,
nonce_authority: None,
},
@ -1201,7 +1204,7 @@ mod tests {
authority: None,
sign_only: false,
signers: None,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: None,
nonce_authority: None,
},
@ -1236,7 +1239,7 @@ mod tests {
authority: None,
sign_only: false,
signers: None,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: Some(nonce_account_pubkey),
nonce_authority: Some(nonce_authority_keypair.into()),
},
@ -1356,7 +1359,7 @@ mod tests {
force: false,
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
},
@ -1389,7 +1392,7 @@ mod tests {
force: false,
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
},
@ -1415,7 +1418,7 @@ mod tests {
force: true,
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
},
@ -1444,7 +1447,7 @@ mod tests {
force: false,
sign_only: false,
signers: None,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: None,
nonce_authority: None,
},
@ -1471,7 +1474,7 @@ mod tests {
force: false,
sign_only: true,
signers: None,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
nonce_account: None,
nonce_authority: None,
},
@ -1503,7 +1506,7 @@ mod tests {
force: false,
sign_only: false,
signers: Some(vec![(key1, sig1)]),
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: None,
nonce_authority: None,
},
@ -1537,7 +1540,7 @@ mod tests {
force: false,
sign_only: false,
signers: Some(vec![(key1, sig1), (key2, sig2)]),
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: None,
nonce_authority: None,
},
@ -1611,7 +1614,7 @@ mod tests {
stake_authority: None,
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
},
@ -1639,7 +1642,7 @@ mod tests {
),
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
},
@ -1665,7 +1668,7 @@ mod tests {
stake_authority: None,
sign_only: false,
signers: None,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: None,
nonce_authority: None,
},
@ -1689,7 +1692,7 @@ mod tests {
stake_authority: None,
sign_only: true,
signers: None,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
nonce_account: None,
nonce_authority: None,
},
@ -1718,7 +1721,7 @@ mod tests {
stake_authority: None,
sign_only: false,
signers: Some(vec![(key1, sig1)]),
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: None,
nonce_authority: None,
},
@ -1749,7 +1752,7 @@ mod tests {
stake_authority: None,
sign_only: false,
signers: Some(vec![(key1, sig1), (key2, sig2)]),
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: None,
nonce_authority: None,
},

View File

@ -1,12 +1,14 @@
use chrono::prelude::*;
use serde_json::Value;
use solana_cli::cli::{
process_command, request_and_confirm_airdrop, CliCommand, CliConfig, PayCommand,
use solana_cli::{
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig, PayCommand},
offline::BlockhashQuery,
};
use solana_client::rpc_client::RpcClient;
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
account_utils::StateMut,
fee_calculator::FeeCalculator,
hash::Hash,
nonce_state::NonceState,
pubkey::Pubkey,
@ -293,7 +295,7 @@ fn test_offline_pay_tx() {
config_offline.command = CliCommand::Pay(PayCommand {
lamports: 10,
to: bob_pubkey,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
sign_only: true,
..PayCommand::default()
});
@ -320,7 +322,7 @@ fn test_offline_pay_tx() {
lamports: 10,
to: bob_pubkey,
signers: Some(signers),
blockhash: Some(blockhash_str.parse::<Hash>().unwrap()),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash_str.parse::<Hash>().unwrap()),
..PayCommand::default()
});
process_command(&config_online).unwrap();
@ -391,7 +393,7 @@ fn test_nonced_pay_tx() {
config.command = CliCommand::Pay(PayCommand {
lamports: 10,
to: bob_pubkey,
blockhash: Some(nonce_hash),
blockhash_query: BlockhashQuery::FeeCalculator(nonce_hash),
nonce_account: Some(nonce_account.pubkey()),
..PayCommand::default()
});

View File

@ -1,9 +1,13 @@
use serde_json::Value;
use solana_cli::cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig};
use solana_cli::{
cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig},
offline::BlockhashQuery,
};
use solana_client::rpc_client::RpcClient;
use solana_faucet::faucet::run_local_faucet;
use solana_sdk::{
account_utils::StateMut,
fee_calculator::FeeCalculator,
hash::Hash,
nonce_state::NonceState,
pubkey::Pubkey,
@ -132,7 +136,7 @@ fn test_seed_stake_delegation_and_deactivation() {
force: true,
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
};
@ -144,7 +148,7 @@ fn test_seed_stake_delegation_and_deactivation() {
stake_authority: None,
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
};
@ -220,7 +224,7 @@ fn test_stake_delegation_and_deactivation() {
force: true,
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
};
@ -232,7 +236,7 @@ fn test_stake_delegation_and_deactivation() {
stake_authority: None,
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
};
@ -313,7 +317,7 @@ fn test_offline_stake_delegation_and_deactivation() {
force: true,
sign_only: true,
signers: None,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
nonce_account: None,
nonce_authority: None,
};
@ -328,7 +332,7 @@ fn test_offline_stake_delegation_and_deactivation() {
force: true,
sign_only: false,
signers: Some(signers),
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
nonce_account: None,
nonce_authority: None,
};
@ -341,7 +345,7 @@ fn test_offline_stake_delegation_and_deactivation() {
stake_authority: None,
sign_only: true,
signers: None,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
nonce_account: None,
nonce_authority: None,
};
@ -354,7 +358,7 @@ fn test_offline_stake_delegation_and_deactivation() {
stake_authority: None,
sign_only: false,
signers: Some(signers),
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: None,
nonce_authority: None,
};
@ -441,7 +445,7 @@ fn test_nonced_stake_delegation_and_deactivation() {
force: true,
sign_only: false,
signers: None,
blockhash: Some(nonce_hash),
blockhash_query: BlockhashQuery::None(nonce_hash, FeeCalculator::default()),
nonce_account: Some(nonce_account.pubkey()),
nonce_authority: None,
};
@ -462,7 +466,7 @@ fn test_nonced_stake_delegation_and_deactivation() {
stake_authority: None,
sign_only: false,
signers: None,
blockhash: Some(nonce_hash),
blockhash_query: BlockhashQuery::FeeCalculator(nonce_hash),
nonce_account: Some(nonce_account.pubkey()),
nonce_authority: Some(config_keypair.into()),
};
@ -516,7 +520,7 @@ fn test_stake_authorize() {
authority: None,
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
};
@ -541,7 +545,7 @@ fn test_stake_authorize() {
authority: Some(read_keypair_file(&online_authority_file).unwrap().into()),
sign_only: false,
signers: None,
blockhash: None,
blockhash_query: BlockhashQuery::default(),
nonce_account: None,
nonce_authority: None,
};
@ -567,7 +571,7 @@ fn test_stake_authorize() {
authority: Some(read_keypair_file(&offline_authority_file).unwrap().into()),
sign_only: true,
signers: None,
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::None(blockhash, FeeCalculator::default()),
nonce_account: None,
nonce_authority: None,
};
@ -580,7 +584,7 @@ fn test_stake_authorize() {
authority: Some(offline_authority_pubkey.into()),
sign_only: false,
signers: Some(signers),
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: None,
nonce_authority: None,
};
@ -628,7 +632,7 @@ fn test_stake_authorize() {
authority: Some(read_keypair_file(&nonced_authority_file).unwrap().into()),
sign_only: true,
signers: None,
blockhash: Some(nonce_hash),
blockhash_query: BlockhashQuery::None(nonce_hash, FeeCalculator::default()),
nonce_account: Some(nonce_account.pubkey()),
nonce_authority: None,
};
@ -642,7 +646,7 @@ fn test_stake_authorize() {
authority: Some(nonced_authority_pubkey.into()),
sign_only: false,
signers: Some(signers),
blockhash: Some(blockhash),
blockhash_query: BlockhashQuery::FeeCalculator(blockhash),
nonce_account: Some(nonce_account.pubkey()),
nonce_authority: None,
};