Skip to content

Commit

Permalink
feat: send_note without hash check
Browse files Browse the repository at this point in the history
  • Loading branch information
Fumuran committed Jul 31, 2024
1 parent 18d86ab commit 34492d8
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 42 deletions.
57 changes: 28 additions & 29 deletions miden-lib/asm/miden/contracts/wallets/basic.masm
Original file line number Diff line number Diff line change
Expand Up @@ -78,19 +78,16 @@ end
#! specified recipient. The key difference with the `send_asset` procedure is that `send_node`
#! allows to create notes without assets whatsoever.
#!
#! Inputs: [tag, aux, note_type, RECIPIENT, num_assets, assets_ptr, ...]
#! Outputs: [note_idx, EMPTY_WORD, EMPTY_WORD, ...]
#! Inputs stack: [tag, aux, note_type, RECIPIENT, ...]
#! Advice stack: [num_assets_felt, [ASSETS]]
#! Outputs: [note_idx, 0, 0, EMPTY_WORD, ...]
#!
#! - num_assets is the number of assets to be added to the note.
#! - assets_ptr is the memory pointer to the array of assets which are going to be added to the
#! note.
#! - num_assets_felt is the number of Felts which constitute the assets to be added to the note.
#! - tag is the tag to be included in the note.
#! - aux is the auxiliary data to be included in the note.
#! - note_type is the note's storage type
#! - RECIPIENT is the recipient of the note, i.e.,
#! hash(hash(hash(serial_num, [0; 4]), script_hash), input_hash)
#! - note_idx is the index of the output note.
#! This cannot directly be accessed from another context.
#!
#! Panics:
#! - The fungible asset is not found in the vault.
Expand All @@ -109,60 +106,62 @@ export.send_note
# 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.0 movdn.12 movdn.12 movdn.12 padw movdnw.3
# => [tag, aux, note_type, RECIPIENT, num_assets, assets_ptr, 0, 0, 0, EMPTY_WORD, ...]
push.0 movdn.11 padw movdnw.3 padw movdnw.3
# => [tag, aux, note_type, RECIPIENT, 0, EMPTY_WORD, EMPTY_WORD, ...]

exec.tx::create_note
swap drop # TODO: remove this line after bug in the api.masm `create_note` procedure will be
# fixed
# => [note_idx, num_assets, assets_ptr, 0, 0, 0, EMPTY_WORD, ...]
# => [note_idx, 0, EMPTY_WORD, EMPTY_WORD, ...]

# get the number of assets
# we need to divide the num_assets_felt by 4 to get the number of assets
adv_push.1 div.4
# => [num_assets, note_idx, 0, EMPTY_WORD, EMPTY_WORD, ...]

# Iterate over the assets and add them to the note
#
# The loop variable is changed with an add instead of sub because the former
# uses one fewer cycle. So here the counter is negated. (1 cycles)
# => [-num_assets, note_idx, assets_ptr, 0, 0, 0, EMPTY_WORD, ...]
swap neg
# => [-num_assets, note_idx, 0, EMPTY_WORD, EMPTY_WORD, ...]
neg

# Pad the stack (4 cycles)
padw
# => [EMPTY_WORD, -num_assets, note_idx, assets_ptr, 0, 0, 0, EMPTY_WORD, ...]
# => [EMPTY_WORD, -num_assets, note_idx, 0, EMPTY_WORD, EMPTY_WORD, ...]

# check loop condition (3 cycles)
dup.4 neq.0
# => [b, EMPTY_WORD, -num_assets, note_idx, assets_ptr, 0, 0, 0, EMPTY_WORD, ...]
# => [b, EMPTY_WORD, -num_assets, note_idx, 0, EMPTY_WORD, EMPTY_WORD, ...]

# while num_assets != 0
while.true
# perform read (2 cycles)
dup.6

mem_loadw
# => [ASSET, -num_assets, note_idx, assets_ptr, 0, 0, 0, EMPTY_WORD, ...]
adv_loadw
# => [ASSET, -num_assets, note_idx, 0, EMPTY_WORD, EMPTY_WORD, ...]

# remove the loaded asset
exec.account::remove_asset
# => [ASSET, -num_assets, note_idx, assets_ptr, 0, 0, 0, EMPTY_WORD, ...]
# => [ASSET, -num_assets, note_idx, 0, EMPTY_WORD, EMPTY_WORD...]

# add current asset to the node
movup.5 exec.tx::add_asset_to_note
# => [note_idx, -num_assets, assets_ptr, 0, 0, 0, EMPTY_WORD, ...]
# => [note_idx, -num_assets, 0, EMPTY_WORD, EMPTY_WORD, ...]

# update counters
swap add.1 movup.2 add.1 movdn.2
# => [-num_assets+1, note_idx, assets_ptr+1, 0, 0, 0, EMPTY_WORD, ...]
swap add.1
# => [-num_assets+1, note_idx, 0, EMPTY_WORD, EMPTY_WORD, ...]

