use.miden::kernel_proc_offsets use.std::crypto::hashes::rpo use.std::mem # ERRORS # ================================================================================================= # Note data does not match the commitment const.ERR_NOTE_DATA_DOES_NOT_MATCH_COMMITMENT=0x0002004E # Number of note inputs exceeded the maximum limit of 128 const.ERR_PROLOGUE_NUMBER_OF_NOTE_INPUTS_EXCEEDED_LIMIT=0x0002004F #! Writes the data currently on the advice stack into the memory at the specified location and #! verifies that the hash of the written data is equal to the provided hash. #! #! Inputs: [start_ptr, end_ptr, HASH] #! Outputs: [] proc.write_advice_data_to_memory # prepare the stack for reading from the advice stack padw padw padw # => [PAD, PAD, PAD, start_ptr, end_ptr, HASH] # read the data from advice stack to memory exec.mem::pipe_double_words_to_memory # => [PERM, PERM, PERM, end_ptr, HASH] # extract the digest exec.rpo::squeeze_digest # => [DIGEST, end_ptr, HASH] # drop pointer for reading from memory movup.4 drop # => [DIGEST, HASH] # assert the computed hash is equal to the expected hash assert_eqw.err=ERR_NOTE_DATA_DOES_NOT_MATCH_COMMITMENT # => [] end #! Writes the assets of the currently executing note into memory starting at the specified address. #! #! Inputs: [dest_ptr] #! Outputs: [num_assets, dest_ptr] #! #! - dest_ptr is the memory address to write the assets. #! - num_assets is the number of assets in the currently executing note. export.get_assets # pad the stack padw padw padw push.0.0.0 # => [PAD(15), dest_ptr] exec.kernel_proc_offsets::get_note_assets_info_offset # => [offset, PAD(15), dest_ptr] syscall.exec_kernel_proc # => [ASSETS_HASH, num_assets, PAD(11), dest_ptr] # clean the stack swapdw dropw dropw movup.7 movup.7 movup.7 drop drop drop # => [ASSETS_HASH, num_assets, dest_ptr] # load the asset data from the advice map to the advice stack adv.push_mapval push.15887 drop # TODO: remove line, see miden-vm/#1122 # => [ASSETS_HASH, num_assets, dest_ptr] # calculate number of assets rounded up to an even number dup.4 dup is_odd add # => [even_num_assets, ASSETS_HASH, num_assets, dest_ptr] # calculate the start and end pointer for reading to memory dup.6 add dup.6 # => [start_ptr, end_ptr, ASSETS_HASH, num_assets, dest_ptr] # write the data from the advice stack into memory exec.write_advice_data_to_memory # => [num_assets, dest_ptr] end #! Loads the note's inputs to `dest_ptr`. #! #! Inputs: #! Stack: [dest_ptr] #! Advice Map: { INPUTS_HASH: [inputs_len, INPUTS] } #! Outputs: #! Stack: [num_inputs, dest_ptr] #! #! Where: #! - dest_ptr is the memory address to write the inputs. #! - INPUTS_HASH, sequential hash of the padded note's inputs. #! - inputs_len, the note's input count. #! - INPUTS, the data corresponding to the note's inputs. export.get_inputs # pad the stack padw padw padw push.0.0.0 # => [PAD(15), dest_ptr] exec.kernel_proc_offsets::get_note_inputs_hash_offset # => [offset, PAD(15), dest_ptr] syscall.exec_kernel_proc # => [INPUTS_HASH, PAD(12), dest_ptr] # clean the stack swapdw dropw dropw swapw dropw # => [INPUTS_HASH, dest_ptr] # load the inputs from the advice map to the advice stack adv.push_mapval push.15973 drop # TODO: remove line, see miden-vm/#1122 # => [INPUTS_HASH, dest_ptr] adv_push.1 # => [num_inputs, INPUTS_HASH, dest_ptr] # validate the input length dup exec.get_max_inputs_per_note lte assert.err=ERR_PROLOGUE_NUMBER_OF_NOTE_INPUTS_EXCEEDED_LIMIT # => [num_inputs, INPUTS_HASH, dest_ptr] # calculate the number of words required to store the inputs dup movdn.5 u32divmod.4 neq.0 add # => [num_words, INPUTS_HASH, num_inputs, dest_ptr] # round up the number of words the next multiple of 2 dup is_odd add # => [even_num_words, INPUTS_HASH, num_inputs, dest_ptr] # calculate the start and end pointer for reading to memory dup.6 add dup.6 # => [start_ptr, end_ptr, INPUTS_HASH, num_inputs, dest_ptr] # check the input data matches the commitment, and write it to memory. exec.write_advice_data_to_memory # => [num_inputs, dest_ptr] end #! Returns the sender of the note currently being processed. Panics if a note is not being #! processed. #! #! Inputs: [] #! Outputs: [sender] #! #! - sender is the sender of the note currently being processed. export.get_sender # pad the stack padw padw padw push.0.0.0 # => [PAD(15)] exec.kernel_proc_offsets::get_note_sender_offset # => [offset, PAD(15)] syscall.exec_kernel_proc # => [sender, PAD(15)] # clean the stack swapdw dropw dropw swapw dropw movdn.3 drop drop drop # => [sender] end #! Returns the serial number of the note currently being processed. #! Panics if no note is not being processed. #! #! Inputs: [] #! Outputs: [SERIAL_NUMBER] #! #! - SERIAL_NUMBER is the serial number of the note currently being processed. export.get_serial_number # pad the stack padw padw padw push.0.0.0 # => [PAD(15)] exec.kernel_proc_offsets::get_note_serial_number_offset # => [offset, PAD(15)] syscall.exec_kernel_proc # => [SERIAL_NUMBER, PAD(12)] # clean the stack swapdw dropw dropw swapw dropw # => [SERIAL_NUMBER] end #! Computes hash of note inputs starting at the specified memory address. #! #! This procedure checks that the provided number of inputs is within limits and then computes the #! hash using the procedure from the standard library. See the documentation of the #! `std::crypto::hashes::rpo::hash_memory` for the more detailed description. #! #! If the number if inputs is 0, procedure returns the empty word: [0, 0, 0, 0]. #! #! Inputs: [inputs_ptr, num_inputs] #! Outputs: [HASH] #! Cycles: #! - If number of elements divides by 8: 56 cycles + 3 * words #! - Else: 189 cycles + 3 * words #! #! Panics if num_inputs is greater than 128. export.compute_inputs_hash # check that number of inputs is less than 128 dup.1 push.128 u32assert2 u32lte assert # compute the hash exec.rpo::hash_memory # => [HASH] end # PROCEDURES COPIED FROM KERNEL (TODO: get rid of this duplication) # ================================================================================================= # The maximum number of input values associated with a single note. const.MAX_INPUTS_PER_NOTE=128 #! Returns the max allowed number of input values per note. #! #! Stack: [] #! Output: [max_inputs_per_note] #! #! - max_inputs_per_note is the max inputs per note. export.get_max_inputs_per_note push.MAX_INPUTS_PER_NOTE end