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_and_plaintext_inputs() {
    let (mut proc, _enc) = make_computer_128();

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

    let memory = Memory::new_default_stack();
    let program_ptr = memory.allocate_program(&[
        IsaOp::Load(T0, SP, 32, 0),
        IsaOp::Load(T1, SP, 32, 4),
        IsaOp::And(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_ptr, &Arc::new(memory), args)
        .unwrap();

    assert_eq!(expected, ans);
}

#[test]
fn can_and_ciphertext_inputs() {
    let (mut proc, enc) = make_computer_128();
    let mut test = |val1: u8, val2: u8| {
        let expected = val1 & val2;

        let sk = get_secret_keys_128();

        let memory = Memory::new_default_stack();

        let program = memory.allocate_program(&[
            IsaOp::Load(T0, SP, 8, 0),
            IsaOp::Load(T1, SP, 8, 1),
            IsaOp::And(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, &Arc::new(memory), args).unwrap();

        assert_eq!(expected, answer.decrypt(&enc, &sk) as u8);
    };

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