Skip to content

Commit

Permalink
fix #600
Browse files Browse the repository at this point in the history
  • Loading branch information
hackaugusto committed May 27, 2024
1 parent 0e5ccd5 commit 37d9765
Show file tree
Hide file tree
Showing 13 changed files with 115 additions and 161 deletions.
18 changes: 7 additions & 11 deletions miden-lib/asm/kernels/transaction/api.masm
Original file line number Diff line number Diff line change
Expand Up @@ -410,23 +410,19 @@ export.get_note_vault_info
# => [VAULT_HASH, num_assets]
end

#! Returns the number of inputs and inputs hash for the note currently being processed. Panics if
#! a note is not being processed.
#! Returns the current note's inputs hash.
#!
#! Inputs: [0, 0, 0, 0, 0]
#! Outputs: [NOTE_INPUTS_HASH, num_inputs]
#! Inputs: [ZERO]
#! Outputs: [NOTE_INPUTS_HASH]
#!
#! Where:
#! - num_inputs is the number of inputs associated with the note.
#! - NOTE_INPUTS_HASH is the note inputs hash of the note currently being processed.
#! - NOTE_INPUTS_HASH, is the current note's inputs hash.
export.get_note_inputs_hash
# get the number of inputs and the inputs hash
exec.note::get_note_inputs_hash
# => [NOTE_INPUTS_HASH, num_inputs, 0, 0, 0, 0, 0]
# => [NOTE_INPUTS_HASH, ZERO]

# organize the stack for return
movup.5 drop movup.5 drop movup.5 drop movup.5 drop movup.5 drop
# => [NOTE_INPUTS_HASH, num_inputs]
swapw dropw
# => [NOTE_INPUTS_HASH]
end

#! Returns the sender of the note currently being processed. Panics if a note is not being
Expand Down
25 changes: 0 additions & 25 deletions miden-lib/asm/miden/kernels/tx/memory.masm
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,6 @@ const.CONSUMED_NOTE_INPUTS_HASH_OFFSET=3
const.CONSUMED_NOTE_ASSETS_HASH_OFFSET=4
const.CONSUMED_NOTE_METADATA_OFFSET=5
const.CONSUMED_NOTE_ARGS_OFFSET=6
const.CONSUMED_NOTE_NUM_INPUTS_OFFSET=7
const.CONSUMED_NOTE_NUM_ASSETS_OFFSET=8
const.CONSUMED_NOTE_ASSETS_OFFSET=9

Expand Down Expand Up @@ -898,30 +897,6 @@ export.set_consumed_note_args
mem_storew dropw
end

#! Returns the number of inputs for the consumed note located at the specified memory address.
#!
#! Stack: [consumed_note_ptr]
#! Output: [num_inputs]
#!
#! - consumed_note_ptr is the memory address at which the consumed note data begins.
#! - num_inputs is the number of inputs defined for the consumed note.
export.get_consumed_note_num_inputs
push.CONSUMED_NOTE_NUM_INPUTS_OFFSET add
mem_load
end

#! Sets the number of inputs for a consumed note located at the specified memory address.
#!
#! Stack: [consumed_note_ptr, num_inputs]
#! Output: []
#!
#! - consumed_note_ptr is the memory address at which the consumed note data begins.
#! - num_inputs is the number of inputs for the consumed note.
export.set_consumed_note_num_inputs
push.CONSUMED_NOTE_NUM_INPUTS_OFFSET add
mem_store
end

#! Returns the number of assets in the consumed note located at the specified memory address.
#!
#! Stack: [consumed_note_ptr]
Expand Down
24 changes: 10 additions & 14 deletions miden-lib/asm/miden/kernels/tx/note.masm
Original file line number Diff line number Diff line change
Expand Up @@ -77,31 +77,27 @@ export.get_vault_info
# => [VAULT_HASH, num_assets]
end

#! Returns the number of inputs and inputs hash for the note currently being processed. Panics if
#! a note is not being processed.
#! Returns the commitment to the note's inputs.
#!
#! Panics if a note is not being processed.
#!
#! Inputs: []
#! Outputs: [NOTE_INPUTS_HASH, num_inputs]
#! Outputs: [NOTE_INPUTS_HASH]
#!
#! - num_inputs is the number of inputs associated with the note.
#! Where:
#! - NOTE_INPUTS_HASH is the note inputs hash of the note currently being processed.
export.get_note_inputs_hash
# get the current consumed note pointer
exec.memory::get_current_consumed_note_ptr
# => [ptr]

# assert the pointer is not zero - this would suggest the procedure has been called from an
# incorrect context
# The kernel memory is initialized by prologue::process_input_notes_data.
# If the value is `0` it is likely this procedure is being called outside
# of the kernel context
dup neq.0 assert.err=ERR_NOTE_INVALID_INPUTS
# => [ptr]

