@ -512,20 +512,20 @@ pub type ProcessResult = Result<String, Box<dyn std::error::Error>>;
|
|||||||
|
|
||||||
pub fn check_account_for_fee(
|
pub fn check_account_for_fee(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
config: &CliConfig,
|
account_pubkey: &Pubkey,
|
||||||
fee_calculator: &FeeCalculator,
|
fee_calculator: &FeeCalculator,
|
||||||
message: &Message,
|
message: &Message,
|
||||||
) -> Result<(), Box<dyn error::Error>> {
|
) -> Result<(), Box<dyn error::Error>> {
|
||||||
check_account_for_multiple_fees(rpc_client, config, fee_calculator, &[message])
|
check_account_for_multiple_fees(rpc_client, account_pubkey, fee_calculator, &[message])
|
||||||
}
|
}
|
||||||
|
|
||||||
fn check_account_for_multiple_fees(
|
fn check_account_for_multiple_fees(
|
||||||
rpc_client: &RpcClient,
|
rpc_client: &RpcClient,
|
||||||
config: &CliConfig,
|
account_pubkey: &Pubkey,
|
||||||
fee_calculator: &FeeCalculator,
|
fee_calculator: &FeeCalculator,
|
||||||
messages: &[&Message],
|
messages: &[&Message],
|
||||||
) -> Result<(), Box<dyn error::Error>> {
|
) -> Result<(), Box<dyn error::Error>> {
|
||||||
let balance = rpc_client.retry_get_balance(&config.keypair.pubkey(), 5)?;
|
let balance = rpc_client.retry_get_balance(account_pubkey, 5)?;
|
||||||
if let Some(lamports) = balance {
|
if let Some(lamports) = balance {
|
||||||
if lamports
|
if lamports
|
||||||
>= messages
|
>= messages
|
||||||
@ -744,7 +744,12 @@ fn process_deploy(
|
|||||||
let mut finalize_tx = Transaction::new(&signers, message, blockhash);
|
let mut finalize_tx = Transaction::new(&signers, message, blockhash);
|
||||||
messages.push(&finalize_tx.message);
|
messages.push(&finalize_tx.message);
|
||||||
|
|
||||||
check_account_for_multiple_fees(rpc_client, config, &fee_calculator, &messages)?;
|
check_account_for_multiple_fees(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&messages,
|
||||||
|
)?;
|
||||||
|
|
||||||
trace!("Creating program account");
|
trace!("Creating program account");
|
||||||
let result = rpc_client.send_and_confirm_transaction(&mut create_account_tx, &signers);
|
let result = rpc_client.send_and_confirm_transaction(&mut create_account_tx, &signers);
|
||||||
@ -804,7 +809,12 @@ fn process_pay(
|
|||||||
if sign_only {
|
if sign_only {
|
||||||
return_signers(&tx)
|
return_signers(&tx)
|
||||||
} else {
|
} else {
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||||
log_instruction_custom_error::<SystemError>(result)
|
log_instruction_custom_error::<SystemError>(result)
|
||||||
}
|
}
|
||||||
@ -838,7 +848,12 @@ fn process_pay(
|
|||||||
if sign_only {
|
if sign_only {
|
||||||
return_signers(&tx)
|
return_signers(&tx)
|
||||||
} else {
|
} else {
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result = rpc_client
|
let result = rpc_client
|
||||||
.send_and_confirm_transaction(&mut tx, &[&config.keypair, &contract_state]);
|
.send_and_confirm_transaction(&mut tx, &[&config.keypair, &contract_state]);
|
||||||
let signature_str = log_instruction_custom_error::<BudgetError>(result)?;
|
let signature_str = log_instruction_custom_error::<BudgetError>(result)?;
|
||||||
@ -883,7 +898,12 @@ fn process_pay(
|
|||||||
} else {
|
} else {
|
||||||
let result = rpc_client
|
let result = rpc_client
|
||||||
.send_and_confirm_transaction(&mut tx, &[&config.keypair, &contract_state]);
|
.send_and_confirm_transaction(&mut tx, &[&config.keypair, &contract_state]);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let signature_str = log_instruction_custom_error::<BudgetError>(result)?;
|
let signature_str = log_instruction_custom_error::<BudgetError>(result)?;
|
||||||
|
|
||||||
Ok(json!({
|
Ok(json!({
|
||||||
@ -905,7 +925,12 @@ fn process_cancel(rpc_client: &RpcClient, config: &CliConfig, pubkey: &Pubkey) -
|
|||||||
&config.keypair.pubkey(),
|
&config.keypair.pubkey(),
|
||||||
);
|
);
|
||||||
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], vec![ix], blockhash);
|
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], vec![ix], blockhash);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||||
log_instruction_custom_error::<BudgetError>(result)
|
log_instruction_custom_error::<BudgetError>(result)
|
||||||
}
|
}
|
||||||
@ -921,7 +946,12 @@ fn process_time_elapsed(
|
|||||||
|
|
||||||
let ix = budget_instruction::apply_timestamp(&config.keypair.pubkey(), pubkey, to, dt);
|
let ix = budget_instruction::apply_timestamp(&config.keypair.pubkey(), pubkey, to, dt);
|
||||||
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], vec![ix], blockhash);
|
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], vec![ix], blockhash);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||||
log_instruction_custom_error::<BudgetError>(result)
|
log_instruction_custom_error::<BudgetError>(result)
|
||||||
}
|
}
|
||||||
@ -936,7 +966,12 @@ fn process_witness(
|
|||||||
|
|
||||||
let ix = budget_instruction::apply_signature(&config.keypair.pubkey(), pubkey, to);
|
let ix = budget_instruction::apply_signature(&config.keypair.pubkey(), pubkey, to);
|
||||||
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], vec![ix], blockhash);
|
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], vec![ix], blockhash);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||||
log_instruction_custom_error::<BudgetError>(result)
|
log_instruction_custom_error::<BudgetError>(result)
|
||||||
}
|
}
|
||||||
|
@ -419,7 +419,12 @@ pub fn process_ping(
|
|||||||
|
|
||||||
let transaction =
|
let transaction =
|
||||||
system_transaction::transfer(&config.keypair, &to, lamports, recent_blockhash);
|
system_transaction::transfer(&config.keypair, &to, lamports, recent_blockhash);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &transaction.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&transaction.message,
|
||||||
|
)?;
|
||||||
|
|
||||||
match rpc_client.send_transaction(&transaction) {
|
match rpc_client.send_transaction(&transaction) {
|
||||||
Ok(signature) => {
|
Ok(signature) => {
|
||||||
|
@ -344,6 +344,7 @@ pub fn parse_stake_delegate_stake(matches: &ArgMatches<'_>) -> Result<CliCommand
|
|||||||
let sign_only = matches.is_present("sign_only");
|
let sign_only = matches.is_present("sign_only");
|
||||||
let signers = pubkeys_sigs_of(&matches, "signer");
|
let signers = pubkeys_sigs_of(&matches, "signer");
|
||||||
let blockhash = value_of(matches, "blockhash");
|
let blockhash = value_of(matches, "blockhash");
|
||||||
|
let require_keypair = signers.is_none();
|
||||||
|
|
||||||
Ok(CliCommandInfo {
|
Ok(CliCommandInfo {
|
||||||
command: CliCommand::DelegateStake {
|
command: CliCommand::DelegateStake {
|
||||||
@ -354,7 +355,7 @@ pub fn parse_stake_delegate_stake(matches: &ArgMatches<'_>) -> Result<CliCommand
|
|||||||
signers,
|
signers,
|
||||||
blockhash,
|
blockhash,
|
||||||
},
|
},
|
||||||
require_keypair: !sign_only,
|
require_keypair,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -378,6 +379,7 @@ pub fn parse_stake_authorize(
|
|||||||
pub fn parse_redeem_vote_credits(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
pub fn parse_redeem_vote_credits(matches: &ArgMatches<'_>) -> Result<CliCommandInfo, CliError> {
|
||||||
let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap();
|
let stake_account_pubkey = pubkey_of(matches, "stake_account_pubkey").unwrap();
|
||||||
let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap();
|
let vote_account_pubkey = pubkey_of(matches, "vote_account_pubkey").unwrap();
|
||||||
|
|
||||||
Ok(CliCommandInfo {
|
Ok(CliCommandInfo {
|
||||||
command: CliCommand::RedeemVoteCredits(stake_account_pubkey, vote_account_pubkey),
|
command: CliCommand::RedeemVoteCredits(stake_account_pubkey, vote_account_pubkey),
|
||||||
require_keypair: true,
|
require_keypair: true,
|
||||||
@ -389,6 +391,8 @@ pub fn parse_stake_deactivate_stake(matches: &ArgMatches<'_>) -> Result<CliComma
|
|||||||
let sign_only = matches.is_present("sign_only");
|
let sign_only = matches.is_present("sign_only");
|
||||||
let signers = pubkeys_sigs_of(&matches, "signer");
|
let signers = pubkeys_sigs_of(&matches, "signer");
|
||||||
let blockhash = value_of(matches, "blockhash");
|
let blockhash = value_of(matches, "blockhash");
|
||||||
|
let require_keypair = signers.is_none();
|
||||||
|
|
||||||
Ok(CliCommandInfo {
|
Ok(CliCommandInfo {
|
||||||
command: CliCommand::DeactivateStake {
|
command: CliCommand::DeactivateStake {
|
||||||
stake_account_pubkey,
|
stake_account_pubkey,
|
||||||
@ -396,7 +400,7 @@ pub fn parse_stake_deactivate_stake(matches: &ArgMatches<'_>) -> Result<CliComma
|
|||||||
signers,
|
signers,
|
||||||
blockhash,
|
blockhash,
|
||||||
},
|
},
|
||||||
require_keypair: !sign_only,
|
require_keypair,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -489,7 +493,12 @@ pub fn process_create_stake_account(
|
|||||||
&[&config.keypair, stake_account],
|
&[&config.keypair, stake_account],
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
);
|
);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result =
|
let result =
|
||||||
rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair, stake_account]);
|
rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair, stake_account]);
|
||||||
log_instruction_custom_error::<SystemError>(result)
|
log_instruction_custom_error::<SystemError>(result)
|
||||||
@ -520,7 +529,12 @@ pub fn process_stake_authorize(
|
|||||||
&[&config.keypair],
|
&[&config.keypair],
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
);
|
);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||||
log_instruction_custom_error::<StakeError>(result)
|
log_instruction_custom_error::<StakeError>(result)
|
||||||
}
|
}
|
||||||
@ -551,7 +565,12 @@ pub fn process_deactivate_stake_account(
|
|||||||
if sign_only {
|
if sign_only {
|
||||||
return_signers(&tx)
|
return_signers(&tx)
|
||||||
} else {
|
} else {
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&tx.message.account_keys[0],
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||||
log_instruction_custom_error::<StakeError>(result)
|
log_instruction_custom_error::<StakeError>(result)
|
||||||
}
|
}
|
||||||
@ -579,7 +598,12 @@ pub fn process_withdraw_stake(
|
|||||||
&[&config.keypair],
|
&[&config.keypair],
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
);
|
);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||||
log_instruction_custom_error::<StakeError>(result)
|
log_instruction_custom_error::<StakeError>(result)
|
||||||
}
|
}
|
||||||
@ -601,7 +625,12 @@ pub fn process_redeem_vote_credits(
|
|||||||
&[&config.keypair],
|
&[&config.keypair],
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
);
|
);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||||
log_instruction_custom_error::<StakeError>(result)
|
log_instruction_custom_error::<StakeError>(result)
|
||||||
}
|
}
|
||||||
@ -791,7 +820,12 @@ pub fn process_delegate_stake(
|
|||||||
if sign_only {
|
if sign_only {
|
||||||
return_signers(&tx)
|
return_signers(&tx)
|
||||||
} else {
|
} else {
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&tx.message.account_keys[0],
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||||
log_instruction_custom_error::<StakeError>(result)
|
log_instruction_custom_error::<StakeError>(result)
|
||||||
}
|
}
|
||||||
@ -1008,7 +1042,7 @@ mod tests {
|
|||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None
|
blockhash: None
|
||||||
},
|
},
|
||||||
require_keypair: false
|
require_keypair: true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1035,7 +1069,7 @@ mod tests {
|
|||||||
signers: Some(vec![(key1, sig1)]),
|
signers: Some(vec![(key1, sig1)]),
|
||||||
blockhash: None
|
blockhash: None
|
||||||
},
|
},
|
||||||
require_keypair: true
|
require_keypair: false
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1064,7 +1098,7 @@ mod tests {
|
|||||||
signers: Some(vec![(key1, sig1), (key2, sig2)]),
|
signers: Some(vec![(key1, sig1), (key2, sig2)]),
|
||||||
blockhash: None
|
blockhash: None
|
||||||
},
|
},
|
||||||
require_keypair: true
|
require_keypair: false
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1143,7 +1177,7 @@ mod tests {
|
|||||||
signers: None,
|
signers: None,
|
||||||
blockhash: None
|
blockhash: None
|
||||||
},
|
},
|
||||||
require_keypair: false
|
require_keypair: true
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1167,7 +1201,7 @@ mod tests {
|
|||||||
signers: Some(vec![(key1, sig1)]),
|
signers: Some(vec![(key1, sig1)]),
|
||||||
blockhash: None
|
blockhash: None
|
||||||
},
|
},
|
||||||
require_keypair: true
|
require_keypair: false
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
@ -1193,7 +1227,7 @@ mod tests {
|
|||||||
signers: Some(vec![(key1, sig1), (key2, sig2)]),
|
signers: Some(vec![(key1, sig1), (key2, sig2)]),
|
||||||
blockhash: None
|
blockhash: None
|
||||||
},
|
},
|
||||||
require_keypair: true
|
require_keypair: false
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -176,7 +176,12 @@ pub fn process_create_storage_account(
|
|||||||
ixs,
|
ixs,
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
);
|
);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result =
|
let result =
|
||||||
rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair, &storage_account]);
|
rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair, &storage_account]);
|
||||||
log_instruction_custom_error::<SystemError>(result)
|
log_instruction_custom_error::<SystemError>(result)
|
||||||
@ -196,7 +201,12 @@ pub fn process_claim_storage_reward(
|
|||||||
let message = Message::new_with_payer(vec![instruction], Some(&signers[0].pubkey()));
|
let message = Message::new_with_payer(vec![instruction], Some(&signers[0].pubkey()));
|
||||||
|
|
||||||
let mut tx = Transaction::new(&signers, message, recent_blockhash);
|
let mut tx = Transaction::new(&signers, message, recent_blockhash);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &signers)?;
|
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &signers)?;
|
||||||
Ok(signature_str.to_string())
|
Ok(signature_str.to_string())
|
||||||
}
|
}
|
||||||
|
@ -347,7 +347,12 @@ pub fn process_set_validator_info(
|
|||||||
// Submit transaction
|
// Submit transaction
|
||||||
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
|
||||||
let mut tx = Transaction::new(&signers, message, recent_blockhash);
|
let mut tx = Transaction::new(&signers, message, recent_blockhash);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &signers)?;
|
let signature_str = rpc_client.send_and_confirm_transaction(&mut tx, &signers)?;
|
||||||
|
|
||||||
println!("Success! Validator info published at: {:?}", info_pubkey);
|
println!("Success! Validator info published at: {:?}", info_pubkey);
|
||||||
|
@ -268,7 +268,12 @@ pub fn process_create_vote_account(
|
|||||||
ixs,
|
ixs,
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
);
|
);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair, vote_account]);
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair, vote_account]);
|
||||||
log_instruction_custom_error::<SystemError>(result)
|
log_instruction_custom_error::<SystemError>(result)
|
||||||
}
|
}
|
||||||
@ -298,7 +303,12 @@ pub fn process_vote_authorize(
|
|||||||
&[&config.keypair],
|
&[&config.keypair],
|
||||||
recent_blockhash,
|
recent_blockhash,
|
||||||
);
|
);
|
||||||
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
|
check_account_for_fee(
|
||||||
|
rpc_client,
|
||||||
|
&config.keypair.pubkey(),
|
||||||
|
&fee_calculator,
|
||||||
|
&tx.message,
|
||||||
|
)?;
|
||||||
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
|
||||||
log_instruction_custom_error::<VoteError>(result)
|
log_instruction_custom_error::<VoteError>(result)
|
||||||
}
|
}
|
||||||
|
252
cli/tests/stake.rs
Normal file
252
cli/tests/stake.rs
Normal file
@ -0,0 +1,252 @@
|
|||||||
|
use serde_json::Value;
|
||||||
|
use solana_cli::cli::{process_command, request_and_confirm_airdrop, CliCommand, CliConfig};
|
||||||
|
use solana_client::rpc_client::RpcClient;
|
||||||
|
use solana_drone::drone::run_local_drone;
|
||||||
|
use solana_sdk::{
|
||||||
|
hash::Hash,
|
||||||
|
pubkey::Pubkey,
|
||||||
|
signature::{read_keypair_file, write_keypair, KeypairUtil, Signature},
|
||||||
|
};
|
||||||
|
use solana_stake_program::stake_state::Lockup;
|
||||||
|
use std::fs::remove_dir_all;
|
||||||
|
use std::str::FromStr;
|
||||||
|
use std::sync::mpsc::channel;
|
||||||
|
|
||||||
|
#[cfg(test)]
|
||||||
|
use solana_core::validator::new_validator_for_tests;
|
||||||
|
use std::thread::sleep;
|
||||||
|
use std::time::Duration;
|
||||||
|
|
||||||
|
use tempfile::NamedTempFile;
|
||||||
|
|
||||||
|
fn make_tmp_file() -> (String, NamedTempFile) {
|
||||||
|
let tmp_file = NamedTempFile::new().unwrap();
|
||||||
|
(String::from(tmp_file.path().to_str().unwrap()), tmp_file)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn check_balance(expected_balance: u64, client: &RpcClient, pubkey: &Pubkey) {
|
||||||
|
(0..5).for_each(|tries| {
|
||||||
|
let balance = client.retry_get_balance(pubkey, 1).unwrap().unwrap();
|
||||||
|
if balance == expected_balance {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if tries == 4 {
|
||||||
|
assert_eq!(balance, expected_balance);
|
||||||
|
}
|
||||||
|
sleep(Duration::from_millis(500));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stake_delegation_and_deactivation() {
|
||||||
|
solana_logger::setup();
|
||||||
|
|
||||||
|
let (server, leader_data, alice, ledger_path) = new_validator_for_tests();
|
||||||
|
let (sender, receiver) = channel();
|
||||||
|
run_local_drone(alice, sender, None);
|
||||||
|
let drone_addr = receiver.recv().unwrap();
|
||||||
|
|
||||||
|
let rpc_client = RpcClient::new_socket(leader_data.rpc);
|
||||||
|
|
||||||
|
let mut config_validator = CliConfig::default();
|
||||||
|
config_validator.json_rpc_url =
|
||||||
|
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
|
||||||
|
|
||||||
|
let mut config_vote = CliConfig::default();
|
||||||
|
config_vote.json_rpc_url =
|
||||||
|
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
|
||||||
|
let (vote_keypair_file, mut tmp_file) = make_tmp_file();
|
||||||
|
write_keypair(&config_vote.keypair, tmp_file.as_file_mut()).unwrap();
|
||||||
|
|
||||||
|
let mut config_stake = CliConfig::default();
|
||||||
|
config_stake.json_rpc_url =
|
||||||
|
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
|
||||||
|
let (stake_keypair_file, mut tmp_file) = make_tmp_file();
|
||||||
|
write_keypair(&config_stake.keypair, tmp_file.as_file_mut()).unwrap();
|
||||||
|
|
||||||
|
request_and_confirm_airdrop(
|
||||||
|
&rpc_client,
|
||||||
|
&drone_addr,
|
||||||
|
&config_validator.keypair.pubkey(),
|
||||||
|
100_000,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
check_balance(100_000, &rpc_client, &config_validator.keypair.pubkey());
|
||||||
|
|
||||||
|
// Create vote account
|
||||||
|
config_validator.command = CliCommand::CreateVoteAccount {
|
||||||
|
vote_account: read_keypair_file(&vote_keypair_file).unwrap().into(),
|
||||||
|
node_pubkey: config_validator.keypair.pubkey(),
|
||||||
|
authorized_voter: None,
|
||||||
|
authorized_withdrawer: None,
|
||||||
|
commission: 0,
|
||||||
|
};
|
||||||
|
process_command(&config_validator).unwrap();
|
||||||
|
|
||||||
|
// Create stake account
|
||||||
|
config_validator.command = CliCommand::CreateStakeAccount {
|
||||||
|
stake_account: read_keypair_file(&stake_keypair_file).unwrap().into(),
|
||||||
|
staker: None,
|
||||||
|
withdrawer: None,
|
||||||
|
lockup: Lockup {
|
||||||
|
custodian: Pubkey::default(),
|
||||||
|
epoch: 0,
|
||||||
|
},
|
||||||
|
lamports: 50_000,
|
||||||
|
};
|
||||||
|
process_command(&config_validator).unwrap();
|
||||||
|
|
||||||
|
// Delegate stake
|
||||||
|
config_validator.command = CliCommand::DelegateStake {
|
||||||
|
stake_account_pubkey: config_stake.keypair.pubkey(),
|
||||||
|
vote_account_pubkey: config_vote.keypair.pubkey(),
|
||||||
|
force: true,
|
||||||
|
sign_only: false,
|
||||||
|
signers: None,
|
||||||
|
blockhash: None,
|
||||||
|
};
|
||||||
|
process_command(&config_validator).unwrap();
|
||||||
|
|
||||||
|
// Deactivate stake
|
||||||
|
config_validator.command = CliCommand::DeactivateStake {
|
||||||
|
stake_account_pubkey: config_stake.keypair.pubkey(),
|
||||||
|
sign_only: false,
|
||||||
|
signers: None,
|
||||||
|
blockhash: None,
|
||||||
|
};
|
||||||
|
process_command(&config_validator).unwrap();
|
||||||
|
|
||||||
|
server.close().unwrap();
|
||||||
|
remove_dir_all(ledger_path).unwrap();
|
||||||
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_stake_delegation_and_deactivation_offline() {
|
||||||
|
solana_logger::setup();
|
||||||
|
|
||||||
|
let (server, leader_data, alice, ledger_path) = new_validator_for_tests();
|
||||||
|
let (sender, receiver) = channel();
|
||||||
|
run_local_drone(alice, sender, None);
|
||||||
|
let drone_addr = receiver.recv().unwrap();
|
||||||
|
|
||||||
|
let rpc_client = RpcClient::new_socket(leader_data.rpc);
|
||||||
|
|
||||||
|
let mut config_validator = CliConfig::default();
|
||||||
|
config_validator.json_rpc_url =
|
||||||
|
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
|
||||||
|
|
||||||
|
let mut config_payer = CliConfig::default();
|
||||||
|
config_payer.json_rpc_url =
|
||||||
|
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
|
||||||
|
|
||||||
|
let mut config_vote = CliConfig::default();
|
||||||
|
config_vote.json_rpc_url =
|
||||||
|
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
|
||||||
|
let (vote_keypair_file, mut tmp_file) = make_tmp_file();
|
||||||
|
write_keypair(&config_vote.keypair, tmp_file.as_file_mut()).unwrap();
|
||||||
|
|
||||||
|
let mut config_stake = CliConfig::default();
|
||||||
|
config_stake.json_rpc_url =
|
||||||
|
format!("http://{}:{}", leader_data.rpc.ip(), leader_data.rpc.port());
|
||||||
|
let (stake_keypair_file, mut tmp_file) = make_tmp_file();
|
||||||
|
write_keypair(&config_stake.keypair, tmp_file.as_file_mut()).unwrap();
|
||||||
|
|
||||||
|
request_and_confirm_airdrop(
|
||||||
|
&rpc_client,
|
||||||
|
&drone_addr,
|
||||||
|
&config_validator.keypair.pubkey(),
|
||||||
|
100_000,
|
||||||
|
)
|
||||||
|
.unwrap();
|
||||||
|
check_balance(100_000, &rpc_client, &config_validator.keypair.pubkey());
|
||||||
|
|
||||||
|
// Create vote account
|
||||||
|
config_validator.command = CliCommand::CreateVoteAccount {
|
||||||
|
vote_account: read_keypair_file(&vote_keypair_file).unwrap().into(),
|
||||||
|
node_pubkey: config_validator.keypair.pubkey(),
|
||||||
|
authorized_voter: None,
|
||||||
|
authorized_withdrawer: None,
|
||||||
|
commission: 0,
|
||||||
|
};
|
||||||
|
process_command(&config_validator).unwrap();
|
||||||
|
|
||||||
|
// Create stake account
|
||||||
|
config_validator.command = CliCommand::CreateStakeAccount {
|
||||||
|
stake_account: read_keypair_file(&stake_keypair_file).unwrap().into(),
|
||||||
|
staker: None,
|
||||||
|
withdrawer: None,
|
||||||
|
lockup: Lockup {
|
||||||
|
custodian: Pubkey::default(),
|
||||||
|
epoch: 0,
|
||||||
|
},
|
||||||
|
lamports: 50_000,
|
||||||
|
};
|
||||||
|
process_command(&config_validator).unwrap();
|
||||||
|
|
||||||
|
// Delegate stake offline
|
||||||
|
config_validator.command = CliCommand::DelegateStake {
|
||||||
|
stake_account_pubkey: config_stake.keypair.pubkey(),
|
||||||
|
vote_account_pubkey: config_vote.keypair.pubkey(),
|
||||||
|
force: true,
|
||||||
|
sign_only: true,
|
||||||
|
signers: None,
|
||||||
|
blockhash: None,
|
||||||
|
};
|
||||||
|
let sig_response = process_command(&config_validator).unwrap();
|
||||||
|
let object: Value = serde_json::from_str(&sig_response).unwrap();
|
||||||
|
let blockhash_str = object.get("blockhash").unwrap().as_str().unwrap();
|
||||||
|
let signer_strings = object.get("signers").unwrap().as_array().unwrap();
|
||||||
|
let signers: Vec<_> = signer_strings
|
||||||
|
.iter()
|
||||||
|
.map(|signer_string| {
|
||||||
|
let mut signer = signer_string.as_str().unwrap().split('=');
|
||||||
|
let key = Pubkey::from_str(signer.next().unwrap()).unwrap();
|
||||||
|
let sig = Signature::from_str(signer.next().unwrap()).unwrap();
|
||||||
|
(key, sig)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Delegate stake online
|
||||||
|
config_payer.command = CliCommand::DelegateStake {
|
||||||
|
stake_account_pubkey: config_stake.keypair.pubkey(),
|
||||||
|
vote_account_pubkey: config_vote.keypair.pubkey(),
|
||||||
|
force: true,
|
||||||
|
sign_only: false,
|
||||||
|
signers: Some(signers),
|
||||||
|
blockhash: Some(blockhash_str.parse::<Hash>().unwrap()),
|
||||||
|
};
|
||||||
|
process_command(&config_payer).unwrap();
|
||||||
|
|
||||||
|
// Deactivate stake offline
|
||||||
|
config_validator.command = CliCommand::DeactivateStake {
|
||||||
|
stake_account_pubkey: config_stake.keypair.pubkey(),
|
||||||
|
sign_only: true,
|
||||||
|
signers: None,
|
||||||
|
blockhash: None,
|
||||||
|
};
|
||||||
|
let sig_response = process_command(&config_validator).unwrap();
|
||||||
|
let object: Value = serde_json::from_str(&sig_response).unwrap();
|
||||||
|
let blockhash_str = object.get("blockhash").unwrap().as_str().unwrap();
|
||||||
|
let signer_strings = object.get("signers").unwrap().as_array().unwrap();
|
||||||
|
let signers: Vec<_> = signer_strings
|
||||||
|
.iter()
|
||||||
|
.map(|signer_string| {
|
||||||
|
let mut signer = signer_string.as_str().unwrap().split('=');
|
||||||
|
let key = Pubkey::from_str(signer.next().unwrap()).unwrap();
|
||||||
|
let sig = Signature::from_str(signer.next().unwrap()).unwrap();
|
||||||
|
(key, sig)
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// Deactivate stake online
|
||||||
|
config_payer.command = CliCommand::DeactivateStake {
|
||||||
|
stake_account_pubkey: config_stake.keypair.pubkey(),
|
||||||
|
sign_only: false,
|
||||||
|
signers: Some(signers),
|
||||||
|
blockhash: Some(blockhash_str.parse::<Hash>().unwrap()),
|
||||||
|
};
|
||||||
|
process_command(&config_payer).unwrap();
|
||||||
|
|
||||||
|
server.close().unwrap();
|
||||||
|
remove_dir_all(ledger_path).unwrap();
|
||||||
|
}
|
Reference in New Issue
Block a user