2020-09-30 20:33:29 -07:00
|
|
|
//! Themis program
|
|
|
|
use crate::{
|
|
|
|
error::ThemisError,
|
|
|
|
instruction::ThemisInstruction,
|
|
|
|
state::{Policies, User},
|
|
|
|
};
|
2020-10-05 17:49:38 -07:00
|
|
|
use curve25519_dalek::{ristretto::RistrettoPoint, scalar::Scalar};
|
|
|
|
use elgamal_ristretto::public::PublicKey;
|
2020-10-22 21:44:27 -07:00
|
|
|
use solana_program::{
|
2020-09-30 20:33:29 -07:00
|
|
|
account_info::{next_account_info, AccountInfo},
|
|
|
|
program_error::ProgramError,
|
|
|
|
pubkey::Pubkey,
|
|
|
|
};
|
|
|
|
|
2020-10-02 20:57:54 -07:00
|
|
|
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());
|
|
|
|
}
|
2020-09-30 20:33:29 -07:00
|
|
|
}
|
2020-10-02 20:57:54 -07:00
|
|
|
let user = User::new(public_key);
|
2020-09-30 20:33:29 -07:00
|
|
|
user.serialize(&mut user_info.data.borrow_mut())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn process_initialize_policies_account(
|
2020-10-02 20:57:54 -07:00
|
|
|
num_scalars: u8,
|
2020-09-30 20:33:29 -07:00
|
|
|
policies_info: &AccountInfo,
|
|
|
|
) -> Result<(), ProgramError> {
|
2020-10-02 20:57:54 -07:00
|
|
|
if let Ok(policies) = Policies::deserialize(&policies_info.data.borrow()) {
|
|
|
|
if policies.is_initialized {
|
|
|
|
return Err(ThemisError::AccountInUse.into());
|
|
|
|
}
|
2020-09-30 20:33:29 -07:00
|
|
|
}
|
2020-10-02 20:57:54 -07:00
|
|
|
let policies = Policies::new(num_scalars);
|
2020-09-30 20:33:29 -07:00
|
|
|
policies.serialize(&mut policies_info.data.borrow_mut())
|
|
|
|
}
|
|
|
|
|
2020-10-02 20:57:54 -07:00
|
|
|
fn process_store_policies(
|
2020-10-05 17:49:38 -07:00
|
|
|
scalars: Vec<(u8, Scalar)>,
|
2020-10-02 20:57:54 -07:00
|
|
|
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(
|
2020-10-05 17:49:38 -07:00
|
|
|
encrypted_interactions: &[(u8, (RistrettoPoint, RistrettoPoint))],
|
2020-09-30 20:33:29 -07:00
|
|
|
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())?;
|
2020-10-02 20:57:54 -07:00
|
|
|
user.submit_interactions(encrypted_interactions, &policies.scalars);
|
2020-09-30 20:33:29 -07:00
|
|
|
user.serialize(&mut user_info.data.borrow_mut())
|
|
|
|
}
|
|
|
|
|
|
|
|
fn process_submit_proof_decryption(
|
2020-10-05 17:49:38 -07:00
|
|
|
plaintext: RistrettoPoint,
|
|
|
|
announcement: (RistrettoPoint, RistrettoPoint),
|
|
|
|
response: Scalar,
|
2020-09-30 20:33:29 -07:00
|
|
|
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(
|
2020-10-05 17:49:38 -07:00
|
|
|
encrypted_aggregate: (RistrettoPoint, RistrettoPoint),
|
|
|
|
decrypted_aggregate: RistrettoPoint,
|
|
|
|
proof_correct_decryption: RistrettoPoint,
|
2020-09-30 20:33:29 -07:00
|
|
|
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<'a>(
|
|
|
|
_program_id: &Pubkey,
|
|
|
|
account_infos: &'a [AccountInfo<'a>],
|
|
|
|
input: &[u8],
|
|
|
|
) -> Result<(), ProgramError> {
|
|
|
|
let account_infos_iter = &mut account_infos.iter();
|
|
|
|
let instruction = ThemisInstruction::deserialize(input)?;
|
|
|
|
|
|
|
|
match instruction {
|
2020-10-02 20:57:54 -07:00
|
|
|
ThemisInstruction::InitializeUserAccount { public_key } => {
|
2020-09-30 20:33:29 -07:00
|
|
|
let user_info = next_account_info(account_infos_iter)?;
|
2020-10-02 20:57:54 -07:00
|
|
|
process_initialize_user_account(&user_info, public_key)
|
2020-09-30 20:33:29 -07:00
|
|
|
}
|
2020-10-02 20:57:54 -07:00
|
|
|
ThemisInstruction::InitializePoliciesAccount { num_scalars } => {
|
2020-09-30 20:33:29 -07:00
|
|
|
let policies_info = next_account_info(account_infos_iter)?;
|
2020-10-02 20:57:54 -07:00
|
|
|
process_initialize_policies_account(num_scalars, &policies_info)
|
2020-09-30 20:33:29 -07:00
|
|
|
}
|
2020-10-02 20:57:54 -07:00
|
|
|
ThemisInstruction::StorePolicies { scalars } => {
|
|
|
|
let policies_info = next_account_info(account_infos_iter)?;
|
|
|
|
process_store_policies(scalars, &policies_info)
|
|
|
|
}
|
|
|
|
ThemisInstruction::SubmitInteractions {
|
2020-09-30 20:33:29 -07:00
|
|
|
encrypted_interactions,
|
|
|
|
} => {
|
|
|
|
let user_info = next_account_info(account_infos_iter)?;
|
|
|
|
let policies_info = next_account_info(account_infos_iter)?;
|
2020-10-02 20:57:54 -07:00
|
|
|
process_submit_interactions(&encrypted_interactions, &user_info, &policies_info)
|
2020-09-30 20:33:29 -07:00
|
|
|
}
|
|
|
|
ThemisInstruction::SubmitProofDecryption {
|
|
|
|
plaintext,
|
|
|
|
announcement,
|
|
|
|
response,
|
|
|
|
} => {
|
|
|
|
let user_info = next_account_info(account_infos_iter)?;
|
2020-10-02 20:57:54 -07:00
|
|
|
process_submit_proof_decryption(plaintext, *announcement, response, &user_info)
|
2020-09-30 20:33:29 -07:00
|
|
|
}
|
|
|
|
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,
|
|
|
|
)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|