miden-protocol 0.14.5

Core components of the Miden protocol
Documentation
# ERRORS
# =================================================================================================

const ERR_ACCOUNT_ID_UNKNOWN_VERSION="unknown version in account ID"

const ERR_ACCOUNT_ID_SUFFIX_MOST_SIGNIFICANT_BIT_MUST_BE_ZERO="most significant bit of the account ID suffix must be zero"

const ERR_ACCOUNT_ID_UNKNOWN_STORAGE_MODE="unknown account storage mode in account ID"

const ERR_ACCOUNT_ID_SUFFIX_LEAST_SIGNIFICANT_BYTE_MUST_BE_ZERO="least significant byte of the account ID suffix must be zero"

const ERR_ACCOUNT_ID_NON_PUBLIC_NETWORK_ACCOUNT="the account ID must have storage mode public if the network flag is set"

# CONSTANTS
# =================================================================================================

# Bit pattern for a faucet account, after the account type mask has been applied.
const FAUCET_ACCOUNT=0x20 # 0b10_0000

# Bit pattern for an account w/ updatable code, after the account type mask has been applied.
const REGULAR_ACCOUNT_UPDATABLE_CODE=0x10 # 0b01_0000

# Bit pattern for an account w/ immutable code, after the account type mask has been applied.
const REGULAR_ACCOUNT_IMMUTABLE_CODE=0 # 0b00_0000

# Bit pattern for a fungible faucet w/ immutable code, after the account type mask has been applied.
const FUNGIBLE_FAUCET_ACCOUNT=0x20 # 0b10_0000

# Bit pattern for a non-fungible faucet w/ immutable code, after the account type mask has been
# applied.
const NON_FUNGIBLE_FAUCET_ACCOUNT=0x30 # 0b11_0000

# Given the least significant 32 bits of an account id's prefix, this mask defines the bits used
# to determine the account type.
const ACCOUNT_ID_TYPE_MASK_U32=0x30 # 0b11_0000

# Given the least significant 32 bits of an account id's prefix, this mask defines the bits used
# to determine the account version.
const ACCOUNT_VERSION_MASK_U32=0x0f # 0b1111

# Given the least significant 32 bits of an account ID's prefix, this mask defines the bits used
# to determine the account storage mode.
const ACCOUNT_ID_STORAGE_MODE_MASK_U32=0xC0 # 0b1100_0000

# Given the least significant 32 bits of an account ID's first felt with the storage mode mask
# applied, this value defines the non-existent, invalid storage mode.
const ACCOUNT_ID_STORAGE_MODE_INVALID_U32=0xc0 # 0b1100_0000

# PROCEDURES
# =================================================================================================

#! Returns a boolean indicating whether the account is a fungible faucet.
#!
#! Inputs:  [account_id_prefix]
#! Outputs: [is_fungible_faucet]
#!
#! Where:
#! - account_id_prefix is the prefix of the account ID.
#! - is_fungible_faucet is a boolean indicating whether the account is a fungible faucet.
pub proc is_fungible_faucet
    exec.id_type eq.FUNGIBLE_FAUCET_ACCOUNT
    # => [is_fungible_faucet]
end

#! Returns a boolean indicating whether the account is a non-fungible faucet.
#!
#! Inputs:  [account_id_prefix]
#! Outputs: [is_non_fungible_faucet]
#!
#! Where:
#! - account_id_prefix is the prefix of the account ID.
#! - is_non_fungible_faucet is a boolean indicating whether the account is a non-fungible faucet.
pub proc is_non_fungible_faucet
    exec.id_type eq.NON_FUNGIBLE_FAUCET_ACCOUNT
    # => [is_non_fungible_faucet]
end

#! Returns a boolean indicating whether the given account_ids are equal.
#!
#! Inputs:  [account_id_suffix, account_id_prefix, other_account_id_suffix, other_account_id_prefix]
#! Outputs: [is_id_equal]
#!
#! Where:
#! - account_id_{suffix,prefix} are the suffix and prefix felts of an account ID.
#! - other_account_id_{suffix,prefix} are the suffix and prefix felts of the other account ID to
#!   compare against.
#! - is_id_equal is a boolean indicating whether the account IDs are equal.
pub proc is_equal
    movup.2 eq
    # => [is_suffix_equal, account_id_prefix, other_account_id_prefix]
    movdn.2 eq
    # => [is_prefix_equal, is_suffix_equal]
    and
    # => [is_id_equal]
end

#! Returns a boolean indicating whether the account is a faucet.
#!
#! Inputs:  [account_id_prefix]
#! Outputs: [is_faucet]
#!
#! Where:
#! - account_id_prefix is the prefix of the account ID.
#! - is_faucet is a boolean indicating whether the account is a faucet.
pub proc is_faucet
    u32split swap drop u32and.FAUCET_ACCOUNT neq.0
    # => [is_faucet]
end

#! Returns a boolean indicating whether the account is a regular updatable account.
#!
#! Inputs:  [account_id_prefix]
#! Outputs: [is_updatable_account]
#!
#! Where:
#! - account_id_prefix is the prefix of the account ID.
#! - is_updatable_account is a boolean indicating whether the account is a regular updatable
#!   account.
pub proc is_updatable_account
    exec.id_type eq.REGULAR_ACCOUNT_UPDATABLE_CODE
    # => [is_updatable_account]
