Skip to content

Commit

Permalink
feat: creating notes without assets
Browse files Browse the repository at this point in the history
  • Loading branch information
Dominik1999 committed May 10, 2024
1 parent 2ad6b0f commit df2e7de
Show file tree
Hide file tree
Showing 13 changed files with 145 additions and 138 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

## 0.3.0 (TBD)

* [BREAKING] Removed assets from `create_note` procedure and added new procedure `add_asset_to_note` (#228, #).
* Introduce the `miden-bench-tx` crate used for transactions benchmarking (#577).
* [BREAKING] Removed the transaction script root output from the transaction kernel (#608).
* [BREAKING] Refactored account update details, moved `Block` to `miden-objects` (#618, #621).
Expand Down
52 changes: 30 additions & 22 deletions docs/architecture/accounts.md
Original file line number Diff line number Diff line change
Expand Up @@ -106,33 +106,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 @@ -153,7 +161,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
10 changes: 9 additions & 1 deletion miden-lib/asm/miden/contracts/faucets/basic_fungible.masm
Original file line number Diff line number Diff line change
Expand Up @@ -72,9 +72,17 @@ export.distribute
exec.faucet::mint
# => [ASSET, tag, note_type, RECIPIENT, ...]

# 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 @@ -99,4 +107,4 @@ export.burn
# clear the stack
padw swapw dropw
# => [...]
end
end
19 changes: 16 additions & 3 deletions miden-lib/asm/miden/contracts/wallets/basic.masm
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,10 @@ export.send_asset
exec.account::remove_asset
# => [ASSET, tag, note_type, RECIPIENT, ...]

# Store the ASSET for later
mem_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 mem_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
56 changes: 20 additions & 36 deletions miden-lib/asm/miden/kernels/tx/tx.masm
Original file line number Diff line number Diff line change
Expand Up @@ -242,73 +242,57 @@ proc.add_fungible_asset_to_note
end

#! Creates a new note and returns a pointer to the memory address at which the note is stored.
#! Panis if
#! - the note_type is not valid
#! - the note_tag is not an u32
#!
#! 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, 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.
#! 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
# 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
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 df2e7de

Please sign in to comment.