use tasm_lib::data_type::DataType;
use tasm_lib::prelude::BasicSnippet;
use tasm_lib::prelude::Library;
use tasm_lib::triton_vm::prelude::*;
use crate::transaction::validity::tasm::claims::new_claim::NewClaim;
#[derive(Debug, Copy, Clone)]
pub(crate) struct GenerateSingleProofClaim;
impl BasicSnippet for GenerateSingleProofClaim {
fn parameters(&self) -> Vec<(DataType, String)> {
let txk_mast_hash = (DataType::Digest, "txk_mast_hash".to_string());
let program_digest = (DataType::Digest, "single_proof_program_digest".to_string());
vec![txk_mast_hash, program_digest]
}
fn return_values(&self) -> Vec<(DataType, String)> {
vec![(DataType::VoidPointer, "single_proof_claim".to_string())]
}
fn entrypoint(&self) -> String {
"neptune_transaction_generate_single_proof_claim".to_string()
}
fn code(&self, library: &mut Library) -> Vec<LabelledInstruction> {
let new_claim = library.import(Box::new(NewClaim));
let single_proof_digest_alloc = library.kmalloc(u32::try_from(Digest::LEN).unwrap());
triton_asm!(
{self.entrypoint()}:
push {single_proof_digest_alloc.write_address()}
write_mem {Digest::LEN} pop 1
push {Digest::LEN} push 0 call {new_claim}
push {single_proof_digest_alloc.read_address()}
read_mem {Digest::LEN} swap 6 write_mem {Digest::LEN} pop 2
dup 3
dup 5
dup 7
dup 9
dup 11 dup 5
write_mem {Digest::LEN}
pop 3
swap 5
pop 5 return
)
}
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use std::collections::HashMap;
use rand::prelude::StdRng;
use rand::Rng;
use tasm_lib::memory::encode_to_memory;
use tasm_lib::rust_shadowing_helper_functions;
use tasm_lib::snippet_bencher::BenchmarkCase;
use tasm_lib::traits::algorithm::Algorithm;
use tasm_lib::traits::algorithm::AlgorithmInitialState;
use tasm_lib::traits::algorithm::ShadowedAlgorithm;
use tasm_lib::traits::rust_shadow::RustShadow;
use tasm_lib::traits::rust_shadow::RustShadowError;
use tasm_lib::triton_vm::proof::Claim;
use super::*;
use crate::prelude::triton_vm::prelude::BFieldElement;
use crate::prelude::triton_vm::prelude::NonDeterminism;
impl Algorithm for GenerateSingleProofClaim {
fn rust_shadow(
&self,
stack: &mut Vec<BFieldElement>,
memory: &mut HashMap<BFieldElement, BFieldElement>,
_: &NonDeterminism,
) -> Result<(), RustShadowError> {
fn pop_digest(stack: &mut Vec<BFieldElement>) -> Digest {
Digest::new([
stack.pop().unwrap(),
stack.pop().unwrap(),
stack.pop().unwrap(),
stack.pop().unwrap(),
stack.pop().unwrap(),
])
}
let single_proof_digest_location_isolated_run =
tasm_lib::library::STATIC_MEMORY_FIRST_ADDRESS
- bfe!(u32::try_from(Digest::LEN).unwrap())
+ bfe!(1);
let single_proof_digest = pop_digest(stack);
let mast_hash = pop_digest(stack);
let claim =
Claim::new(single_proof_digest).with_input(mast_hash.reversed().values().to_vec());
let claim_pointer =
rust_shadowing_helper_functions::dyn_malloc::dynamic_allocator(memory);
encode_to_memory(memory, claim_pointer, &claim);
stack.push(claim_pointer);
encode_to_memory(
memory,
single_proof_digest_location_isolated_run,
&single_proof_digest,
);
Ok(())
}
fn pseudorandom_initial_state(
&self,
seed: [u8; 32],
_: Option<BenchmarkCase>,
) -> AlgorithmInitialState {
let mut rng: StdRng = rand::prelude::SeedableRng::from_seed(seed);
let mast_hash = rng.random::<Digest>();
let single_proof_digest = rng.random::<Digest>();
let mut stack = self.init_stack_for_isolated_run();
stack.extend(mast_hash.reversed().values());
stack.extend(single_proof_digest.reversed().values());
AlgorithmInitialState {
stack,
..Default::default()
}
}
}
#[test]
fn rust_and_tasm_agree() {
ShadowedAlgorithm::new(GenerateSingleProofClaim).test()
}
}