Skip to content

Commit

Permalink
test: rcomb_base and falcon test prove-verify (#1232)
Browse files Browse the repository at this point in the history
  • Loading branch information
Al-Kindi-0 authored Feb 14, 2024
1 parent 0561bff commit f4e3545
Show file tree
Hide file tree
Showing 3 changed files with 144 additions and 17 deletions.
99 changes: 98 additions & 1 deletion processor/src/operations/comb_ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -171,7 +171,8 @@ where

#[cfg(test)]
mod tests {
use test_utils::rand::rand_array;
use crate::Vec;
use test_utils::{build_test, rand::rand_array};
use vm_core::{Felt, FieldElement, Operation, StackInputs, ONE, ZERO};

use crate::{ContextId, Process, QuadFelt};
Expand Down Expand Up @@ -267,4 +268,100 @@ mod tests {
let helper_reg_expected = [tz0, tz1, tgz0, tgz1, a0, a1];
assert_eq!(helper_reg_expected, process.decoder.get_user_op_helpers());
}

#[test]
fn prove_verify() {
let source = " begin
# I) Prepare memory and stack
# 1) Load T_i(x) for i=0,..,7
push.0 padw
adv_pipe
# 2) Load [T_i(z), T_i(gz)] for i=0,..,7
repeat.4
adv_pipe
end
# 3) Load [a0, a1, 0, 0] for i=0,..,7
repeat.4
adv_pipe
end
# 4) Clean up stack
dropw dropw dropw drop
# 5) Prepare stack
## a) Push pointers
push.10 # a_ptr
push.2 # z_ptr
push.0 # x_ptr
## b) Push accumulators
padw
## c) Add padding for mem_stream
padw padw
# II) Execute `rcomb_base` op
mem_stream
repeat.8
rcomb_base
end
end
";

// generate the data
let tx: [Felt; 8] = rand_array();
let tz_tgz: [QuadFelt; 16] = rand_array();
let a: [QuadFelt; 8] = rand_array();

// compute the expected values of the accumulators
let mut p = QuadFelt::ZERO;
let mut r = QuadFelt::ZERO;
let tz: Vec<QuadFelt> = tz_tgz.iter().step_by(2).map(|e| e.to_owned()).collect();
let tgz: Vec<QuadFelt> = tz_tgz.iter().skip(1).step_by(2).map(|e| e.to_owned()).collect();
for i in 0..8 {
p += a[i] * (QuadFelt::from(tx[i]) - tz[i]);
r += a[i] * (QuadFelt::from(tx[i]) - tgz[i]);
}

// prepare the advice stack with the generated data
let mut adv_stack = Vec::new();
let tz_tgz: Vec<Felt> = tz_tgz.iter().flat_map(|e| e.to_base_elements()).collect();
let a: Vec<Felt> = a
.iter()
.flat_map(|e| {
let element = e.to_base_elements();
[element[0], element[1], ZERO, ZERO]
})
.collect();
adv_stack.extend_from_slice(&tx);
adv_stack.extend_from_slice(&tz_tgz);
adv_stack.extend_from_slice(&a);
let adv_stack: Vec<u64> = adv_stack.iter().map(|e| e.as_int()).collect();

// create the expected operand stack
let mut expected = Vec::new();
// updated pointers
expected.extend_from_slice(&[ZERO, Felt::from(18_u8), Felt::from(10_u8), Felt::from(2_u8)]);
// updated accumulators
expected.extend_from_slice(&[
r.to_base_elements()[0],
r.to_base_elements()[1],
p.to_base_elements()[0],
p.to_base_elements()[1],
]);
// the top 8 stack elements should equal tx since 8 calls to `rcomb_base` implies 8 circular
// shifts of the top 8 elements i.e., the identity map on the top 8 element.
expected.extend_from_slice(&tx);
let expected: Vec<u64> = expected.iter().rev().map(|e| e.as_int()).collect();

let test = build_test!(source, &[], &adv_stack);
test.expect_stack(&expected);

let pub_inputs: Vec<u64> = Vec::new();
test.prove_and_verify(pub_inputs, false);
}
}
60 changes: 45 additions & 15 deletions stdlib/tests/crypto/falcon.rs
Original file line number Diff line number Diff line change
@@ -1,25 +1,56 @@
use assembly::utils::Serializable;
use miden_air::Felt;
use processor::Digest;

use std::vec;
use assembly::{utils::Serializable, Assembler};
use miden_air::{Felt, ProvingOptions};
use miden_stdlib::StdLibrary;
use processor::{AdviceInputs, DefaultHost, Digest, MemAdviceProvider, StackInputs};
use test_utils::{
crypto::{rpo_falcon512::KeyPair, MerkleStore},
rand::rand_vector,
Test, Word,
ProgramInfo, Word,
};

#[test]
fn test_falcon() {
fn falcon_execution() {
let keypair = KeyPair::new().unwrap();

let message = rand_vector::<Felt>(4).try_into().unwrap();
let (source, op_stack, adv_stack, store, advice_map) = generate_test(keypair, message);

let test = generate_test(keypair, message);
let test = build_test!(source, &op_stack, &adv_stack, store, advice_map.into_iter());
test.expect_stack(&[])
}

fn generate_test(keypair: KeyPair, message: Word) -> Test {
#[test]
#[ignore]
fn falcon_prove_verify() {
let keypair = KeyPair::new().unwrap();
let message = rand_vector::<Felt>(4).try_into().unwrap();
let (source, op_stack, _, _, advice_map) = generate_test(keypair, message);

let program = Assembler::default()
.with_library(&StdLibrary::default())
.expect("failed to load stdlib")
.compile(&source)
.expect("failed to compile test source");

let stack_inputs =
StackInputs::try_from_values(op_stack).expect("failed to create stack inputs");
let advice_inputs = AdviceInputs::default().with_map(advice_map);
let advice_provider = MemAdviceProvider::from(advice_inputs);
let host = DefaultHost::new(advice_provider);

let options = ProvingOptions::with_96_bit_security(false);
let (stack_outputs, proof) = test_utils::prove(&program, stack_inputs.clone(), host, options)
.expect("failed to generate proof");

let program_info = ProgramInfo::from(program);
let result = test_utils::verify(program_info, stack_inputs, stack_outputs, proof);

assert!(result.is_ok(), "error: {result:?}");
}

fn generate_test(
keypair: KeyPair,
message: Word,
) -> (&'static str, Vec<u64>, Vec<u64>, MerkleStore, Vec<([u8; 32], Vec<Felt>)>) {
let source = "
use.std::crypto::dsa::rpo_falcon512
Expand All @@ -31,18 +62,17 @@ fn generate_test(keypair: KeyPair, message: Word) -> Test {
let pk: Word = keypair.public_key().into();
let pk: Digest = pk.into();
let pk_sk_bytes = keypair.to_bytes();
let to_adv_map = pk_sk_bytes.iter().map(|a| Felt::new(*a as u64)).collect::<Vec<Felt>>();

let to_adv_map = pk_sk_bytes.iter().map(|a| Felt::new(*a as u64)).collect::<Vec<Felt>>();
let advice_map: Vec<([u8; 32], Vec<Felt>)> = vec![(pk.as_bytes(), to_adv_map.into())];

let message = message.into_iter().map(|a| a.as_int() as u64).collect::<Vec<u64>>();

let mut op_stack = vec![];
let message = message.into_iter().map(|a| a.as_int() as u64).collect::<Vec<u64>>();
op_stack.extend_from_slice(&message);
op_stack.extend_from_slice(&pk.as_elements().iter().map(|a| a.as_int()).collect::<Vec<u64>>());

let adv_stack = vec![];
let store = MerkleStore::new();
let test = build_test!(source, &op_stack, &adv_stack, store, advice_map.into_iter());

test
(source, op_stack, adv_stack, store, advice_map)
}
2 changes: 1 addition & 1 deletion test-utils/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ pub use processor::{
};
pub use prover::{prove, MemAdviceProvider, ProvingOptions};
pub use test_case::test_case;
pub use verifier::{AcceptableOptions, ProgramInfo, VerifierError};
pub use verifier::{verify, AcceptableOptions, ProgramInfo, VerifierError};
pub use vm_core::{
stack::STACK_TOP_SIZE,
utils::{collections, group_slice_elements, group_vector_elements, IntoBytes, ToElements},
Expand Down

0 comments on commit f4e3545

Please sign in to comment.