Skip to content

Commit

Permalink
Sanitize preflight (bp #11373) (#11376)
Browse files Browse the repository at this point in the history
* Add failing test for unsane tx in RPC preflight

(cherry picked from commit e25846e)

* Add From for SanitizeError > TransactionError

(cherry picked from commit 3f73aff)

* Sanitize transactions during RPC preflight test

(cherry picked from commit 29b3265)

* Harden RPC preflight test inputs

(cherry picked from commit 14339de)

Co-authored-by: Trent Nelson <trent@solana.com>
  • Loading branch information
mergify[bot] and t-nelson authored Aug 5, 2020
1 parent 80525ac commit 7b8e5a9
Show file tree
Hide file tree
Showing 4 changed files with 31 additions and 7 deletions.
22 changes: 18 additions & 4 deletions core/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3475,7 +3475,7 @@ pub mod tests {
let block_commitment_cache = Arc::new(RwLock::new(
BlockCommitmentCache::default_with_blockstore(blockstore.clone()),
));
let bank_forks = new_bank_forks().0;
let (bank_forks, mint_keypair, ..) = new_bank_forks();
let health = RpcHealth::stub();

// Freeze bank 0 to prevent a panic in `run_transaction_simulation()`
Expand Down Expand Up @@ -3503,8 +3503,8 @@ pub mod tests {
)),
);

let bad_transaction =
system_transaction::transfer(&Keypair::new(), &Pubkey::default(), 42, Hash::default());
let mut bad_transaction =
system_transaction::transfer(&mint_keypair, &Pubkey::new_rand(), 42, Hash::default());

// sendTransaction will fail because the blockhash is invalid
let req = format!(
Expand All @@ -3519,9 +3519,23 @@ pub mod tests {
)
);

// sendTransaction will fail due to insanity
bad_transaction.message.instructions[0].program_id_index = 255u8;
let recent_blockhash = bank_forks.read().unwrap().root_bank().last_blockhash();
bad_transaction.sign(&[&mint_keypair], recent_blockhash);
let req = format!(
r#"{{"jsonrpc":"2.0","id":1,"method":"sendTransaction","params":["{}"]}}"#,
bs58::encode(serialize(&bad_transaction).unwrap()).into_string()
);
let res = io.handle_request_sync(&req, meta.clone());
assert_eq!(
res,
Some(
r#"{"jsonrpc":"2.0","error":{"code":-32002,"message":"Transaction simulation failed: TransactionError::SanitizeFailure"},"id":1}"#.to_string(),
)
);
let mut bad_transaction =
system_transaction::transfer(&Keypair::new(), &Pubkey::default(), 42, recent_blockhash);
system_transaction::transfer(&mint_keypair, &Pubkey::new_rand(), 42, recent_blockhash);

// sendTransaction will fail due to poor node health
health.stub_set_health_status(Some(RpcHealthStatus::Behind));
Expand Down
3 changes: 1 addition & 2 deletions runtime/src/accounts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -629,8 +629,7 @@ impl Accounts {
use solana_sdk::sanitize::Sanitize;
let keys: Vec<Result<_>> = OrderedIterator::new(txs, txs_iteration_order)
.map(|tx| {
tx.sanitize()
.map_err(|_| TransactionError::SanitizeFailure)?;
tx.sanitize().map_err(TransactionError::from)?;

if Self::has_duplicates(&tx.message.account_keys) {
return Err(TransactionError::AccountLoadedTwice);
Expand Down
7 changes: 6 additions & 1 deletion runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,7 @@ use solana_sdk::{
native_loader, nonce,
program_utils::limited_deserialize,
pubkey::Pubkey,
sanitize::Sanitize,
signature::{Keypair, Signature},
slot_hashes::SlotHashes,
slot_history::SlotHistory,
Expand Down Expand Up @@ -1135,7 +1136,11 @@ impl Bank {
&'a self,
txs: &'b [Transaction],
) -> TransactionBatch<'a, 'b> {
let mut batch = TransactionBatch::new(vec![Ok(()); txs.len()], &self, txs, None);
let lock_results: Vec<_> = txs
.iter()
.map(|tx| tx.sanitize().map_err(|e| e.into()))
.collect();
let mut batch = TransactionBatch::new(lock_results, &self, txs, None);
batch.needs_unlock = false;
batch
}
Expand Down
6 changes: 6 additions & 0 deletions sdk/src/transaction.rs
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,12 @@ impl std::fmt::Display for TransactionError {
}
}

impl From<SanitizeError> for TransactionError {
fn from(_: SanitizeError) -> Self {
Self::SanitizeFailure
}
}

/// An atomic transaction
#[derive(Debug, PartialEq, Default, Eq, Clone, Serialize, Deserialize)]
pub struct Transaction {
Expand Down

0 comments on commit 7b8e5a9

Please sign in to comment.