Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add new get_script_hash kernel procedure #995

Merged
merged 11 commits into from
Dec 2, 2024
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] Add error messages to errors and implement `core::error::Error` (#974).
- Implemented new `digest_from_hex!` macro (#984).
- Added Format Guidebook to the `miden-lib` crate (#987).
- Added `miden::note::get_script_hash` procedure (#995).
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we should note this change as breaking, since it changes the offsets of the kernel procedures.


## 0.6.2 (2024-11-20)

Expand Down
2 changes: 2 additions & 0 deletions docs/architecture/transactions/procedures.md
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@ To import the note procedures, set `use.miden::note` at the beginning of the fil
| `get_inputs` | `[dest_ptr]` | `[dest_ptr]` | note | <ul> <li>Writes the inputs of the currently executed note into memory starting at the specified address, `dest_ptr`. </li> </ul> |
| `get_sender` | `[]` | `[sender]` | note | <ul> <li>Returns the `sender` of the note currently being processed. Panics if a note is not being processed. </li> </ul> |
| `compute_inputs_hash` | `[inputs_ptr, num_inputs]` | `[HASH]` | note | <ul> <li>Computes hash of note inputs starting at the specified memory address.</li> </ul> |
| `get_note_serial_number`| `[]` | `[SERIAL_NUMBER]` | note | <ul> <li>Returns the serial number of the note currently being processed.</li> </ul> |
| `get_script_hash` | `[]` | `[SCRIPT_HASH]` | note | <ul> <li>Returns the script hash of the note currently being processed.</li> </ul> |

### Tx

Expand Down
21 changes: 21 additions & 0 deletions miden-lib/asm/kernels/transaction/api.masm
Original file line number Diff line number Diff line change
Expand Up @@ -852,6 +852,27 @@ export.get_note_serial_number
# => [SERIAL_NUMBER, pad(12)]
end

#! Returns the script hash of the note currently being processed.
#!
#! Inputs: [pad(16)]
#! Outputs: [SCRIPT_HASH, pad(12)]
#!
#! Where:
#! - SCRIPT_HASH is the script hash of the note currently being processed.
#!
#! Panics if:
#! - no note is not being processed.
#!
#! Invocation: dynexec
export.get_script_hash
exec.note::get_script_hash
# => [SCRIPT_HASH, pad(16)]

# truncate the stack
swapw dropw
# => [SCRIPT_HASH, pad(12)]
end

#! Tells the transaction kernel that we are about to execute a procedure on a foreign account.
#!
#! Checks whether the current foreign account was already loaded to the memory, and loads it if not.
Expand Down
18 changes: 18 additions & 0 deletions miden-lib/asm/kernels/transaction/lib/note.masm
Original file line number Diff line number Diff line change
Expand Up @@ -337,3 +337,21 @@ export.get_serial_number
exec.memory::get_input_note_serial_num
# => [SERIAL_NUMBER, ...]
end

#! Returns the script hash of the note currently being processed.
#!
#! Inputs: []
#! Outputs: [SCRIPT_HASH]
#!
#! Where:
#! - SCRIPT_HASH is the serial number of the note currently being processed.
#!
#! Panics if:
#! - no note is being processed.
export.get_script_hash
exec.memory::get_current_input_note_ptr
# => [note_ptr]

exec.memory::get_input_note_script_root
# => [SCRIPT_HASH]
end
27 changes: 20 additions & 7 deletions miden-lib/asm/miden/kernel_proc_offsets.masm
Original file line number Diff line number Diff line change
Expand Up @@ -31,15 +31,16 @@ const.GET_NOTE_ASSETS_INFO_OFFSET=21
const.GET_NOTE_INPUTS_HASH_OFFSET=22
const.GET_NOTE_SENDER_OFFSET=23
const.GET_NOTE_SERIAL_NUMBER_OFFSET=24
const.GET_OUTPUT_NOTES_COMMITMENT_OFFSET=25
const.GET_SCRIPT_HASH_OFFSET=25
const.GET_OUTPUT_NOTES_COMMITMENT_OFFSET=26

# Transaction
const.GET_BLOCK_HASH_OFFSET=26
const.GET_BLOCK_NUMBER_OFFSET=27
const.START_FOREIGN_CONTEXT_OFFSET=28
const.END_FOREIGN_CONTEXT_OFFSET=29
const.UPDATE_EXPIRATION_BLOCK_NUM_OFFSET=30
const.GET_EXPIRATION_DELTA_OFFSET=31
const.GET_BLOCK_HASH_OFFSET=27
const.GET_BLOCK_NUMBER_OFFSET=28
const.START_FOREIGN_CONTEXT_OFFSET=29
const.END_FOREIGN_CONTEXT_OFFSET=30
const.UPDATE_EXPIRATION_BLOCK_NUM_OFFSET=31
const.GET_EXPIRATION_DELTA_OFFSET=32

# ACCESSORS
# -------------------------------------------------------------------------------------------------
Expand Down Expand Up @@ -404,6 +405,18 @@ export.get_note_serial_number_offset
push.GET_NOTE_SERIAL_NUMBER_OFFSET
end

#! Returns an offset of the `get_script_hash` kernel procedure.
#!
#! Inputs: []
#! Outputs: [proc_offset]
#!
#! Where:
#! - proc_offset is the offset of the `get_script_hash` kernel procedure required to get the
#! address where this procedure is stored.
export.get_script_hash_offset
push.GET_SCRIPT_HASH_OFFSET
end

#! Returns an offset of the `start_foreign_context` kernel procedure.
#!
#! Inputs: []
Expand Down
28 changes: 28 additions & 0 deletions miden-lib/asm/miden/note.masm
Original file line number Diff line number Diff line change
Expand Up @@ -225,6 +225,34 @@ export.compute_inputs_hash
# => [HASH]
end

#! Returns the script hash of the note currently being processed.
#!
#! Inputs: []
#! Outputs: [SCRIPT_HASH]
#!
#! Where:
#! - SCRIPT_HASH is the script hash of the note currently being processed.
#!
#! Panics if:
#! - no note is being processed.
#!
#! Invocation: exec
export.get_script_hash
# pad the stack
padw padw padw push.0.0.0
# => [pad(15)]

exec.kernel_proc_offsets::get_script_hash_offset
# => [offset, pad(15)]

syscall.exec_kernel_proc
# => [SCRIPT_HASH, pad(12)]

# clean the stack
swapdw dropw dropw swapw dropw
# => [SCRIPT_HASH]
end

# PROCEDURES COPIED FROM KERNEL (TODO: get rid of this duplication)
# =================================================================================================

Expand Down
4 changes: 3 additions & 1 deletion miden-lib/src/transaction/procedures/kernel_v0.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ use miden_objects::{digest, Digest};
// ================================================================================================

/// Hashes of all dynamically executed procedures from the kernel 0.
pub const KERNEL0_PROCEDURES: [Digest; 32] = [
pub const KERNEL0_PROCEDURES: [Digest; 33] = [
// account_vault_add_asset
digest!("0xc69b608da541fea9a41322359cc049cac55f816858f530005e333d0b54f2f284"),
// account_vault_get_balance
Expand Down Expand Up @@ -57,6 +57,8 @@ pub const KERNEL0_PROCEDURES: [Digest; 32] = [
digest!("0xc579a0432b8f7b9640c13ab3f73c8afb6f0aa409b14a3cfaff536e60d04ea2fd"),
// get_note_serial_number
digest!("0xad91130ec219756213c6cadeaf8a38de8768e50c620cb7c347c531874c6054b6"),
// get_script_hash
digest!("0x82a32c90566e7de09e99b2151851c77a6b4117aa05aba20fe7d8244f065d6870"),
// get_output_notes_commitment
digest!("0x5d5aa6e32c3e7eafa7dd16683c090cd260c84d980199029d98ea7d5cec68998a"),
// get_block_hash
Expand Down
33 changes: 28 additions & 5 deletions miden-tx/src/tests/kernel_tests/test_note.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ use miden_lib::{
use miden_objects::{
notes::Note, testing::prepare_word, transaction::TransactionArgs, Hasher, WORD_SIZE,
};
use vm_processor::{ProcessState, EMPTY_WORD, ONE};
use vm_processor::{ProcessState, Word, EMPTY_WORD, ONE};

use super::{Felt, Process, ZERO};
use crate::{
Expand Down Expand Up @@ -403,13 +403,10 @@ fn test_get_note_serial_number() {
// calling get_serial_number should return the serial number of the note
let code = "
use.kernel::prologue
use.kernel::note->note_internal
use.kernel::note
use.miden::note

begin
exec.prologue::prepare_transaction
exec.note_internal::prepare_note
dropw dropw dropw dropw
exec.note::get_serial_number

# truncate the stack
Expand Down Expand Up @@ -520,3 +517,29 @@ fn test_get_inputs_hash() {

assert_eq!(process.get_stack_state()[0..16], expected_stack);
}

#[test]
fn test_get_current_script_hash() {
let tx_context = TransactionContextBuilder::with_standard_account(ONE)
.with_mock_notes_preserved()
.build();

// calling get_script_hash should return script hash
let code = "
use.kernel::prologue
use.miden::note

begin
exec.prologue::prepare_transaction
exec.note::get_script_hash

# truncate the stack
swapw dropw
end
";

let process = tx_context.execute_code(code).unwrap();

let script_hash: Word = tx_context.input_notes().get_note(0).note().script().hash().into();
assert_eq!(process.stack.get_word(0), script_hash);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think we can avoid importing the Word here by calling the .as_elements() on the RpoDigest returned from the .hash():

let script_hash = tx_context.input_notes().get_note(0).note().script().hash();
assert_eq!(process.stack.get_word(0), script_hash.as_elements());

}
Loading