parasol_cpu 0.10.0

This crate contains the Parasol CPU, which runs programs over a mix of encrypted and plaintext data.
Documentation
use std::sync::Arc;

use rand::{RngCore, rng};

use crate::{ArgsBuilder, Memory, proc::IsaOp, register_names::*, test_utils::make_computer_128};

use parasol_runtime::{fluent::UInt8, test_utils::get_secret_keys_128};

#[test]
fn can_or_plaintext_inputs() {
    let (mut proc, _enc) = make_computer_128();

    let val1 = 14u32;
    let val2 = 7u32;
    let expected = val1 | val2;

    let memory = Arc::new(Memory::new_default_stack());

    let program = memory.allocate_program(&[
        IsaOp::Load(T0, SP, 32, 0),
        IsaOp::Load(T1, SP, 32, 4),
        IsaOp::Or(T0, T0, T1),
        IsaOp::Store(RP, T0, 32, 0),
        IsaOp::Ret(),
    ]);

    let args = ArgsBuilder::new().arg(val1).arg(val2).return_value::<u32>();

    let ans = proc.run_program(program, &memory, args).unwrap();

    assert_eq!(expected, ans);
}

#[test]
fn can_or_ciphertext_inputs() {
    let (mut proc, enc) = make_computer_128();
    let sk = get_secret_keys_128();

    let mut test = |val1: u8, val2: u8| {
        let expected = val1 | val2;

        let memory = Arc::new(Memory::new_default_stack());

        let program = memory.allocate_program(&[
            IsaOp::Load(T0, SP, 8, 0),
            IsaOp::Load(T1, SP, 8, 1),
            IsaOp::Or(T0, T0, T1),
            IsaOp::Store(RP, T0, 8, 0),
            IsaOp::Ret(),
        ]);

        let args = ArgsBuilder::new()
            .arg(UInt8::encrypt_secret(val1 as u128, &enc, &sk))
            .arg(UInt8::encrypt_secret(val2 as u128, &enc, &sk))
            .return_value::<UInt8>();

        let answer = proc.run_program(program, &memory, args).unwrap();

        let answer = answer.decrypt(&enc, &sk) as u8;

        assert_eq!(expected, answer);
    };

    for _ in 0..=10 {
        let val1 = (rng().next_u64() % 16) as u8;
        let val2 = (rng().next_u64() % 16) as u8;
        test(val1, val2);
    }
}