use miden::protocol::kernel_proc_offsets::TX_GET_BLOCK_NUMBER_OFFSET
use miden::protocol::kernel_proc_offsets::TX_GET_BLOCK_COMMITMENT_OFFSET
use miden::protocol::kernel_proc_offsets::TX_GET_BLOCK_TIMESTAMP_OFFSET
use miden::protocol::kernel_proc_offsets::TX_GET_INPUT_NOTES_COMMITMENT_OFFSET
use miden::protocol::kernel_proc_offsets::TX_GET_OUTPUT_NOTES_COMMITMENT_OFFSET
use miden::protocol::kernel_proc_offsets::TX_GET_NUM_INPUT_NOTES_OFFSET
use miden::protocol::kernel_proc_offsets::TX_GET_NUM_OUTPUT_NOTES_OFFSET
use miden::protocol::kernel_proc_offsets::TX_PREPARE_FPI_OFFSET
use miden::protocol::kernel_proc_offsets::TX_EXEC_FOREIGN_PROC_OFFSET
use miden::protocol::kernel_proc_offsets::TX_UPDATE_EXPIRATION_BLOCK_DELTA_OFFSET
use miden::protocol::kernel_proc_offsets::TX_GET_EXPIRATION_DELTA_OFFSET
#! Returns the block number of the transaction reference block.
#!
#! Inputs: []
#! Outputs: [num]
#!
#! Where:
#! - num is the transaction reference block number.
#!
#! Invocation: exec
pub proc get_block_number
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.TX_GET_BLOCK_NUMBER_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [num, pad(15)]
# clean the stack
swapdw dropw dropw swapw dropw movdn.3 drop drop drop
# => [num]
end
#! Returns the block commitment of the transaction reference block.
#!
#! Inputs: []
#! Outputs: [BLOCK_COMMITMENT]
#!
#! Where:
#! - BLOCK_COMMITMENT is the commitment to the reference block of the transaction.
#!
#! Invocation: exec
pub proc get_block_commitment
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.TX_GET_BLOCK_COMMITMENT_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [BLOCK_COMMITMENT, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [BLOCK_COMMITMENT]
end
#! Returns the timestamp of the reference block for this transaction.
#!
#! WARNING: the returned timestamp is not guaranteed to be precise (i.e., could be several seconds
#! off) or recent, unless recency is separately enforced by setting transaction expiration delta.
#!
#! Specifically, the reference blocks (and therefore the corresponding block timestamp) can be
#! chosen somewhat arbitrarily by the transaction executor. While this does not allow executors to
#! choose future timestamps, they can choose older timestamps for their benefit.
#!
#! For example, consider a script that includes a "time boundary", where before time 10 account X
#! can consume the note and after time 10 another account Y can consume the note. Even if the latest
#! block in the chain is at time 11, the owner of account X can choose to create a transaction
#! referencing the block at time 5 and still consume the note, while account Y would also be able
#! to consume the note when referencing the latest block. This is not necessarily a problem in all
#! cases, but must be taken into consideration by script developers.
#!
#! If the above is undesired, then one possible countermeasure is to set a transaction expiration
#! delta. For example, with a delta of 3, the oldest block account X could reference is the one at
#! time 8. This still allows for consumption by both accounts during a period of time, but shortens
#! that window.
#!
#! Inputs: []
#! Outputs: [timestamp]
#!
#! Where:
#! - timestamp is the timestamp of the reference block for this transaction. The underlying value is
#! of type u32, so u32 operations can be safely used on it.
pub proc get_block_timestamp
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.TX_GET_BLOCK_TIMESTAMP_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [timestamp, pad(15)]
# clean the stack
swapdw dropw dropw swapw dropw movdn.3 drop drop drop
# => [timestamp]
end
#! Returns the input notes commitment hash.
#!
#! See `transaction::api::get_input_notes_commitment` for details.
#!
#! Inputs: []
#! Outputs: [INPUT_NOTES_COMMITMENT]
#!
#! Where:
#! - INPUT_NOTES_COMMITMENT is the input notes commitment hash.
#!
#! Invocation: exec
pub proc get_input_notes_commitment
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.TX_GET_INPUT_NOTES_COMMITMENT_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [INPUT_NOTES_COMMITMENT, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [INPUT_NOTES_COMMITMENT]
end
#! Returns the output notes commitment. This is computed as a sequential hash of (note_id, note_metadata)
#! tuples over all output notes.
#!
#! Inputs: [0, 0, 0, 0]
#! Outputs: [OUTPUT_NOTES_COMMITMENT]
#!
#! Where:
#! - OUTPUT_NOTES_COMMITMENT is the output notes commitment.
#!
#! Invocation: exec
pub proc get_output_notes_commitment
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.TX_GET_OUTPUT_NOTES_COMMITMENT_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [OUTPUT_NOTES_COMMITMENT, pad(12)]
# clean the stack
swapdw dropw dropw swapw dropw
# => [OUTPUT_NOTES_COMMITMENT]
end
#! Returns the total number of input notes consumed by this transaction.
#!
#! Inputs: []
#! Outputs: [num_input_notes]
#!
#! Where:
#! - num_input_notes is the total number of input notes consumed by this transaction.
#!
#! Invocation: exec
pub proc get_num_input_notes
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.TX_GET_NUM_INPUT_NOTES_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [num_input_notes, pad(15)]
# clean the stack
swapdw dropw dropw swapw dropw movdn.3 drop drop drop
# => [num_input_notes]
end
#! Returns the current number of output notes created in this transaction.
#!
#! The number of output notes can changes during transaction execution. This will happen any time
#! as new output notes is created.
#!
#! Inputs: []
#! Outputs: [num_output_notes]
#!
#! Where:
#! - num_output_notes is the number of output notes created in this transaction so far.
#!
#! Invocation: exec
pub proc get_num_output_notes
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.TX_GET_NUM_OUTPUT_NOTES_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [num_output_notes, pad(15)]
# clean the stack
swapdw dropw dropw swapw dropw movdn.3 drop drop drop
# => [num_output_notes]
end
#! Executes the provided procedure against the foreign account.
#!
#! Inputs: [foreign_account_id_suffix, foreign_account_id_prefix, FOREIGN_PROC_ROOT, foreign_procedure_inputs(16)]
#! Outputs: [foreign_procedure_outputs(16)]
#!
#! Where:
#! - foreign_account_id_{suffix,prefix} are the suffix and prefix felts of the account ID of the
#! foreign account to execute the procedure on.
#! - foreign_procedure_inputs are the inputs to the foreign procedure padded to 16 felts.
#! - foreign_procedure_outputs are the outputs of the foreign procedure padded to 16 felts.
#!
#! Panics if:
#! - the provided foreign account ID is invalid.
#!
#! Invocation: exec
@locals(6) # foreign proc root (4) + foreign account ID (2)
pub proc execute_foreign_procedure
# store the foreign account ID and foreign procedure root to the local memory
# this will allow us to get the 16th element of the foreign procedure inputs to pass it to the
# `tx_prepare_fpi` kernel procedure
loc_store.4 loc_store.5 loc_storew_le.0 dropw
# OS => [foreign_procedure_inputs(16)]
# LM => [FOREIGN_PROC_ROOT, foreign_account_id_suffix, foreign_account_id_prefix]
# move up the last element of the foreign procedure inputs
movup.15
# => [foreign_proc_input_value_15, foreign_procedure_inputs(15)]
# load the foreign account ID and foreign procedure root back to the operand stack
padw loc_loadw_le.0 loc_load.5 loc_load.4
# => [foreign_account_id_suffix, foreign_account_id_prefix, FOREIGN_PROC_ROOT, foreign_proc_input_value_15, foreign_procedure_inputs(15)]
# get the tx_prepare_fpi procedure offset
push.TX_PREPARE_FPI_OFFSET
# => [offset, foreign_account_id_suffix, foreign_account_id_prefix, FOREIGN_PROC_ROOT, foreign_proc_input_value_15, foreign_procedure_inputs(15)]
# pad the stack before the syscall
padw padw swapdw
# => [offset, foreign_account_id_suffix, foreign_account_id_prefix, FOREIGN_PROC_ROOT,
# foreign_proc_input_value_15, pad(8), foreign_procedure_inputs(15)]
# store the foreign account ID, foreign procedure root, and the 16th (last) element of the
# foreign procedure inputs to the memory
syscall.exec_kernel_proc
# => [pad(16), foreign_procedure_inputs(15)]
# clean the stack
dropw dropw dropw dropw
# => [foreign_procedure_inputs(15)]
# perform the FPI call
push.TX_EXEC_FOREIGN_PROC_OFFSET syscall.exec_kernel_proc
# => [foreign_procedure_outputs(16)]
end
#! Updates the transaction expiration delta.
#!
#! The transaction expiration delta specifies how close to the transaction's reference block the
#! transaction must be included into the chain. For example, if the transaction's reference block is
#! 100 and transaction expiration delta is 10, the transaction can be included into the chain by
#! block 110. If this does not happen, the transaction is considered expired and cannot be included
#! into the chain.
#!
#! Once set, transaction expiration delta can be decreased, but not increased.
#!
#! Inputs: [block_height_delta, ...]
#! Output: [...]
#!
#! Where:
#! - block_height_delta is the desired expiration time delta (1 to 0xFFFF).
#!
#! Annotation hint: is not used anywhere
pub proc update_expiration_block_delta
push.TX_UPDATE_EXPIRATION_BLOCK_DELTA_OFFSET
# => [offset, expiration_delta, ...]
# pad the stack
push.0 movdn.2 push.0 movdn.2 padw swapw padw padw swapdw
# => [offset, expiration_delta, pad(14)]
syscall.exec_kernel_proc
# clear the stack
dropw dropw dropw dropw
end
#! Returns the transaction expiration delta, or 0 if the delta has not been set.
#!
#! Inputs: [...]
#! Output: [block_height_delta, ...]
#!
#! Where:
#! - block_height_delta is the stored expiration time delta (1 to 0xFFFF).
#!
#! Annotation hint: is not used anywhere
pub proc get_expiration_block_delta
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]
push.TX_GET_EXPIRATION_DELTA_OFFSET
# => [offset, pad(15)]
syscall.exec_kernel_proc
# => [expiration_delta, pad(15)]
# clear the stack
swapdw dropw dropw swapw dropw movdn.3 drop drop drop
# => [expiration_delta]
end