# get the number of inputs for the note
dup exec.memory::get_consumed_note_num_inputs
# => [num_inputs, ptr]

# get the note inputs hash from the note pointer
swap exec.memory::get_consumed_note_inputs_hash
# => [NOTE_INPUTS_HASH, num_inputs]
exec.memory::get_consumed_note_inputs_hash
# => [NOTE_INPUTS_HASH]
end

#! Increment current consumed note pointer to the next note and returns the pointer value.
Expand Down
30 changes: 4 additions & 26 deletions miden-lib/asm/miden/kernels/tx/prologue.masm
Original file line number Diff line number Diff line change
Expand Up @@ -59,9 +59,6 @@ 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

# Number of note inputs exceeded the maximum limit of 128
const.ERR_PROLOGUE_NOTE_TOO_MANY_INPUTS=0x0002001B

# Number of note assets exceeded the maximum limit of 256
const.ERR_PROLOGUE_NOTE_TOO_MANY_ASSETS=0x0002001C

Expand Down Expand Up @@ -162,7 +159,7 @@ end
#! This procedure loads the MMR peaks from the advice provider, verifies their hash matches the
#! reference block, and insert the reference block in the MMR. The reference block is added to the
#! MMR so that notes created at this block can be consumed, since the MMR can't contain it and is
#! always one block behind. The number MMR peaks in is variable, from 16 up to 63, depending on
#! always one block behind. The number MMR peaks is variable, from 16 up to 63, depending on
#! `num_blocks`.
#!
#! Stack: []
Expand Down Expand Up @@ -564,7 +561,6 @@ end
#! ASSETS_HASH,
#! METADATA,
#! ARGS,
#! inputs_count,
#! assets_count,
#! ASSET_0, ..., ASSET_N,
#! block_num,
Expand Down Expand Up @@ -621,18 +617,6 @@ proc.process_input_note
padw adv_loadw dup.4 exec.memory::set_consumed_note_args
# => [note_ptr]

# number of inputs
# ---------------------------------------------------------------------------------------------

adv_push.1
# => [num_inputs, note_ptr]

dup exec.constants::get_max_inputs_per_note lte assert.err=ERR_PROLOGUE_NOTE_TOO_MANY_INPUTS
# => [num_inputs, note_ptr]

dup.1 exec.memory::set_consumed_note_num_inputs
# => [note_ptr]

# assets
# ---------------------------------------------------------------------------------------------

Expand Down Expand Up @@ -761,19 +745,13 @@ end
#!
#! Stack: []
#! Advice stack: [num_notes],
#! Advice map: { NULLIFIER_COMMITMENT => [(SERIAL_NUMBER, SCRIPT_ROOT, INPUTS_HASH, ASSETS_HASH, METADATA, NA, A0, ..., An){num_notes}] }
#! Advice map: { NULLIFIER_COMMITMENT => NOTE_DATA }
#! Output: []
#!
#! Where:
#! - num_notes is the number of input notes.
#! - NULLIFIER_COMMITMENT, sequential hash of all input notes' nullifiers.
#! - SERIAL_NUMBER, note's serial.
#! - SCRIPT_ROOT, note's script root.
#! - INPUTS_HASH, sequential hash of the padded note's inputs.
#! - ASSETS_HASH, sequential hash of the padded note's assets.
#! - METADATA, note's metadata.
#! - NA are optional note args for the nth input note.
#! - A0..An are the assets of the nth input note.
#! - NOTE_DATA, input notes' details, for format see prologue::process_input_note.
proc.process_input_notes_data
# get the number of input notes from the advice stack
adv_push.1
Expand Down Expand Up @@ -952,7 +930,7 @@ end
#! - number_of_input_notes, number of input notes.
#! - TX_SCRIPT_ROOT, the transaction's script root.
#! - MMR_PEAKS, is the MMR peak data, see process_chain_data
#! - NOTE_DATA, is the data of all input notes, see process_input_notes_data
#! - NOTE_DATA, input notes' details, for format see prologue::process_input_note.
export.prepare_transaction
exec.process_global_inputs
# => []
Expand Down
25 changes: 18 additions & 7 deletions miden-lib/asm/miden/note.masm
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use.miden::kernels::tx::constants
use.std::crypto::hashes::native
use.std::mem

Expand All @@ -7,6 +8,9 @@ use.std::mem
# Provided note data does not match the commitment
const.ERR_NOTE_DATA_MISMATCH=0x00020040

# Number of note inputs exceeded the maximum limit of 128
const.ERR_NOTE_TOO_MANY_INPUTS=0x0002001B

