solana-program-library/themis/program_ristretto/src/processor.rs

142 lines
4.9 KiB
Rust

//! Themis program
use crate::{
error::ThemisError,
instruction::ThemisInstruction,
state::{Policies, User},
};
use curve25519_dalek::{ristretto::RistrettoPoint, scalar::Scalar};
use elgamal_ristretto::public::PublicKey;
use solana_program::{
account_info::{next_account_info, AccountInfo},
program_error::ProgramError,
pubkey::Pubkey,
};
fn process_initialize_user_account(
user_info: &AccountInfo,
public_key: PublicKey,
) -> Result<(), ProgramError> {
// TODO: verify the program ID
if let Ok(user) = User::deserialize(&user_info.data.borrow()) {
if user.is_initialized {
return Err(ThemisError::AccountInUse.into());
}
}
let user = User::new(public_key);
user.serialize(&mut user_info.data.borrow_mut())
}
fn process_initialize_policies_account(
num_scalars: u8,
policies_info: &AccountInfo,
) -> Result<(), ProgramError> {
if let Ok(policies) = Policies::deserialize(&policies_info.data.borrow()) {
if policies.is_initialized {
return Err(ThemisError::AccountInUse.into());
}
}
let policies = Policies::new(num_scalars);
policies.serialize(&mut policies_info.data.borrow_mut())
}
fn process_store_policies(
scalars: Vec<(u8, Scalar)>,
policies_info: &AccountInfo,
) -> Result<(), ProgramError> {
let mut policies = Policies::deserialize(&policies_info.data.borrow())?;
for (i, scalar) in scalars {
policies.scalars[i as usize] = scalar;
}
policies.serialize(&mut policies_info.data.borrow_mut())
}
fn process_submit_interactions(
encrypted_interactions: &[(u8, (RistrettoPoint, RistrettoPoint))],
user_info: &AccountInfo,
policies_info: &AccountInfo,
) -> Result<(), ProgramError> {
let mut user = User::deserialize(&user_info.data.borrow())?;
let policies = Policies::deserialize(&policies_info.data.borrow())?;
user.submit_interactions(encrypted_interactions, &policies.scalars);
user.serialize(&mut user_info.data.borrow_mut())
}
fn process_submit_proof_decryption(
plaintext: RistrettoPoint,
announcement: (RistrettoPoint, RistrettoPoint),
response: Scalar,
user_info: &AccountInfo,
) -> Result<(), ProgramError> {
let mut user = User::deserialize(&user_info.data.borrow())?;
user.submit_proof_decryption(plaintext, announcement.0, announcement.1, response);
user.serialize(&mut user_info.data.borrow_mut())
}
fn process_request_payment(
encrypted_aggregate: (RistrettoPoint, RistrettoPoint),
decrypted_aggregate: RistrettoPoint,
proof_correct_decryption: RistrettoPoint,
user_info: &AccountInfo,
) -> Result<(), ProgramError> {
let mut user = User::deserialize(&user_info.data.borrow())?;
user.request_payment(
encrypted_aggregate,
decrypted_aggregate,
proof_correct_decryption,
);
user.serialize(&mut user_info.data.borrow_mut())
}
/// Process the given transaction instruction
pub fn process_instruction(
_program_id: &Pubkey,
account_infos: &[AccountInfo],
input: &[u8],
) -> Result<(), ProgramError> {
let account_infos_iter = &mut account_infos.iter();
let instruction = ThemisInstruction::deserialize(input)?;
match instruction {
ThemisInstruction::InitializeUserAccount { public_key } => {
let user_info = next_account_info(account_infos_iter)?;
process_initialize_user_account(&user_info, public_key)
}
ThemisInstruction::InitializePoliciesAccount { num_scalars } => {
let policies_info = next_account_info(account_infos_iter)?;
process_initialize_policies_account(num_scalars, &policies_info)
}
ThemisInstruction::StorePolicies { scalars } => {
let policies_info = next_account_info(account_infos_iter)?;
process_store_policies(scalars, &policies_info)
}
ThemisInstruction::SubmitInteractions {
encrypted_interactions,
} => {
let user_info = next_account_info(account_infos_iter)?;
let policies_info = next_account_info(account_infos_iter)?;
process_submit_interactions(&encrypted_interactions, &user_info, &policies_info)
}
ThemisInstruction::SubmitProofDecryption {
plaintext,
announcement,
response,
} => {
let user_info = next_account_info(account_infos_iter)?;
process_submit_proof_decryption(plaintext, *announcement, response, &user_info)
}
ThemisInstruction::RequestPayment {
encrypted_aggregate,
decrypted_aggregate,
proof_correct_decryption,
} => {
let user_info = next_account_info(account_infos_iter)?;
process_request_payment(
*encrypted_aggregate,
decrypted_aggregate,
proof_correct_decryption,
&user_info,
)
}
}
}