Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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 Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,7 @@ generate-solidity-test-vectors: ## Regenerate Solidity MMR test vectors using Fo
cd crates/miden-agglayer/solidity-compat && forge test -vv --match-test test_generateCanonicalZeros
cd crates/miden-agglayer/solidity-compat && forge test -vv --match-test test_generateVerificationProofData
cd crates/miden-agglayer/solidity-compat && forge test -vv --match-test test_generateLeafValueVectors
cd crates/miden-agglayer/solidity-compat && forge test -vv --match-test test_generateClaimAssetVectors

# --- benchmarking --------------------------------------------------------------------------------

Expand Down
66 changes: 31 additions & 35 deletions crates/miden-agglayer/asm/bridge/crypto_utils.masm
Original file line number Diff line number Diff line change
Expand Up @@ -161,71 +161,67 @@ end
#! represented as 32 Keccak256Digest values (64 words).
#! - leaf_idx is the index of the provided leaf in the SMT.
#! - [ROOT_LO, ROOT_HI] is the calculated root.
@locals(9) # current hash + is_odd flag
@locals(8) # current hash
proc calculate_root(
leaf_value: DoubleWord,
merkle_path_ptr: MemoryAddress,
leaf_idx: u32
) -> DoubleWord
# Local memory stores the current hash. It is initialized to the leaf value
loc_storew_be.CUR_HASH_LO_LOCAL dropw loc_storew_be.CUR_HASH_HI_LOCAL dropw
loc_storew_le.CUR_HASH_LO_LOCAL dropw loc_storew_le.CUR_HASH_HI_LOCAL dropw
# => [merkle_path_ptr, leaf_idx]

# prepare the stack for the hash computation cycle
padw padw padw
# => [PAD, PAD, PAD, merkle_path_ptr, leaf_idx]

# Merkle path is guaranteed to contain 32 nodes
repeat.32
# load the Merkle path node onto the stack
mem_stream
Copy link
Contributor

Choose a reason for hiding this comment

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

I wonder do we have an incorrect documentation for the mem_stream instruction or it was just already updated to work with the latest VM which uses LE.

If we have [1, 2, 3, 4, 5, 6, 7, 8] memory layout, where 1 is placed at memory address 0 and 8 at memory address 7, then the mem_stream will load this double word onto the stack in the reversed order: [8, 7, 6, 5, 4, 3, 2, 1], where 8 is placed at the top. At the same time in the mem_stream docs it is written:

Stack transition: [C, B, A, a, ... ] -> [E, D, A, a', ... ], where
[E, D] ← [mem[a..(a+4)], mem[(a+4)..(a+8)]], a' ← a+8.

So it describes the transition in LE, not BE.

Also the necessity of whiting the LE mem_stream by your own made me think whether should we create the LE version of the mem_stream (the same way it was done with mem_storew_le and the others) and rename the current mem_stream into the mem_stream_be.

# => [PATH_NODE_LO, PATH_NODE_HI, PAD, merkle_path_ptr, leaf_idx]
# load the Merkle path node word-by-word in LE-felt order
padw dup.4 mem_loadw_le
# => [PATH_NODE_LO, merkle_path_ptr, leaf_idx]
padw dup.8 add.4 mem_loadw_le
swapw
# => [PATH_NODE_LO, PATH_NODE_HI, merkle_path_ptr, leaf_idx]

# determine whether the last `leaf_idx` bit is 1 (is `leaf_idx` odd)
dup.13 u32and.1
# => [is_odd, PATH_NODE_LO, PATH_NODE_HI, PAD, merkle_path_ptr, leaf_idx]
# advance merkle_path_ptr by 8 (two words = 8 element addresses)
movup.8 add.8 movdn.8
# => [PATH_NODE_LO, PATH_NODE_HI, merkle_path_ptr+8, leaf_idx]

# store the is_odd flag to the local memory, so we could use it while all 16 top elements
# are occupied by the nodes
loc_store.8
# => [PATH_NODE_LO, PATH_NODE_HI, PAD, merkle_path_ptr, leaf_idx]
# determine whether the last `leaf_idx` bit is 1 (is `leaf_idx` odd)
dup.9 u32and.1
# => [is_odd, PATH_NODE_LO, PATH_NODE_HI, merkle_path_ptr+8, leaf_idx]

# load the hash respective to the current height from the local memory
padw loc_loadw_be.CUR_HASH_HI_LOCAL padw loc_loadw_be.CUR_HASH_LO_LOCAL
# => [CURR_HASH_LO, CURR_HASH_HI, PATH_NODE_LO, PATH_NODE_HI, PAD, merkle_path_ptr, leaf_idx]
padw loc_loadw_le.CUR_HASH_HI_LOCAL padw loc_loadw_le.CUR_HASH_LO_LOCAL
# => [CURR_HASH_LO, CURR_HASH_HI, is_odd, PATH_NODE_LO, PATH_NODE_HI, merkle_path_ptr, leaf_idx]

# load the is_odd flag back to the stack
loc_load.8
# => [is_odd, CURR_HASH_LO, CURR_HASH_HI, PATH_NODE_LO, PATH_NODE_HI, PAD, merkle_path_ptr, leaf_idx]
# move the `is_odd` flag to the top of the stack
movup.8
# => [is_odd, CURR_HASH_LO, CURR_HASH_HI, PATH_NODE_LO, PATH_NODE_HI, merkle_path_ptr, leaf_idx]

# if is_odd flag equals 1 (`leaf_idx` is odd), change the order of the nodes on the stack
if.true
# rearrange the hashes: current position of the hash is odd, so it should be on the
if.true
# rearrange the hashes: current position of the hash is odd, so it should be on the
# right
swapdw
# => [PATH_NODE_LO, PATH_NODE_HI, CURR_HASH_LO, CURR_HASH_HI, PAD, merkle_path_ptr, leaf_idx]
# => [PATH_NODE_LO, PATH_NODE_HI, CURR_HASH_LO, CURR_HASH_HI, merkle_path_ptr, leaf_idx]
end

# compute the next height hash
exec.keccak256::merge
# => [CURR_HASH_LO', CURR_HASH_HI', PAD, merkle_path_ptr, leaf_idx]
# => [CURR_HASH_LO', CURR_HASH_HI', merkle_path_ptr, leaf_idx]

# store the resulting hash to the local memory
loc_storew_be.CUR_HASH_LO_LOCAL swapw loc_storew_be.CUR_HASH_HI_LOCAL
# => [CURR_HASH_HI', CURR_HASH_LO', PAD, merkle_path_ptr, leaf_idx]
# store the resulting hash to the local memory and drop the hash words
loc_storew_le.CUR_HASH_LO_LOCAL dropw
loc_storew_le.CUR_HASH_HI_LOCAL dropw
# => [merkle_path_ptr, leaf_idx]

# update the `leaf_idx` (shift it right by 1 bit)
movup.13 u32shr.1 movdn.13
# => [CURR_HASH_HI', CURR_HASH_LO', PAD, merkle_path_ptr, leaf_idx>>1]
swap u32shr.1 swap
# => [merkle_path_ptr, leaf_idx>>1]
end

# after all 32 hashes have been computed, the current hash stored in local memory represents
# the root of the SMT, which should be returned
#
# remove 6 elements from the stack so that exactly 8 are remaining and rewrite them with the
# root value from the local memory
dropw drop drop
loc_loadw_be.CUR_HASH_HI_LOCAL swapw loc_loadw_be.CUR_HASH_LO_LOCAL
drop drop
padw loc_loadw_le.CUR_HASH_HI_LOCAL padw loc_loadw_le.CUR_HASH_LO_LOCAL
# => [ROOT_LO, ROOT_HI]
end

Expand Down
24 changes: 12 additions & 12 deletions crates/miden-agglayer/asm/bridge/mmr_frontier32_keccak.masm
Original file line number Diff line number Diff line change
Expand Up @@ -136,8 +136,8 @@ const CANONICAL_ZEROES_LOCAL = 8
@locals(264) # new_leaf/curr_hash + canonical_zeros
pub proc append_and_update_frontier
# set CUR_HASH = NEW_LEAF and store to local memory
loc_storew_be.CUR_HASH_LO_LOCAL dropw
loc_storew_be.CUR_HASH_HI_LOCAL dropw
loc_storew_le.CUR_HASH_LO_LOCAL dropw
loc_storew_le.CUR_HASH_HI_LOCAL dropw
# => [mmr_frontier_ptr]

# get the current leaves number
Expand Down Expand Up @@ -203,8 +203,8 @@ pub proc append_and_update_frontier
# load the current hash from the local memory back to the stack
#
# in the first iteration the current hash will be equal to the new node
padw loc_loadw_be.CUR_HASH_HI_LOCAL
padw loc_loadw_be.CUR_HASH_LO_LOCAL
padw loc_loadw_le.CUR_HASH_HI_LOCAL
padw loc_loadw_le.CUR_HASH_LO_LOCAL
swapdw
# => [
# FRONTIER[curr_tree_height]_LO, FRONTIER[curr_tree_height]_HI, CUR_HASH_LO,
Expand All @@ -217,16 +217,16 @@ pub proc append_and_update_frontier
# => [CUR_HASH_LO', CUR_HASH_HI', curr_tree_height, num_leaves, mmr_frontier_ptr]

# store the current hash of the next height back to the local memory
loc_storew_be.CUR_HASH_LO_LOCAL dropw
loc_storew_be.CUR_HASH_HI_LOCAL dropw
loc_storew_le.CUR_HASH_LO_LOCAL dropw
loc_storew_le.CUR_HASH_HI_LOCAL dropw
# => [curr_tree_height, num_leaves, mmr_frontier_ptr]
else
# => [frontier[curr_tree_height]_ptr, curr_tree_height, num_leaves, mmr_frontier_ptr]
#
# this height wasn't "occupied" yet: store the current hash as the subtree root
# (frontier node) at height `curr_tree_height`
padw loc_loadw_be.CUR_HASH_HI_LOCAL
padw loc_loadw_be.CUR_HASH_LO_LOCAL
padw loc_loadw_le.CUR_HASH_HI_LOCAL
padw loc_loadw_le.CUR_HASH_LO_LOCAL
# => [
# CUR_HASH_LO, CUR_HASH_HI, frontier[curr_tree_height]_ptr, curr_tree_height,
# num_leaves, mmr_frontier_ptr
Expand Down Expand Up @@ -256,8 +256,8 @@ pub proc append_and_update_frontier
# => [CUR_HASH_LO', CUR_HASH_HI', curr_tree_height, num_leaves, mmr_frontier_ptr]

# store the current hash of the next height back to the local memory
loc_storew_be.CUR_HASH_LO_LOCAL dropw
loc_storew_be.CUR_HASH_HI_LOCAL dropw
loc_storew_le.CUR_HASH_LO_LOCAL dropw
loc_storew_le.CUR_HASH_HI_LOCAL dropw
# => [curr_tree_height, num_leaves, mmr_frontier_ptr]
end
# => [curr_tree_height, num_leaves, mmr_frontier_ptr]
Expand Down Expand Up @@ -292,8 +292,8 @@ pub proc append_and_update_frontier
# compute.

# load the final hash (which is also the root of the tree)
padw loc_loadw_be.CUR_HASH_HI_LOCAL
padw loc_loadw_be.CUR_HASH_LO_LOCAL
padw loc_loadw_le.CUR_HASH_HI_LOCAL
padw loc_loadw_le.CUR_HASH_LO_LOCAL
# => [NEW_ROOT_LO, NEW_ROOT_HI, new_leaf_count]
end

Expand Down
8 changes: 4 additions & 4 deletions crates/miden-agglayer/asm/bridge/utils.masm
Original file line number Diff line number Diff line change
Expand Up @@ -46,10 +46,10 @@ pub proc mem_store_double_word(
double_word_to_store: DoubleWord,
mem_ptr: MemoryAddress
) -> (DoubleWord, MemoryAddress)
dup.8 mem_storew_be swapw
dup.8 mem_storew_le swapw
# => [WORD_2, WORD_1, ptr]

dup.8 add.4 mem_storew_be swapw
dup.8 add.4 mem_storew_le swapw
# => [WORD_1, WORD_2, ptr]
end

Expand All @@ -58,9 +58,9 @@ end
#! Inputs: [ptr]
#! Outputs: [WORD_1, WORD_2]
pub proc mem_load_double_word(mem_ptr: MemoryAddress) -> DoubleWord
padw dup.4 add.4 mem_loadw_be
padw dup.4 add.4 mem_loadw_le
# => [WORD_2, ptr]

padw movup.8 mem_loadw_be
padw movup.8 mem_loadw_le
# => [WORD_1, WORD_2]
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,82 @@
{
"amount": "0x00000000000000000000000000000000000000000000000000005af3107a4000",
"destination_address": "0x00000000b0E79c68cafC54802726C6F102Cca300",
"destination_network": 20,
"global_exit_root": "0xe1cbfbde30bd598ee9aa2ac913b60d53e3297e51ed138bf86c500dd7d2391e7d",
"global_index": "0x0000000000000000000000000000000000000000000000010000000000039e88",
"leaf_type": 0,
"leaf_value": "0xc58420b9b4ba439bb5f6f68096270f4df656553ec67150d4d087416b9ef6ea9d",
"mainnet_exit_root": "0x31d3268d3a0145d65482b336935fa07dab0822f7dccd865f361d2bf122c4905c",
"metadata_hash": "0x945d61756eddd06a335ceff22d61480fc2086e85e74a55db5485f814626247d5",
"origin_network": 0,
"origin_token_address": "0x2DC70fb75b88d2eB4715bc06E1595E6D97c34DFF",
"rollup_exit_root": "0x8452a95fd710163c5fa8ca2b2fe720d8781f0222bb9e82c2a442ec986c374858",
"smt_proof_local_exit_root": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5",
"0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30",
"0xe37d456460231cf80063f57ee83a02f70d810c568b3bfb71156d52445f7a885a",
"0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344",
"0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d",
"0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968",
"0x3236bf576fca1adf85917ec7888c4b89cce988564b6028f7d66807763aaa7b04",
"0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af",
"0x054ba828046324ff4794fce22adefb23b3ce749cd4df75ade2dc9f41dd327c31",
"0x4e9220076c344bf223c7e7cb2d47c9f0096c48def6a9056e41568de4f01d2716",
"0xca6369acd49a7515892f5936227037cc978a75853409b20f1145f1d44ceb7622",
"0x5a925caf7bfdf31344037ba5b42657130d049f7cb9e87877317e79fce2543a0c",
"0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb",
"0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc",
"0x4111a1a05cc06ad682bb0f213170d7d57049920d20fc4e0f7556a21b283a7e2a",
"0x77a0f8b0e0b4e5a57f5e381b3892bb41a0bcdbfdf3c7d591fae02081159b594d",
"0x361122b4b1d18ab577f2aeb6632c690713456a66a5670649ceb2c0a31e43ab46",
"0x5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0",
"0xb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0",
"0xc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2",
"0xf4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9",
"0x5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377",
"0x4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652",
"0xcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef",
"0x0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d",
"0xb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0",
"0x838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e",
"0x662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e",
"0x388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322",
"0x93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735",
"0x8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9"
],
"smt_proof_rollup_exit_root": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0x0000000000000000000000000000000000000000000000000000000000000000"
]
}
Loading