#! 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.
#!
Expand Down Expand Up @@ -70,23 +74,30 @@ end
#!
#! Inputs: [dest_ptr]
#! Outputs: [num_inputs, dest_ptr]
#! Advice Map: { INPUTS_HASH: INPUTS }
#! Advice Map: { INPUTS_HASH: [inputs_len, INPUTS] }
#!
#! Where:
#! - dest_ptr is the memory address to write the inputs.
#! - INPUTS_HASH, sequential hash of the padded note's inputs.
#! - inputs_len, the note's input count.
#! - INPUTS, the data corresponding to the note's inputs.
export.get_inputs
# get the current consumed note inputs hash
padw push.0 syscall.get_note_inputs_hash
# => [INPUTS_HASH, num_inputs, dest_ptr]
padw syscall.get_note_inputs_hash
# => [INPUTS_HASH, dest_ptr]

# load the inputs from the advice map to the advice stack
adv.push_mapval
# => [INPUTS_HASH, num_inputs, dest_ptr]
# => [INPUTS_HASH, dest_ptr]

adv_push.1
# => [num_inputs, INPUTS_HASH, dest_ptr]

# validate the input length
dup exec.constants::get_max_inputs_per_note lte assert.err=ERR_NOTE_TOO_MANY_INPUTS
# => [num_inputs, INPUTS_HASH, dest_ptr]

# calculate the number of words required to store the inputs
dup.4 u32divmod.4 neq.0 add
dup movdn.5 u32divmod.4 neq.0 add
# => [num_words, INPUTS_HASH, num_inputs, dest_ptr]

# round up the number of words the next multiple of 2
Expand All @@ -97,7 +108,7 @@ export.get_inputs
dup.6 add dup.6
# => [start_ptr, end_ptr, INPUTS_HASH, num_inputs, dest_ptr]

# write the data from the advice stack into memory
# check the input data matches the commitment, and write it to memory.
exec.write_advice_data_to_memory
# => [num_inputs, dest_ptr]
end
Expand Down
16 changes: 5 additions & 11 deletions miden-lib/src/tests/test_prologue.rs
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ use crate::transaction::{
CHAIN_MMR_NUM_LEAVES_PTR, CHAIN_MMR_PEAKS_PTR, CHAIN_ROOT_PTR, CONSUMED_NOTE_ARGS_OFFSET,
CONSUMED_NOTE_ASSETS_HASH_OFFSET, CONSUMED_NOTE_ASSETS_OFFSET, CONSUMED_NOTE_ID_OFFSET,
CONSUMED_NOTE_INPUTS_HASH_OFFSET, CONSUMED_NOTE_METADATA_OFFSET,
CONSUMED_NOTE_NUM_ASSETS_OFFSET, CONSUMED_NOTE_NUM_INPUTS_OFFSET,
CONSUMED_NOTE_SCRIPT_ROOT_OFFSET, CONSUMED_NOTE_SECTION_OFFSET,
CONSUMED_NOTE_SERIAL_NUM_OFFSET, INIT_ACCT_HASH_PTR, INIT_NONCE_PTR, NOTE_ROOT_PTR,
NULLIFIER_COMMITMENT_PTR, NULLIFIER_DB_ROOT_PTR, PREV_BLOCK_HASH_PTR, PROOF_HASH_PTR,
PROTOCOL_VERSION_IDX, TIMESTAMP_IDX, TX_SCRIPT_ROOT_PTR,
CONSUMED_NOTE_NUM_ASSETS_OFFSET, CONSUMED_NOTE_SCRIPT_ROOT_OFFSET,
CONSUMED_NOTE_SECTION_OFFSET, CONSUMED_NOTE_SERIAL_NUM_OFFSET, INIT_ACCT_HASH_PTR,
INIT_NONCE_PTR, NOTE_ROOT_PTR, NULLIFIER_COMMITMENT_PTR, NULLIFIER_DB_ROOT_PTR,
PREV_BLOCK_HASH_PTR, PROOF_HASH_PTR, PROTOCOL_VERSION_IDX, TIMESTAMP_IDX,
TX_SCRIPT_ROOT_PTR,
},
TransactionKernel,
};
Expand Down Expand Up @@ -320,12 +320,6 @@ fn consumed_notes_memory_assertions(
"note args should be stored at the correct offset"
);

assert_eq!(
read_note_element(process, note_idx, CONSUMED_NOTE_NUM_INPUTS_OFFSET),
[Felt::from(note.inputs().num_values() as u32), ZERO, ZERO, ZERO],
"number of inputs should be stored at the correct offset"
);

