miden-protocol 0.14.3

Core components of the Miden protocol
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
// TYPE ALIASES
// ================================================================================================

pub type MemoryAddress = u32;
pub type MemoryOffset = u32;
pub type DataIndex = usize;
pub type MemSize = usize;
pub type StorageSlot = u8;

// PUBLIC CONSTANTS
// ================================================================================================

// General layout
//
// | Section            | Start address | Size in elements | Comment                                    |
// | ------------------ | ------------- | ---------------- | ------------------------------------------ |
// | Bookkeeping        | 0             | 85               |                                            |
// | Global inputs      | 400           | 40               |                                            |
// | Block header       | 800           | 44               |                                            |
// | Partial blockchain | 1_200         | 132              |                                            |
// | Kernel data        | 1_600         | 140              | 34 procedures in total, 4 elements each    |
// | Accounts data      | 8_192         | 524_288          | 64 accounts max, 8192 elements each        |
// | Account delta      | 532_480       | 263              |                                            |
// | Input notes        | 4_194_304     | 3_211_264        | nullifiers data segment (2^16 elements)    |
// |                    |               |                  | + 1024 input notes max, 3072 elements each |
// | Output notes       | 16_777_216    | 3_145_728        | 1024 output notes max, 3072 elements each  |
// | Link Map Memory    | 33_554_432    | 33_554_432       | Enough for 2_097_151 key-value pairs       |

// Relative layout of one account
//
// | Section            | Start address | Size in elements | Comment                                |
// | ------------------ | ------------- | ---------------- | -------------------------------------- |
// | ID and nonce       | 0             | 4                |                                        |
// | Vault root         | 4             | 4                |                                        |
// | Storage commitment | 8             | 4                |                                        |
// | Code commitment    | 12            | 4                |                                        |
// | Padding            | 16            | 12               |                                        |
// | Num procedures     | 28            | 4                |                                        |
// | Procedures roots   | 32            | 1_024            | 256 procedures max, 4 elements each    |
// | Padding            | 1_056         | 4                |                                        |
// | Proc tracking      | 1_060         | 256              | 256 procedures max, 1 element each     |
// | Num storage slots  | 1_316         | 4                |                                        |
// | Initial slot info  | 1_320         | 2_040            | Only initialized on the native account |
// | Active slot info   | 3_360         | 2_040            | 255 slots max, 8 elements each         |
// | Padding            | 5_400         | 2_792            |                                        |
//
// Storage slots are laid out as [[0, slot_type, slot_id_suffix, slot_id_prefix], SLOT_VALUE].

// Relative layout of the native account's delta.
//
// For now each Storage Map pointer (a link map ptr) occupies a single element.
//
// | Section                      | Start address | Size in elements | Comment                             |
// | ---------------------------- | ------------- | ---------------- | ----------------------------------- |
// | Fungible Asset Delta Ptr     | 0             | 4                |                                     |
// | Non-Fungible Asset Delta Ptr | 4             | 4                |                                     |
// | Storage Map Delta Ptrs       | 8             | 256              | Max 255 storage map deltas          |

// BOOKKEEPING
// ------------------------------------------------------------------------------------------------

/// The memory address at which a pointer to the currently active input note is stored.
pub const ACTIVE_INPUT_NOTE_PTR: MemoryAddress = 0;

/// The memory address at which the number of output notes is stored.
pub const NUM_OUTPUT_NOTES_PTR: MemoryAddress = 1;

/// The memory address at which the transaction expiration block number is stored.
pub const TX_EXPIRATION_BLOCK_NUM_PTR: MemoryAddress = 2;

/// The memory address at which the dirty flag of the storage commitment of the native account is
/// stored.
///
/// This binary flag specifies whether the commitment is outdated: it holds 1 if some changes were
/// made to the account storage since the last re-computation, and 0 otherwise.
pub const NATIVE_ACCT_STORAGE_COMMITMENT_DIRTY_FLAG_PTR: MemoryAddress = 3;

