Skip to content

Commit 7912f59

Browse files
authored
Merge pull request #461 from Ackee-Blockchain/transaction-result
🔥 Move transaction result to trident svm
2 parents 9df4a12 + 9ed3f53 commit 7912f59

24 files changed

Lines changed: 7247 additions & 1147 deletions

File tree

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ incremented upon a breaking change and the patch version will be incremented for
1212

1313
**Added**
1414

15+
- add invariant macros for better invariant checking and error handling ([461](https://github.com/Ackee-Blockchain/trident/pull/461))
1516
- introduce simple Fork Testing allowing forking and caching programs and accounts from desired clusters ([434](https://github.com/Ackee-Blockchain/trident/pull/434))
1617
- add new random generation methods ([444](https://github.com/Ackee-Blockchain/trident/pull/444))
1718
- add `AccountDiscriminator` trait to derive discriminator for account types ([443](https://github.com/Ackee-Blockchain/trident/pull/443))
@@ -24,6 +25,7 @@ incremented upon a breaking change and the patch version will be incremented for
2425

2526
**Changed**
2627

28+
- move transaction result to trident-svm crate ([461](https://github.com/Ackee-Blockchain/trident/pull/461))
2729
- Allow initialization for Vanilla Solana projects with IDLs ([435](https://github.com/Ackee-Blockchain/trident/pull/435))
2830
- improve invariant handling and exit-code behavior in fuzzing ([457](https://github.com/Ackee-Blockchain/trident/pull/457))
2931

Cargo.lock

Lines changed: 38 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/client/src/utils.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -533,12 +533,14 @@ mod tests {
533533
]
534534
}"#;
535535

536+
// Pin temp_dir across the await so the async state machine won't drop it early.
537+
let _guard = &temp_dir;
538+
536539
// Should not create a backup for empty file
537540
create_or_update_json_file(&root, &settings_path, new_content)
538541
.await
539542
.unwrap();
540543

541-
// Keep TempDir alive across post-await checks to avoid eager drop in async state machine.
542544
assert!(temp_dir.path().exists());
543545

544546
// Verify no backup was created
@@ -572,12 +574,14 @@ mod tests {
572574
]
573575
}"#;
574576

577+
// Pin temp_dir across the await so the async state machine won't drop it early.
578+
let _guard = &temp_dir;
579+
575580
// Should not create a backup for whitespace-only file
576581
create_or_update_json_file(&root, &settings_path, new_content)
577582
.await
578583
.unwrap();
579584

580-
// Keep TempDir alive across post-await checks to avoid eager drop in async state machine.
581585
assert!(temp_dir.path().exists());
582586

583587
// Verify no backup was created

crates/fuzz/Cargo.toml

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,8 @@ workspace = true
5353

5454
# Trident-SVM
5555
[dependencies.trident-svm]
56-
version = "0.3.0-rc.2"
56+
git = "https://github.com/Ackee-Blockchain/trident-svm"
57+
branch = "develop"
5758

5859
[dependencies]
5960

crates/fuzz/src/invariant.rs

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,3 +36,26 @@ macro_rules! invariant {
3636
}
3737
};
3838
}
39+
40+
/// Checks if two expressions are equal and panics with `InvariantViolation` if not.
41+
///
42+
/// Use this macro to check if two expressions are equal.
43+
/// When the expressions are not equal, it will be counted and collected separately
44+
/// from unexpected panics (bugs in fuzz test code).
45+
///
46+
/// # Examples
47+
///
48+
/// ```ignore
49+
/// // Simple condition check
50+
/// invariant_eq!(balance_after, balance_before - amount);
51+
/// invariant_eq!(account.is_initialized, true, "Account is not initialized");
52+
/// ```
53+
#[macro_export]
54+
macro_rules! invariant_eq {
55+
($a:expr, $b:expr) => {
56+
invariant!($a == $b);
57+
};
58+
($a:expr, $b:expr, $($msg:tt)*) => {
59+
invariant!($a == $b, $($msg)*);
60+
};
61+
}

crates/fuzz/src/lib.rs

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -60,8 +60,6 @@ pub mod fuzzing {
6060

6161
/// Trident
6262
pub use super::trident::flow_executor::FlowExecutor;
63-
pub use super::trident::transaction_result::TransactionResult;
64-
pub use super::trident::transaction_result::TransactionReturnData;
6563
pub use super::trident::Trident;
6664
pub use trident_fuzz_metrics::TridentFuzzingData;
6765

crates/fuzz/src/trident/client.rs

Lines changed: 48 additions & 127 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,8 @@ use borsh::BorshDeserialize;
22
use borsh::BorshSerialize;
33
use solana_sdk::instruction::Instruction;
44
use solana_sdk::pubkey::Pubkey;
5-
use solana_sdk::transaction::TransactionError;
6-
use trident_svm::prelude::TridentTransactionProcessingResult;
7-
use trident_svm::processor::InstructionError;
5+
use trident_svm::prelude::TridentTransactionResult;
86

9-
use crate::trident::transaction_result::TransactionResult;
10-
use crate::trident::transaction_result::TransactionReturnData;
117
use crate::trident::Trident;
128
use crate::AccountDiscriminator;
139

@@ -46,7 +42,7 @@ impl Trident {
4642
&mut self,
4743
instructions: &[Instruction],
4844
log_as: Option<&str>,
49-
) -> TransactionResult {
45+
) -> TridentTransactionResult {
5046
let fuzzing_metrics = std::env::var("FUZZING_METRICS");
5147
let fuzzing_debug = std::env::var("TRIDENT_FUZZ_DEBUG");
5248

@@ -63,8 +59,9 @@ impl Trident {
6359
);
6460
}
6561
let processing_data = self.process_instructions(instructions);
62+
self.handle_tx_result(&processing_data, log_as, instructions);
6663

67-
self.handle_tx_result(&processing_data, log_as, instructions)
64+
processing_data
6865
}
6966

7067
/// Deploys an entrypoint program to the SVM runtime
@@ -284,10 +281,7 @@ impl Trident {
284281
panic!("Not yet implemented for TridentSVM");
285282
}
286283

287-
fn process_instructions(
288-
&mut self,
289-
instructions: &[Instruction],
290-
) -> TridentTransactionProcessingResult {
284+
fn process_instructions(&mut self, instructions: &[Instruction]) -> TridentTransactionResult {
291285
// there should be at least 1 RW fee-payer account.
292286
// But we do not pay for TX currently so has to be manually updated
293287
// tx.message.header.num_required_signatures = 1;
@@ -393,131 +387,58 @@ impl Trident {
393387

394388
fn handle_tx_result(
395389
&mut self,
396-
tx_processing_result: &TridentTransactionProcessingResult,
390+
tx_processing_result: &TridentTransactionResult,
397391
log_as: Option<&str>,
398392
instructions: &[Instruction],
399-
) -> TransactionResult {
393+
) {
400394
let fuzzing_metrics = std::env::var("FUZZING_METRICS");
401395
let fuzzing_debug = std::env::var("TRIDENT_FUZZ_DEBUG");
402396

403-
// NOTE: for now we just expect that one transaction was executed
404-
let tx_result = &tx_processing_result.get_result().processing_results[0];
397+
let is_program_failed_to_complete = tx_processing_result.is_program_failed_to_complete();
398+
399+
let log_messages = tx_processing_result.logs();
400+
401+
if is_program_failed_to_complete && fuzzing_metrics.is_ok() {
402+
if fuzzing_debug.is_ok() {
403+
trident_svm::prelude::trident_svm_log::log_message(
404+
"TRANSACTION PANICKED",
405+
trident_svm::prelude::Level::Error,
406+
);
407+
}
408+
if let Some(log_as) = log_as {
409+
let rng = self.rng.get_seed();
410+
// TODO format instructions
411+
let tx = format!("{:#?}", instructions);
412+
self.fuzzing_data.add_transaction_panicked(
413+
log_as,
414+
rng,
415+
"Program failed to complete".to_string(),
416+
Some(log_messages.clone()),
417+
tx,
418+
);
419+
}
420+
}
405421

406-
let transaction_timestamp = tx_processing_result.get_transaction_timestamp();
422+
let tx_result = &tx_processing_result.status();
407423

408424
match tx_result {
409-
Ok(result) => match result {
410-
trident_svm::prelude::solana_svm::transaction_processing_result::ProcessedTransaction::Executed(executed_transaction) => match &executed_transaction.execution_details.status {
411-
Ok(_) => {
412-
let transaction_return_data = executed_transaction
413-
.execution_details
414-
.return_data
415-
.clone()
416-
.map(|return_data| TransactionReturnData {
417-
program_id: return_data.program_id,
418-
data: return_data.data,
419-
});
420-
// Record successful execution
421-
if fuzzing_metrics.is_ok() && log_as.is_some() {
422-
if let Some(log_as) = log_as {
423-
self.fuzzing_data
424-
.add_successful_transaction(log_as);
425-
}
426-
}
427-
TransactionResult::new(
428-
Ok(()),
429-
executed_transaction
430-
.execution_details
431-
.log_messages
432-
.clone()
433-
.unwrap_or_default(),
434-
transaction_timestamp,
435-
transaction_return_data,
436-
)
437-
},
438-
Err(transaction_error) => {
439-
let transaction_return_data = executed_transaction
440-
.execution_details
441-
.return_data
442-
.clone()
443-
.map(|return_data| TransactionReturnData {
444-
program_id: return_data.program_id,
445-
data: return_data.data,
446-
});
447-
if let TransactionError::InstructionError(_error_code, instruction_error) =
448-
&transaction_error
449-
{
450-
match instruction_error {
451-
InstructionError::ProgramFailedToComplete => {
452-
if fuzzing_metrics.is_ok() {
453-
if fuzzing_debug.is_ok() {
454-
trident_svm::prelude::trident_svm_log::log_message(
455-
"TRANSACTION PANICKED",
456-
trident_svm::prelude::Level::Error,
457-
);
458-
}
459-
if let Some(log_as) = log_as {
460-
let rng = self.rng.get_seed();
461-
// TODO format instructions
462-
let tx = format!("{:#?}", instructions);
463-
self.fuzzing_data.add_transaction_panicked(
464-
log_as,
465-
rng,
466-
instruction_error.to_string(),
467-
executed_transaction.execution_details.log_messages.clone(),
468-
tx,
469-
);
470-
}
471-
}
472-
}
473-
InstructionError::Custom(error_code) => {
474-
if fuzzing_metrics.is_ok() && log_as.is_some() {
475-
if let Some(log_as) = log_as {
476-
self.fuzzing_data.add_custom_instruction_error(
477-
log_as,
478-
error_code,
479-
executed_transaction.execution_details.log_messages.clone(),
480-
);
481-
}
482-
}
483-
}
484-
_ => {
485-
if fuzzing_metrics.is_ok() && log_as.is_some() {
486-
if let Some(log_as) = log_as {
487-
self.fuzzing_data.add_failed_transaction(
488-
log_as,
489-
instruction_error.to_string(),
490-
executed_transaction.execution_details.log_messages.clone(),
491-
);
492-
}
493-
}
494-
}
495-
}
496-
} else if fuzzing_metrics.is_ok() && log_as.is_some() {
497-
if let Some(log_as) = log_as {
498-
self.fuzzing_data.add_failed_transaction(
499-
log_as,
500-
transaction_error.to_string(),
501-
executed_transaction.execution_details.log_messages.clone(),
502-
);
503-
}
504-
}
505-
TransactionResult::new(
506-
Err(transaction_error.clone()),
507-
executed_transaction
508-
.execution_details
509-
.log_messages
510-
.clone()
511-
.unwrap_or_default(),
512-
transaction_timestamp,
513-
transaction_return_data,
514-
)
515-
},
516-
},
517-
trident_svm::prelude::solana_svm::transaction_processing_result::ProcessedTransaction::FeesOnly(_) => todo!(),
518-
},
425+
Ok(_) => {
426+
if fuzzing_metrics.is_ok() && log_as.is_some() {
427+
if let Some(log_as) = log_as {
428+
self.fuzzing_data.add_successful_transaction(log_as);
429+
}
430+
}
431+
}
519432
Err(transaction_error) => {
520-
TransactionResult::new(Err(transaction_error.clone()), vec![], transaction_timestamp, None)
433+
if fuzzing_metrics.is_ok() && log_as.is_some() {
434+
if let Some(log_as) = log_as {
435+
self.fuzzing_data.add_failed_transaction(
436+
log_as,
437+
transaction_error.to_string(),
438+
Some(log_messages),
439+
);
440+
}
441+
}
521442
}
522443
}
523444
}

crates/fuzz/src/trident/mod.rs

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,6 @@ use crate::trident_rng::TridentRng;
1212
mod client;
1313
pub mod flow_executor;
1414
mod system;
15-
pub mod transaction_result;
1615

1716
mod metrics;
1817
mod progress;

0 commit comments

Comments
 (0)