Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions banks-server/src/banks_server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -174,6 +174,8 @@ fn simulate_transaction(
Some(false), // is_simple_vote_tx
bank,
bank.get_reserved_account_keys(),
bank.feature_set
.is_active(&agave_feature_set::static_instruction_limit::id()),
) {
Err(err) => {
return BanksTransactionResultWithSimulation {
Expand Down
2 changes: 2 additions & 0 deletions core/src/banking_stage/consume_worker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1207,6 +1207,8 @@ mod tests {
None,
loader,
&HashSet::default(),
bank.feature_set
.is_active(&agave_feature_set::static_instruction_limit::id()),
)
.unwrap()
};
Expand Down
2 changes: 2 additions & 0 deletions core/src/banking_stage/consumer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1789,6 +1789,8 @@ mod tests {
Some(false),
bank.as_ref(),
&ReservedAccountKeys::empty_key_set(),
bank.feature_set
.is_active(&agave_feature_set::static_instruction_limit::id()),
)
.unwrap();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -667,7 +667,7 @@ impl TransactionViewReceiveAndBuffer {
transaction_account_lock_limit: usize,
) -> Result<TransactionViewState, PacketHandlingError> {
// Parsing and basic sanitization checks
let Ok(view) = SanitizedTransactionView::try_new_sanitized(bytes) else {
let Ok(view) = SanitizedTransactionView::try_new_sanitized(bytes, working_bank.feature_set.is_active(&agave_feature_set::static_instruction_limit::id())) else {
return Err(PacketHandlingError::Sanitization);
};

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -474,7 +474,7 @@ mod tests {

let reserved_addresses = HashSet::default();
let packet_parser = |data, priority, cost| {
let view = SanitizedTransactionView::try_new_sanitized(data).unwrap();
let view = SanitizedTransactionView::try_new_sanitized(data, true).unwrap();
let view = RuntimeTransaction::<SanitizedTransactionView<_>>::try_from(
view,
MessageHash::Compute,
Expand Down
29 changes: 17 additions & 12 deletions core/src/forwarding_stage.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,6 +291,9 @@ impl<VoteClient: ForwardingClient, NonVoteClient: ForwardingClient>
is_tpu_vote_batch: bool,
bank: &Bank,
) {
let enable_static_instruction_limit = bank
.feature_set
.is_active(&agave_feature_set::static_instruction_limit::id());
for batch in packet_batches.iter() {
for packet in batch
.iter()
Expand All @@ -311,19 +314,21 @@ impl<VoteClient: ForwardingClient, NonVoteClient: ForwardingClient>

// Perform basic sanitization checks and calculate priority.
// If any steps fail, drop the packet.
let Some(priority) = SanitizedTransactionView::try_new_sanitized(packet_data)
let Some(priority) = SanitizedTransactionView::try_new_sanitized(
packet_data,
enable_static_instruction_limit,
)
.map_err(|_| ())
.and_then(|transaction| {
RuntimeTransaction::<SanitizedTransactionView<_>>::try_from(
transaction,
MessageHash::Compute,
Some(packet.meta().is_simple_vote_tx()),
)
.map_err(|_| ())
.and_then(|transaction| {
RuntimeTransaction::<SanitizedTransactionView<_>>::try_from(
transaction,
MessageHash::Compute,
Some(packet.meta().is_simple_vote_tx()),
)
.map_err(|_| ())
})
.ok()
.and_then(|transaction| calculate_priority(&transaction, bank))
else {
})
.ok()
.and_then(|transaction| calculate_priority(&transaction, bank)) else {
self.metrics.votes_dropped_on_receive += vote_count;
self.metrics.non_votes_dropped_on_receive += non_vote_count;
continue;
Expand Down
2 changes: 2 additions & 0 deletions cost-model/src/transaction_cost.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,6 +341,7 @@ mod tests {
Some(true),
SimpleAddressLoader::Disabled,
&ReservedAccountKeys::empty_key_set(),
true,
)
.unwrap();

Expand All @@ -360,6 +361,7 @@ mod tests {
Some(false),
SimpleAddressLoader::Disabled,
&ReservedAccountKeys::empty_key_set(),
true,
)
.unwrap();

Expand Down
2 changes: 2 additions & 0 deletions entry/benches/entry_sigverify.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ fn bench_gpusigverify(bencher: &mut Bencher) {
None,
SimpleAddressLoader::Disabled,
&ReservedAccountKeys::empty_key_set(),
true,
)
}?;

Expand Down Expand Up @@ -89,6 +90,7 @@ fn bench_cpusigverify(bencher: &mut Bencher) {
None,
SimpleAddressLoader::Disabled,
&ReservedAccountKeys::empty_key_set(),
true,
)
}?;

Expand Down
1 change: 1 addition & 0 deletions entry/src/entry.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1076,6 +1076,7 @@ mod tests {
None,
SimpleAddressLoader::Disabled,
&ReservedAccountKeys::empty_key_set(),
true,
)
}?;

Expand Down
8 changes: 8 additions & 0 deletions feature-set/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1137,6 +1137,10 @@ pub mod provide_instruction_data_offset_in_vm_r2 {
solana_pubkey::declare_id!("5xXZc66h4UdB6Yq7FzdBxBiRAFMMScMLwHxk2QZDaNZL");
}

pub mod static_instruction_limit {
solana_pubkey::declare_id!("64ixypL1HPu8WtJhNSMb9mSgfFaJvsANuRkTbHyuLfnx");
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

64ix 🫡

}

pub static FEATURE_NAMES: LazyLock<AHashMap<Pubkey, &'static str>> = LazyLock::new(|| {
[
(secp256k1_program_enabled::id(), "secp256k1 program"),
Expand Down Expand Up @@ -2054,6 +2058,10 @@ pub static FEATURE_NAMES: LazyLock<AHashMap<Pubkey, &'static str>> = LazyLock::n
provide_instruction_data_offset_in_vm_r2::id(),
"SIMD-0321: Provide instruction data offset in VM r2",
),
(
static_instruction_limit::id(),
"SIMD-0160: static instruction limit",
),
/*************** ADD NEW FEATURES HERE ***************/
]
.iter()
Expand Down
1 change: 1 addition & 0 deletions ledger-tool/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -470,6 +470,7 @@ fn compute_slot_cost(
None,
SimpleAddressLoader::Disabled,
&reserved_account_keys.active,
feature_set.is_active(&agave_feature_set::static_instruction_limit::id()),
)
.map_err(|err| {
warn!("Failed to compute cost of transaction: {err:?}");
Expand Down
2 changes: 2 additions & 0 deletions programs/sbf/Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

20 changes: 16 additions & 4 deletions rpc/src/rpc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3838,6 +3838,9 @@ pub mod rpc_full {
unsanitized_tx,
preflight_bank,
preflight_bank.get_reserved_account_keys(),
preflight_bank
.feature_set
.is_active(&agave_feature_set::static_instruction_limit::id()),
)?;
let blockhash = *transaction.message().recent_blockhash();
let message_hash = *transaction.message_hash();
Expand Down Expand Up @@ -3988,8 +3991,13 @@ pub mod rpc_full {
});
}

let transaction =
sanitize_transaction(unsanitized_tx, bank, bank.get_reserved_account_keys())?;
let transaction = sanitize_transaction(
unsanitized_tx,
bank,
bank.get_reserved_account_keys(),
bank.feature_set
.is_active(&agave_feature_set::static_instruction_limit::id()),
)?;
if sig_verify {
verify_transaction(&transaction)?;
}
Expand Down Expand Up @@ -4391,13 +4399,15 @@ fn sanitize_transaction(
transaction: VersionedTransaction,
address_loader: impl AddressLoader,
reserved_account_keys: &HashSet<Pubkey>,
enable_static_instruction_limit: bool,
) -> Result<RuntimeTransaction<SanitizedTransaction>> {
RuntimeTransaction::try_create(
transaction,
MessageHash::Compute,
None,
address_loader,
reserved_account_keys,
enable_static_instruction_limit,
)
.map_err(|err| Error::invalid_params(format!("invalid transaction: {err}")))
}
Expand Down Expand Up @@ -9097,7 +9107,8 @@ pub mod tests {
sanitize_transaction(
unsanitary_versioned_tx,
SimpleAddressLoader::Disabled,
&ReservedAccountKeys::empty_key_set()
&ReservedAccountKeys::empty_key_set(),
true,
)
.unwrap_err(),
expect58
Expand All @@ -9122,7 +9133,8 @@ pub mod tests {
sanitize_transaction(
versioned_tx,
SimpleAddressLoader::Disabled,
&ReservedAccountKeys::empty_key_set()
&ReservedAccountKeys::empty_key_set(),
true,
)
.unwrap_err(),
Error::invalid_params(
Expand Down
1 change: 1 addition & 0 deletions runtime-transaction/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ solana-sdk-ids = { workspace = true }
solana-signature = { workspace = true }
solana-svm-transaction = { workspace = true }
solana-transaction = { workspace = true }
solana-transaction-context = { workspace = true }
solana-transaction-error = { workspace = true }
thiserror = { workspace = true }

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,7 +80,14 @@ impl RuntimeTransaction<SanitizedTransaction> {
is_simple_vote_tx: Option<bool>,
address_loader: impl AddressLoader,
reserved_account_keys: &HashSet<Pubkey>,
enable_static_instruction_limit: bool,
) -> Result<Self> {
if enable_static_instruction_limit
&& tx.message.instructions().len()
> solana_transaction_context::MAX_INSTRUCTION_TRACE_LENGTH
{
return Err(solana_transaction_error::TransactionError::SanitizeFailure);
}
let statically_loaded_runtime_tx =
RuntimeTransaction::<SanitizedVersionedTransaction>::try_from(
SanitizedVersionedTransaction::try_from(tx)?,
Expand Down Expand Up @@ -142,12 +149,14 @@ impl TransactionWithMeta for RuntimeTransaction<SanitizedTransaction> {
impl RuntimeTransaction<SanitizedTransaction> {
pub fn from_transaction_for_tests(transaction: solana_transaction::Transaction) -> Self {
let versioned_transaction = VersionedTransaction::from(transaction);
let enable_static_instruction_limit = true;
Self::try_create(
versioned_transaction,
MessageHash::Compute,
None,
solana_message::SimpleAddressLoader::Disabled,
&HashSet::new(),
enable_static_instruction_limit,
)
.expect("failed to create RuntimeTransaction from Transaction")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -220,7 +220,7 @@ mod tests {

let hash = Hash::new_unique();
let transaction =
SanitizedTransactionView::try_new_sanitized(&serialized_transaction[..]).unwrap();
SanitizedTransactionView::try_new_sanitized(&serialized_transaction[..], true).unwrap();
let static_runtime_transaction =
RuntimeTransaction::<SanitizedTransactionView<_>>::try_from(
transaction,
Expand Down Expand Up @@ -252,7 +252,8 @@ mod tests {
reserved_account_keys: &HashSet<Pubkey>,
) {
let bytes = bincode::serialize(&original_transaction).unwrap();
let transaction_view = SanitizedTransactionView::try_new_sanitized(&bytes[..]).unwrap();
let transaction_view =
SanitizedTransactionView::try_new_sanitized(&bytes[..], true).unwrap();
let runtime_transaction = RuntimeTransaction::<SanitizedTransactionView<_>>::try_from(
transaction_view,
MessageHash::Compute,
Expand Down Expand Up @@ -318,7 +319,8 @@ mod tests {
) {
let bytes =
bincode::serialize(&original_transaction.to_versioned_transaction()).unwrap();
let transaction_view = SanitizedTransactionView::try_new_sanitized(&bytes[..]).unwrap();
let transaction_view =
SanitizedTransactionView::try_new_sanitized(&bytes[..], true).unwrap();
let runtime_transaction = RuntimeTransaction::<SanitizedTransactionView<_>>::try_from(
transaction_view,
MessageHash::Compute,
Expand Down
15 changes: 15 additions & 0 deletions runtime/src/bank.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2901,6 +2901,9 @@ impl Bank {
&self,
txs: Vec<VersionedTransaction>,
) -> Result<TransactionBatch<RuntimeTransaction<SanitizedTransaction>>> {
let enable_static_instruction_limit = self
.feature_set
.is_active(&agave_feature_set::static_instruction_limit::id());
let sanitized_txs = txs
.into_iter()
.map(|tx| {
Expand All @@ -2910,6 +2913,7 @@ impl Bank {
None,
self,
self.get_reserved_account_keys(),
enable_static_instruction_limit,
)
})
.collect::<Result<Vec<_>>>()?;
Expand Down Expand Up @@ -4591,6 +4595,9 @@ impl Bank {
tx: VersionedTransaction,
verification_mode: TransactionVerificationMode,
) -> Result<RuntimeTransaction<SanitizedTransaction>> {
let enable_static_instruction_limit = self
.feature_set
.is_active(&agave_feature_set::static_instruction_limit::id());
let sanitized_tx = {
let size =
bincode::serialized_size(&tx).map_err(|_| TransactionError::SanitizeFailure)?;
Expand All @@ -4599,6 +4606,13 @@ impl Bank {
}
let message_hash = if verification_mode == TransactionVerificationMode::FullVerification
{
// SIMD-0160, check instruction limit before signature verificaton
Comment thread
apfitzge marked this conversation as resolved.
if enable_static_instruction_limit
&& tx.message.instructions().len()
> solana_transaction_context::MAX_INSTRUCTION_TRACE_LENGTH
{
return Err(solana_transaction_error::TransactionError::SanitizeFailure);
}
tx.verify_and_hash_message()?
} else {
tx.message.hash()
Expand All @@ -4610,6 +4624,7 @@ impl Bank {
None,
self,
self.get_reserved_account_keys(),
enable_static_instruction_limit,
)
}?;

Expand Down
Loading
Loading