miden-protocol 0.14.5

Core components of the Miden protocol
Documentation
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