use tasm_lib::data_type::DataType;
use tasm_lib::field;
use tasm_lib::field_with_size;
use tasm_lib::prelude::Digest;
use tasm_lib::prelude::*;
use tasm_lib::traits::basic_snippet::BasicSnippet;
use tasm_lib::triton_vm::prelude::*;
use crate::proof_abstractions::tasm::program::TritonProgram;
use crate::transaction::validity::collect_lock_scripts::CollectLockScripts;
use crate::transaction::validity::proof_collection::ProofCollection;
use crate::transaction::validity::tasm::claims::new_claim::NewClaim;
pub(crate) struct GenerateCollectLockScriptsClaim;
impl BasicSnippet for GenerateCollectLockScriptsClaim {
fn parameters(&self) -> Vec<(DataType, String)> {
vec![(DataType::VoidPointer, "proof_collection_pointer".to_owned())]
}
fn return_values(&self) -> Vec<(DataType, String)> {
vec![(DataType::VoidPointer, "claim".to_owned())]
}
fn entrypoint(&self) -> String {
"tasm_neptune_transaction_proof_collection_generate_collect_lock_scripts_claim".to_owned()
}
fn code(&self, library: &mut Library) -> Vec<LabelledInstruction> {
let entrypoint = self.entrypoint();
let push_collect_lock_scripts_hash = {
let Digest([d0, d1, d2, d3, d4]) = CollectLockScripts.program().hash();
triton_asm!(push {d4} push {d3} push {d2} push {d1} push {d0})
};
let new_claim = library.import(Box::new(NewClaim));
let lock_script_hashes_loop = format!("{entrypoint}_lock_script_hashes_loop");
triton_asm!(
{entrypoint}:
dup 0
{&field_with_size!(ProofCollection::lock_script_hashes)}
dup 1
dup 1
add
addi {Digest::LEN - 1}
pick 2
read_mem 1
addi {1 + Digest::LEN}
pick 1
push {Digest::LEN}
mul
addi 1
dup 3
eq
assert
pick 2
addi -1
hint output_len = stack[0]
push {Digest::LEN}
place 1
call {new_claim}
{&push_collect_lock_scripts_hash}
hint collect_lock_scripts_hash: Digest = stack[0..5]
pick 5
write_mem {Digest::LEN}
pop 1
pick 5
{&field!(ProofCollection::salted_inputs_hash)}
addi {Digest::LEN - 1}
read_mem {Digest::LEN}
hint salted_inputs_hash: Digest = stack[1..6]
pop 1
pick 1 pick 2 pick 3 pick 4
pick 5
write_mem {Digest::LEN}
pop 1
pick 1
place 3
call {lock_script_hashes_loop}
pop 3
return
{lock_script_hashes_loop}:
dup 2
dup 2
eq
skiz
return
pick 1
read_mem {Digest::LEN}
addi {Digest::LEN * 2}
place 6
pick 5
write_mem {Digest::LEN}
recurse
)
}
}
#[cfg(test)]
#[cfg_attr(coverage_nightly, coverage(off))]
mod tests {
use std::collections::HashMap;
use neptune_primitives::network::Network;
use proptest::prelude::Strategy;
use proptest::test_runner::TestRunner;
use rand::rngs::StdRng;
use rand::Rng;
use rand::RngCore;
use rand::SeedableRng;
use tasm_lib::memory::encode_to_memory;
use tasm_lib::rust_shadowing_helper_functions;
use tasm_lib::snippet_bencher::BenchmarkCase;
use tasm_lib::traits::function::Function;
use tasm_lib::traits::function::FunctionInitialState;
use tasm_lib::traits::function::ShadowedFunction;
use tasm_lib::traits::rust_shadow::RustShadow;
use tasm_lib::traits::rust_shadow::RustShadowError;
use super::*;
use crate::proof_abstractions::tasm::program::TritonVmProofJobOptions;
use crate::proof_abstractions::triton_vm_job_queue::TritonVmJobQueue;
use crate::transaction::primitive_witness::PrimitiveWitness;
#[test]
fn unit_test() {
ShadowedFunction::new(GenerateCollectLockScriptsClaim).test();
}
impl Function for GenerateCollectLockScriptsClaim {
fn rust_shadow(
&self,
stack: &mut Vec<BFieldElement>,
memory: &mut HashMap<BFieldElement, BFieldElement>,
) -> Result<(), RustShadowError> {
let proof_collection_pointer = stack.pop().unwrap();
let proof_collection =
*ProofCollection::decode_from_memory(memory, proof_collection_pointer).unwrap();
let claim = proof_collection.collect_lock_scripts_claim();
let claim_pointer =
rust_shadowing_helper_functions::dyn_malloc::dynamic_allocator(memory);
encode_to_memory(memory, claim_pointer, &claim);
stack.push(claim_pointer);
Ok(())
}
fn pseudorandom_initial_state(
&self,
seed: [u8; 32],
_bench_case: Option<BenchmarkCase>,
) -> FunctionInitialState {
let mut rng: StdRng = SeedableRng::from_seed(seed);
let mut test_runner = TestRunner::deterministic();
let num_inputs = rng.random_range(0usize..4);
let primitive_witness =
PrimitiveWitness::arbitrary_with_size_numbers(Some(num_inputs), 2, 2)
.new_tree(&mut test_runner)
.unwrap()
.current();
let rt = crate::proof_abstractions::test_runtime::tokio_runtime();
let _guard = rt.enter();
let proof_collection = rt
.block_on(ProofCollection::produce(
&primitive_witness,
TritonVmJobQueue::get_instance(),
TritonVmProofJobOptions::default_with_network(Network::Main),
))
.unwrap();
let pw_pointer = rng.next_u32() >> 1;
let pw_pointer = bfe!(pw_pointer);
let mut memory = HashMap::default();
encode_to_memory(&mut memory, pw_pointer, &proof_collection);
FunctionInitialState {
stack: [self.init_stack_for_isolated_run(), vec![pw_pointer]].concat(),
memory,
}
}
}
}