/// The memory address at which the input vault root is stored.
pub const INPUT_VAULT_ROOT_PTR: MemoryAddress = 4;

/// The memory address at which the output vault root is stored.
pub const OUTPUT_VAULT_ROOT_PTR: MemoryAddress = 8;

// Pointer to the suffix and prefix of the ID of the foreign account which will be loaded during the
// upcoming FPI call. This ID is updated during the `prepare_fpi_call` kernel procedure.
pub const UPCOMING_FOREIGN_ACCOUNT_PREFIX_PTR: MemoryAddress = 12;
pub const UPCOMING_FOREIGN_ACCOUNT_SUFFIX_PTR: MemoryAddress =
    UPCOMING_FOREIGN_ACCOUNT_PREFIX_PTR + 1;

// Pointer to the 16th input value of the foreign procedure which will be loaded during the upcoming
// FPI call. This "buffer" value helps to work around the 15 value limitation of the
// `exec_kernel_proc` kernel procedure, so that any account procedure, even if it has 16 input
// values, could be executed as foreign.
pub const UPCOMING_FOREIGN_PROC_INPUT_VALUE_15_PTR: MemoryAddress = 14;

// Pointer to the root of the foreign procedure which will be executed during the upcoming FPI call.
// This root is updated during the `prepare_fpi_call` kernel procedure.
pub const UPCOMING_FOREIGN_PROCEDURE_PTR: MemoryAddress = 16;

/// The memory address at which the pointer to the stack element containing the pointer to the
/// active account data is stored.
///
/// The stack starts at the address `29`. Stack has a length of `64` elements meaning that the
/// maximum depth of FPI calls is `63` — the first slot is always occupied by the native account
/// data pointer.
///
/// ```text
/// ┌───────────────┬────────────────┬───────────────────┬─────┬────────────────────┐
/// │ STACK TOP PTR │ NATIVE ACCOUNT │ FOREIGN ACCOUNT 1 │ ... │ FOREIGN ACCOUNT 63 │
/// ├───────────────┼────────────────┼───────────────────┼─────┼────────────────────┤
///        20               21                22                         84
/// ```
pub const ACCOUNT_STACK_TOP_PTR: MemoryAddress = 20;

// GLOBAL INPUTS
// ------------------------------------------------------------------------------------------------

/// The memory address at which the global inputs section begins.
pub const GLOBAL_INPUTS_SECTION_OFFSET: MemoryOffset = 400;

/// The memory address at which the commitment of the transaction's reference block is stored.
pub const BLOCK_COMMITMENT_PTR: MemoryAddress = 400;

/// The memory address at which the native account ID suffix provided as a global transaction input
/// is stored.
pub const GLOBAL_ACCOUNT_ID_SUFFIX_PTR: MemoryAddress = 404;
/// The memory address at which the native account ID prefix provided as a global transaction input
/// is stored.
pub const GLOBAL_ACCOUNT_ID_PREFIX_PTR: MemoryAddress = GLOBAL_ACCOUNT_ID_SUFFIX_PTR + 1;

/// The memory address at which the initial account commitment is stored.
pub const INIT_ACCT_COMMITMENT_PTR: MemoryAddress = 408;

/// The memory address at which the initial nonce is stored.
pub const INIT_NONCE_PTR: MemoryAddress = 412;

/// The memory address at which the initial vault root of the native account is stored.
pub const INIT_NATIVE_ACCT_VAULT_ROOT_PTR: MemoryAddress = 416;

/// The memory address at which the initial storage commitment of the native account is stored.
pub const INIT_NATIVE_ACCT_STORAGE_COMMITMENT_PTR: MemoryAddress = 420;

/// The memory address at which the input notes commitment is stored.
pub const INPUT_NOTES_COMMITMENT_PTR: MemoryAddress = 424;

