diff --git a/miden-lib/asm/kernels/transaction/api.masm b/miden-lib/asm/kernels/transaction/api.masm index e76f347c4..b4aa5e1be 100644 --- a/miden-lib/asm/kernels/transaction/api.masm +++ b/miden-lib/asm/kernels/transaction/api.masm @@ -5,6 +5,15 @@ use.miden::kernels::tx::memory use.miden::kernels::tx::note use.miden::kernels::tx::tx +# ERRORS +# ================================================================================================= + +# For faucets the slot FAUCET_STORAGE_DATA_SLOT is reserved and can not be used with set_account_item +const.ERR_FAUCET_RESERVED_DATA_SLOT=0x00020000 + +# Procedure can only be called for faucet accounts +const.ERR_ACCT_MUST_BE_A_FAUCET=0x00020001 + # EVENTS # ================================================================================================= @@ -153,7 +162,7 @@ export.set_account_item # index != FAUCET_STORAGE_DATA_SLOT (reserved slot) dup exec.account::get_faucet_storage_data_slot eq exec.account::get_id exec.account::is_faucet - and assertz + and assertz.err=ERR_FAUCET_RESERVED_DATA_SLOT # => [index, V', 0, 0, 0] # authenticate that the procedure invocation originates from the account context @@ -508,7 +517,7 @@ end #! against. export.get_fungible_faucet_total_issuance # assert that we are executing a transaction against a fungible faucet (access checks) - exec.account::get_id exec.account::is_fungible_faucet assert + exec.account::get_id exec.account::is_fungible_faucet assert.err=ERR_ACCT_MUST_BE_A_FAUCET # => [0] # get the total issuance diff --git a/miden-lib/asm/miden/asset.masm b/miden-lib/asm/miden/asset.masm index 3fb8de02a..b61fc7ac8 100644 --- a/miden-lib/asm/miden/asset.masm +++ b/miden-lib/asm/miden/asset.masm @@ -2,6 +2,18 @@ use.miden::kernels::tx::account->internal_account use.miden::kernels::tx::asset use.miden::account +# ERRORS +# ================================================================================================= + +# Can not build the fungible asset because provided id is not a fungible id +const.ERR_ASSET_NOT_FUNGIBLE_ID=0x00020041 + +# Can not build the asset because amount exceeds the maximum +const.ERR_ASSET_INVALID_AMOUNT=0x00020042 + +# Can not build the non-fungible asset because provided id is not a non-fungible id +const.ERR_ASSET_NOT_NON_FUNGIBLE_ID=0x00020043 + # CONSTANTS # ================================================================================================= @@ -21,11 +33,11 @@ const.TWO_POW_32=4294967296 #! - ASSET is the built fungible asset. export.build_fungible_asset # assert the faucet is a fungible faucet - dup exec.internal_account::is_fungible_faucet assert + dup exec.internal_account::is_fungible_faucet assert.err=ERR_ASSET_NOT_FUNGIBLE_ID # => [faucet_id, amount] # assert the amount is valid - dup.1 exec.asset::get_fungible_asset_max_amount lte assert + dup.1 exec.asset::get_fungible_asset_max_amount lte assert.err=ERR_ASSET_INVALID_AMOUNT # => [faucet_id, amount] # create the asset @@ -60,7 +72,7 @@ end #! - ASSET is the built non-fungible asset. export.build_non_fungible_asset # assert the faucet is a non-fungible faucet - dup exec.internal_account::is_non_fungible_faucet assert + dup exec.internal_account::is_non_fungible_faucet assert.err=ERR_ASSET_NOT_NON_FUNGIBLE_ID # => [faucet_id, DATA_HASH] # build the asset diff --git a/miden-lib/asm/miden/contracts/faucets/basic_fungible.masm b/miden-lib/asm/miden/contracts/faucets/basic_fungible.masm index 25ad4b165..31d2d1f3f 100644 --- a/miden-lib/asm/miden/contracts/faucets/basic_fungible.masm +++ b/miden-lib/asm/miden/contracts/faucets/basic_fungible.masm @@ -13,6 +13,12 @@ use.miden::faucet use.miden::tx use.miden::contracts::auth::basic +# ERRORS +# ================================================================================================= + +# Distribute would cause the max supply to be exceeded +const.ERR_BASIC_FUNGIBLE_MAX_SUPPLY_OVERFLOW=0x00020021 + # CONSTANTS # ================================================================================================= @@ -51,7 +57,7 @@ export.distribute # => [max_supply - total_issuance, amount, tag, RECIPIENT, ...] # check that amount =< max_supply - total_issuance, fails if otherwise - dup.1 gte assert + dup.1 gte assert.err=ERR_BASIC_FUNGIBLE_MAX_SUPPLY_OVERFLOW # => [asset, tag, RECIPIENT, ...] # creating the asset diff --git a/miden-lib/asm/miden/kernels/tx/account.masm b/miden-lib/asm/miden/kernels/tx/account.masm index 63c97f946..b88fe8a4b 100644 --- a/miden-lib/asm/miden/kernels/tx/account.masm +++ b/miden-lib/asm/miden/kernels/tx/account.masm @@ -1,6 +1,24 @@ use.miden::kernels::tx::constants use.miden::kernels::tx::memory +# ERRORS +# ================================================================================================= + +# The nonce increase must be a u32 +const.ERR_ACCOUNT_NONCE_INCR_MUST_BE_U32=0x0002003B + +# Account id format is invalid, insufficient ones +const.ERR_ACCOUNT_INSUFFICIENT_ONES=0x0002003C + +# Account must be updatable for it to be possible to update its code +const.ERR_ACCOUNT_SET_CODE_ACCOUNT_MUST_BE_UPDATABLE=0x0002003D + +# Account seed digest mismatch +const.ERR_ACCOUNT_SEED_DIGEST_MISMATCH=0x0002003E + +# Account pow is insufficient +const.ERR_ACCOUNT_INVALID_POW=0x0002003F + # CONSTANTS # ================================================================================================= @@ -120,7 +138,7 @@ export.incr_nonce # emit event to signal that account nonce is being incremented emit.ACCOUNT_INCREMENT_NONCE_EVENT - u32assert + u32assert.err=ERR_ACCOUNT_NONCE_INCR_MUST_BE_U32 exec.memory::get_acct_nonce add exec.memory::set_acct_nonce end @@ -280,7 +298,7 @@ export.validate_id # => [ones] # check if the number of ones is at least MIN_ACCOUNT_ONES ones. - push.MIN_ACCOUNT_ONES u32gte assert + push.MIN_ACCOUNT_ONES u32gte assert.err=ERR_ACCOUNT_INSUFFICIENT_ONES end #! Sets the code of the account the transaction is being executed against. This procedure can only @@ -296,7 +314,7 @@ export.set_code # => [acct_id, CODE_ROOT] # assert the account is an updatable regular account - exec.is_updatable_account assert + exec.is_updatable_account assert.err=ERR_ACCOUNT_SET_CODE_ACCOUNT_MUST_BE_UPDATABLE # => [CODE_ROOT] # set the code root @@ -431,7 +449,7 @@ export.validate_seed # assert the account id matches the account id of the new account and extract pow # element - movdn.3 drop drop exec.memory::get_acct_id eq assert + movdn.3 drop drop exec.memory::get_acct_id eq assert.err=ERR_ACCOUNT_SEED_DIGEST_MISMATCH # => [pow] # get acct and facuet modulus to check the min number of trailing zeros required in the pow @@ -449,6 +467,6 @@ export.validate_seed # => [pow, modulus] # assert that the pow is valid - u32split drop swap u32divmod assertz drop + u32split drop swap u32divmod assertz.err=ERR_ACCOUNT_INVALID_POW drop # => [] end diff --git a/miden-lib/asm/miden/kernels/tx/asset.masm b/miden-lib/asm/miden/kernels/tx/asset.masm index d647b8b1f..ad8cb0f2d 100644 --- a/miden-lib/asm/miden/kernels/tx/asset.masm +++ b/miden-lib/asm/miden/kernels/tx/asset.masm @@ -1,5 +1,32 @@ use.miden::kernels::tx::account +# ERRORS +# ================================================================================================= + +# The felt at position 1 must be zero +const.ERR_FUNGIBLE_ASSET_FORMAT_POSITION_ONE_MUST_BE_ZERO=0x00020033 + +# The felt at position 2 must be zero +const.ERR_ASSET_FORMAT_POSITION_TWO_MUST_BE_ZERO=0x00020034 + +# The felt at position 3 must correspond to a fungible +const.ERR_FUNGIBLE_ASSET_FORMAT_POSITION_THREE_MUST_BE_ZERO=0x00020035 + +# The felt at position 0 must be within limit +const.ERR_FUNGIBLE_ASSET_FORMAT_POSITION_ZERO_MUST_BE_ZERO=0x00020036 + +# The felt at position 1 must be zero +const.ERR_NON_FUNGIBLE_ASSET_FORMAT_POSITION_ONE_MUST_FUNGIBLE=0x00020037 + +# The felt at position 3 must be zero +const.ERR_NON_FUNGIBLE_ASSET_FORMAT_POSITION_THREE_HAS_HIGH_BIT_SET=0x00020038 + +# Fungible asset origin validation failed +const.ERR_FUNGIBLE_ASSET_MISMATCH=0x00020039 + +# Fungible asset origin validation failed +const.ERR_NON_FUNGIBLE_ASSET_MISMATCH=0x0002003A + # CONSTANTS # ================================================================================================= @@ -27,11 +54,11 @@ end #! ASSET is the asset to validate. export.validate_fungible_asset # assert that ASSET[1] == ZERO - dup.1 not assert + dup.1 not assert.err=ERR_FUNGIBLE_ASSET_FORMAT_POSITION_ONE_MUST_BE_ZERO # => [ASSET] # assert that ASSET[2] == ZERO - dup.2 not assert + dup.2 not assert.err=ERR_ASSET_FORMAT_POSITION_TWO_MUST_BE_ZERO # => [ASSET] # assert that ASSET[3] is a valid account id @@ -39,11 +66,11 @@ export.validate_fungible_asset # => [ASSET] # assert that ASSET[3] is a fungible faucet - dup exec.account::is_fungible_faucet assert + dup exec.account::is_fungible_faucet assert.err=ERR_FUNGIBLE_ASSET_FORMAT_POSITION_THREE_MUST_BE_ZERO # => [ASSET] # assert that the max amount (ASSET[0]) of a fungible asset is not exceeded - dup.3 push.FUNGIBLE_ASSET_MAX_AMOUNT lte assert + dup.3 push.FUNGIBLE_ASSET_MAX_AMOUNT lte assert.err=ERR_FUNGIBLE_ASSET_FORMAT_POSITION_ZERO_MUST_BE_ZERO # => [ASSET] end @@ -74,11 +101,14 @@ export.validate_non_fungible_asset # => [ASSET] # assert that ASSET[1] is a fungible faucet - dup.2 exec.account::is_non_fungible_faucet assert + dup.2 exec.account::is_non_fungible_faucet assert.err=ERR_NON_FUNGIBLE_ASSET_FORMAT_POSITION_ONE_MUST_FUNGIBLE # => [ASSET] # assert the most significant bit of the most significant element (ASSET[3]) is 0 - dup u32split swap drop u32assert u32shr.31 not assert + dup u32split swap drop + u32assert.err=ERR_NON_FUNGIBLE_ASSET_FORMAT_POSITION_THREE_HAS_HIGH_BIT_SET + u32shr.31 not + assert.err=ERR_NON_FUNGIBLE_ASSET_FORMAT_POSITION_THREE_HAS_HIGH_BIT_SET # => [ASSET] end @@ -127,7 +157,7 @@ end #! - ASSET is the asset to validate. export.validate_fungible_asset_origin # assert the origin of the asset is the faucet_id provided via the stack - dup.1 assert_eq + dup.1 assert_eq.err=ERR_FUNGIBLE_ASSET_MISMATCH # => [ASSET] # assert the fungible asset is valid @@ -144,7 +174,7 @@ end #! - ASSET is the asset to validate. export.validate_non_fungible_asset_origin # assert the origin of the asset is the faucet_id provided via the stack - dup.3 assert_eq + dup.3 assert_eq.err=ERR_NON_FUNGIBLE_ASSET_MISMATCH # => [ASSET] # assert the non-fungible asset is valid diff --git a/miden-lib/asm/miden/kernels/tx/asset_vault.masm b/miden-lib/asm/miden/kernels/tx/asset_vault.masm index 5cf2c7589..f5457a106 100644 --- a/miden-lib/asm/miden/kernels/tx/asset_vault.masm +++ b/miden-lib/asm/miden/kernels/tx/asset_vault.masm @@ -4,6 +4,33 @@ use.miden::kernels::tx::account use.miden::kernels::tx::asset use.miden::kernels::tx::memory +# ERRORS +# ================================================================================================= + +# The get_balance procedure can be called only with a fungible faucet +const.ERR_VAULT_GET_BALANCE_WRONG_ASSET_TYPE=0x0002002B + +# The has_non_fungible_asset procedure can be called only with a non-fungible faucet +const.ERR_VAULT_HAS_NON_FUNGIBLE_WRONG_ACCOUNT_TYPE=0x0002002C + +# Adding the fungible asset would exceed the max_amount +const.ERR_VAULT_FUNGIBLE_MAX_AMOUNT_EXCEEDED=0x0002002D + +# Decorator value did not match the assert commitment +const.ERR_VAULT_ADD_FUNGIBLE_ASSET_MISMATCH=0x0002002E + +# The non-fungible asset already existed, can not be added again. +const.ERR_VAULT_NON_FUNGIBLE_ALREADY_EXISTED=0x0002002F + +# Removing the fungible asset would have current amount being negative +const.ERR_VAULT_FUNGIBLE_AMOUNT_UNDERFLOW=0x00020030 + +# Data provided via decorator did not match the commitment +const.ERR_VAULT_REMOVE_FUNGIBLE_ASSET_MISMATCH=0x00020031 + +# Removing inexisting non-fungible asset +const.ERR_VAULT_NON_FUNGIBLE_MISSING_ASSET=0x00020032 + # ACCESSORS # ================================================================================================= @@ -18,7 +45,7 @@ use.miden::kernels::tx::memory #! - balance is the vault balance of the fungible asset. export.get_balance # assert that the faucet id is a fungible faucet - dup exec.account::is_fungible_faucet assert + dup exec.account::is_fungible_faucet assert.err=ERR_VAULT_GET_BALANCE_WRONG_ASSET_TYPE # => [faucet_id, vault_root_ptr] # get the asset vault root @@ -49,7 +76,7 @@ end #! - has_asset is a boolean indicating whether the account vault has the asset of interest export.has_non_fungible_asset # check if the asset is a non-fungible asset - exec.asset::is_non_fungible_asset assert + exec.asset::is_non_fungible_asset assert.err=ERR_VAULT_HAS_NON_FUNGIBLE_WRONG_ACCOUNT_TYPE # => [ASSET, vault_root_ptr] # prepare the stack to read non-fungible asset from vault @@ -103,7 +130,7 @@ export.add_fungible_asset # => [(max_amount - cur_amount), amount, amount, cur_amount, faucet_id, 0, 0, VAULT_ROOT, CUR_VAULT_VALUE, vault_root_ptr] # assert amount + cur_amount < max_amount - lte assert + lte assert.err=ERR_VAULT_FUNGIBLE_MAX_AMOUNT_EXCEEDED # => [amount, cur_amount, faucet_id, 0, 0, VAULT_ROOT, CUR_VAULT_VALUE, vault_root_ptr] # add asset amounts @@ -116,7 +143,7 @@ export.add_fungible_asset # update asset in vault and assert the old value is equivalent to the value provided via the # decorator - exec.smt::set movupw.2 assert_eqw + exec.smt::set movupw.2 assert_eqw.err=ERR_VAULT_ADD_FUNGIBLE_ASSET_MISMATCH # => [VAULT_ROOT', ASSET', vault_root_ptr] # update the vault root @@ -144,7 +171,7 @@ export.add_non_fungible_asset # => [OLD_VAL, VAULT_ROOT', ASSET, vault_root_ptr] # Assert old value was empty - padw assert_eqw + padw assert_eqw.err=ERR_VAULT_NON_FUNGIBLE_ALREADY_EXISTED # => [VAULT_ROOT', ASSET, vault_root_ptr] # update the vault root @@ -219,7 +246,7 @@ export.remove_fungible_asset # => [cur_amount, amount, amount, cur_amount, faucet_id, 0, 0, VAULT_ROOT, CUR_VAULT_VALUE, ASSET, vault_root_ptr] # assert amount <= cur_amount - lte assert + lte assert.err=ERR_VAULT_FUNGIBLE_AMOUNT_UNDERFLOW # => [amount, cur_amount, faucet_id, 0, 0, VAULT_ROOT, CUR_VAULT_VALUE, ASSET, vault_root_ptr] # asset amount + cur_amount < max_amount @@ -242,7 +269,7 @@ export.remove_fungible_asset # update asset in vault and assert the old value is equivalent to the value provided via the # decorator - exec.smt::set movupw.2 assert_eqw + exec.smt::set movupw.2 assert_eqw.err=ERR_VAULT_REMOVE_FUNGIBLE_ASSET_MISMATCH # => [VAULT_ROOT', ASSET, vault_root_ptr] # update the vault root @@ -271,7 +298,7 @@ export.remove_non_fungible_asset # => [OLD_VAL, VAULT_ROOT', ASSET, vault_root_ptr] # Assert old value was not empty (we only need to check ASSET[1] which is the faucet id) - drop drop eq.0 assertz drop + drop drop eq.0 assertz.err=ERR_VAULT_NON_FUNGIBLE_MISSING_ASSET drop # => [VAULT_ROOT', ASSET, vault_root_ptr] # update the vault root diff --git a/miden-lib/asm/miden/kernels/tx/epilogue.masm b/miden-lib/asm/miden/kernels/tx/epilogue.masm index 0575b81d9..554126ef1 100644 --- a/miden-lib/asm/miden/kernels/tx/epilogue.masm +++ b/miden-lib/asm/miden/kernels/tx/epilogue.masm @@ -4,6 +4,15 @@ use.miden::kernels::tx::constants use.miden::kernels::tx::memory use.miden::kernels::tx::note +# ERRORS +# ================================================================================================= + +# The nonce did not increase after a state changing transaction. +const.ERR_KERNEL_TX_NONCE_DID_NOT_INCREASE=0x00020009 + +# Total assets at the transaction end must match +const.ERR_KERNEL_ASSET_MISMATCH=0x0002000A + # OUTPUT NOTES PROCEDURES # ================================================================================================= @@ -212,7 +221,7 @@ export.finalize_transaction # => [current_nonce, init_nonce, FINAL_ACCOUNT_HASH, INIT_ACCT_HASH] # assert that initial nonce is less than current nonce - lt assert + lt assert.err=ERR_KERNEL_TX_NONCE_DID_NOT_INCREASE # => [FINAL_ACCOUNT_HASH, INIT_ACCT_HASH] end @@ -241,6 +250,6 @@ export.finalize_transaction # => [TX_SCRIPT_ROOT, OUTPUT_NOTES_COMMITMENT, FINAL_ACCOUNT_HASH] # assert no net creation or destruction of assets over the transaction - exec.memory::get_input_vault_root exec.memory::get_output_vault_root assert_eqw + exec.memory::get_input_vault_root exec.memory::get_output_vault_root assert_eqw.err=ERR_KERNEL_ASSET_MISMATCH # => [TX_SCRIPT_ROOT, OUTPUT_NOTES_COMMITMENT, FINAL_ACCOUNT_HASH] end diff --git a/miden-lib/asm/miden/kernels/tx/faucet.masm b/miden-lib/asm/miden/kernels/tx/faucet.masm index 356e1b42e..fe6835e37 100644 --- a/miden-lib/asm/miden/kernels/tx/faucet.masm +++ b/miden-lib/asm/miden/kernels/tx/faucet.masm @@ -5,6 +5,24 @@ use.miden::kernels::tx::asset use.miden::kernels::tx::asset_vault use.miden::kernels::tx::memory +# ERRORS +# ================================================================================================= + +# Asset mint operation would acuse a issuance overflow +const.ERR_FAUCET_ISSUANCE_OVERFLOW=0x00020022 + +# Asset burn can not exceed the existing supply +const.ERR_FAUCET_BURN_OVER_ISSUANCE=0x00020023 + +# Non fungible token already exists, it can be issue only once +const.ERR_FAUCET_NON_FUNGIBLE_ALREADY_EXISTS=0x00020024 + +# Non fungible burn called on the wrong faucet type +const.ERR_FAUCET_NON_FUNGIBLE_BURN_WRONG_TYPE=0x00020025 + +# Non fungible burn called on inexisting token. +const.ERR_FAUCET_NONEXISTING_TOKEN=0x00020026 + # FUNGIBLE ASSETS # ================================================================================================== @@ -38,7 +56,7 @@ export.mint_fungible_asset # => [total_issuance, max_allowed_issuance, amount, amount, TOTAL_ISSUANCE, ASSET] # compute difference to ensure that the total issuance will not exceed the maximum - sub lte assert + sub lte assert.err=ERR_FAUCET_ISSUANCE_OVERFLOW # => [amount, TOTAL_ISSUANCE, ASSET] # update the total issuance @@ -75,7 +93,7 @@ proc.burn_fungible_asset # => [TOTAL_ISSUANCE, ASSET] # assert that the asset amount being burned is less or equal to the total issuance - dup.7 dup dup.2 lte assert + dup.7 dup dup.2 lte assert.err=ERR_FAUCET_BURN_OVER_ISSUANCE # => [amount, TOTAL_ISSUANCE, ASSET] # compute new total issuance @@ -140,7 +158,7 @@ proc.mint_non_fungible_asset # assert the `OLD_VAL` is ZERO, indicating that the non-fungible asset did not already exist # we only need to check ASSET[1] as this is always set to the faucet_id and can not be 0. - drop drop eq.0 assert drop + drop drop eq.0 assert.err=ERR_FAUCET_NON_FUNGIBLE_ALREADY_EXISTS drop # => [SMT_ROOT', ASSET] # update the root of the SMT containing the non-fungible assets @@ -168,7 +186,7 @@ end #! - ASSET is the asset that was burned. proc.burn_non_fungible_asset # assert that we are executing a transaction against the non-fungible faucet (access checks) - exec.account::get_id exec.account::is_non_fungible_faucet assert + exec.account::get_id exec.account::is_non_fungible_faucet assert.err=ERR_FAUCET_NON_FUNGIBLE_BURN_WRONG_TYPE # => [ASSET] # duplicate asset @@ -189,7 +207,7 @@ proc.burn_non_fungible_asset # assert the `OLD_VAL` is not ZERO, indicating that the non-fungible asset exists. # we only need to check ASSET[1] as this is always set to the faucet_id and can not be 0. - drop drop eq.0 not assert drop + drop drop eq.0 not assert.err=ERR_FAUCET_NONEXISTING_TOKEN drop # => [SMT_ROOT', ASSET] # update the root of the SMT containing the non-fungible assets diff --git a/miden-lib/asm/miden/kernels/tx/note.masm b/miden-lib/asm/miden/kernels/tx/note.masm index 831f96633..702f25cf5 100644 --- a/miden-lib/asm/miden/kernels/tx/note.masm +++ b/miden-lib/asm/miden/kernels/tx/note.masm @@ -1,6 +1,21 @@ use.miden::kernels::tx::constants use.miden::kernels::tx::memory +# ERRORS +# ================================================================================================= + +# Input note can not have an empty sender, procedure was likely called from the wrong context +const.ERR_NOTE_INVALID_SENDER=0x00020027 + +# Input note can not have an empty vault, procedure was likely called from the wrong context +const.ERR_NOTE_INVALID_VAULT=0x00020028 + +# Input note can not have empty inputs, procedure was likely called from the wrong context +const.ERR_NOTE_INVALID_INPUTS=0x00020029 + +# Note's asset must fit in a u32 +const.ERR_NOTE_TOO_MANY_ASSETS=0x0002002A + # CONSTANTS # ================================================================================================= @@ -25,7 +40,7 @@ export.get_sender # assert the pointer is not zero - this would suggest the procedure has been called from an # incorrect context - dup neq.0 assert + dup neq.0 assert.err=ERR_NOTE_INVALID_SENDER # => [ptr] # get the sender from the note pointer @@ -48,7 +63,7 @@ export.get_vault_info # assert the pointer is not zero - this would suggest the procedure has been called from an # incorrect context - dup neq.0 assert + dup neq.0 assert.err=ERR_NOTE_INVALID_VAULT # => [ptr] # get the number of assets in the note @@ -75,7 +90,7 @@ export.get_inputs_info # assert the pointer is not zero - this would suggest the procedure has been called from an # incorrect context - dup neq.0 assert + dup neq.0 assert.err=ERR_NOTE_INVALID_INPUTS # => [ptr] # get the number of inputs for the note @@ -159,7 +174,9 @@ proc.compute_output_note_assets_hash # => [num_assets, note_data_ptr, note_data_ptr] # calculate the number of pairs of assets (takes ceiling if we have an odd number) - add.1 u32assert u32div.2 + add.1 + u32assert.err=ERR_NOTE_TOO_MANY_ASSETS + u32div.2 # => [num_asset_pairs, note_data_ptr, note_data_ptr] # initiate counter for assets diff --git a/miden-lib/asm/miden/kernels/tx/prologue.masm b/miden-lib/asm/miden/kernels/tx/prologue.masm index 6edc1709c..11c3bf98e 100644 --- a/miden-lib/asm/miden/kernels/tx/prologue.masm +++ b/miden-lib/asm/miden/kernels/tx/prologue.masm @@ -7,6 +7,71 @@ use.miden::kernels::tx::constants use.miden::kernels::tx::memory use.miden::kernels::tx::utils +# ERRORS +# ================================================================================================= + +# The global inputs provided via the advice provider do not match the block hash commitment +const.ERR_PROLOGUE_GLOBAL_INPUTS_MISMATCH=0x0002000B + +# The account storage data provided via the advice provider do not match its state commitment +const.ERR_PROLOGUE_ACCT_STORAGE_MISMATCH=0x0002000C + +# Data store in account's storage exceeds the maximum capacity of 256 elements +const.ERR_PROLOGUE_ACCT_STORAGE_ARITY_TOO_HIGH=0x0002000D + +# Data store in account's storage contains invalid type discriminant +const.ERR_PROLOGUE_ACCT_STORAGE_TYPE_INVALID=0x0002000E + +# New account must start with an empty vault +const.ERR_PROLOGUE_NEW_ACCT_VAULT_NOT_EMPTY=0x0002000F + +# New account must have valid slot type s +const.ERR_PROLOGUE_NEW_ACCT_INVALID_SLOT_TYPE=0x00020010 + +# Fungible faucet reserved slot must start empty +const.ERR_PROLOGUE_NEW_FUNGIBLE_FAUCET_NON_EMPTY_RESERVED_SLOT=0x00020011 + +# Fungible faucet reserved slot must start with zero arity +const.ERR_PROLOGUE_NEW_FUNGIBLE_FAUCET_NON_ZERO_RESERVED_SLOT=0x00020012 + +# Fungible faucet reserved slot must start with no type +const.ERR_PROLOGUE_NEW_FUNGIBLE_FAUCET_INVALID_TYPE_RESERVED_SLOT=0x00020013 + +# Non-fungible faucet reserved slot must start as an empty SMT +const.ERR_PROLOGUE_NEW_NON_FUNGIBLE_FAUCET_INVALID_RESERVED_SLOT=0x00020014 + +# Non-fungible faucet reserved slot must start with zero arity +const.ERR_PROLOGUE_NEW_NON_FUNGIBLE_FAUCET_NON_ZERO_RESERVED_SLOT=0x00020015 + +# Non-fungible faucet reserved slot must start with no type +const.ERR_PROLOGUE_NEW_NON_FUNGIBLE_FAUCET_INVALID_TYPE_RESERVED_SLOT=0x00020016 + +# The account data provided via advice provider did not match the initial hash +const.ERR_PROLOGUE_ACCT_HASH_MISMATCH=0x00020017 + +# Existing account must not have a zero nonce. +const.ERR_PROLOGUE_OLD_ACCT_NONCE_ZERO=0x00020018 + +# Account id and global account id must match +const.ERR_PROLOGUE_ACCT_ID_MISMATCH=0x00020019 + +# Reference block MMR and note's authentication MMR must match +const.ERR_PROLOGUE_NOTE_MMR_DIGEST_MISMATCH=0x0002001A + +# Note with too many inputs +const.ERR_PROLOGUE_NOTE_TOO_MANY_INPUTS=0x0002001B + +# Note with too many assets +const.ERR_PROLOGUE_NOTE_TOO_MANY_ASSETS=0x0002001C + +# Note's consumed assets provided via advice provider mistmatch its commitment +const.ERR_PROLOGUE_NOTE_CONSUMED_ASSETS_MISMATCH=0x0002001D + +# Number of input notes can no exceed the kernel's maximum limit +const.ERR_PROLOGUE_TOO_MANY_INPUT_NOTES=0x0002001E + +# Input notes nullifier commitment did not match the provided data +const.ERR_PROLOGUE_INPUT_NOTES_NULLIFIER_COMMITMENT_MISMATCH=0x0002001F # PUBLIC INPUTS # ================================================================================================= @@ -90,7 +155,7 @@ proc.process_block_data # => [BH, block_data_ptr'] # assert that the block hash matches the hash in global inputs - exec.memory::get_blk_hash assert_eqw + exec.memory::get_blk_hash assert_eqw.err=ERR_PROLOGUE_GLOBAL_INPUTS_MISMATCH # => [block_data_ptr'] # clear the stack @@ -187,7 +252,7 @@ proc.ingest_acct_storage_types # => [DIGEST, TYPES_COM] # assert the digest matches the commitment - assert_eqw + assert_eqw.err=ERR_PROLOGUE_ACCT_STORAGE_MISMATCH # => [] end @@ -214,11 +279,13 @@ proc.validate_storage_slot_types # => [arity, type, ...] # assert the entry arity is less than or equal to 255 - u32split assertz push.255 u32lte assert + u32split assertz.err=ERR_PROLOGUE_ACCT_STORAGE_ARITY_TOO_HIGH + push.255 u32lte assert.err=ERR_PROLOGUE_ACCT_STORAGE_ARITY_TOO_HIGH # => [type, ...] # assert the slot type is valid - u32split assertz exec.account::get_max_slot_type u32lte assert + u32split assertz.err=ERR_PROLOGUE_ACCT_STORAGE_TYPE_INVALID + exec.account::get_max_slot_type u32lte assert.err=ERR_PROLOGUE_ACCT_STORAGE_TYPE_INVALID # => [...] end # => [slot_type_data_ptr] @@ -264,7 +331,7 @@ proc.validate_new_account exec.constants::get_empty_smt_root # => [EMPTY_VAULT_ROOT, ACCT_VAULT_ROOT] - assert_eqw + assert_eqw.err=ERR_PROLOGUE_NEW_ACCT_VAULT_NOT_EMPTY # => [] # Assert storage slot types are well formed @@ -279,7 +346,9 @@ proc.validate_new_account # => [entry_arity, storage_type] # assert the slot type is a scalar of arity 64 - push.64 assert_eq assertz + push.64 + assert_eq.err=ERR_PROLOGUE_NEW_ACCT_INVALID_SLOT_TYPE + assertz.err=ERR_PROLOGUE_NEW_ACCT_INVALID_SLOT_TYPE # => [] drop drop @@ -302,7 +371,7 @@ proc.validate_new_account if.true # assert the fungible faucet reserved slot is initialized correctly (EMPTY_WORD) - or or or assertz + or or or assertz.err=ERR_PROLOGUE_NEW_FUNGIBLE_FAUCET_NON_EMPTY_RESERVED_SLOT # => [] # get the faucet reserved storage data slot type and entry arity @@ -310,12 +379,13 @@ proc.validate_new_account # => [entry_arity, storage_type] # assert the fungible faucet reserved slot type is a scalar of arity 0 - assertz assertz + assertz.err=ERR_PROLOGUE_NEW_FUNGIBLE_FAUCET_NON_ZERO_RESERVED_SLOT + assertz.err=ERR_PROLOGUE_NEW_FUNGIBLE_FAUCET_INVALID_TYPE_RESERVED_SLOT # => [] else # assert the non-fungible faucet reserved slot is initialized correctly (root of # empty SMT) - exec.constants::get_empty_smt_root assert_eqw + exec.constants::get_empty_smt_root assert_eqw.err=ERR_PROLOGUE_NEW_NON_FUNGIBLE_FAUCET_INVALID_RESERVED_SLOT # => [] # get the faucet reserved storage data slot type and entry arity @@ -323,7 +393,8 @@ proc.validate_new_account # => [entry_arity, storage_type] # assert the non-fungible faucet reserved slot type is a map of arity 0 - assertz assert + assertz.err=ERR_PROLOGUE_NEW_NON_FUNGIBLE_FAUCET_NON_ZERO_RESERVED_SLOT + assert.err=ERR_PROLOGUE_NEW_NON_FUNGIBLE_FAUCET_INVALID_TYPE_RESERVED_SLOT # => [] end else @@ -399,11 +470,13 @@ proc.process_acct_data # => [] else # assert that the existing account hash matches the hash in global inputs - exec.memory::get_init_acct_hash assert_eqw + exec.memory::get_init_acct_hash + assert_eqw.err=ERR_PROLOGUE_ACCT_HASH_MISMATCH # => [] # assert the nonce of an existing account is non-zero - exec.memory::get_acct_nonce neq.0 assert + exec.memory::get_acct_nonce neq.0 + assert.err=ERR_PROLOGUE_OLD_ACCT_NONCE_ZERO # => [] end @@ -413,7 +486,7 @@ proc.process_acct_data # assert the account id matches the account id in global inputs exec.memory::get_global_acct_id exec.memory::get_acct_id - assert_eq + assert_eq.err=ERR_PROLOGUE_ACCT_ID_MISMATCH # => [] # store a copy of the initial nonce in global inputs @@ -472,7 +545,8 @@ proc.authenticate_note.2 # => [PERM, PERM, PERM, mem_ptr', MMR_LEAF, AUTH_DIGEST] # extract the digest and assert it matches MMR_LEAF - dropw movup.8 drop movupw.2 assert_eqw + dropw movup.8 drop movupw.2 + assert_eqw.err=ERR_PROLOGUE_NOTE_MMR_DIGEST_MISMATCH # => [AUTH_DIGEST] # load the note root from memory @@ -578,7 +652,8 @@ proc.process_input_note # => [num_inputs, note_ptr] # make sure the number of inputs is in the valid range - exec.constants::get_max_inputs_per_note lte assert + exec.constants::get_max_inputs_per_note lte + assert.err=ERR_PROLOGUE_NOTE_TOO_MANY_INPUTS # => [note_ptr] # ingest note assets @@ -590,7 +665,8 @@ proc.process_input_note # => [num_assets, note_ptr] # assert the number of assets is within limits - dup exec.constants::get_max_assets_per_note lte assert + dup exec.constants::get_max_assets_per_note lte + assert.err=ERR_PROLOGUE_NOTE_TOO_MANY_ASSETS # => [num_assets, note_ptr] # round up the number of assets to the next multiple of 2 (simplifies reading of assets) @@ -634,7 +710,7 @@ proc.process_input_note # => [V, DIG, note_ptr] # assert that the computed hash matches the expected hash - assert_eqw + assert_eqw.err=ERR_PROLOGUE_NOTE_CONSUMED_ASSETS_MISMATCH # => [note_ptr] # TODO: make sure the last asset is not [ZERO; 4]? @@ -747,7 +823,10 @@ proc.process_input_notes_data # assert the number of input notes is within limits; since max number of input notes is # expected to be smaller than 2^32, we can use a more efficient u32 comparison - dup exec.constants::get_max_num_consumed_notes u32assert2 u32lte assert + dup exec.constants::get_max_num_consumed_notes + u32assert2.err=ERR_PROLOGUE_TOO_MANY_INPUT_NOTES + u32lte + assert.err=ERR_PROLOGUE_TOO_MANY_INPUT_NOTES # => [num_notes, ...] # if there are input notes, load input notes data from the advice map onto the advice stack @@ -831,7 +910,8 @@ proc.process_input_notes_data # assert nullifier hash is what we would expect; when there are no input notes, the nullifier # hash should be [ZERO; 4] because the while loop above was not entered and, thus, hperm # instruction was not executed. - exec.memory::get_nullifier_com assert_eqw + exec.memory::get_nullifier_com + assert_eqw.err=ERR_PROLOGUE_INPUT_NOTES_NULLIFIER_COMMITMENT_MISMATCH # => [num_processed_notes + 1, num_notes, ...] # clear stack diff --git a/miden-lib/asm/miden/kernels/tx/tx.masm b/miden-lib/asm/miden/kernels/tx/tx.masm index 98f13f13e..2e4a0a1cb 100644 --- a/miden-lib/asm/miden/kernels/tx/tx.masm +++ b/miden-lib/asm/miden/kernels/tx/tx.masm @@ -4,6 +4,12 @@ use.miden::kernels::tx::constants use.miden::kernels::tx::memory use.miden::kernels::tx::note +# ERRORS +# ================================================================================================= + +# Output notes exceeded the maximum limit +const.ERR_TX_OUTPUT_NOTES_OVERFLOW=0x00020020 + #! Returns the block hash of the last known block at the time of transaction execution. #! #! Inputs: [] @@ -48,7 +54,7 @@ proc.increment_num_created_notes # => [note_idx] # assert that there is space for a new note - dup exec.constants::get_max_num_created_notes lt assert + dup exec.constants::get_max_num_created_notes lt assert.err=ERR_TX_OUTPUT_NOTES_OVERFLOW # => [note_idx] # increment the number of created notes diff --git a/miden-lib/asm/miden/note.masm b/miden-lib/asm/miden/note.masm index 348813e9e..963e810a7 100644 --- a/miden-lib/asm/miden/note.masm +++ b/miden-lib/asm/miden/note.masm @@ -1,6 +1,12 @@ use.std::crypto::hashes::native use.std::mem +# ERRORS +# ================================================================================================= + +# Note's advice data does not match the expected commitment. +const.ERR_NOTE_DATA_MISMATCH=0x00020040 + #! 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. #! @@ -24,7 +30,7 @@ proc.write_advice_data_to_memory # => [DIGEST, HASH] # assert the computed hash is equal to the expected hash - assert_eqw + assert_eqw.err=ERR_NOTE_DATA_MISMATCH # => [] end diff --git a/miden-lib/asm/note_scripts/P2ID.masm b/miden-lib/asm/note_scripts/P2ID.masm index 1a80e14af..f25fcea07 100644 --- a/miden-lib/asm/note_scripts/P2ID.masm +++ b/miden-lib/asm/note_scripts/P2ID.masm @@ -2,6 +2,15 @@ use.miden::account use.miden::note use.miden::contracts::wallets::basic->wallet +# ERRORS +# ================================================================================================= + +# P2ID scripts expect exactly 1 note input +const.ERR_P2ID_WRONG_NUMBER_OF_INPUTS=0x00020002 + +# P2ID's target account address and transaction address do no match +const.ERR_P2ID_TARGET_ACCT_MISMATCH=0x00020003 + #! Helper procedure to add all assets of a note to an account. #! #! Inputs: [] @@ -70,7 +79,7 @@ begin # => [num_inputs, inputs_ptr] # make sure the number of inputs is 1 - eq.1 assert + eq.1 assert.err=ERR_P2ID_WRONG_NUMBER_OF_INPUTS # => [inputs_ptr] # read the target account id from the note inputs @@ -81,7 +90,7 @@ begin # => [account_id, target_account_id, ...] # ensure account_id = target_account_id, fails otherwise - assert_eq + assert_eq.err=ERR_P2ID_TARGET_ACCT_MISMATCH # => [...] exec.add_note_assets_to_account diff --git a/miden-lib/asm/note_scripts/P2IDR.masm b/miden-lib/asm/note_scripts/P2IDR.masm index 678c4206d..5666c10bc 100644 --- a/miden-lib/asm/note_scripts/P2IDR.masm +++ b/miden-lib/asm/note_scripts/P2IDR.masm @@ -3,6 +3,18 @@ use.miden::note use.miden::tx use.miden::contracts::wallets::basic->wallet +# ERRORS +# ================================================================================================= + +# P2IDR scripts expect exactly 2 note inputs +const.ERR_P2IDR_WRONG_NUMBER_OF_INPUTS=0x00020004 + +# P2IDR's can only be reclaimed by the sender +const.ERR_P2IDR_RECLAIM_ACCT_IS_NOT_SENDER=0x00020005 + +# Transaction's reference block is lower than reclaim height. The P2IDR can not be reclaimed +const.ERR_P2IDR_RECLAIM_HEIGHT_NOT_REACHED=0x00020006 + #! Helper procedure to add all assets of a note to an account. #! #! Inputs: [] @@ -74,7 +86,7 @@ begin # => [num_inputs, inputs_ptr] # make sure the number of inputs is 2 - eq.2 assert + eq.2 assert.err=ERR_P2IDR_WRONG_NUMBER_OF_INPUTS # => [inputs_ptr] # read the reclaim block height and target account id from the note inputs @@ -98,14 +110,14 @@ begin exec.note::get_sender # => [sender_account_id, account_id, reclaim_block_height, ...] - assert_eq + assert_eq.err=ERR_P2IDR_RECLAIM_ACCT_IS_NOT_SENDER # => [reclaim_block_height, ...] # now check that sender is allowed to reclaim, current block >= reclaim block height exec.tx::get_block_number # => [current_block_height, reclaim_block_height, ...] - u32assert2 u32lte assert + u32assert2 u32lte assert.err=ERR_P2IDR_RECLAIM_HEIGHT_NOT_REACHED end exec.add_note_assets_to_account diff --git a/miden-lib/asm/note_scripts/SWAP.masm b/miden-lib/asm/note_scripts/SWAP.masm index e844baf33..2d84b9ebb 100644 --- a/miden-lib/asm/note_scripts/SWAP.masm +++ b/miden-lib/asm/note_scripts/SWAP.masm @@ -1,6 +1,15 @@ use.miden::note use.miden::contracts::wallets::basic->wallet +# ERRORS +# ================================================================================================= + +# SWAP script expects exactly 9 note inputs +const.ERR_SWAP_WRONG_NUMBER_OF_INPUTS=0x00020007 + +# SWAP script requires exactly one note asset +const.ERR_SWAP_WRONG_NUMBER_OF_ASSETS=0x00020008 + # Swap script: adds an asset from the note into consumers account and # creates a note consumable by note issuer containing requested ASSET. # @@ -26,7 +35,7 @@ begin # => [] # store asset into memory at address 3 - push.3 exec.note::get_assets assert + push.3 exec.note::get_assets assert.err=ERR_SWAP_WRONG_NUMBER_OF_ASSETS # => [ptr] # load the asset and add it to the account @@ -38,7 +47,7 @@ begin # => [num_inputs, inputs_ptr] # make sure the number of inputs is 9 - eq.9 assert + eq.9 assert.err=ERR_SWAP_WRONG_NUMBER_OF_INPUTS # => [inputs_ptr] # load recipient