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

Adding IsWallet rule #146

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
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
59 changes: 41 additions & 18 deletions programs/token-auth-rules/src/state/rules.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,14 +4,19 @@ use crate::{
types::Assertable,
// TODO: Uncomment this after on-curve sycall available.
// utils::is_on_curve,
utils::{assert_derivation, compute_merkle_root, is_zeroed},
utils::{assert_derivation, cmp_pubkeys, compute_merkle_root, is_zeroed},
};
use serde::{Deserialize, Serialize};
#[cfg(feature = "serde-with-feature")]
use serde_with::{As, DisplayFromStr};
use solana_program::{
account_info::AccountInfo, entrypoint::ProgramResult, msg, program_error::ProgramError,
pubkey::Pubkey, system_program,
account_info::AccountInfo,
entrypoint::ProgramResult,
msg,
program_error::ProgramError,
pubkey::Pubkey,
system_program,
sysvar::{self, instructions::get_instruction_relative},
};
use std::collections::{HashMap, HashSet};

Expand Down Expand Up @@ -639,28 +644,46 @@ impl Rule {
Rule::IsWallet { field } => {
msg!("Validating IsWallet");

let sysvar_instructions_info = match accounts.get(&sysvar::instructions::ID) {
Some(sysvar_instructions_info) => *sysvar_instructions_info,
_ => return RuleResult::Error(RuleSetError::MissingAccount.into()),
};

// Fetch the Pubkey of the caller from the payload.
let caller = match payload.get_pubkey(&"caller".to_string()) {
Some(pubkey) => pubkey,
_ => return RuleResult::Error(RuleSetError::MissingPayloadValue.into()),
};

// If the program id of the current instruction is anything other than our program id
// we know this is a CPI call from another program.
let current_ix = get_instruction_relative(0, sysvar_instructions_info).unwrap();

let is_cpi = !cmp_pubkeys(&current_ix.program_id, caller);

// Get the `Pubkey` we are checking from the payload.
let key = match payload.get_pubkey(field) {
let key = match payload.get_pubkey(&field.to_string()) {
Some(pubkey) => pubkey,
_ => return Error(RuleSetError::MissingPayloadValue.into()),
_ => return RuleResult::Error(RuleSetError::MissingPayloadValue.into()),
};

// Get the `AccountInfo` struct for the `Pubkey` and verify that
// its owner is the System Program.
if let Some(account) = accounts.get(key) {
if *account.owner != system_program::ID {
// TODO: Change error return to commented line after on-curve syscall
// available.
return Error(RuleSetError::NotImplemented.into());
//return (false, self.to_error());
}
} else {
return Error(RuleSetError::MissingAccount.into());
}
// Get the `AccountInfo` struct for the `Pubkey`.
let account = match accounts.get(key) {
Some(account) => *account,
_ => return RuleResult::Error(RuleSetError::MissingAccount.into()),
};

// These checks can be replaced with a sys call to curve25519 once that feature activates.
let system_program_owned = cmp_pubkeys(account.owner, &system_program::ID);

// TODO: Uncomment call to `is_on_curve()` after on-curve sycall available.
Error(RuleSetError::NotImplemented.into())
//(is_on_curve(key), self.to_error())

if !is_cpi && system_program_owned {
Success(self.to_error())
} else {
Failure(self.to_error())
}
}
Rule::ProgramOwnedSet { programs, field } => {
msg!("Validating ProgramOwnedSet");
Expand Down
50 changes: 36 additions & 14 deletions programs/token-auth-rules/src/state/v2/constraint/is_wallet.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,7 @@
use solana_program::{msg, system_program};
use solana_program::{
msg, system_program,
sysvar::{self, instructions::get_instruction_relative},
};

use crate::{
error::RuleSetError,
Expand All @@ -7,6 +10,7 @@ use crate::{
v2::{Constraint, ConstraintType, Str32, HEADER_SECTION},
Header,
},
utils::cmp_pubkeys,
};

/// Constraint that represents a test on whether a pubkey can be signed from a client and therefore
Expand Down Expand Up @@ -65,27 +69,45 @@ impl<'a> Constraint<'a> for IsWallet<'a> {
) -> RuleResult {
msg!("Validating IsWallet");

let sysvar_instructions_info = match accounts.get(&sysvar::instructions::ID) {
Some(sysvar_instructions_info) => *sysvar_instructions_info,
_ => return RuleResult::Error(RuleSetError::MissingAccount.into()),
};

// Fetch the Pubkey of the caller from the payload.
let caller = match payload.get_pubkey(&"caller".to_string()) {
Some(pubkey) => pubkey,
_ => return RuleResult::Error(RuleSetError::MissingPayloadValue.into()),
};

// If the program id of the current instruction is anything other than our program id
// we know this is a CPI call from another program.
let current_ix = get_instruction_relative(0, sysvar_instructions_info).unwrap();

let is_cpi = !cmp_pubkeys(&current_ix.program_id, caller);

// Get the `Pubkey` we are checking from the payload.
let key = match payload.get_pubkey(&self.field.to_string()) {
Some(pubkey) => pubkey,
_ => return RuleResult::Error(RuleSetError::MissingPayloadValue.into()),
};

// Get the `AccountInfo` struct for the `Pubkey` and verify that
// its owner is the System Program.
if let Some(account) = accounts.get(key) {
if *account.owner != system_program::ID {
// TODO: Change error return to commented line after on-curve syscall
// available.
return RuleResult::Error(RuleSetError::NotImplemented.into());
//return (false, self.to_error());
}
} else {
return RuleResult::Error(RuleSetError::MissingAccount.into());
}
// Get the `AccountInfo` struct for the `Pubkey`.
let account = match accounts.get(key) {
Some(account) => *account,
_ => return RuleResult::Error(RuleSetError::MissingAccount.into()),
};

// These checks can be replaced with a sys call to curve25519 once that feature activates.
let system_program_owned = cmp_pubkeys(account.owner, &system_program::ID);

// TODO: Uncomment call to `is_on_curve()` after on-curve sycall available.
RuleResult::Error(RuleSetError::NotImplemented.into())
//(is_on_curve(key), self.to_error())

if !is_cpi && system_program_owned {
RuleResult::Success(self.constraint_type().to_error())
} else {
RuleResult::Failure(self.constraint_type().to_error())
}
}
}
Loading