/// The memory address at which the transaction script mast root is store
pub const TX_SCRIPT_ROOT_PTR: MemoryAddress = 428;

/// The memory address at which the transaction script arguments are stored.
pub const TX_SCRIPT_ARGS: MemoryAddress = 432;

/// The memory address at which the key of the auth procedure arguments is stored.
pub const AUTH_ARGS_PTR: MemoryAddress = 436;

// BLOCK DATA
// ------------------------------------------------------------------------------------------------

/// The memory address at which the block data section begins.
pub const BLOCK_DATA_SECTION_OFFSET: MemoryOffset = 800;

/// The memory address at which the previous block commitment is stored.
pub const PREV_BLOCK_COMMITMENT_PTR: MemoryAddress = 800;

/// The memory address at which the chain commitment is stored.
pub const CHAIN_COMMITMENT_PTR: MemoryAddress = 804;

/// The memory address at which the state root is stored.
pub const ACCT_DB_ROOT_PTR: MemoryAddress = 808;

/// The memory address at which the nullifier db root is store.
pub const NULLIFIER_DB_ROOT_PTR: MemoryAddress = 812;

/// The memory address at which the TX commitment is stored.
pub const TX_COMMITMENT_PTR: MemoryAddress = 816;

/// The memory address at which the transaction kernel commitment is stored.
pub const TX_KERNEL_COMMITMENT_PTR: MemoryAddress = 820;

/// The memory address at which the public key is stored.
pub const VALIDATOR_KEY_COMMITMENT_PTR: MemoryAddress = 824;

/// The memory address at which the block number is stored.
pub const BLOCK_METADATA_PTR: MemoryAddress = 828;

/// The index of the block number within the block metadata.
pub const BLOCK_NUMBER_IDX: DataIndex = 0;

/// The index of the protocol version within the block metadata.
pub const PROTOCOL_VERSION_IDX: DataIndex = 1;

/// The index of the timestamp within the block metadata.
pub const TIMESTAMP_IDX: DataIndex = 2;

/// The memory address at which the fee parameters are stored. These occupy a double word.
pub const FEE_PARAMETERS_PTR: MemoryAddress = 832;

/// The index of the verification base fee within the block fee parameters.
pub const VERIFICATION_BASE_FEE_IDX: DataIndex = 1;

/// The index of the native asset ID suffix within the block fee parameters.
pub const NATIVE_ASSET_ID_SUFFIX_IDX: DataIndex = 2;

/// The index of the native asset ID prefix within the block fee parameters.
pub const NATIVE_ASSET_ID_PREFIX_IDX: DataIndex = 3;

/// The memory address at which the note root is stored.
pub const NOTE_ROOT_PTR: MemoryAddress = 840;

// CHAIN DATA
// ------------------------------------------------------------------------------------------------

/// The memory address at which the chain data section begins.
pub const PARTIAL_BLOCKCHAIN_PTR: MemoryAddress = 1200;

/// The memory address at which the total number of leaves in the partial blockchain is stored.
pub const PARTIAL_BLOCKCHAIN_NUM_LEAVES_PTR: MemoryAddress = 1200;

/// The memory address at which the partial blockchain peaks are stored.
pub const PARTIAL_BLOCKCHAIN_PEAKS_PTR: MemoryAddress = 1204;

// KERNEL DATA
// ------------------------------------------------------------------------------------------------

/// The memory address at which the number of the kernel procedures is stored.
pub const NUM_KERNEL_PROCEDURES_PTR: MemoryAddress = 1600;

/// The memory address at which the section, where the hashes of the kernel procedures are stored,
/// begins.
pub const KERNEL_PROCEDURES_PTR: MemoryAddress = 1604;

// ACCOUNT DATA
// ------------------------------------------------------------------------------------------------

/// The size of the memory segment allocated to core account data (excluding new code commitment).
pub const ACCT_DATA_MEM_SIZE: MemSize = 16;