assert_eq!(
read_note_element(process, note_idx, CONSUMED_NOTE_NUM_ASSETS_OFFSET),
[Felt::from(note.assets().num_assets() as u32), ZERO, ZERO, ZERO],
Expand Down
12 changes: 12 additions & 0 deletions miden-lib/src/transaction/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,11 @@ use miden_objects::{
pub enum TransactionKernelError {
FailedToAddAssetToNote(NoteError),
InvalidStorageSlotIndex(u64),
InvalidNoteInputs {
expected: Digest,
got: Digest,
data: Option<Vec<Felt>>,
},
MalformedAccountId(AccountError),
MalformedAsset(AssetError),
MalformedAssetOnAccountVaultUpdate(AssetError),
Expand All @@ -39,6 +44,13 @@ impl fmt::Display for TransactionKernelError {
let num_slots = AccountStorage::NUM_STORAGE_SLOTS;
write!(f, "storage slot index {index} is invalid, must be smaller than {num_slots}")
},
TransactionKernelError::InvalidNoteInputs { expected, got, data } => {
write!(
f,
"The note input data does not match its hash, expected: {} got: {} data {:?}",
expected, got, data
)
},
TransactionKernelError::MalformedAccountId(err) => {
write!( f, "Account id data extracted from the stack by the event handler is not well formed {err}")
},
Expand Down
48 changes: 13 additions & 35 deletions miden-lib/src/transaction/inputs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -262,37 +262,14 @@ fn add_account_to_advice_inputs(

/// Populates the advice inputs for all input notes.
///
/// For each note the authentication path is populated into the Merkle store, the note inputs
/// and assets are populated in the advice map.
/// The advice provider is populated with:
///
/// A combined note data vector is also constructed that holds core data for all notes. This
/// combined vector is added to the advice map against the input notes commitment. For each note
/// the following data items are added to the vector:
/// out[0..4] = serial_num
/// out[4..8] = script_root
/// out[8..12] = inputs_hash
/// out[12..16] = assets_hash
/// out[16..20] = metadata
/// out[20..24] = note_args
/// out[24] = num_inputs
/// out[25] = num_assets
/// out[26..30] = asset_1
/// out[30..34] = asset_2
/// ...
/// out[34 + num_assets * 4..] = Word::default() (this is conditional padding only applied
/// if the number of assets is odd)
/// out[-10] = origin.block_number
/// out[-9..-5] = origin.SUB_HASH
/// out[-5..-1] = origin.NOTE_ROOT
/// out[-1] = origin.node_index
/// - For each note:
/// - The note's authentication path against its block's note tree.
/// - The note's input padded prefixed by its length.
/// - The note's asset padded.
/// - And all notes details together under the nullifier commitment.
///
/// Inserts the following items into the Merkle store:
/// - The Merkle nodes associated with the note's authentication path.
///
/// Inserts the following entries into the advice map:
/// - inputs_hash |-> inputs
/// - asset_hash |-> assets
/// - notes_hash |-> combined note data
fn add_input_notes_to_advice_inputs(
notes: &InputNotes,
tx_args: &TransactionArgs,
Expand All @@ -311,9 +288,12 @@ fn add_input_notes_to_advice_inputs(
let recipient = note.recipient();
let note_arg = tx_args.get_note_args(note.id()).unwrap_or(&[ZERO; 4]);

// insert note inputs and assets into the advice map
inputs
.extend_map([(recipient.inputs().commitment(), recipient.inputs().to_padded_values())]);
// NOTE: keep map in sync with the `note::get_inputs` API procedure
inputs.extend_map([(
recipient.inputs().commitment(),
recipient.inputs().format_for_advice(),
)]);

inputs.extend_map([(assets.commitment(), assets.to_padded_assets())]);

// insert note authentication path nodes into the Merkle store
Expand All @@ -333,8 +313,6 @@ fn add_input_notes_to_advice_inputs(
note_data.extend(Word::from(note.metadata()));
note_data.extend(Word::from(*note_arg));

note_data.push(recipient.inputs().num_values().into());

note_data.push((assets.num_assets() as u32).into());
note_data.extend(assets.to_padded_assets());

Expand All @@ -351,6 +329,6 @@ fn add_input_notes_to_advice_inputs(
);
}

// insert the combined note data into the advice map
// NOTE: keep map in sync with the `process_input_notes_data` kernel procedure
inputs.extend_map([(notes.nullifier_commitment(), note_data)]);
}
1 change: 0 additions & 1 deletion miden-lib/src/transaction/memory.rs
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,6 @@ pub const CONSUMED_NOTE_INPUTS_HASH_OFFSET: MemoryOffset = 3;
pub const CONSUMED_NOTE_ASSETS_HASH_OFFSET: MemoryOffset = 4;
pub const CONSUMED_NOTE_METADATA_OFFSET: MemoryOffset = 5;
pub const CONSUMED_NOTE_ARGS_OFFSET: MemoryOffset = 6;
pub const CONSUMED_NOTE_NUM_INPUTS_OFFSET: MemoryOffset = 7;
pub const CONSUMED_NOTE_NUM_ASSETS_OFFSET: MemoryOffset = 8;
pub const CONSUMED_NOTE_ASSETS_OFFSET: MemoryOffset = 9;

Expand Down
Loading

0 comments on commit 37d9765

Please sign in to comment.