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
7 changes: 7 additions & 0 deletions p-token/src/entrypoint-runtime-verification.rs
Original file line number Diff line number Diff line change
Expand Up @@ -652,6 +652,11 @@ fn inner_process_remaining_instruction(
#[no_mangle]
pub unsafe extern "C" fn use_tests(acc: &AccountInfo) {
test_ptoken_domain_data(acc, acc, acc);
let _ =
test_validate_owner(unsafe { &*(acc as *const AccountInfo as *const [AccountInfo; 2]) });
let _ = test_validate_owner_multisig(unsafe {
&*(acc as *const AccountInfo as *const [AccountInfo; 5])
});
}

// special test for basic domain data access
Expand Down Expand Up @@ -742,6 +747,8 @@ include!("../../specs/shared/test_process_transfer.rs");
include!("../../specs/shared/test_process_transfer_multisig.rs");
include!("../../specs/shared/test_process_amount_to_ui_amount.rs");
include!("../../specs/shared/test_process_ui_amount_to_amount.rs");
include!("../../specs/shared/test_validate_owner.rs");
include!("../../specs/shared/test_validate_owner_multisig.rs");

// Withdraw Excess Lamports test harnesses (p-token specific)
include!("../../specs/withdraw-p-token.rs");
2 changes: 2 additions & 0 deletions p-token/test-properties/proofs.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@ Proofs to run with `run-proofs.sh -a`:
| Start symbol name |
|------------------------------------------------|
| test_ptoken_domain_data |
| test_validate_owner |
| test_validate_owner_multisig |
| test_process_approve |
| test_process_approve_checked |
| test_process_withdraw_excess_lamports_account |
Expand Down
62 changes: 62 additions & 0 deletions specs/shared/inner_test_validate_owner.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,65 @@
/// Computes the expected result of mod.rs::validate_owner.
#[inline(never)]
fn expected_validate_owner_result(
expected_owner: &Pubkey,
owner_account_info: &AccountInfo,
tx_signers: &[AccountInfo],
maybe_multisig_is_initialised: Option<Result<bool, ProgramError>>,
) -> Result<(), ProgramError> {
if expected_owner != key!(owner_account_info) {
return Err(ProgramError::Custom(4));
}
// We add the `maybe_multisig_is_initialised.is_some()` to not branch vacuously in the
// non-multisig cases
else if maybe_multisig_is_initialised.is_some()
&& owner_account_info.data_len() == Multisig::LEN
&& (owner!(owner_account_info) == &PROGRAM_ID)
{
// Guaranteed to succeed by `cheatcode_is_multisig`
let multisig_is_initialised = maybe_multisig_is_initialised.unwrap();
if multisig_is_initialised.is_err() {
return Err(ProgramError::InvalidAccountData);
} else if !multisig_is_initialised.unwrap() {
return Err(ProgramError::UninitializedAccount);
} else {
let multisig = get_multisig(owner_account_info);

// Did all declared and allowd signers sign?
let unsigned_exists = tx_signers.iter().any(|potential_signer| {
multisig.signers.iter().any(|registered_key| {
registered_key == key!(potential_signer) && !is_signer!(potential_signer)
})
});
if unsigned_exists {
return Err(ProgramError::MissingRequiredSignature);
}

// Were enough signatures received?
let signers_count = multisig.signers
.iter()
.filter_map(|registered_key| {
tx_signers.iter().find(|potential_signer| {
key!(potential_signer) == registered_key && is_signer!(potential_signer)
})
})
.count();

// Check if we have enough signers
if signers_count < multisig.m as usize {
return Err(ProgramError::MissingRequiredSignature);
}

return Ok(());
}
}
// Non-multisig case - check if owner_account_info.is_signer()
else if !is_signer!(owner_account_info) {
return Err(ProgramError::MissingRequiredSignature);
}

Ok(())
}

/// This function encapsulates the specification of validating the signature
/// requirements In particular, code from mod.rs::validate_owner is checked
#[inline(never)]
Expand Down
33 changes: 33 additions & 0 deletions specs/shared/test_validate_owner.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
/// accounts[0] // Source Account Info (provides expected_owner)
/// accounts[1] // Owner Info
#[inline(never)]
fn test_validate_owner(
accounts: &[AccountInfo; 2],
) -> ProgramResult {
cheatcode_account!(&accounts[0]); // Source Account
cheatcode_account!(&accounts[1]); // Owner

//-Initial State-----------------------------------------------------------
let src_old = get_account(&accounts[0]);
let expected_owner = src_old.owner;
let maybe_multisig_is_initialised = None;

//-Process Instruction-----------------------------------------------------
let result = expected_validate_owner_result(
&expected_owner,
&accounts[1],
&accounts[2..],
maybe_multisig_is_initialised.clone(),
);

//-Assert Postconditions---------------------------------------------------
inner_test_validate_owner(
&expected_owner,
&accounts[1],
&accounts[2..],
maybe_multisig_is_initialised,
result.clone(),
)?;

result
}
34 changes: 34 additions & 0 deletions specs/shared/test_validate_owner_multisig.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/// accounts[0] // Source Account Info (provides expected_owner)
/// accounts[1] // Owner Info (multisig)
/// accounts[2..4] // Signers
#[inline(never)]
fn test_validate_owner_multisig(
accounts: &[AccountInfo; 5],
) -> ProgramResult {
cheatcode_account!(&accounts[0]); // Source Account
cheatcode_multisig!(&accounts[1]); // Owner (multisig)

//-Initial State-----------------------------------------------------------
let src_old = get_account(&accounts[0]);
let expected_owner = src_old.owner;
let maybe_multisig_is_initialised = Some(get_multisig(&accounts[1]).is_initialized());

//-Process Instruction-----------------------------------------------------
let result = expected_validate_owner_result(
&expected_owner,
&accounts[1],
&accounts[2..],
maybe_multisig_is_initialised.clone(),
);

//-Assert Postconditions---------------------------------------------------
inner_test_validate_owner(
&expected_owner,
&accounts[1],
&accounts[2..],
maybe_multisig_is_initialised,
result.clone(),
)?;

result
}
Loading