/// The memory address at which the native account is stored.
pub const NATIVE_ACCOUNT_DATA_PTR: MemoryAddress = 8192;

/// The length of the memory interval that the account data occupies.
pub const ACCOUNT_DATA_LENGTH: MemSize = 8192;

/// The offset at which the account ID and nonce are stored relative to the start of
/// the account data segment.
pub const ACCT_ID_AND_NONCE_OFFSET: MemoryOffset = 0;

/// The memory address at which the account ID and nonce are stored in the native account.
pub const NATIVE_ACCT_ID_AND_NONCE_PTR: MemoryAddress =
    NATIVE_ACCOUNT_DATA_PTR + ACCT_ID_AND_NONCE_OFFSET;

/// The index of the account nonce within the account ID and nonce data.
pub const ACCT_NONCE_IDX: DataIndex = 0;

/// The index of the account ID within the account ID and nonce data.
pub const ACCT_ID_SUFFIX_IDX: DataIndex = 2;
pub const ACCT_ID_PREFIX_IDX: DataIndex = 3;

/// The offset at which the account vault root is stored relative to the start of the account
/// data segment.
pub const ACCT_VAULT_ROOT_OFFSET: MemoryOffset = 4;

/// The memory address at which the account vault root is stored in the native account.
pub const NATIVE_ACCT_VAULT_ROOT_PTR: MemoryAddress =
    NATIVE_ACCOUNT_DATA_PTR + ACCT_VAULT_ROOT_OFFSET;

/// The offset at which the account storage commitment is stored relative to the start of the
/// account data segment.
pub const ACCT_STORAGE_COMMITMENT_OFFSET: MemoryOffset = 8;

/// The memory address at which the account storage commitment is stored in the native account.
pub const NATIVE_ACCT_STORAGE_COMMITMENT_PTR: MemoryAddress =
    NATIVE_ACCOUNT_DATA_PTR + ACCT_STORAGE_COMMITMENT_OFFSET;

/// The offset at which the account code commitment is stored relative to the start of the account
/// data segment.
pub const ACCT_CODE_COMMITMENT_OFFSET: MemoryOffset = 12;

/// The memory address at which the account code commitment is stored in the native account.
pub const NATIVE_ACCT_CODE_COMMITMENT_PTR: MemoryAddress =
    NATIVE_ACCOUNT_DATA_PTR + ACCT_CODE_COMMITMENT_OFFSET;

/// The offset at which the number of procedures contained in the account code is stored relative to
/// the start of the account data segment.
pub const ACCT_NUM_PROCEDURES_OFFSET: MemoryAddress = 28;

/// The memory address at which the number of procedures contained in the account code is stored in
/// the native account.
pub const NATIVE_NUM_ACCT_PROCEDURES_PTR: MemoryAddress =
    NATIVE_ACCOUNT_DATA_PTR + ACCT_NUM_PROCEDURES_OFFSET;

/// The offset at which the account procedures section begins relative to the start of the account
/// data segment.
pub const ACCT_PROCEDURES_SECTION_OFFSET: MemoryAddress = 32;

/// The memory address at which the account procedures section begins in the native account.
pub const NATIVE_ACCT_PROCEDURES_SECTION_PTR: MemoryAddress =
    NATIVE_ACCOUNT_DATA_PTR + ACCT_PROCEDURES_SECTION_OFFSET;

/// The offset at which the account procedures call tracking section begins relative to the start of
/// the account data segment.
pub const ACCT_PROCEDURES_CALL_TRACKING_OFFSET: MemoryAddress = 1060;

/// The memory address at which the account procedures call tracking section begins in the native
/// account.
pub const NATIVE_ACCT_PROCEDURES_CALL_TRACKING_PTR: MemoryAddress =
    NATIVE_ACCOUNT_DATA_PTR + ACCT_PROCEDURES_CALL_TRACKING_OFFSET;

