Skip to content
This repository has been archived by the owner on Jan 22, 2025. It is now read-only.

Commit

Permalink
Check that transaction fee-payer is a debitable account (#6454)
Browse files Browse the repository at this point in the history
automerge
  • Loading branch information
CriesofCarrots authored and solana-grimes committed Oct 19, 2019
1 parent 1a77f7c commit 785c257
Show file tree
Hide file tree
Showing 3 changed files with 67 additions and 8 deletions.
35 changes: 30 additions & 5 deletions cli/src/stake.rs
Original file line number Diff line number Diff line change
Expand Up @@ -371,7 +371,12 @@ pub fn process_create_stake_account(
lamports,
);
let (recent_blockhash, fee_calculator) = rpc_client.get_recent_blockhash()?;
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, recent_blockhash);
let mut tx = Transaction::new_signed_with_payer(
ixs,
Some(&config.keypair.pubkey()),
&[&config.keypair],
recent_blockhash,
);
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
log_instruction_custom_error::<SystemError>(result)
Expand All @@ -396,7 +401,12 @@ pub fn process_stake_authorize(
stake_authorize, // stake or withdraw
)];

let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, recent_blockhash);
let mut tx = Transaction::new_signed_with_payer(
ixs,
Some(&config.keypair.pubkey()),
&[&config.keypair],
recent_blockhash,
);
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
log_instruction_custom_error::<StakeError>(result)
Expand All @@ -412,7 +422,12 @@ pub fn process_deactivate_stake_account(
stake_account_pubkey,
&config.keypair.pubkey(),
)];
let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, recent_blockhash);
let mut tx = Transaction::new_signed_with_payer(
ixs,
Some(&config.keypair.pubkey()),
&[&config.keypair],
recent_blockhash,
);
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
log_instruction_custom_error::<StakeError>(result)
Expand All @@ -434,7 +449,12 @@ pub fn process_withdraw_stake(
lamports,
)];

let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, recent_blockhash);
let mut tx = Transaction::new_signed_with_payer(
ixs,
Some(&config.keypair.pubkey()),
&[&config.keypair],
recent_blockhash,
);
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
log_instruction_custom_error::<StakeError>(result)
Expand Down Expand Up @@ -587,7 +607,12 @@ pub fn process_delegate_stake(
vote_account_pubkey,
)];

let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, recent_blockhash);
let mut tx = Transaction::new_signed_with_payer(
ixs,
Some(&config.keypair.pubkey()),
&[&config.keypair],
recent_blockhash,
);
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
log_instruction_custom_error::<StakeError>(result)
Expand Down
7 changes: 6 additions & 1 deletion cli/src/vote.rs
Original file line number Diff line number Diff line change
Expand Up @@ -271,7 +271,12 @@ pub fn process_vote_authorize(
vote_authorize, // vote or withdraw
)];

let mut tx = Transaction::new_signed_instructions(&[&config.keypair], ixs, recent_blockhash);
let mut tx = Transaction::new_signed_with_payer(
ixs,
Some(&config.keypair.pubkey()),
&[&config.keypair],
recent_blockhash,
);
check_account_for_fee(rpc_client, config, &fee_calculator, &tx.message)?;
let result = rpc_client.send_and_confirm_transaction(&mut tx, &[&config.keypair]);
log_instruction_custom_error::<VoteError>(result)
Expand Down
33 changes: 31 additions & 2 deletions core/src/sigverify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -54,10 +54,11 @@ impl PacketOffsets {
#[derive(Debug, PartialEq)]
pub enum PacketError {
InvalidLen,
InvalidSignatureLen,
InvalidPubkeyLen,
MismatchSignatureLen,
InvalidShortVec,
InvalidSignatureLen,
MismatchSignatureLen,
PayerNotDebitable,
}

impl std::convert::From<std::boxed::Box<bincode::ErrorKind>> for PacketError {
Expand Down Expand Up @@ -146,6 +147,14 @@ fn do_get_packet_offsets(

let message_account_keys_len_offset = msg_start_offset + message_header_size;

// This reads and compares the MessageHeader num_required_signatures and
// num_credit_only_signed_accounts bytes. If num_required_signatures is not larger than
// num_credit_only_signed_accounts, the first account is not debitable, and cannot be charged
// required transaction fees.
if packet.data[msg_start_offset] <= packet.data[msg_start_offset + 1] {
return Err(PacketError::PayerNotDebitable);
}

// read the length of Message.account_keys (serialized with short_vec)
let (pubkey_len, pubkey_len_size) =
decode_len(&packet.data[message_account_keys_len_offset..])?;
Expand Down Expand Up @@ -537,6 +546,26 @@ mod tests {
assert_eq!(res, Err(PacketError::InvalidPubkeyLen));
}

#[test]
fn test_fee_payer_is_debitable() {
let message = Message {
header: MessageHeader {
num_required_signatures: 1,
num_credit_only_signed_accounts: 1,
num_credit_only_unsigned_accounts: 1,
},
account_keys: vec![],
recent_blockhash: Hash::default(),
instructions: vec![],
};
let mut tx = Transaction::new_unsigned(message);
tx.signatures = vec![Signature::default()];
let packet = sigverify::make_packet_from_transaction(tx.clone());
let res = sigverify::do_get_packet_offsets(&packet, 0);

assert_eq!(res, Err(PacketError::PayerNotDebitable));
}

#[test]
fn test_system_transaction_data_layout() {
use crate::packet::PACKET_DATA_SIZE;
Expand Down

0 comments on commit 785c257

Please sign in to comment.