end

#! Returns a boolean indicating whether the account is a regular immutable account.
#!
#! Inputs:  [account_id_prefix]
#! Outputs: [is_immutable_account]
#!
#! Where:
#! - account_id_prefix is the prefix of the account ID.
#! - is_immutable_account is a boolean indicating whether the account is a regular immutable
#!   account.
pub proc is_immutable_account
    exec.id_type eq.REGULAR_ACCOUNT_IMMUTABLE_CODE
    # => [is_immutable_account]
end

#! Validates an account ID. Note that this does not validate anything about the account type,
#! since any 2-bit pattern is a valid account type.
#!
#! Inputs:  [account_id_suffix, account_id_prefix]
#! Outputs: []
#!
#! Where:
#! - account_id_{suffix,prefix} are the suffix and prefix felts of the account ID.
#!
#! Panics if:
#! - account_id_prefix does not contain version zero.
#! - account_id_prefix does not contain either the public, network or private storage mode.
#! - account_id_suffix does not have its most significant bit set to zero.
#! - account_id_suffix does not have its lower 8 bits set to zero.
pub proc validate
    # Validate lower 8 bits of suffix are zero.
    # ---------------------------------------------------------------------------------------------

    u32split
    # => [account_id_suffix_lo, account_id_suffix_hi, account_id_prefix]
    u32and.0xff eq.0
    # => [is_least_significant_byte_zero, account_id_suffix_hi, account_id_prefix]
    assert.err=ERR_ACCOUNT_ID_SUFFIX_LEAST_SIGNIFICANT_BYTE_MUST_BE_ZERO
    # => [account_id_suffix_hi, account_id_prefix]

    # Validate most significant bit in suffix is zero.
    # ---------------------------------------------------------------------------------------------

    u32shr.31 eq.0
    # => [is_most_significant_bit_zero, account_id_prefix]
    assert.err=ERR_ACCOUNT_ID_SUFFIX_MOST_SIGNIFICANT_BIT_MUST_BE_ZERO
    # => [account_id_prefix]

    # Validate version in prefix. For now only version 0 is supported.
    # ---------------------------------------------------------------------------------------------

    dup exec.id_version
    # => [id_version, account_id_prefix]
    assertz.err=ERR_ACCOUNT_ID_UNKNOWN_VERSION
    # => [account_id_prefix]

    # Validate storage mode in prefix.
    # ---------------------------------------------------------------------------------------------

    # there are 3 valid and 1 invalid storage mode
    # instead of checking the presence of any of the valid modes, we check the absence of the
    # invalid mode
    u32split swap drop
    # => [account_id_prefix_lo]
    u32and.ACCOUNT_ID_STORAGE_MODE_MASK_U32
    # => [id_storage_mode_masked]
    eq.ACCOUNT_ID_STORAGE_MODE_INVALID_U32
    # => [is_storage_mode_invalid]
    assertz.err=ERR_ACCOUNT_ID_UNKNOWN_STORAGE_MODE
    # => []
end

#! Shapes the suffix so it meets the requirements of the account ID, by setting the lower 8 bits to
#! zero.
#!
#! Inputs:  [seed_digest_suffix]
#! Outputs: [account_id_suffix]
#!
#! Where:
#! - seed_digest_suffix is the suffix of the digest that should be shaped into the suffix
#!   of an account ID.
#! - account_id_suffix is the suffix of an account ID.
pub proc shape_suffix
    u32split
    # => [seed_digest_suffix_lo, seed_digest_suffix_hi]

    # clear lower 8 bits of the lo part
    u32and.0xffffff00 swap
    # => [seed_digest_suffix_hi, seed_digest_suffix_lo']

    # reassemble the suffix by multiplying the hi part with 2^32 and adding the lo part
    mul.0x0100000000 add
    # => [account_id_suffix]
end

# HELPER PROCEDURES
# =================================================================================================

#! Extracts the account ID version from the prefix of an account ID.
#!
#! Inputs:  [account_id_prefix]
#! Outputs: [id_version]
#!
#! Where:
#! - account_id_prefix is the prefix of an account ID.
#! - id_version is the version number of the ID.
proc id_version
    # extract the lower 32 bits
    u32split swap drop
    # => [account_id_prefix_lo]

    # mask out the version
    u32and.ACCOUNT_VERSION_MASK_U32
    # => [id_version]
end

#! Returns the least significant half of an account ID prefix with the account type bits masked out.
#!
#! The account type can be obtained by comparing this value with the following constants:
#! - REGULAR_ACCOUNT_UPDATABLE_CODE
#! - REGULAR_ACCOUNT_IMMUTABLE_CODE
#! - FUNGIBLE_FAUCET_ACCOUNT
#! - NON_FUNGIBLE_FAUCET_ACCOUNT
#!
#! Inputs:  [account_id_prefix]
#! Outputs: [account_type]
#!
#! Where:
#! - account_id_prefix is the prefix of the account ID.
#! - account_type is the account type.
proc id_type
    u32split swap drop u32and.ACCOUNT_ID_TYPE_MASK_U32
    # => [account_type]
end