/// The offset at which the number of storage slots contained in the account storage is stored
/// relative to the start of the account data segment.
pub const ACCT_NUM_STORAGE_SLOTS_OFFSET: MemoryAddress = 1316;

/// The memory address at which number of storage slots contained in the account storage is stored
/// in the native account.
pub const NATIVE_NUM_ACCT_STORAGE_SLOTS_PTR: MemoryAddress =
    NATIVE_ACCOUNT_DATA_PTR + ACCT_NUM_STORAGE_SLOTS_OFFSET;

/// The number of elements that each storage slot takes up in memory.
pub const ACCT_STORAGE_SLOT_NUM_ELEMENTS: u8 = 8;

/// The offset of the slot type in the storage slot.
pub const ACCT_STORAGE_SLOT_TYPE_OFFSET: u8 = 1;

/// The offset of the slot's ID suffix in the storage slot.
pub const ACCT_STORAGE_SLOT_ID_SUFFIX_OFFSET: u8 = 2;

/// The offset of the slot's ID prefix in the storage slot.
pub const ACCT_STORAGE_SLOT_ID_PREFIX_OFFSET: u8 = 3;

/// The offset of the slot value in the storage slot.
pub const ACCT_STORAGE_SLOT_VALUE_OFFSET: u8 = 4;

/// The offset at which the account's active storage slots section begins relative to the start of
/// the account data segment.
///
/// This section contains the current values of the account storage slots.
pub const ACCT_ACTIVE_STORAGE_SLOTS_SECTION_OFFSET: MemoryAddress = 3360;

/// The memory address at which the account's active storage slots section begins in the native
/// account.
pub const NATIVE_ACCT_STORAGE_SLOTS_SECTION_PTR: MemoryAddress =
    NATIVE_ACCOUNT_DATA_PTR + ACCT_ACTIVE_STORAGE_SLOTS_SECTION_OFFSET;

// NOTES DATA
// ================================================================================================

/// The size of the memory segment allocated to each note.
pub const NOTE_MEM_SIZE: MemoryAddress = 3072;

#[allow(clippy::empty_line_after_outer_attr)]
#[rustfmt::skip]
// INPUT NOTES DATA
// ------------------------------------------------------------------------------------------------
// Inputs note section contains data of all notes consumed by a transaction. The section starts at
// memory offset 4_194_304 with a word containing the total number of input notes and is followed
// by note nullifiers and note data like so:
//
// ┌──────────┬───────────┬───────────┬─────┬────────────────┬─────────┬──────────┬────────┬───────┬────────┐
// │    NUM   │  NOTE 0   │  NOTE 1   │ ... │     NOTE n     │ PADDING │  NOTE 0  │ NOTE 1 │  ...  │ NOTE n │
// │   NOTES  │ NULLIFIER │ NULLIFIER │     │    NULLIFIER   │         │   DATA   │  DATA  │       │  DATA  │
// ├──────────┼───────────┼───────────┼─────┼────────────────┼─────────┼──────────┼────────┼───────┼────────┤
// 4_194_304  4_194_308   4_194_312         4_194_304+4(n+1)           4_259_840  +3072    +6144   +3072n
//
// Here `n` represents number of input notes.
//
// Each nullifier occupies a single word. A data section for each note consists of exactly 3072
// elements and is laid out like so:
//
// ┌──────┬────────┬────────┬─────────┬────────────┬───────────┬──────────┬────────────┬───────┬
// │ NOTE │ SERIAL │ SCRIPT │ STORAGE │   ASSETS   │ RECIPIENT │ METADATA │ ATTACHMENT │ NOTE  │
// │  ID  │  NUM   │  ROOT  │  COMM   │ COMMITMENT │           │  HEADER  │            │ ARGS  │
// ├──────┼────────┼────────┼─────────┼────────────┼───────────┼──────────┼────────────┼───────┼
// 0      4        8        12        16           20          24         28           32
//
// ┬─────────┬────────┬───────┬─────────┬─────┬────────┬─────────┬─────────┐
// │ STORAGE │  NUM   │ ASSET │  ASSET  │ ... │ ASSET  │  ASSET  │ PADDING │
// │ LENGTH  │ ASSETS │ KEY 0 │ VALUE 0 │     │ KEY n  │ VALUE n │         │
// ┼─────────┼────────┼───────┼─────────┼─────┼────────┼─────────┼─────────┘
// 36        40       44      48              44 + 8n  48 + 8n
//
// - NUM_STORAGE_ITEMS is encoded as [num_storage_items, 0, 0, 0].
// - NUM_ASSETS is encoded as [num_assets, 0, 0, 0].
// - STORAGE_COMMITMENT is the key to look up note storage in the advice map.
// - ASSETS_COMMITMENT is the key to look up note assets in the advice map.
//
// Notice that note storage item are not loaded to the memory, only their length. In order to obtain
// the storage values the advice map should be used: they are stored there as
// `STORAGE_COMMITMENT -> STORAGE`.
//
// As opposed to the asset values, storage items are never used in kernel memory, so their presence
// there is unnecessary.

