Skip to content

Commit

Permalink
add support for return data (#63)
Browse files Browse the repository at this point in the history
  • Loading branch information
2501babe authored Dec 10, 2024
1 parent 11d1530 commit 2be6299
Show file tree
Hide file tree
Showing 7 changed files with 46 additions and 7 deletions.
7 changes: 5 additions & 2 deletions fuzz/fixture/proto/invoke.proto
Original file line number Diff line number Diff line change
Expand Up @@ -64,14 +64,17 @@ message InstrEffects {
// Program return code. Zero is success, errors are non-zero.
uint32 program_result = 3;

// The instruction return data.
bytes return_data = 4;

// Copies of accounts that were provided to the instruction. May be in an
// arbitrary order. The pubkey of each account is unique in this list. Each
// account address must also be in the InstrContext.
repeated AcctState resulting_accounts = 4;
repeated AcctState resulting_accounts = 5;
}

// An instruction processing test fixture.
message InstrFixture {
InstrContext input = 1;
InstrEffects output = 2;
}
}
5 changes: 5 additions & 0 deletions fuzz/fixture/src/effects.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ pub struct Effects {
pub execution_time: u64,
// Program return code. Zero is success, errors are non-zero.
pub program_result: u32,
pub return_data: Vec<u8>,
/// Resulting accounts with state, to be checked post-simulation.
pub resulting_accounts: Vec<(Pubkey, AccountSharedData)>,
}
Expand All @@ -24,6 +25,7 @@ impl From<ProtoEffects> for Effects {
compute_units_consumed,
execution_time,
program_result,
return_data,
resulting_accounts,
} = value;

Expand All @@ -34,6 +36,7 @@ impl From<ProtoEffects> for Effects {
compute_units_consumed,
execution_time,
program_result,
return_data,
resulting_accounts,
}
}
Expand All @@ -45,6 +48,7 @@ impl From<Effects> for ProtoEffects {
compute_units_consumed,
execution_time,
program_result,
return_data,
resulting_accounts,
} = value;

Expand All @@ -55,6 +59,7 @@ impl From<Effects> for ProtoEffects {
compute_units_consumed,
execution_time,
program_result,
return_data,
resulting_accounts,
}
}
Expand Down
6 changes: 5 additions & 1 deletion harness/src/fuzz/firedancer.rs
Original file line number Diff line number Diff line change
Expand Up @@ -169,6 +169,8 @@ fn build_fixture_effects(context: &FuzzContext, result: &InstructionResult) -> F
}
};

let return_data = result.return_data.clone();

let modified_accounts = context
.accounts
.iter()
Expand All @@ -191,7 +193,7 @@ fn build_fixture_effects(context: &FuzzContext, result: &InstructionResult) -> F
compute_units_available: context
.compute_units_available
.saturating_sub(result.compute_units_consumed),
return_data: Vec::new(), // TODO: Mollusk doesn't capture return data.
return_data,
}
}

Expand All @@ -210,6 +212,7 @@ fn parse_fixture_effects(
};

let program_result = raw_result.clone().into();
let return_data = effects.return_data.clone();

