Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feat/fuzz pkey to acc #116

Merged
merged 6 commits into from
Feb 15, 2024
Merged
Show file tree
Hide file tree
Changes from 2 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
36 changes: 31 additions & 5 deletions crates/client/src/fuzzer/fuzzer_generator.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ pub fn generate_source_code(idl: &Idl) -> String {
let program_name = idl_program.name.snake_case.replace('-', "_");
let fuzz_instructions_module_name = format_ident!("{}_fuzz_instructions", program_name);
let module_name: syn::Ident = parse_str(&program_name).unwrap();
let mut accounts_from_instr_input: Vec<(String, String)> = vec![];

let instructions = idl_program
.instruction_account_pairs
Expand Down Expand Up @@ -52,9 +53,25 @@ pub fn generate_source_code(idl: &Idl) -> String {
.parameters
.iter()
.map(|(name, ty)| {
let name = format_ident!("{name}");
let ty: syn::Type = parse_str(ty).unwrap();
let parameter: syn::FnArg = parse_quote!(#name: #ty);
let name_ident = format_ident!("{name}");
// TODO What about custom Enums and Structs on Instr Input ?
let ty = parse_str(ty).unwrap();
let ty: syn::Type = match &ty {
Copy link
Contributor

@Ikrk Ikrk Feb 14, 2024

Choose a reason for hiding this comment

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

Why so complicated? You can compare the ty variable directly as it is a String before it is shadowed by the let ty = parse_str(ty).unwrap(); line. So you can do only if ty == "Pubkey" directly.

Also I think the accounts_from_instr_input HashMap is not necessary. If it is one of the accounts, that will be required by another instruction, than it will be automatically generated anyway. And if it is not an account used by any instruction, than there is no need to add it.

Update: maybe it won't be so easy if the type is fully qualified with its path, but anyway, I think you can simply check if it is "Pubkey" or if it ends by "::Pubkey" or something similar...

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

Thanks for the comments. Removed the unnecessary HashMap.
Regarding the Pubkey parse, simplified with "ends_with". Long option "anchor_lang::pubkey::Pubkey" is stored inside ty as "anchor_lang :: pubkey :: Pubkey" so for that case I check for ":: Pubkey". I think it won't hurt to check also for "::Pubkey", and for the short path I check for "Pubkey"

syn::Type::Path(tp) => {
let last_type =
&tp.path.segments.last().unwrap().ident.to_string();
if last_type == "Pubkey" {
let t: syn::Type = parse_str("AccountId").unwrap();
accounts_from_instr_input
.push((name.to_string(), "AccountId".to_string()));
t
} else {
ty
}
}
_ => ty,
};
let parameter: syn::FnArg = parse_quote!(#name_ident: #ty);
parameter
})
.collect::<Vec<_>>();
Expand Down Expand Up @@ -173,7 +190,7 @@ pub fn generate_source_code(idl: &Idl) -> String {
)
.into_iter();

let fuzz_accounts = idl_program.instruction_account_pairs.iter().fold(
let mut fuzz_accounts = idl_program.instruction_account_pairs.iter().fold(
HashMap::new(),
|mut fuzz_accounts, (_idl_instruction, idl_account_group)| {
idl_account_group.accounts.iter().fold(
Expand All @@ -184,10 +201,19 @@ pub fn generate_source_code(idl: &Idl) -> String {
fuzz_accounts
},
);

fuzz_accounts
},
);

fuzz_accounts.extend(accounts_from_instr_input.iter().fold(
HashMap::new(),
|mut fuzz_accounts, (name, _ty)| {
let name = format_ident!("{name}");
fuzz_accounts.entry(name).or_insert_with(|| "".to_string());
fuzz_accounts
},
));

// this ensures that the order of accounts is deterministic
// so we can use expected generated template within tests
let mut sorted_fuzz_accounts: Vec<_> = fuzz_accounts.keys().collect();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -108,7 +108,7 @@ mod instructions {
error_msg: VestingError::InvalidAmount.to_string(),
error_origin: Some(anchor_lang::error::ErrorOrigin::Source(
anchor_lang::error::Source {
filename: "programs/fuzz_example3/src/instructions/initialize.rs",
filename: "src/instructions/initialize.rs",
line: 18u32,
},
)),
Expand All @@ -124,7 +124,7 @@ mod instructions {
error_msg: VestingError::InvalidTimeRange.to_string(),
error_origin: Some(anchor_lang::error::ErrorOrigin::Source(
anchor_lang::error::Source {
filename: "programs/fuzz_example3/src/instructions/initialize.rs",
filename: "src/instructions/initialize.rs",
line: 20u32,
},
)),
Expand All @@ -140,7 +140,7 @@ mod instructions {
error_msg: VestingError::InvalidInterval.to_string(),
error_origin: Some(anchor_lang::error::ErrorOrigin::Source(
anchor_lang::error::Source {
filename: "programs/fuzz_example3/src/instructions/initialize.rs",
filename: "src/instructions/initialize.rs",
line: 22u32,
},
)),
Expand All @@ -156,7 +156,7 @@ mod instructions {
error_msg: VestingError::InvalidInterval.to_string(),
error_origin: Some(anchor_lang::error::ErrorOrigin::Source(
anchor_lang::error::Source {
filename: "programs/fuzz_example3/src/instructions/initialize.rs",
filename: "src/instructions/initialize.rs",
line: 23u32,
},
)),
Expand Down Expand Up @@ -365,7 +365,7 @@ mod instructions {
error_code_number: anchor_lang::error::ErrorCode::TryingToInitPayerAsProgramAccount.into(),
error_msg: anchor_lang::error::ErrorCode::TryingToInitPayerAsProgramAccount.to_string(),
error_origin: Some(anchor_lang::error::ErrorOrigin::Source(anchor_lang::error::Source {
filename: "programs/fuzz_example3/src/instructions/initialize.rs",
filename: "src/instructions/initialize.rs",
line: 64u32,
})),
compared_values: None,
Expand Down Expand Up @@ -1364,7 +1364,7 @@ pub mod state {
.to_string(),
error_origin: Some(anchor_lang::error::ErrorOrigin::Source(
anchor_lang::error::Source {
filename: "programs/fuzz_example3/src/state.rs",
filename: "src/state.rs",
line: 3u32,
},
)),
Expand Down Expand Up @@ -1764,7 +1764,7 @@ mod __private {
.to_string(),
error_origin: Some(anchor_lang::error::ErrorOrigin::Source(
anchor_lang::error::Source {
filename: "programs/fuzz_example3/src/lib.rs",
filename: "src/lib.rs",
line: 11u32,
},
)),
Expand Down Expand Up @@ -3424,7 +3424,7 @@ mod __private {
error_msg: anchor_lang::error::ErrorCode::RequireEqViolated.to_string(),
error_origin: Some(anchor_lang::error::ErrorOrigin::Source(
anchor_lang::error::Source {
filename: "programs/fuzz_example3/src/lib.rs",
filename: "src/lib.rs",
line: 11u32,
},
)),
Expand Down Expand Up @@ -3466,7 +3466,7 @@ mod __private {
error_msg: anchor_lang::error::ErrorCode::RequireGteViolated.to_string(),
error_origin: Some(anchor_lang::error::ErrorOrigin::Source(
anchor_lang::error::Source {
filename: "programs/fuzz_example3/src/lib.rs",
filename: "src/lib.rs",
line: 11u32,
},
)),
Expand All @@ -3492,7 +3492,7 @@ mod __private {
let ix = instruction::InitVesting::deserialize(&mut &__ix_data[..])
.map_err(|_| anchor_lang::error::ErrorCode::InstructionDidNotDeserialize)?;
let instruction::InitVesting {
recipient,
i_recipient,
amount,
start_at,
end_at,
Expand All @@ -3515,7 +3515,7 @@ mod __private {
__remaining_accounts,
__bumps,
),
recipient,
i_recipient,
amount,
start_at,
end_at,
Expand Down Expand Up @@ -3557,13 +3557,13 @@ pub mod fuzz_example3 {
use super::*;
pub fn init_vesting(
ctx: Context<InitVesting>,
recipient: Pubkey,
i_recipient: Pubkey,
amount: u64,
start_at: u64,
end_at: u64,
interval: u64,
) -> Result<()> {
_init_vesting(ctx, recipient, amount, start_at, end_at, interval)
_init_vesting(ctx, i_recipient, amount, start_at, end_at, interval)
}
pub fn withdraw_unlocked(ctx: Context<WithdrawUnlocked>) -> Result<()> {
_withdraw_unlocked(ctx)
Expand All @@ -3579,7 +3579,7 @@ pub mod instruction {
use super::*;
#[doc = r" Instruction."]
pub struct InitVesting {
pub recipient: Pubkey,
pub i_recipient: Pubkey,
pub amount: u64,
pub start_at: u64,
pub end_at: u64,
Expand All @@ -3597,7 +3597,7 @@ pub mod instruction {
&self,
writer: &mut W,
) -> ::core::result::Result<(), borsh::maybestd::io::Error> {
borsh::BorshSerialize::serialize(&self.recipient, writer)?;
borsh::BorshSerialize::serialize(&self.i_recipient, writer)?;
borsh::BorshSerialize::serialize(&self.amount, writer)?;
borsh::BorshSerialize::serialize(&self.start_at, writer)?;
borsh::BorshSerialize::serialize(&self.end_at, writer)?;
Expand All @@ -3617,7 +3617,7 @@ pub mod instruction {
reader: &mut R,
) -> ::core::result::Result<Self, borsh::maybestd::io::Error> {
Ok(Self {
recipient: borsh::BorshDeserialize::deserialize_reader(reader)?,
i_recipient: borsh::BorshDeserialize::deserialize_reader(reader)?,
amount: borsh::BorshDeserialize::deserialize_reader(reader)?,
start_at: borsh::BorshDeserialize::deserialize_reader(reader)?,
end_at: borsh::BorshDeserialize::deserialize_reader(reader)?,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ pub mod fuzz_example3_fuzz_instructions {
}
#[derive(Arbitrary, Clone)]
pub struct InitVestingData {
pub recipient: Pubkey,
pub i_recipient: AccountId,
pub amount: u64,
pub start_at: u64,
pub end_at: u64,
Expand Down Expand Up @@ -57,7 +57,7 @@ pub mod fuzz_example3_fuzz_instructions {
_fuzz_accounts: &mut FuzzAccounts,
) -> Result<Self::IxData, FuzzingError> {
let data = fuzz_example3::instruction::InitVesting {
recipient: todo!(),
i_recipient: todo!(),
amount: todo!(),
start_at: todo!(),
end_at: todo!(),
Expand Down Expand Up @@ -123,6 +123,7 @@ pub mod fuzz_example3_fuzz_instructions {
escrow: AccountsStorage<todo!()>,
escrow_pda_authority: AccountsStorage<todo!()>,
escrow_token_account: AccountsStorage<todo!()>,
i_recipient: AccountsStorage<todo!()>,
mint: AccountsStorage<todo!()>,
recipient: AccountsStorage<todo!()>,
recipient_token_account: AccountsStorage<todo!()>,
Expand Down
2 changes: 2 additions & 0 deletions crates/client/tests/test_program/fuzz_example3/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
[workspace]

[package]
name = "fuzz_example3"
version = "0.1.0"
Expand Down
4 changes: 2 additions & 2 deletions crates/client/tests/test_program/fuzz_example3/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,13 +14,13 @@ pub mod fuzz_example3 {

pub fn init_vesting(
ctx: Context<InitVesting>,
recipient: Pubkey,
i_recipient: Pubkey,
amount: u64,
start_at: u64,
end_at: u64,
interval: u64,
) -> Result<()> {
_init_vesting(ctx, recipient, amount, start_at, end_at, interval)
_init_vesting(ctx, i_recipient, amount, start_at, end_at, interval)
}

pub fn withdraw_unlocked(ctx: Context<WithdrawUnlocked>) -> Result<()> {
Expand Down
Loading