/// The memory address at which the input note section begins.
pub const INPUT_NOTE_SECTION_PTR: MemoryAddress = 4_194_304;

/// The memory address at which the nullifier section of the input notes begins.
pub const INPUT_NOTE_NULLIFIER_SECTION_PTR: MemoryAddress = 4_194_308;

/// The memory address at which the input note data section begins.
pub const INPUT_NOTE_DATA_SECTION_OFFSET: MemoryAddress = 4_259_840;

/// The memory address at which the number of input notes is stored.
pub const NUM_INPUT_NOTES_PTR: MemoryAddress = INPUT_NOTE_SECTION_PTR;

/// The offsets at which data of an input note is stored relative to the start of its data segment.
pub const INPUT_NOTE_ID_OFFSET: MemoryOffset = 0;
pub const INPUT_NOTE_SERIAL_NUM_OFFSET: MemoryOffset = 4;
pub const INPUT_NOTE_SCRIPT_ROOT_OFFSET: MemoryOffset = 8;
pub const INPUT_NOTE_STORAGE_COMMITMENT_OFFSET: MemoryOffset = 12;
pub const INPUT_NOTE_ASSETS_COMMITMENT_OFFSET: MemoryOffset = 16;
pub const INPUT_NOTE_RECIPIENT_OFFSET: MemoryOffset = 20;
pub const INPUT_NOTE_METADATA_HEADER_OFFSET: MemoryOffset = 24;
pub const INPUT_NOTE_ATTACHMENT_OFFSET: MemoryOffset = 28;
pub const INPUT_NOTE_ARGS_OFFSET: MemoryOffset = 32;
pub const INPUT_NOTE_NUM_STORAGE_ITEMS_OFFSET: MemoryOffset = 36;
pub const INPUT_NOTE_NUM_ASSETS_OFFSET: MemoryOffset = 40;
pub const INPUT_NOTE_ASSETS_OFFSET: MemoryOffset = 44;