let resulting_accounts = accounts
.iter()
Expand All @@ -232,6 +235,7 @@ fn parse_fixture_effects(
.compute_budget
.compute_unit_limit
.saturating_sub(effects.compute_units_available),
return_data,
resulting_accounts,
}
}
Expand Down
4 changes: 4 additions & 0 deletions harness/src/fuzz/mollusk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ impl From<&InstructionResult> for FuzzEffects {
fn from(input: &InstructionResult) -> Self {
let compute_units_consumed = input.compute_units_consumed;
let execution_time = input.execution_time;
let return_data = input.return_data.clone();

let program_result = match &input.program_result {
ProgramResult::Success => 0,
Expand All @@ -69,6 +70,7 @@ impl From<&InstructionResult> for FuzzEffects {
compute_units_consumed,
execution_time,
program_result,
return_data,
resulting_accounts,
}
}
Expand All @@ -78,6 +80,7 @@ impl From<&FuzzEffects> for InstructionResult {
fn from(input: &FuzzEffects) -> Self {
let compute_units_consumed = input.compute_units_consumed;
let execution_time = input.execution_time;
let return_data = input.return_data.clone();

let raw_result = if input.program_result == 0 {
Ok(())
Expand All @@ -94,6 +97,7 @@ impl From<&FuzzEffects> for InstructionResult {
execution_time,
program_result,
raw_result,
return_data,
resulting_accounts,
}
}
Expand Down
3 changes: 3 additions & 0 deletions harness/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -217,6 +217,8 @@ impl Mollusk {
}
};

let return_data = transaction_context.get_return_data().1.to_vec();

let resulting_accounts: Vec<(Pubkey, AccountSharedData)> = accounts
.iter()
.map(|(pubkey, account)| {
Expand All @@ -236,6 +238,7 @@ impl Mollusk {
execution_time: timings.details.execute_us,
program_result: invoke_result.clone().into(),
raw_result: invoke_result,
return_data,
resulting_accounts,
}
}
Expand Down
20 changes: 20 additions & 0 deletions harness/src/result.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,8 @@ pub struct InstructionResult {
pub program_result: ProgramResult,
/// The raw result of the program's execution.
pub raw_result: Result<(), InstructionError>,
/// The return data produced by the instruction, if any.
pub return_data: Vec<u8>,
/// The resulting accounts after executing the instruction.
///
/// This includes all accounts provided to the processor, in the order
Expand All @@ -66,6 +68,7 @@ impl Default for InstructionResult {
execution_time: 0,
program_result: ProgramResult::Success,
raw_result: Ok(()),
return_data: vec![],
resulting_accounts: vec![],
}
}
Expand Down Expand Up @@ -111,6 +114,15 @@ impl InstructionResult {
actual_result, check_result,
);
}
CheckType::ReturnData(return_data) => {
let check_return_data = return_data;
let actual_return_data = &self.return_data;
assert_eq!(
actual_return_data, check_return_data,
"CHECK: return_data: got {:?}, expected {:?}",
actual_return_data, check_return_data,
);
}
CheckType::ResultingAccount(account) => {
let pubkey = account.pubkey;
let resulting_account = self
Expand Down Expand Up @@ -199,6 +211,7 @@ impl InstructionResult {
b.resulting_accounts.len(),
"resulting accounts length mismatch"
);
assert_eq!(self.return_data, b.return_data, "return data mismatch");
for (a, b) in self
.resulting_accounts
.iter()
Expand All @@ -217,6 +230,8 @@ enum CheckType<'a> {
ExecutionTime(u64),
/// Check the result code of the program's execution.
ProgramResult(ProgramResult),
/// Check the return data produced by executing the instruction.
ReturnData(Vec<u8>),
/// Check a resulting account after executing the instruction.
ResultingAccount(AccountCheck<'a>),
}
Expand Down Expand Up @@ -255,6 +270,11 @@ impl<'a> Check<'a> {
Check::new(CheckType::ProgramResult(ProgramResult::UnknownError(error)))
}

/// Check the return data produced by executing the instruction.
pub fn return_data(return_data: Vec<u8>) -> Self {
Check::new(CheckType::ReturnData(return_data))
}

/// Check a resulting account after executing the instruction.
pub fn account(pubkey: &Pubkey) -> AccountCheckBuilder {
AccountCheckBuilder::new(pubkey)
Expand Down
8 changes: 4 additions & 4 deletions harness/tests/fd_test_vectors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -106,10 +106,10 @@ fn test_load_firedancer_fixtures() {
loaded_fixture.output.compute_units_available,
generated_fixture.output.compute_units_available,
);
// assert_eq!(
// loaded_fixture.output.return_data,
// generated_fixture.output.return_data,
// );
assert_eq!(
loaded_fixture.output.return_data,
generated_fixture.output.return_data,
);
}
});
});
Expand Down

0 comments on commit 2be6299

Please sign in to comment.