Skip to content

Commit

Permalink
feat: remove asset from create note (#686)
Browse files Browse the repository at this point in the history
* feat: creating notes without assets

* after review

* pacifying linter

* after review
  • Loading branch information
Dominik1999 authored and bobbinth committed May 14, 2024
1 parent 841e78e commit 1808446
Show file tree
Hide file tree
Showing 13 changed files with 157 additions and 146 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
* [BREAKING] Updated `create_swap_note()` procedure to return `NoteDetails` and defined SWAP note tag format (#665).
* [BREAKING] Added support for full details of private notes, renamed `OutputNote` variants and changed their meaning (#673).
* Implemented `OutputNoteBuilder` (#669).
* [BREAKING] Removed assets from `create_note` procedure and added new procedure `add_asset_to_note` (#686, #674).

## 0.2.3 (2024-04-26) - `miden-tx` crate only

Expand Down
52 changes: 30 additions & 22 deletions docs/architecture/accounts.md
Original file line number Diff line number Diff line change
Expand Up @@ -110,33 +110,41 @@ There is also a standard for a [basic fungible faucet](https://github.com/0xPoly
#!
#! ...
export.distribute
# get max supply of this faucet. We assume it is stored at pos 3 of slot 1
push.METADATA_SLOT exec.account::get_item drop drop drop
# => [max_supply, amount, tag, note_type, RECIPIENT, ...]
# get max supply of this faucet. We assume it is stored at pos 3 of slot 1
push.METADATA_SLOT exec.account::get_item drop drop drop
# => [max_supply, amount, tag, note_type, RECIPIENT, ...]
# get total issuance of this faucet so far and add amount to be minted
exec.faucet::get_total_issuance
# => [total_issuance, max_supply, amount, tag, note_type RECIPIENT, ...]
# get total issuance of this faucet so far and add amount to be minted
exec.faucet::get_total_issuance
# => [total_issuance, max_supply, amount, tag, note_type RECIPIENT, ...]
# compute maximum amount that can be minted, max_mint_amount = max_supply - total_issuance
sub
# => [max_supply - total_issuance, amount, tag, note_type, RECIPIENT, ...]
# compute maximum amount that can be minted, max_mint_amount = max_supply - total_issuance
sub
# => [max_supply - total_issuance, amount, tag, note_type, RECIPIENT, ...]
# check that amount =< max_supply - total_issuance, fails if otherwise
dup.1 gte assert.err=ERR_BASIC_FUNGIBLE_MAX_SUPPLY_OVERFLOW
# => [asset, tag, note_type, RECIPIENT, ...]
# check that amount =< max_supply - total_issuance, fails if otherwise
dup.1 gte assert.err=ERR_BASIC_FUNGIBLE_MAX_SUPPLY_OVERFLOW
# => [asset, tag, note_type, RECIPIENT, ...]
# creating the asset
exec.asset::create_fungible_asset
# => [ASSET, tag, note_type, RECIPIENT, ...]
# creating the asset
exec.asset::create_fungible_asset
# => [ASSET, tag, note_type, RECIPIENT, ...]
# mint the asset; this is needed to satisfy asset preservation logic.
exec.faucet::mint
# => [ASSET, tag, note_type, RECIPIENT, ...]
# mint the asset; this is needed to satisfy asset preservation logic.
exec.faucet::mint
# => [ASSET, tag, note_type, RECIPIENT, ...]
# create a note containing the asset
exec.tx::create_note
# => [note_ptr, ZERO, ZERO, ...]
# store and drop the ASSET
mem_storew.3 dropw
# => [tag, note_type, RECIPIENT, ...]
# create a note containing the asset
exec.tx::create_note
# => [note_ptr, ZERO, ZERO, ...]
# store and drop the ASSET
padw mem_loadw.3 movup.4 exec.tx::add_asset_to_note
# => [note_ptr, ASSET, ZERO, ...]
end
#! Burns fungible assets.
Expand All @@ -157,7 +165,7 @@ There is also a standard for a [basic fungible faucet](https://github.com/0xPoly
```
</details>

The contract exposes two functions `distribute` and `burn`.
The contract exposes two functions `distribute` and `burn`.

The first function `distribute` can only be called by the faucet owner, otherwise it fails. As inputs, the function expects everything that is needed to create a note containing the freshly minted asset, i.e., amount, metadata, and recipient.

Expand Down
19 changes: 13 additions & 6 deletions miden-lib/asm/kernels/transaction/api.masm
Original file line number Diff line number Diff line change
Expand Up @@ -514,21 +514,28 @@ end

#! Creates a new note and returns a pointer to the memory address at which the note is stored.
#!
#! Inputs: [ASSET, tag, note_type, RECIPIENT]
#! Outputs: [ptr, 0, 0, 0, 0, 0, 0, 0, 0, 0]
#! Inputs: [tag, note_type, RECIPIENT]
#! Outputs: [note_ptr, 0, 0, 0, 0, 0]
#!
#! ASSET is the asset to be included in the note.
#! tag is the tag to be included in the note.
#! note_type is the note storage type
#! RECIPIENT is the recipient of the note.
#! ptr is the pointer to the memory address at which the note is stored.
#! note_ptr is the pointer to the memory address at which the note is stored.
export.create_note
# authenticate that the procedure invocation originates from the account context
exec.authenticate_account_origin
# => [ASSET, tag, note_type, RECIPIENT]
# => [tag, note_type, RECIPIENT]

exec.tx::create_note
# => [ptr, 0, 0, 0, 0, 0, 0, 0, 0, 0]
# => [note_ptr]

# prepare stack for return. Note: when create_note is called, the stack looks
# like [tag, note_type, RECIPIENT, x, x, X], with 16 elements and X might be important data
# for the user. Without padding the kernel returns [note_ptr, x, x, X, 0, ZERO] adding 0's.
# To keep the data in position we insert 0's between ptr and the potentially important
# first element x.
movupw.3 movup.15 movup.5
# => [note_ptr, 0, 0, 0, 0, 0]
end

#! Adds an ASSET to the specified note and returns a pointer to the memory address
Expand Down
14 changes: 11 additions & 3 deletions miden-lib/asm/miden/contracts/faucets/basic_fungible.masm
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@ export.basic::auth_tx_rpo_falcon512
#! FAILS if:
#! - The transaction is being executed against an account that is not a fungible asset faucet.
#! - The total issuance after minting is greater than the maximum allowed supply.
export.distribute
export.distribute.1
# get max supply of this faucet. We assume it is stored at pos 3 of slot 1
push.METADATA_SLOT exec.account::get_item drop drop drop
# => [max_supply, amount, tag, note_type, RECIPIENT, ...]
Expand All @@ -72,9 +72,17 @@ export.distribute
exec.faucet::mint
# => [ASSET, tag, note_type, RECIPIENT, ...]

# create a note containing the asset
# store and drop the ASSET
loc_storew.0 dropw
# => [tag, note_type, RECIPIENT, ...]

# create a note
exec.tx::create_note
# => [note_ptr, ZERO, ZERO, ...]

# load the ASSET and add it to the note
padw loc_loadw.0 movup.4 exec.tx::add_asset_to_note
# => [note_ptr, ASSET, ZERO, ...]
end

#! Burns fungible assets.
Expand All @@ -99,4 +107,4 @@ export.burn
# clear the stack
padw swapw dropw
# => [...]
end
end
21 changes: 17 additions & 4 deletions miden-lib/asm/miden/contracts/wallets/basic.masm
Original file line number Diff line number Diff line change
Expand Up @@ -39,10 +39,14 @@ end
#! - The fungible asset is not found in the vault.
#! - The amount of the fungible asset in the vault is less than the amount to be removed.
#! - The non-fungible asset is not found in the vault.
export.send_asset
export.send_asset.1
exec.account::remove_asset
# => [ASSET, tag, note_type, RECIPIENT, ...]

# Store the ASSET for later
loc_storew.0 dropw
# => [tag, note_type, RECIPIENT, ...]

# This procedure is written to be executed with `exec` or `call`. When this
# procedure is `call`ed the stack has to be carefully manipulated to avoid
# inserting unwanted elements between the user data. The convention is to
Expand All @@ -53,9 +57,18 @@ export.send_asset
# is because the VM stack has a minimum size of 16 elements, trying to push
# elements after the call to `create_note` would increase the stack in
# addition to the minimum 16 elements.
push.0.0 padw movdnw.3 padw movdnw.3 movdn.11 drop
# => [ASSET, tag, note_type, RECIPIENT, ZERO, ZERO, 0, ...]
push.0 movdn.6 push.0 movdn.6 padw movdnw.2 padw movdnw.2
# => [tag, note_type, RECIPIENT, 0, 0, ZERO, ZERO, ...]

exec.tx::create_note
# => [note_ptr, ZERO, ZERO, 0, ...]
# => [note_ptr, 0, ZERO, ZERO, ...]

padw loc_loadw.0 movup.4
# => [note_ptr, ASSET, 0, ZERO, ZERO, ...]

exec.tx::add_asset_to_note
# => [note_ptr, 0, ZERO, ZERO, ...]

# prepare the stack for return - stack has 5 elements too many
movupw.3 dropw swap drop
end
2 changes: 1 addition & 1 deletion miden-lib/asm/miden/kernels/tx/note.masm
Original file line number Diff line number Diff line change
Expand Up @@ -163,7 +163,7 @@ end
#! Computes the assets hash of the output note located at the specified memory address. The hash
#! is computed as a sequential hash of the assets contained in the note. If there is an odd number
#! of assets, then for the final hashing permutation we pad the last word of the hasher rate with
#! ZERO's.
#! ZERO's. Returns [ZERO] if no assets are present.
#!
#! Stack: [note_data_ptr]
#! Output: [ASSETS_HASH]
Expand Down
70 changes: 29 additions & 41 deletions miden-lib/asm/miden/kernels/tx/tx.masm
Original file line number Diff line number Diff line change
Expand Up @@ -243,87 +243,75 @@ end

#! Creates a new note and returns a pointer to the memory address at which the note is stored.
#!
#! Inputs: [ASSET, tag, note_type, RECIPIENT]
#! Outputs: [note_ptr, 0, 0, 0, 0, 0, 0, 0, 0]
#! Inputs: [tag, note_type, RECIPIENT]
#! Outputs: [note_ptr]
#!
#! ASSET is the asset to be included in the note.
#! tag is the tag to be included in the note.
#! RECIPIENT is the recipient of the note.
#! ptr is the pointer to the memory address at which the note is stored.
#! note_ptr is the pointer to the memory address at which the note is stored.
#!
#! Panics if
#! - the note_type is not valid
#! - the note_tag is not an u32
#! - if note_tag starts with anything but 0b11, note_type must be public
#! - the number of created notes exceeds the maximum limit of 4096
export.create_note
# validate the asset
exec.asset::validate_asset
# => [ASSET, tag, note_type, RECIPIENT]

# validate the note type
# NOTE: encrypted notes are currently unsupported `dup.6 push.ENCRYPTED_NOTE eq or`
dup.5 push.OFFCHAIN_NOTE eq dup.6 push.PUBLIC_NOTE eq or assert.err=ERR_INVALID_NOTE_TYPE
# => [ASSET, tag, note_type, RECIPIENT]
# NOTE: encrypted notes are currently unsupported
dup.1 push.OFFCHAIN_NOTE eq dup.2 push.PUBLIC_NOTE eq or assert.err=ERR_INVALID_NOTE_TYPE
# => [tag, note_type, RECIPIENT]

# copy data to validate the tag
dup.5 push.PUBLIC_NOTE dup.1 dup.7
# => [tag, note_type, public_note, note_type, ASSET, tag, note_type, RECIPIENT]
dup.1 push.PUBLIC_NOTE dup.1 dup.3
# => [tag, note_type, public_note, note_type, tag, note_type, RECIPIENT]

u32assert.err=ERR_NOTE_TAG_MUST_BE_U32
# => [tag, note_type, public_note, note_type, ASSET, tag, note_type, RECIPIENT]
# => [tag, note_type, public_note, note_type, tag, note_type, RECIPIENT]

# enforce the note type depending on the tag's bits
u32shr.30 push.ALL_NOTE_TYPES_ALLOWED eq cdrop assert_eq.err=ERR_NOTE_INVALID_TYPE_FOR_TAG
# => [ASSET, tag, note_type, RECIPIENT]
# => [tag, note_type, RECIPIENT]

# get the index for the next note to be created and increment counter
exec.increment_num_created_notes
# => [note_idx, ASSET, tag, note_type, RECIPIENT]
# => [note_idx, tag, note_type, RECIPIENT]

# get a pointer to the memory address at which the note will be stored
exec.memory::get_created_note_ptr
# => [note_ptr, ASSET, tag, note_type, RECIPIENT]
# => [note_ptr, tag, note_type, RECIPIENT]

# populate the metadata
movup.5 exec.account::get_id movup.7
# => [note_type, sender_acct_id, tag, note_ptr, ASSET, RECIPIENT]
swap exec.account::get_id movup.3
# => [note_type, sender_acct_id, tag, note_ptr, RECIPIENT]

push.0 # TODO: allow the user to push the aux data
# => [aux, note_type, sender_acct_id, tag, note_ptr, ASSET, RECIPIENT]
# => [aux, note_type, sender_acct_id, tag, note_ptr, RECIPIENT]

emit.NEW_NOTE_EVENT

# set the metadata for the new created note
dup.4 exec.memory::set_created_note_metadata
# => [note_ptr, ASSET, RECIPIENT]

# set the number of assets for the note to 1
push.1 dup.1 exec.memory::set_created_note_num_assets
# => [note_ptr, ASSET, RECIPIENT]

movdn.4 padw swapw movup.8
# => [note_ptr, ASSET, 0, 0, 0, 0, RECIPIENT]

# add the asset to the note
dup movdn.5 exec.memory::get_created_note_asset_data_ptr mem_storew dropw
# => [note_ptr, 0, 0, 0, 0, RECIPIENT]

movdn.8 swapw padw swapw movup.12
# => [note_ptr, RECIPIENT, 0, 0, 0, 0, 0, 0, 0, 0]
# => [note_ptr, RECIPIENT]

# set the recipient
dup movdn.5 exec.memory::set_created_note_recipient
# => [note_ptr, 0, 0, 0, 0, 0, 0, 0, 0]
# => [note_ptr]
end

#! Adds an ASSET to the specified note and returns a pointer to the memory address
#! at which the note is stored.
#!
#! Panics if
#! - the ASSET is malformed (invalid faucet ID)
#! - the max amount of fungible assets is exceeded
#! - the non-fungible asset already exists in the note
#!
#! Inputs: [note_ptr, ASSET]
#! Outputs: [note_ptr]
#!
#! note_ptr is the pointer to the memory address at which the note is stored.
#! ASSET can be a fungible or non-fungible asset.
#!
#! Panics if
#! - the ASSET is malformed (invalid faucet ID)
#! - the max amount of fungible assets is exceeded
#! - the non-fungible asset already exists in the note
#! - the total number of ASSETs exceeds the maximum of 256
export.add_asset_to_note
# get current num of assets
dup exec.memory::get_created_note_num_assets movdn.5
Expand Down
7 changes: 3 additions & 4 deletions miden-lib/asm/miden/tx.masm
Original file line number Diff line number Diff line change
Expand Up @@ -58,20 +58,19 @@ end

#! Creates a new note and returns a pointer to the memory address at which the note is stored.
#!
#! Inputs: [ASSET, tag, note_type, RECIPIENT]
#! Inputs: [tag, note_type, RECIPIENT]
#! Outputs: [note_ptr]
#!
#! ASSET is the asset to be included in the note.
#! tag is the tag to be included in the note.
#! note_type is the storage type of the note
#! RECIPIENT is the recipient of the note.
#! note_ptr is the pointer to the memory address at which the note is stored.
export.create_note
syscall.create_note
# => [note_ptr, ZERO, ZERO, 0]
# => [note_ptr, ZERO, 0]

# clear the padding from the kernel response
movdn.8 dropw dropw swap drop
movdn.4 dropw swap drop
# => [note_ptr]
end

Expand Down
Loading

0 comments on commit 1808446

Please sign in to comment.