use triton_vm::prelude::*;
use crate::prelude::*;
use crate::verifier::stark_verify::NUM_PROOF_ITEMS_EXCLUDING_FRI;
use crate::verifier::stark_verify::NUM_PROOF_ITEMS_PER_FRI_ROUND;
use crate::verifier::vm_proof_iter::shared::vm_proof_iter_type;
#[derive(Debug, Copy, Clone, Eq, PartialEq, Hash)]
pub struct New;
impl New {
pub const FIRST_PROOF_ITEM_OFFSET: u64 = 4;
pub const MAX_PROOF_SIZE: usize = 1 << 26;
const MAX_NUMBER_OF_FRI_ROUNDS: usize = 24;
const SAFETY_MARGIN_PER_FRI_ROUND: usize = 1;
pub const MAX_NUM_PROOF_ITEMS: usize = Self::MAX_NUMBER_OF_FRI_ROUNDS
* (NUM_PROOF_ITEMS_PER_FRI_ROUND + Self::SAFETY_MARGIN_PER_FRI_ROUND)
+ NUM_PROOF_ITEMS_EXCLUDING_FRI;
}
impl BasicSnippet for New {
fn parameters(&self) -> Vec<(DataType, String)> {
vec![(DataType::VoidPointer, "*proof".to_string())]
}
fn return_values(&self) -> Vec<(DataType, String)> {
vec![(
DataType::StructRef(vm_proof_iter_type()),
"vm_proof_iter".to_owned(),
)]
}
fn entrypoint(&self) -> String {
"tasmlib_verifier_vm_proof_iter_new".to_owned()
}
fn code(&self, library: &mut Library) -> Vec<LabelledInstruction> {
let entrypoint = self.entrypoint();
let dyn_malloc = library.import(Box::new(DynMalloc));
triton_asm!(
{entrypoint}:
addi {Self::FIRST_PROOF_ITEM_OFFSET}
dup 0
addi -1
read_mem {Self::FIRST_PROOF_ITEM_OFFSET}
addi 1
push 0
place 5
hint first_proof_item: u32 = stack[6]
hint current_proof_item: u32 = stack[5]
hint num_proof_items: u32 = stack[4]
hint proof_len: u32 = stack[1]
place 3
place 2
addi 1
dup 2
eq
assert error_id 300
addi 2
dup 1
eq
assert error_id 301
push {Self::MAX_PROOF_SIZE}
dup 1
lt
assert error_id 302
push {Self::MAX_NUM_PROOF_ITEMS}
dup 3
lt
assert error_id 303
dup 1
pop_count
pop 1
dup 0
pop_count
pop 1
dup 1
dup 1
add
pop_count
pop 1
pick 4
call {dyn_malloc}
write_mem 5
addi -5
return
)
}
}
#[cfg(test)]
mod tests {
use arbitrary::Arbitrary;
use arbitrary::Unstructured;
use triton_vm::proof_item::ProofItem;
use triton_vm::proof_stream::ProofStream;
use super::*;
use crate::rust_shadowing_helper_functions;
use crate::test_prelude::*;
use crate::verifier::vm_proof_iter::shared::vm_proof_iter_struct::VmProofIter;
#[test]
fn vm_proof_iter_new_pbt() {
ShadowedFunction::new(New).test()
}
impl New {
fn init_state(
&self,
proof_items: Vec<ProofItem>,
proof_pointer: BFieldElement,
) -> FunctionInitialState {
let mut proof_stream = ProofStream::default();
for proof_item in proof_items {
proof_stream.enqueue(proof_item);
}
let proof: Proof = proof_stream.into();
let mut memory = HashMap::default();
encode_to_memory(&mut memory, proof_pointer, &proof);
FunctionInitialState {
stack: [self.init_stack_for_isolated_run(), vec![proof_pointer]].concat(),
memory,
}
}
}
impl Function for New {
fn rust_shadow(
&self,
stack: &mut Vec<BFieldElement>,
memory: &mut HashMap<BFieldElement, BFieldElement>,
) {
let pointer_to_proof = stack.pop().unwrap();
let proof = *Proof::decode_from_memory(memory, pointer_to_proof).unwrap();
let pointer_to_vm_proof_iter =
rust_shadowing_helper_functions::dyn_malloc::dynamic_allocator(memory);
let vm_proof_iter = VmProofIter::new(pointer_to_proof, &proof);
encode_to_memory(memory, pointer_to_vm_proof_iter, &vm_proof_iter);
stack.push(pointer_to_vm_proof_iter);
}
fn pseudorandom_initial_state(
&self,
seed: [u8; 32],
_bench_case: Option<BenchmarkCase>,
) -> FunctionInitialState {
let mut rng = StdRng::from_seed(seed);
let proof_pointer = bfe!(rng.random_range(0..(1 << 20)));
let mut randomness = vec![0; 1_000_000];
rng.fill_bytes(&mut randomness);
let mut unstructured = Unstructured::new(&randomness);
let proof_items = (0..rng.random_range(10..25))
.map(|_| ProofItem::arbitrary(&mut unstructured).unwrap())
.collect();
self.init_state(proof_items, proof_pointer)
}
}
}