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
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ incremented upon a breaking change and the patch version will be incremented for
- add more stake program related methods ([441](https://github.com/Ackee-Blockchain/trident/pull/441))
- add remove functionality to AddressStorage ([442](https://github.com/Ackee-Blockchain/trident/pull/442))
- add support for exit code mode ([454](https://github.com/Ackee-Blockchain/trident/pull/454))
- add support for return data ([456](https://github.com/Ackee-Blockchain/trident/pull/456))

**Removed**

Expand Down
2 changes: 2 additions & 0 deletions crates/fuzz/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,8 @@ pub mod fuzzing {

/// Trident
pub use super::trident::flow_executor::FlowExecutor;
pub use super::trident::transaction_result::TransactionResult;
pub use super::trident::transaction_result::TransactionReturnData;
pub use super::trident::Trident;
pub use trident_fuzz_metrics::TridentFuzzingData;

Expand Down
43 changes: 40 additions & 3 deletions crates/fuzz/src/trident/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use trident_svm::prelude::TridentTransactionProcessingResult;
use trident_svm::processor::InstructionError;

use crate::trident::transaction_result::TransactionResult;
use crate::trident::transaction_result::TransactionReturnData;
use crate::trident::Trident;
use crate::AccountDiscriminator;

Expand Down Expand Up @@ -408,16 +409,41 @@ impl Trident {
Ok(result) => match result {
trident_svm::prelude::solana_svm::transaction_processing_result::ProcessedTransaction::Executed(executed_transaction) => match &executed_transaction.execution_details.status {
Ok(_) => {
let transaction_return_data = executed_transaction
.execution_details
.return_data
.clone()
.map(|return_data| TransactionReturnData {
program_id: return_data.program_id,
data: return_data.data,
});
// Record successful execution
if fuzzing_metrics.is_ok() && log_as.is_some() {
if let Some(log_as) = log_as {
self.fuzzing_data
.add_successful_transaction(log_as);
}
}
TransactionResult::new(Ok(()), executed_transaction.execution_details.log_messages.clone().unwrap_or_default(), transaction_timestamp)
TransactionResult::new(
Ok(()),
executed_transaction
.execution_details
.log_messages
.clone()
.unwrap_or_default(),
transaction_timestamp,
transaction_return_data,
)
},
Err(transaction_error) => {
let transaction_return_data = executed_transaction
.execution_details
.return_data
.clone()
.map(|return_data| TransactionReturnData {
program_id: return_data.program_id,
data: return_data.data,
});
if let TransactionError::InstructionError(_error_code, instruction_error) =
&transaction_error
{
Expand Down Expand Up @@ -476,12 +502,23 @@ impl Trident {
);
}
}
TransactionResult::new(Err(transaction_error.clone()), executed_transaction.execution_details.log_messages.clone().unwrap_or_default(), transaction_timestamp)
TransactionResult::new(
Err(transaction_error.clone()),
executed_transaction
.execution_details
.log_messages
.clone()
.unwrap_or_default(),
transaction_timestamp,
transaction_return_data,
)
},
},
trident_svm::prelude::solana_svm::transaction_processing_result::ProcessedTransaction::FeesOnly(_) => todo!(),
},
Err(transaction_error) => TransactionResult::new(Err(transaction_error.clone()), vec![], transaction_timestamp),
Err(transaction_error) => {
TransactionResult::new(Err(transaction_error.clone()), vec![], transaction_timestamp, None)
}
}
}
}
23 changes: 23 additions & 0 deletions crates/fuzz/src/trident/transaction_result.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,14 @@
use solana_sdk::pubkey::Pubkey;
use solana_sdk::transaction::TransactionError;
use trident_svm::processor::InstructionError;

/// Return data emitted by a Solana program during transaction execution.
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct TransactionReturnData {
pub program_id: Pubkey,
pub data: Vec<u8>,
}

/// Result of a transaction execution containing both the result and logs
///
/// This struct encapsulates the outcome of executing a transaction,
Expand All @@ -10,6 +18,7 @@ pub struct TransactionResult {
transaction_result: solana_sdk::transaction::Result<()>,
transaction_logs: Vec<String>,
transaction_timestamp: u64,
transaction_return_data: Option<TransactionReturnData>,
}

impl TransactionResult {
Expand All @@ -22,11 +31,13 @@ impl TransactionResult {
transaction_result: solana_sdk::transaction::Result<()>,
transaction_logs: Vec<String>,
transaction_timestamp: u64,
transaction_return_data: Option<TransactionReturnData>,
) -> Self {
Self {
transaction_result,
transaction_logs,
transaction_timestamp,
transaction_return_data,
}
}

Expand Down Expand Up @@ -118,4 +129,16 @@ impl TransactionResult {
pub fn get_transaction_timestamp(&self) -> u64 {
self.transaction_timestamp
}

/// Returns the raw return data emitted during transaction execution.
///
/// When a program calls `set_return_data`, Solana stores the emitting program ID
/// together with the returned bytes. This accessor exposes that data to Trident users.
///
/// # Returns
///
/// `Some(&TransactionReturnData)` if a program returned data, `None` otherwise.
pub fn get_return_data(&self) -> Option<&TransactionReturnData> {
self.transaction_return_data.as_ref()
}
}
20 changes: 19 additions & 1 deletion documentation/docs/trident-api/transaction-result/index.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# TransactionResult

The `TransactionResult` struct encapsulates the outcome of executing a transaction in the Trident fuzzing environment. It provides methods to inspect transaction success/failure status, access logs, and extract error information.
The `TransactionResult` struct encapsulates the outcome of executing a transaction in the Trident fuzzing environment. It provides methods to inspect transaction success/failure status, access logs, extract error information, and read Solana return data.

## Overview

Expand All @@ -10,6 +10,7 @@ The `TransactionResult` struct encapsulates the outcome of executing a transacti
- Log messages generated during execution
- Custom program error codes
- Transaction timestamp
- Return data emitted by the executed program

## Core Methods

Expand Down Expand Up @@ -118,6 +119,23 @@ pub fn get_transaction_timestamp(&self) -> u64

---

### `get_return_data`

Returns the raw Solana return data for the transaction, if any program emitted it via `set_return_data`.

```rust
pub fn get_return_data(&self) -> Option<&TransactionReturnData>
```

**Returns:**

- `Some(&TransactionReturnData)` - If a program emitted return data during execution
- `None` - If no return data was set

**Description:** The returned value contains the emitting `program_id` and the raw returned `data` bytes.

---

## Example Usage

### Basic Transaction Verification
Expand Down
4 changes: 2 additions & 2 deletions examples/hello_world/programs/hello_world/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ declare_id!("FtevoQoDMv6ZB3N9Lix5Tbjs8EVuNL8vDSqG9kzaZPit");
pub mod hello_world {
use super::*;

pub fn initialize_fn(ctx: Context<InitializeContext>, input: u8) -> Result<()> {
pub fn initialize_fn(ctx: Context<InitializeContext>, input: u8) -> Result<u8> {
msg!(
"Hello World address: {}",
ctx.accounts.hello_world_account.key()
Expand All @@ -21,7 +21,7 @@ pub mod hello_world {
let timestamp = Clock::get()?.unix_timestamp;
hello_world_store.timestamp = timestamp as u64;

Ok(())
Ok(5)
}
}

Expand Down
55 changes: 43 additions & 12 deletions examples/hello_world/trident-tests/Cargo.lock

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

5 changes: 5 additions & 0 deletions examples/hello_world/trident-tests/fuzz_0/test_fuzz.rs
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,11 @@ impl FuzzTest {
assert!(hello_world_account.input == input);
assert!(hello_world_account.timestamp == res.get_transaction_timestamp());
}

let returned_value = res.get_return_data().unwrap();

assert!(returned_value.program_id.eq(&hello_world::program_id()));
assert!(returned_value.data.eq(&[5]));
}
}

Expand Down