Skip to content

Commit

Permalink
feat: Add generic snippet for new claim
Browse files Browse the repository at this point in the history
  • Loading branch information
aszepieniec committed Sep 30, 2024
1 parent f6c0867 commit 08dfcbc
Show file tree
Hide file tree
Showing 2 changed files with 161 additions and 0 deletions.
1 change: 1 addition & 0 deletions src/models/blockchain/transaction/validity/tasm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ pub(crate) mod coinbase_amount;
pub mod compute_indices;
mod hash_removal_record_indices;
mod hash_utxo;
pub mod new_claim;
pub mod proof_collection;
pub mod removal_records_integrity;
pub mod transaction_kernel_mast_hash;
160 changes: 160 additions & 0 deletions src/models/blockchain/transaction/validity/tasm/new_claim.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,160 @@
use tasm_lib::{
data_type::DataType,
prelude::{BasicSnippet, DynMalloc, Library},
triton_vm::{prelude::LabelledInstruction, triton_asm},
};

/// Generates a new Claim object given the lengths of the input and output.
/// Returns pointers to:
/// - the claim
/// - the output
/// - the input
/// - the program digest.
pub struct NewClaim;

impl BasicSnippet for NewClaim {
fn inputs(&self) -> Vec<(DataType, String)> {
vec![
(DataType::U32, "input_length".to_string()),
(DataType::U32, "output_length".to_string()),
]
}

fn outputs(&self) -> Vec<(DataType, String)> {
vec![
(DataType::VoidPointer, "*claim".to_string()),
(DataType::VoidPointer, "*output".to_string()),
(DataType::VoidPointer, "*input".to_string()),
(DataType::VoidPointer, "*program_digest".to_string()),
]
}

fn entrypoint(&self) -> String {
"neptune_transaction_new_claim".to_string()
}

fn code(&self, library: &mut Library) -> Vec<LabelledInstruction> {
let entrypoint = self.entrypoint();

let dyn_malloc = library.import(Box::new(DynMalloc));

triton_asm! {
// BEFORE: _ input_length output_length
// AFTER: _ *claim *output *input *program_digest
{entrypoint}:

call {dyn_malloc}
// _ input_length output_length *claim

swap 2
// _ *claim output_length input_length

dup 1 dup 2 push 1 add
// _ *claim output_length input_length output_length output_size

dup 4
// _ *claim output_length input_length output_length output_size *output_si

write_mem 2
// _ *claim output_length input_length *output

dup 0 swap 3
// _ *claim *output input_length *output output_length

add
// _ *claim *output input_length *input_si

dup 1 dup 2 push 1 add
// _ *claim *output input_length *input_si input_length input_size

dup 2 write_mem 2
// _ *claim *output input_length *input_si *input

swap 1 pop 1
// _ *claim *output input_length *input

dup 0 swap 2 add
// _ *claim *output *input *program_digest

return
}
}
}

#[cfg(test)]
mod test {
use std::collections::HashMap;

use num_traits::ConstZero;
use rand::{rngs::StdRng, Rng, SeedableRng};
use tasm_lib::{
empty_stack,
memory::encode_to_memory,
rust_shadowing_helper_functions,
snippet_bencher::BenchmarkCase,
traits::{
function::{Function, FunctionInitialState, ShadowedFunction},
rust_shadow::RustShadow,
},
triton_vm::{prelude::BFieldElement, proof::Claim},
twenty_first::bfe,
};

use super::NewClaim;

impl Function for NewClaim {
fn rust_shadow(
&self,
stack: &mut Vec<BFieldElement>,
memory: &mut HashMap<BFieldElement, BFieldElement>,
) {
let output_length = stack.pop().unwrap().value() as usize;
let input_length = stack.pop().unwrap().value() as usize;

let claim_pointer =
rust_shadowing_helper_functions::dyn_malloc::dynamic_allocator(memory);

let claim = Claim {
program_digest: Default::default(),
input: vec![BFieldElement::ZERO; input_length],
output: vec![BFieldElement::ZERO; output_length],
};

encode_to_memory(memory, claim_pointer, &claim);

let output_pointer = claim_pointer;
let input_pointer = claim_pointer + bfe!(2) + bfe!(output_length as u64);
let program_digest_pointer = input_pointer + bfe!(2) + bfe!(input_length as u64);

stack.push(claim_pointer);
stack.push(output_pointer);
stack.push(input_pointer);
stack.push(program_digest_pointer);
}

fn pseudorandom_initial_state(
&self,
seed: [u8; 32],
bench_case: Option<BenchmarkCase>,
) -> FunctionInitialState {
let mut rng: StdRng = SeedableRng::from_seed(seed);

let input_length = rng.gen_range(0..10);
let output_length = rng.gen_range(0..10);

FunctionInitialState {
stack: [
empty_stack(),
[bfe!(input_length as u64), bfe!(output_length as u64)].to_vec(),
]
.concat(),
memory: HashMap::new(),
}
}
}

#[test]
fn unit_test() {
ShadowedFunction::new(NewClaim).test()
}
}

0 comments on commit 08dfcbc

Please sign in to comment.