# Pad the stack (4 cycles)
padw
# => [EMPTY_WORD, -num_assets+1, note_idx, assets_ptr+1, 0, 0, 0, EMPTY_WORD, ...]
# => [EMPTY_WORD, -num_assets+1, note_idx, 0, EMPTY_WORD, EMPTY_WORD, ...]

# check loop condition (3 cycles)
dup.4 neq.0
# => [b, EMPTY_WORD, -num_assets+1, note_idx, assets_ptr+1, 0, 0, 0, EMPTY_WORD, ...]
# => [b, EMPTY_WORD, -num_assets+1, note_idx, 0, EMPTY_WORD, EMPTY_WORD, ...]
end
# => [EMPTY_WORD, -num_assets+1, note_idx, 0, EMPTY_WORD, EMPTY_WORD, ...]

# clean the stack
# note: use `num_assets` as a 0 here
dropw drop movup.2 drop swap
# => [note_idx, EMPTY_WORD, EMPTY_WORD, ...]
end
dropw swap movdn.4 dropw
# => [note_idx, 0, 0, EMPTY_WORD, ...]
end
29 changes: 17 additions & 12 deletions miden-tx/src/tests/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ use miden_objects::{
storage::{STORAGE_INDEX_0, STORAGE_INDEX_2},
},
transaction::{ProvenTransaction, TransactionArgs, TransactionWitness},
Felt, Word, MIN_PROOF_SECURITY_LEVEL,
Felt, Hasher, Word, MIN_PROOF_SECURITY_LEVEL,
};
use miden_prover::ProvingOptions;
use vm_processor::{
Expand Down Expand Up @@ -456,6 +456,13 @@ fn test_send_note_proc() {
Asset::mock_non_fungible(ACCOUNT_ID_NON_FUNGIBLE_FAUCET_ON_CHAIN, &NON_FUNGIBLE_ASSET_DATA);

let removed_assets = [removed_asset_1, removed_asset_2, removed_asset_3];
let removed_assets_felt = removed_assets
.iter()
.flat_map(<&Asset as Into<Word>>::into)
.collect::<Vec<Felt>>();

let sequential_assets_hash = Hasher::hash_elements(&removed_assets_felt).into();
let advice_map = vec![(sequential_assets_hash, removed_assets_felt)];

let tag = NoteTag::from_account_id(
ACCOUNT_ID_REGULAR_ACCOUNT_IMMUTABLE_CODE_ON_CHAIN.try_into().unwrap(),
Expand Down Expand Up @@ -488,16 +495,16 @@ fn test_send_note_proc() {
## ========================================================================================
begin
dropw
# store assets to the memory
push.{REMOVED_ASSET_1} mem_storew.1000 dropw # asset 1
push.{REMOVED_ASSET_2} mem_storew.1001 dropw # asset 2
push.{REMOVED_ASSET_3} mem_storew.1002 dropw # asset 3
# get the assets from the advice map to the advice stack
push.{ASSETS_HASH}
adv.push_mapvaln
dropw
push.1000.0 # assets pointer and number of assets
push.0.1.2.3 # recipient
push.{NOTETYPE} # note_type
push.{note_type} # note_type
push.{aux} # aux
push.{tag} # tag
# => [tag, aux, note_type, RECIPIENT, ...]
call.wallet::send_note
dropw dropw dropw dropw
Expand All @@ -508,13 +515,11 @@ fn test_send_note_proc() {
# => []
end
",
REMOVED_ASSET_1 = prepare_word(&Word::from(removed_asset_1)),
REMOVED_ASSET_2 = prepare_word(&Word::from(removed_asset_2)),
REMOVED_ASSET_3 = prepare_word(&Word::from(removed_asset_3)),
NOTETYPE = note_type as u8,
ASSETS_HASH = prepare_word(&sequential_assets_hash),
note_type = note_type as u8,
);
let tx_script_code = ProgramAst::parse(&tx_script).unwrap();
let tx_script = executor.compile_tx_script(tx_script_code, vec![], vec![]).unwrap();
let tx_script = executor.compile_tx_script(tx_script_code, advice_map, vec![]).unwrap();
let tx_args = TransactionArgs::new(
Some(tx_script),
None,
Expand Down
2 changes: 1 addition & 1 deletion objects/src/testing/account_code.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use crate::accounts::AccountCode;
const MASTS: [&str; 12] = [
"0xe3c24a1109379344874ac5dec91a6311e5563d0194ded29b44ed71535e78b34a",
"0x52fd1b2cdbffd91778bc4c31ff939a03c8921461a628bdd91fe3e0a1d3be2b50",
"0xa2c23e054de8066c5b0e4ba382ab0882f26632d23abd5a0f9fafe2bee4442d94",
"0xde47979f6039e875f0897a748a0291a323d40a298acc1b1bdd6b2dc3a3adc43c",
"0x28c514e509fc044a2ea6cddbab0abf2b5fa589d5c91978ae9c935ab40e6ec402",
"0xa61cdf8c75943d293ffcfca73ea07a6639dad1820d64586a2a292bb9f80a4296",
"0x6877f03ef52e490f7c9e41b297fb79bb78075ff28c6e018aaa1ee30f73e7ea4b",
Expand Down

0 comments on commit 34492d8

Please sign in to comment.