verifies that serialized size of transactions does not exceed packet data size (#13945)
This commit is contained in:
@ -18,6 +18,7 @@ use solana_perf::perf_libs;
|
|||||||
use solana_perf::recycler::Recycler;
|
use solana_perf::recycler::Recycler;
|
||||||
use solana_rayon_threadlimit::get_thread_count;
|
use solana_rayon_threadlimit::get_thread_count;
|
||||||
use solana_sdk::hash::Hash;
|
use solana_sdk::hash::Hash;
|
||||||
|
use solana_sdk::packet::PACKET_DATA_SIZE;
|
||||||
use solana_sdk::timing;
|
use solana_sdk::timing;
|
||||||
use solana_sdk::transaction::Transaction;
|
use solana_sdk::transaction::Transaction;
|
||||||
use std::cell::RefCell;
|
use std::cell::RefCell;
|
||||||
@ -490,20 +491,24 @@ impl EntrySlice for [Entry] {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn verify_transaction_signatures(&self, secp256k1_program_enabled: bool) -> bool {
|
fn verify_transaction_signatures(&self, secp256k1_program_enabled: bool) -> bool {
|
||||||
|
let verify = |tx: &Transaction| {
|
||||||
|
tx.verify().is_ok()
|
||||||
|
&& {
|
||||||
|
match bincode::serialized_size(tx) {
|
||||||
|
Ok(size) => size <= PACKET_DATA_SIZE as u64,
|
||||||
|
Err(_) => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
&& (
|
||||||
|
// Verify tx precompiles if secp256k1 program is enabled.
|
||||||
|
!secp256k1_program_enabled || tx.verify_precompiles().is_ok()
|
||||||
|
)
|
||||||
|
};
|
||||||
PAR_THREAD_POOL.with(|thread_pool| {
|
PAR_THREAD_POOL.with(|thread_pool| {
|
||||||
thread_pool.borrow().install(|| {
|
thread_pool.borrow().install(|| {
|
||||||
self.par_iter().all(|e| {
|
self.par_iter()
|
||||||
e.transactions.par_iter().all(|transaction| {
|
.flat_map(|entry| &entry.transactions)
|
||||||
let sig_verify = transaction.verify().is_ok();
|
.all(verify)
|
||||||
if sig_verify
|
|
||||||
&& secp256k1_program_enabled
|
|
||||||
&& transaction.verify_precompiles().is_err()
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
sig_verify
|
|
||||||
})
|
|
||||||
})
|
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -690,7 +695,7 @@ mod tests {
|
|||||||
use chrono::prelude::Utc;
|
use chrono::prelude::Utc;
|
||||||
use solana_budget_program::budget_instruction;
|
use solana_budget_program::budget_instruction;
|
||||||
use solana_sdk::{
|
use solana_sdk::{
|
||||||
hash::{hash, Hash},
|
hash::{hash, new_rand as hash_new_rand, Hash},
|
||||||
message::Message,
|
message::Message,
|
||||||
signature::{Keypair, Signer},
|
signature::{Keypair, Signer},
|
||||||
system_transaction,
|
system_transaction,
|
||||||
@ -896,6 +901,50 @@ mod tests {
|
|||||||
assert_eq!(bad_ticks.verify(&one), false); // inductive step, bad
|
assert_eq!(bad_ticks.verify(&one), false); // inductive step, bad
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[test]
|
||||||
|
fn test_verify_transaction_signatures_packet_data_size() {
|
||||||
|
let mut rng = rand::thread_rng();
|
||||||
|
let recent_blockhash = hash_new_rand(&mut rng);
|
||||||
|
let keypair = Keypair::new();
|
||||||
|
let pubkey = keypair.pubkey();
|
||||||
|
let budget_contract = Keypair::new();
|
||||||
|
let budget_pubkey = budget_contract.pubkey();
|
||||||
|
let make_transaction = |size| {
|
||||||
|
let ixs: Vec<_> = std::iter::repeat_with(|| {
|
||||||
|
budget_instruction::payment(&pubkey, &pubkey, &budget_pubkey, 1)
|
||||||
|
})
|
||||||
|
.take(size)
|
||||||
|
.flat_map(|x| x.into_iter())
|
||||||
|
.collect();
|
||||||
|
let message = Message::new(&ixs[..], Some(&pubkey));
|
||||||
|
Transaction::new(&[&keypair, &budget_contract], message, recent_blockhash)
|
||||||
|
};
|
||||||
|
// Small transaction.
|
||||||
|
{
|
||||||
|
let tx = make_transaction(5);
|
||||||
|
let entries = vec![next_entry(&recent_blockhash, 1, vec![tx.clone()])];
|
||||||
|
assert!(bincode::serialized_size(&tx).unwrap() <= PACKET_DATA_SIZE as u64);
|
||||||
|
assert!(entries[..].verify_transaction_signatures(false));
|
||||||
|
}
|
||||||
|
// Big transaction.
|
||||||
|
{
|
||||||
|
let tx = make_transaction(15);
|
||||||
|
let entries = vec![next_entry(&recent_blockhash, 1, vec![tx.clone()])];
|
||||||
|
assert!(bincode::serialized_size(&tx).unwrap() > PACKET_DATA_SIZE as u64);
|
||||||
|
assert!(!entries[..].verify_transaction_signatures(false));
|
||||||
|
}
|
||||||
|
// Assert that verify fails as soon as serialized
|
||||||
|
// size exceeds packet data size.
|
||||||
|
for size in 1..20 {
|
||||||
|
let tx = make_transaction(size);
|
||||||
|
let entries = vec![next_entry(&recent_blockhash, 1, vec![tx.clone()])];
|
||||||
|
assert_eq!(
|
||||||
|
bincode::serialized_size(&tx).unwrap() <= PACKET_DATA_SIZE as u64,
|
||||||
|
entries[..].verify_transaction_signatures(false),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[test]
|
#[test]
|
||||||
fn test_verify_tick_hash_count() {
|
fn test_verify_tick_hash_count() {
|
||||||
let hashes_per_tick = 10;
|
let hashes_per_tick = 10;
|
||||||
|
Reference in New Issue
Block a user