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

AccountCode refactor from MerkleTree to Sequential hash for offset based storage access #763

Merged
merged 35 commits into from
Jul 30, 2024
Merged
Show file tree
Hide file tree
Changes from 30 commits
Commits
Show all changes
35 commits
Select commit Hold shift + click to select a range
cd0ef51
Rebased from next
phklive Jul 18, 2024
7d43073
Added rust memory & added prologue memory test for account procs
phklive Jul 18, 2024
58d7ee6
Fixed dropw error in authenticate_account_origin
phklive Jul 18, 2024
acc9969
Merge branch 'next' into phklive-account-code-refactor
phklive Jul 19, 2024
f634073
Cleanup MASM code
phklive Jul 19, 2024
c712835
Cleanup Rust code
phklive Jul 19, 2024
98b4137
Merge branch 'next' into phklive-account-code-refactor
phklive Jul 22, 2024
40ee7da
Remove procedure_commitment() changed value to reference
phklive Jul 22, 2024
392987e
Account code_root to code_commitment first pass
phklive Jul 22, 2024
285e404
replaced with any()
phklive Jul 23, 2024
711d14e
Added procedure_roots() method on AccountCode
phklive Jul 23, 2024
3bd86a7
Added TransactionHostError for AccountProcedureIndexMapError
phklive Jul 23, 2024
cc7303d
Account code_root to code_commitment second pass
phklive Jul 23, 2024
9cc6661
Added AccountProcedure and TryFrom [Felt; 8]
phklive Jul 23, 2024
3b31161
MASM improvements + AccountProcedure + AccountCode updates
phklive Jul 23, 2024
cfe49ea
Merge branch 'next' into phklive-account-code-refactor
phklive Jul 24, 2024
f164bbb
Added requested changes
phklive Jul 24, 2024
08ca435
Added errors in MASM and rust
phklive Jul 24, 2024
c20d28e
Optimized procedure
phklive Jul 24, 2024
acf352e
Added in-kernel test fix
phklive Jul 26, 2024
86728c0
Updated changelog.md
phklive Jul 26, 2024
4d9eaf0
Merge branch 'next' into phklive-account-code-refactor
phklive Jul 26, 2024
b44c6c8
Updated validate_account_procedures to use pipe_double_words_to_memory
phklive Jul 26, 2024
be55ddf
Improved comments
phklive Jul 26, 2024
95cc6ba
Fix cargo doc
phklive Jul 26, 2024
55558ef
docs: added comments to AccountProcedureInfo
bobbinth Jul 27, 2024
828d734
docs: update comments for AccountCode
bobbinth Jul 27, 2024
069b265
docs: improved comments in the prologue MASM
bobbinth Jul 27, 2024
8fd9ecf
Added check for MAX_NUM_PROCEDURES
phklive Jul 29, 2024
c93c547
Fixed check, added constants, removed testing account_procs
phklive Jul 29, 2024
d073035
Updated account_procs, changed pub from module to struct, split prolo…
phklive Jul 30, 2024
2eaf813
lint
phklive Jul 30, 2024
ff5e8a5
Added doc comment for helper functions in account code
phklive Jul 30, 2024
32dbaab
Move num_procs down to prevent index out of bounds error
phklive Jul 30, 2024
68c419b
Merge branch 'next' into phklive-account-code-refactor
phklive Jul 30, 2024
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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] Increase of nonce does not require changes in account state any more (#796).
- Added `CHANGELOG.md` warning message on CI (#799).
- Account deltas can now be merged (#797).
- Changed `AccountCode` procedures from merkle tree to sequential hash + added storage_offset support (#763).

## 0.4.0 (2024-07-03)

Expand Down
6 changes: 4 additions & 2 deletions bench-tx/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,8 @@ pub fn benchmark_default_tx() -> Result<TransactionProgress, String> {
let (stack_inputs, advice_inputs) = transaction.get_kernel_inputs();
let advice_recorder: RecAdviceProvider = advice_inputs.into();
let mut host: TransactionHost<_, ()> =
TransactionHost::new(transaction.account().into(), advice_recorder, None);
TransactionHost::new(transaction.account().into(), advice_recorder, None)
.map_err(|e| format!("Failed to create transaction host: {}", e))?;

vm_processor::execute(
transaction.program(),
Expand Down Expand Up @@ -174,7 +175,8 @@ pub fn benchmark_p2id() -> Result<TransactionProgress, String> {
)]);
let authenticator = Some(Rc::new(authenticator));
let mut host =
TransactionHost::new(transaction.account().into(), advice_recorder, authenticator);
TransactionHost::new(transaction.account().into(), advice_recorder, authenticator)
.map_err(|e| format!("Failed to create transaction host: {}", e))?;

vm_processor::execute(
transaction.program(),
Expand Down
89 changes: 43 additions & 46 deletions docs/architecture/transactions/procedures.md

Large diffs are not rendered by default.

15 changes: 8 additions & 7 deletions miden-lib/asm/kernels/transaction/api.masm
Original file line number Diff line number Diff line change
Expand Up @@ -50,10 +50,11 @@ proc.authenticate_account_origin

# assert that the caller is from the user context
exec.account::authenticate_procedure
# => [CALLER, ...]
# => [storage_offset, ...]

# drop the caller
dropw
# TODO: use the storage_offset for storage access
# drop the storage_offset
drop
bobbinth marked this conversation as resolved.
Show resolved Hide resolved
# => [...]
end

Expand Down Expand Up @@ -260,18 +261,18 @@ end
#! Sets the code of the account the transaction is being executed against. This procedure can only
#! executed on regular accounts with updatable code. Otherwise, this procedure fails.
#!
#! Stack: [CODE_ROOT]
#! Stack: [CODE_COMMITMENT]
#! Output: [0, 0, 0, 0]
#!
#! - CODE_ROOT is the hash of the code to set.
#! - CODE_COMMITMENT is the hash of the code to set.
export.set_account_code
# authenticate that the procedure invocation originates from the account context
exec.authenticate_account_origin
# => [CODE_ROOT]
# => [CODE_COMMITMENT]

# arrange stack
padw swapw
# => [CODE_ROOT, 0, 0, 0, 0]
# => [CODE_COMMITMENT, 0, 0, 0, 0]

# set the account code
exec.account::set_code
Expand Down
4 changes: 2 additions & 2 deletions miden-lib/asm/miden/account.masm
Original file line number Diff line number Diff line change
Expand Up @@ -143,10 +143,10 @@ end
#! Sets the code of the account the transaction is being executed against. This procedure can only
#! executed on regular accounts with updatable code. Otherwise, this procedure fails.
#!
#! Stack: [CODE_ROOT]
#! Stack: [CODE_COMMITMENT]
#! Output: []
#!
#! - CODE_ROOT is the hash of the code to set.
#! - CODE_COMMITMENT is the hash of the code to set.
export.set_code
syscall.set_account_code
# => [0, 0, 0, 0]
Expand Down
129 changes: 94 additions & 35 deletions miden-lib/asm/miden/kernels/tx/account.masm
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,12 @@ const.ERR_SETTING_NON_VALUE_ITEM_ON_VALUE_SLOT=0x00020047
# Setting a map item on a non-map slot
const.ERR_SETTING_MAP_ITEM_ON_NON_MAP_SLOT=0x00020048

# Account procedure is not part of the account code
const.ERR_PROC_NOT_PART_OF_ACCOUNT_CODE=0x0002004A

# Provided index is out of bounds
const.ERR_PROC_INDEX_OUT_OF_BOUNDS=0x0002004B

# CONSTANTS
# =================================================================================================

Expand Down Expand Up @@ -69,6 +75,9 @@ const.SLOT_TYPES_COMMITMENT_STORAGE_SLOT=255
# The maximum value a slot type can take (An array of depth 64).
const.MAX_SLOT_TYPE=64

# The maximum number of account interface procedures.
const.MAX_NUM_PROCEDURES=65535

# EVENTS
# =================================================================================================

Expand Down Expand Up @@ -127,6 +136,16 @@ export.get_max_slot_type
push.MAX_SLOT_TYPE
end

#! Returns the maximum number of account interface procedures.
#!
#! Stack: []
#! Output: [max_num_procedures]
#!
#! - max_num_procedures is the maximum number of account interface procedures.
export.get_max_num_procedures
push.MAX_NUM_PROCEDURES
end

# PROCEDURES
# =================================================================================================

Expand Down Expand Up @@ -299,21 +318,21 @@ end
#! Sets the code of the account the transaction is being executed against. This procedure can only
#! executed on regular accounts with updatable code. Otherwise, this procedure fails.
#!
#! Stack: [CODE_ROOT]
#! Stack: [CODE_COMMITMENT]
#! Output: []
#!
#! - CODE_ROOT is the hash of the code to set.
#! - CODE_COMMITMENT is the hash of the code to set.
export.set_code
# get the account id
exec.memory::get_acct_id
# => [acct_id, CODE_ROOT]
# => [acct_id, CODE_COMMITMENT]

# assert the account is an updatable regular account
exec.is_updatable_account assert.err=ERR_ACCOUNT_SET_CODE_ACCOUNT_MUST_BE_UPDATABLE
# => [CODE_ROOT]
# => [CODE_COMMITMENT]

# set the code root
exec.memory::set_new_acct_code_root dropw
# set the code commitment
exec.memory::set_new_acct_code_commitment dropw
# => []
end

Expand Down Expand Up @@ -374,7 +393,7 @@ proc.set_item_raw
# => [OLD_VALUE]
end

#! Sets an item in the account storage. Panics if
#! Sets an item in the account storage. Panics if
#! - the index is out of bounds
#! - the slot type is not value
#!
Expand Down Expand Up @@ -469,39 +488,79 @@ export.set_map_item.3
# => [OLD_MAP_ROOT, OLD_VALUE, ...]
end

#! Verifies that the procedure root is part of the account code Merkle tree. Panics if the
#! procedure root is not part of the account code Merkle tree.
#! Returns the procedure information
#!
#! Stack: [index, ...]
#! Output: [PROC_ROOT, storage_offset, ...]
#!
#! - PROC_ROOT is the hash of the procedure.
#! - storage_offset is the procedure storage offset.
#!
#! Panics if
#! - index is out of bounds
export.get_procedure_info
# TODO: Fix VM caller == [0,0,0,0] bug and remove this check
# check if index == 255
dup push.255 neq
# => [is_255, index]
bobbinth marked this conversation as resolved.
Show resolved Hide resolved

# load procedure information from memory
if.true
# check that index < number of procedures contained in the account code
dup exec.memory::get_num_account_procedures lt assert.err=ERR_PROC_INDEX_OUT_OF_BOUNDS
# => [index]

# get procedure section ptr
push.2 mul exec.memory::get_account_procedures_section_offset add dup push.1 add
# => [proc_ptr, offset_ptr]

# load procedure information from memory
mem_load swap padw movup.4 mem_loadw
# => [PROC_ROOT, storage_offset]
end
end

#! Verifies that the procedure root is part of the account code
#!
#! Stack: [PROC_ROOT]
#! Output: [PROC_ROOT]
#! Output: [storage_offset]
#!
#! - PROC_ROOT is the hash of the procedure to authenticate.
export.authenticate_procedure.1
# load the account code root onto the stack
exec.memory::get_acct_code_root swapw
# => [PROC_ROOT, CODE_ROOT]

# load the index of the procedure root onto the advice stack, and move it to the operand stack
emit.ACCOUNT_PUSH_PROCEDURE_INDEX_EVENT adv_push.1 movdn.4
# => [PROC_ROOT, index, CODE_ROOT]

# push the depth of the code Merkle tree onto the stack
push.ACCOUNT_CODE_TREE_DEPTH movdn.4
# => [PROC_ROOT, depth, index, CODE_ROOT]

# verify the procedure exists in the account code Merkle tree
mtree_verify
# => [PROC_ROOT, depth, index, CODE_ROOT]

# drop accessory variables
movup.4 drop movup.4 drop swapw dropw
# => [PROC_ROOT]
#!
#! Panics if
#! - procedure root is not part of the account code.
export.authenticate_procedure
# load procedure index
emit.ACCOUNT_PUSH_PROCEDURE_INDEX_EVENT adv_push.1
# => [index, PROC_ROOT]

# get procedure info (PROC_ELEMENTS, storage_offset) from memory stored at index
exec.get_procedure_info
# In production:
# => [PROC_ELEMENTS, storage_offset, PROC_ROOT]
# During testing:
# => [255, PROC_ROOT]

# TODO: Fix VM caller == [0,0,0,0] bug and remove this check
# check if get_procedure_info returned 255
dup push.255 neq
# => [is_255, index, PROC_ROOT]
bobbinth marked this conversation as resolved.
Show resolved Hide resolved

# verify that PROC_ROOT matches returned procedure information
if.true
# verify that PROC_ROOT exists in memory at index
movup.4 movdn.8 assert_eqw.err=ERR_PROC_NOT_PART_OF_ACCOUNT_CODE
# => [storage_offset]
else
# drop PROC_ROOT
movdn.4 dropw
end
bobbinth marked this conversation as resolved.
Show resolved Hide resolved
end

#! Validates that the account seed, provided via the advice map, satisfies the seed requirements.
#!
#! Validation is performed via the following steps:
#! 1. compute the hash of (SEED, CODE_ROOT, STORAGE_ROOT, 0, 0, 0, 0)
#! 1. compute the hash of (SEED, CODE_commitment, STORAGE_ROOT, 0, 0, 0, 0)
#! 2. Assert the least significant element of the digest is equal to the account id of the account
#! the transaction is being executed against.
#! 3. Assert the most significant element has sufficient proof of work (trailing zeros) for the account
Expand All @@ -514,11 +573,11 @@ export.validate_seed
padw exec.memory::get_acct_id push.0.0.0 adv.push_mapval adv_loadw
# => [SEED, 0, 0, 0, 0]

# populate last four elements of the hasher rate with the code root
exec.memory::get_acct_code_root
# => [CODE_ROOT, SEED, 0, 0, 0, 0]
# populate last four elements of the hasher rate with the code commitment
exec.memory::get_acct_code_commitment
# => [CODE_COMMITMENT, SEED, 0, 0, 0, 0]

# perform first permutation of seed and code_root (from advice stack) perm(seed, code_root)
# perform first permutation of seed and code_commitment (from advice stack) perm(seed, code_commitment)
hperm
# => [RATE, RATE, PERM]

Expand Down
18 changes: 9 additions & 9 deletions miden-lib/asm/miden/kernels/tx/epilogue.masm
Original file line number Diff line number Diff line change
Expand Up @@ -144,20 +144,20 @@ end
# ACCOUNT CODE UPDATE
# =================================================================================================

#! Updates the account code root if the account code has changed. `NEW_ACCT_CODE_ROOT` is set to
#! the initial account code root in the prologue and as such this procedure will not result in a
#! change to the account code root if the `account::set_code` procedure has not been invoked in
#! this transaction.
#! Updates the account code commitment if the account code has changed. `NEW_ACCT_CODE_COMMITMENT`
#! is set to the initial account code commitment in the prologue and as such this procedure will
#! not result in a change to the account code commitment if the `account::set_code` procedure has
#! not been invoked in this transaction.
#!
#! Stack: []
#! Output: []
proc.update_account_code
# check if the account code root has been updated
exec.memory::get_new_acct_code_root
# => [NEW_ACCT_CODE_ROOT]
# check if the account code commitment has been updated
exec.memory::get_new_acct_code_commitment
# => [NEW_ACCT_CODE_COMMITMENT]

# set the account code root to the new account code root (may not have changed)
exec.memory::set_acct_code_root dropw
# set the account code commitment to the new account code commitment (may not have changed)
exec.memory::set_acct_code_commitment dropw
# => []
end

Expand Down
Loading
Loading