#[allow(clippy::empty_line_after_outer_attr)]
#[rustfmt::skip]
// OUTPUT NOTES DATA
// ------------------------------------------------------------------------------------------------
// Output notes section contains data of all notes produced by a transaction. The section starts at
// memory offset 16_777_216 with each note data laid out one after another in 512 word increments.
//
//     ┌─────────────┬─────────────┬───────────────┬─────────────┐
//     │ NOTE 0 DATA │ NOTE 1 DATA │      ...      │ NOTE n DATA │
//     └─────────────┴─────────────┴───────────────┴─────────────┘
// 16_777_216      +3072         +6144           +3072n
//
// The total number of output notes for a transaction is stored in the bookkeeping section of the
// memory. Data section of each note is laid out like so:
//
// ┌──────┬──────────┬────────────┬───────────┬────────────┬────────┬───────┬
// │ NOTE │ METADATA │  METADATA  │ RECIPIENT │   ASSETS   │  NUM   │ DIRTY │
// │  ID  │  HEADER  │ ATTACHMENT │           │ COMMITMENT │ ASSETS │ FLAG  │
// ├──────┼──────────┼────────────┼───────────┼────────────┼────────┼───────┼
// 0      4          8            12          16           20       21
//
// ┬───────┬─────────┬─────┬────────┬─────────┬─────────┐
// │ ASSET │  ASSET  │ ... │ ASSET  │  ASSET  │ PADDING │
// │ KEY 0 │ VALUE 0 │     │ KEY n  │ VALUE n │         │
// ┼───────┼─────────┼─────┼────────┼─────────┼─────────┘
// 24      28              24 + 8n  28 + 8n
//
// The DIRTY_FLAG is the binary flag which specifies whether the assets commitment stored in this
// note is outdated. It holds 1 if some changes were made to the note assets since the last
// re-computation, and 0 otherwise.
// It is set to 0 after every recomputation of the assets commitment in the
// `$kernel::note::compute_output_note_assets_commitment` procedure. It is set to 1 in the
// `$kernel::output_note::add_asset` procedure after any change was made to the assets data.

/// The memory address at which the output notes section begins.
pub const OUTPUT_NOTE_SECTION_OFFSET: MemoryOffset = 16_777_216;

/// The offsets at which data of an output note is stored relative to the start of its data segment.
pub const OUTPUT_NOTE_ID_OFFSET: MemoryOffset = 0;
pub const OUTPUT_NOTE_METADATA_HEADER_OFFSET: MemoryOffset = 4;
pub const OUTPUT_NOTE_ATTACHMENT_OFFSET: MemoryOffset = 8;
pub const OUTPUT_NOTE_RECIPIENT_OFFSET: MemoryOffset = 12;
pub const OUTPUT_NOTE_ASSET_COMMITMENT_OFFSET: MemoryOffset = 16;
pub const OUTPUT_NOTE_NUM_ASSETS_OFFSET: MemoryOffset = 20;
pub const OUTPUT_NOTE_DIRTY_FLAG_OFFSET: MemoryOffset = 21;
pub const OUTPUT_NOTE_ASSETS_OFFSET: MemoryOffset = 24;

// ASSETS
// ------------------------------------------------------------------------------------------------

/// The size of an asset's memory representation.
#[cfg(any(feature = "testing", test))]
pub const ASSET_SIZE: MemoryOffset = 8;

/// The offset of the asset value in an asset's memory representation.
#[cfg(any(feature = "testing", test))]
pub const ASSET_VALUE_OFFSET: MemoryOffset = 4;

// LINK MAP
// ------------------------------------------------------------------------------------------------

/// The inclusive start of the link map dynamic memory region.
pub const LINK_MAP_REGION_START_PTR: MemoryAddress = 33_554_448;

/// The non-inclusive end of the link map dynamic memory region.
pub const LINK_MAP_REGION_END_PTR: MemoryAddress = 67_108_864;

/// [`LINK_MAP_REGION_START_PTR`] + the currently used size stored at this pointer defines the next
/// entry pointer that will be allocated.
pub const LINK_MAP_USED_MEMORY_SIZE: MemoryAddress = 33_554_432;

/// The size of each map entry, i.e. four words.
pub const LINK_MAP_ENTRY_SIZE: MemoryOffset = 16;

const _: () = assert!(
    LINK_MAP_REGION_START_PTR.is_multiple_of(LINK_MAP_ENTRY_SIZE),
    "link map region start ptr should be aligned to entry size"
);

const _: () = assert!(
    (LINK_MAP_REGION_END_PTR - LINK_MAP_REGION_START_PTR).is_multiple_of(LINK_MAP_ENTRY_SIZE),
    "the link map memory range should cleanly contain a multiple of the entry size"
);