Skip to content

Commit

Permalink
🚀 Add program id tied to each generated instruction
Browse files Browse the repository at this point in the history
  • Loading branch information
lukacan committed Sep 14, 2024
1 parent b99e54c commit 1332ee1
Show file tree
Hide file tree
Showing 37 changed files with 114 additions and 2,119 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ incremented upon a breaking change and the patch version will be incremented for

## [dev] - Unreleased

**Added**

- impr/ added get_program_id function to the IxOps and FuzzTestExecutor ([199](https://github.com/Ackee-Blockchain/trident/pull/199))

**Changed**

- feat/ option to add account into Fuzz Test environment with base64 data ([197](https://github.com/Ackee-Blockchain/trident/pull/197))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -208,7 +208,9 @@ fn get_instruction_ixops(
type IxData = #module_name::instruction::#instruction_ident_name;
type IxAccounts = FuzzAccounts;
type IxSnapshot = #ix_snapshot<'info>;

fn get_program_id(&self) -> solana_sdk::pubkey::Pubkey {
#module_name::ID
}
fn get_data(
&self,
_client: &mut impl FuzzClient,
Expand Down
17 changes: 1 addition & 16 deletions crates/client/src/source_code_generators/test_fuzz_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -23,20 +23,6 @@ pub fn generate_source_code(idl_instructions: &[Idl]) -> String {
),
};

let run_with_runtime: syn::Stmt = match fuzz_instructions.len() {
1 => {
let program_name_upper = idl_instructions[0].metadata.name.to_case(Case::UpperSnake);
let program_id_name_ident = format_ident!("PROGRAM_ID_{}", program_name_upper);

parse_quote!(
let _ = fuzz_data.run_with_runtime(#program_id_name_ident, &mut client);
)
}
_ => parse_quote!(
let _ = fuzz_data.run_with_runtime(todo!(), &mut client);
),
};

let test_fuzz_definition: syn::File = parse_quote! {
use trident_client::fuzzing::*;
mod fuzz_instructions;
Expand All @@ -60,8 +46,7 @@ pub fn generate_source_code(idl_instructions: &[Idl]) -> String {

let mut client = ProgramTestClientBlocking::new(&#programs_array,&[]).unwrap();

#run_with_runtime

let _ = fuzz_data.run_with_runtime(&mut client);

}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -54,6 +54,9 @@ pub mod dummy_example_fuzz_instructions {
type IxData = dummy_example::instruction::InitializeIx;
type IxAccounts = FuzzAccounts;
type IxSnapshot = InitializeIxSnapshot<'info>;
fn get_program_id(&self) -> solana_sdk::pubkey::Pubkey {
dummy_example::ID
}
fn get_data(
&self,
_client: &mut impl FuzzClient,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ fn fuzz_iteration<T: FuzzTestExecutor<U> + std::fmt::Display, U>(fuzz_data: Fuzz

let mut client = ProgramTestClientBlocking::new(&[fuzzing_program_dummy_example], &[]).unwrap();

let _ = fuzz_data.run_with_runtime(PROGRAM_ID_DUMMY_EXAMPLE, &mut client);
let _ = fuzz_data.run_with_runtime(&mut client);
}

fn main() {
Expand Down
3 changes: 2 additions & 1 deletion crates/fuzz/derive/fuzz_test_executor/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ pub fn fuzz_test_executor(input: TokenStream) -> TokenStream {
let variant_name = &variant.ident;
quote! {
#enum_name::#variant_name (ix) => {
let program_id = ix.get_program_id();

let (mut signers, metas) = ix.get_accounts(client, &mut accounts.borrow_mut())
.map_err(|e| e.with_origin(Origin::Instruction(self.to_context_string())))
.expect("Accounts calculation expect");
Expand Down Expand Up @@ -99,7 +101,6 @@ pub fn fuzz_test_executor(input: TokenStream) -> TokenStream {
impl FuzzTestExecutor<FuzzAccounts> for FuzzInstruction {
fn run_fuzzer(
&self,
program_id: Pubkey,
accounts: &RefCell<FuzzAccounts>,
client: &mut impl FuzzClient,
sent_txs: &mut HashMap<Hash, ()>,
Expand Down
4 changes: 1 addition & 3 deletions crates/fuzz/src/fuzz_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use arbitrary::Arbitrary;
use arbitrary::Unstructured;
use solana_sdk::account::Account;
use solana_sdk::instruction::AccountMeta;
use solana_sdk::pubkey::Pubkey;
use std::cell::RefCell;
use std::collections::HashMap;
use std::error::Error;
Expand Down Expand Up @@ -56,7 +55,6 @@ where
{
pub fn run_with_runtime(
&self,
program_id: Pubkey,
client: &mut impl FuzzClient,
) -> core::result::Result<(), Box<dyn Error + 'static>> {
// solana_logger::setup_with_default("off");
Expand Down Expand Up @@ -85,7 +83,7 @@ where
eprintln!("\x1b[34mCurrently processing\x1b[0m: {}", fuzz_ix);

if fuzz_ix
.run_fuzzer(program_id, &self.accounts, client, &mut sent_txs)
.run_fuzzer(&self.accounts, client, &mut sent_txs)
.is_err()
{
// for now skip following instructions in case of error and move to the next fuzz iteration
Expand Down
3 changes: 0 additions & 3 deletions crates/fuzz/src/fuzz_test_executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,6 @@

use anchor_lang::solana_program::hash::Hash;

use solana_sdk::pubkey::Pubkey;

use std::cell::RefCell;
use std::collections::HashMap;

Expand All @@ -13,7 +11,6 @@ use crate::fuzz_client::FuzzClient;
pub trait FuzzTestExecutor<T> {
fn run_fuzzer(
&self,
program_id: Pubkey,
accounts: &RefCell<T>,
client: &mut impl FuzzClient,
sent_txs: &mut HashMap<Hash, ()>,
Expand Down
4 changes: 4 additions & 0 deletions crates/fuzz/src/ix_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,10 @@ pub trait IxOps<'info> {
/// The structure to which the instruction accounts will be deserialized
type IxSnapshot;

/// Specify Program ID to which the Instruction corresponds. This is particularly helpful when using multiple
/// programs in the workspace, to differentiate between possible program calls.
fn get_program_id(&self) -> solana_sdk::pubkey::Pubkey;

/// Provides instruction data for the fuzzed instruction.
/// It is assumed that the instruction data will be based on the fuzzer input stored in the `self.data` variable.
/// However it is on the developer to decide and it can be also for example a hardcoded constant.
Expand Down
Loading

0 comments on commit 1332ee1

Please sign in to comment.