Skip to content
Merged
Show file tree
Hide file tree
Changes from 6 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
133 changes: 108 additions & 25 deletions crates/miden-agglayer/asm/agglayer/bridge/bridge_in.masm
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ type MemoryAddress = u32
# ERRORS
# =================================================================================================

const ERR_BRIDGE_NOT_MAINNET = "bridge not mainnet"
const ERR_BRIDGE_NOT_MAINNET = "mainnet flag must be 1 for a mainnet deposit"
const ERR_BRIDGE_NOT_ROLLUP = "mainnet flag must be 0 for a rollup deposit"
const ERR_LEADING_BITS_NON_ZERO = "leading bits of global index must be zero"
const ERR_MAINNET_FLAG_INVALID = "mainnet flag must be 0 or 1"
const ERR_ROLLUP_INDEX_NON_ZERO = "rollup index must be zero for a mainnet deposit"
const ERR_SMT_ROOT_VERIFICATION_FAILED = "merkle proof verification failed: provided SMT root does not match the computed root"

Expand All @@ -29,6 +31,8 @@ const SMT_PROOF_LOCAL_EXIT_ROOT_PTR = 0 # local SMT proof is first
const GLOBAL_INDEX_PTR = PROOF_DATA_PTR + 2 * 256 # 512
const EXIT_ROOTS_PTR = GLOBAL_INDEX_PTR + 8 # 520
const MAINNET_EXIT_ROOT_PTR = EXIT_ROOTS_PTR # it's the first exit root
const SMT_PROOF_ROLLUP_EXIT_ROOT_PTR = 256 # rollup SMT proof starts after local
const ROLLUP_EXIT_ROOT_PTR = EXIT_ROOTS_PTR + 8 # 528

# the memory address where leaf data is stored for get_leaf_value
const LEAF_DATA_START_PTR = 0
Expand Down Expand Up @@ -116,17 +120,16 @@ end
#!
#! Invocation: exec
pub proc process_global_index_mainnet
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 have a helper procedure which takes GLOBAL_INDEX[8] and returns leaf_index & sourceBridgeNetwork. Not for this PR, but for the nullifier tracking PR.

# for v0.1, let's only implement the mainnet branch
# the top 191 bits of the global index are zero
repeat.5 assertz.err=ERR_LEADING_BITS_NON_ZERO end

# the next element is the mainnet flag (LE-packed u32)
# byte-swap to get the BE value, then assert it is exactly 1
# => [mainnet_flag_le, rollup_index_le, leaf_index_le, ...]
# => [mainnet_flag_le, rollup_index_le, leaf_index_le]
exec.utils::swap_u32_bytes
assert.err=ERR_BRIDGE_NOT_MAINNET

# the next element is the rollup index, must be zero for a mainnet deposit
# the rollup index must be zero for a mainnet deposit
# (zero is byte-order-independent, so no swap needed)
assertz.err=ERR_ROLLUP_INDEX_NON_ZERO

Expand All @@ -135,6 +138,38 @@ pub proc process_global_index_mainnet
# => [leaf_index]
end

#! Assert the global index is valid for a rollup deposit.
#!
#! Each element of the global index is a LE-packed u32 felt (as produced by
#! `bytes_to_packed_u32_felts` / `GlobalIndex::to_elements()`).
#!
#! Inputs: [GLOBAL_INDEX[8]]
#! Outputs: [leaf_index, rollup_index]
#!
#! Panics if:
#! - the leading bits of the global index are not zero.
#! - the mainnet flag is not 0.
#!
#! Invocation: exec
pub proc process_global_index_rollup
# the top 191 bits of the global index are zero
repeat.5 assertz.err=ERR_LEADING_BITS_NON_ZERO end

# the next element is the mainnet flag (LE-packed u32)
# for a rollup deposit it must be exactly 0; zero is byte-order-independent,
# so no swap is needed before asserting
# => [mainnet_flag_le, rollup_index_le, leaf_index_le]
assertz.err=ERR_BRIDGE_NOT_ROLLUP

# byte-swap rollup_index from LE to BE
exec.utils::swap_u32_bytes
# => [rollup_index, leaf_index_le]

# byte-swap leaf_index from LE to BE
swap exec.utils::swap_u32_bytes
# => [leaf_index, rollup_index]
end

#! Computes the Global Exit Tree (GET) root from the mainnet and rollup exit roots.
#!
#! The mainnet exit root is expected at `exit_roots_ptr` and
Expand Down Expand Up @@ -263,27 +298,75 @@ proc verify_leaf
padw push.GLOBAL_INDEX_PTR add.4 mem_loadw_le swapw
# => [GLOBAL_INDEX[8], LEAF_VALUE[8]]

# to see if we're dealing with a deposit from mainnet or from a rollup, process the global index
# TODO currently only implemented for mainnet deposits (mainnet flag must be 1)
exec.process_global_index_mainnet
# => [leaf_index, LEAF_VALUE[8]]

# load the pointers to the merkle proof and root, to pass to `verify_merkle_proof`
push.MAINNET_EXIT_ROOT_PTR swap
push.SMT_PROOF_LOCAL_EXIT_ROOT_PTR
# => [smt_proof_ptr, leaf_index, mainnet_exit_root_ptr, LEAF_VALUE[8]]

# prepare the stack for the verify_merkle_proof procedure: move the pointers deep in the stack
movdn.10 movdn.10 movdn.10
# => [LEAF_VALUE[8], smt_proof_ptr, leaf_index, mainnet_exit_root_ptr]

exec.verify_merkle_proof
# => [verification_flag]

# verify_merkle_proof procedure returns `true` if the verification was successful and `false`
# otherwise. Assert that `true` was returned.
assert.err=ERR_SMT_ROOT_VERIFICATION_FAILED
# => []
# Determine if we're dealing with a deposit from mainnet or from a rollup.
# The global index is laid out as:
# [gi0, gi1, gi2, gi3, gi4, mainnet_flag_le, rollup_index_le, leaf_index_le]
# gi0 is on top (position 0). The mainnet flag is at MAINNET_FLAG_STACK_POS.

# Duplicate the mainnet flag element, byte-swap from LE to BE,
# assert it is a valid boolean (0 or 1), then use it to branch.
dup.5 exec.utils::swap_u32_bytes dup
# => [mainnet_flag, mainnet_flag, GLOBAL_INDEX[8], LEAF_VALUE[8]]

u32lt.2 assert.err=ERR_MAINNET_FLAG_INVALID
# => [mainnet_flag, GLOBAL_INDEX[8], LEAF_VALUE[8]]

if.true
# ==================== MAINNET DEPOSIT ====================
exec.process_global_index_mainnet
# => [leaf_index, LEAF_VALUE[8]]

# verify single Merkle proof: leaf against mainnetExitRoot
push.MAINNET_EXIT_ROOT_PTR swap
push.SMT_PROOF_LOCAL_EXIT_ROOT_PTR
# => [smt_proof_ptr, leaf_index, mainnet_exit_root_ptr, LEAF_VALUE[8]]

movdn.10 movdn.10 movdn.10
# => [LEAF_VALUE[8], smt_proof_ptr, leaf_index, mainnet_exit_root_ptr]

exec.verify_merkle_proof
# => [verification_flag]

assert.err=ERR_SMT_ROOT_VERIFICATION_FAILED
Copy link
Contributor

Choose a reason for hiding this comment

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

Should we have different error messages for if the proof verification failed for rollup vs mainnet deposit?

Say, ERR_SMT_ROOT_VERIFICATION_FAILED_ROLLUP & ERR_SMT_ROOT_VERIFICATION_FAILED_MAINNET?

Copy link
Collaborator Author

Choose a reason for hiding this comment

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

We could, but we only ever verify one of them per CLAIM note, and I think it should be clear for the submitted of the CLAIM note which path they're taking (by definition, they must know where this data came from, mainnet or rollup). So I think not strictly necessary, lmk if you disagree though (I'll merge as-is, this can be done in a follow up if needed)

# => []
else
# ==================== ROLLUP DEPOSIT ====================
# mainnet_flag = 0; extract rollup_index and leaf_index via helper,
# then do two-level verification
exec.process_global_index_rollup
# => [leaf_index, rollup_index, LEAF_VALUE[8]]

# Step 1: calculate_root(leafValue, smtProofLocalExitRoot, leafIndex) -> localExitRoot
# We need to save rollup_index while calculate_root runs.
# calculate_root expects: [LEAF_VALUE_LO, LEAF_VALUE_HI, merkle_path_ptr, leaf_idx]
# => [leaf_index, rollup_index, LEAF_VALUE[8]]

# Rearrange to: [LEAF_VALUE[8], smt_proof_local_ptr, leaf_index, rollup_index]
# First, move leaf_index and rollup_index past LEAF_VALUE
movdn.9 movdn.9
# => [LEAF_VALUE[8], leaf_index, rollup_index]

# Insert smt_proof_local_ptr before leaf_index
push.SMT_PROOF_LOCAL_EXIT_ROOT_PTR movdn.8
# => [LEAF_VALUE[8], smt_proof_local_ptr, leaf_index, rollup_index]

exec.calculate_root
# => [LOCAL_EXIT_ROOT_LO, LOCAL_EXIT_ROOT_HI, rollup_index]

# Step 2: verify_merkle_proof(localExitRoot, smtProofRollupExitRoot, rollupIndex, rollupExitRootPtr)
push.ROLLUP_EXIT_ROOT_PTR movup.9
push.SMT_PROOF_ROLLUP_EXIT_ROOT_PTR
# => [smt_proof_rollup_ptr, rollup_index, rollup_exit_root_ptr, LOCAL_EXIT_ROOT[8]]

movdn.10 movdn.10 movdn.10
# => [LOCAL_EXIT_ROOT[8], smt_proof_rollup_ptr, rollup_index, rollup_exit_root_ptr]

exec.verify_merkle_proof
# => [verification_flag]

assert.err=ERR_SMT_ROOT_VERIFICATION_FAILED
# => []
end
end

#! Computes the root of the SMT based on the provided Merkle path, leaf value and leaf index.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,86 @@
{
"amount": "100000000000000000000",
"deposit_count": 3,
"description": "Rollup deposit test vectors with valid two-level Merkle proofs (non-zero indices)",
"destination_address": "0x00000000AA0000000000bb000000cc000000Dd00",
"destination_network": 20,
"global_exit_root": "0x677d4ecba0ff4871f33163e70ea39a13fe97f2fa9b4dbad110e398830a324159",
"global_index": "0x0000000000000000000000000000000000000000000000000000000500000002",
"leaf_type": 0,
"leaf_value": "0x4a6a047a2b89dd9c557395833c5e34c4f72e6f9aae70779e856f14a6a2827585",
"local_exit_root": "0x985cff7ee35794b30fba700b64546b4ec240d2d78aaf356d56e83d907009367f",
"mainnet_exit_root": "0x4d63440b08ffffe5a049aae4161d54821a09973965a1a1728534a0f117b6d6c9",
"metadata": "0x000000000000000000000000000000000000000000000000000000000000006000000000000000000000000000000000000000000000000000000000000000a00000000000000000000000000000000000000000000000000000000000000012000000000000000000000000000000000000000000000000000000000000000a5465737420546f6b656e0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045445535400000000000000000000000000000000000000000000000000000000",
"metadata_hash": "0x4d0d9fb7f9ab2f012da088dc1c228173723db7e09147fe4fea2657849d580161",
"origin_network": 3,
"origin_token_address": "0x2DC70fb75b88d2eB4715bc06E1595E6D97c34DFF",
"rollup_exit_root": "0x91105681934ca0791f4e760fb1f702050d81e4b7c866d42f540710999c90ea97",
"smt_proof_local_exit_root": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0xa8367b4263332f7e5453faa770f07ef4ce3e74fc411e0a788a98b38b91fd3b3e",
"0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30",
"0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85",
"0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344",
"0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d",
"0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968",
"0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83",
"0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af",
"0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0",
"0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5",
"0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892",
"0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c",
"0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb",
"0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc",
"0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2",
"0x2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f",
"0xe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a",
"0x5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0",
"0xb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0",
"0xc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2",
"0xf4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9",
"0x5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377",
"0x4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652",
"0xcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef",
"0x0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d",
"0xb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0",
"0x838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e",
"0x662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e",
"0x388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322",
"0x93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735",
"0x8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9"
],
"smt_proof_rollup_exit_root": [
"0x0000000000000000000000000000000000000000000000000000000000000000",
"0xad3228b676f7d3cd4284a5443f17f1962b36e491b30a40b2405849e597ba5fb5",
"0xb4c11951957c6f8f642c4af61cd6b24640fec6dc7fc607ee8206a99e92410d30",
"0x21ddb9a356815c3fac1026b6dec5df3124afbadb485c9ba5a3e3398a04b7ba85",
"0xe58769b32a1beaf1ea27375a44095a0d1fb664ce2dd358e7fcbfb78c26a19344",
"0x0eb01ebfc9ed27500cd4dfc979272d1f0913cc9f66540d7e8005811109e1cf2d",
"0x887c22bd8750d34016ac3c66b5ff102dacdd73f6b014e710b51e8022af9a1968",
"0xffd70157e48063fc33c97a050f7f640233bf646cc98d9524c6b92bcf3ab56f83",
"0x9867cc5f7f196b93bae1e27e6320742445d290f2263827498b54fec539f756af",
"0xcefad4e508c098b9a7e1d8feb19955fb02ba9675585078710969d3440f5054e0",
"0xf9dc3e7fe016e050eff260334f18a5d4fe391d82092319f5964f2e2eb7c1c3a5",
"0xf8b13a49e282f609c317a833fb8d976d11517c571d1221a265d25af778ecf892",
"0x3490c6ceeb450aecdc82e28293031d10c7d73bf85e57bf041a97360aa2c5d99c",
"0xc1df82d9c4b87413eae2ef048f94b4d3554cea73d92b0f7af96e0271c691e2bb",
"0x5c67add7c6caf302256adedf7ab114da0acfe870d449a3a489f781d659e8becc",
"0xda7bce9f4e8618b6bd2f4132ce798cdc7a60e7e1460a7299e3c6342a579626d2",
"0x2733e50f526ec2fa19a22b31e8ed50f23cd1fdf94c9154ed3a7609a2f1ff981f",
"0xe1d3b5c807b281e4683cc6d6315cf95b9ade8641defcb32372f1c126e398ef7a",
"0x5a2dce0a8a7f68bb74560f8f71837c2c2ebbcbf7fffb42ae1896f13f7c7479a0",
"0xb46a28b6f55540f89444f63de0378e3d121be09e06cc9ded1c20e65876d36aa0",
"0xc65e9645644786b620e2dd2ad648ddfcbf4a7e5b1a3a4ecfe7f64667a3f0b7e2",
"0xf4418588ed35a2458cffeb39b93d26f18d2ab13bdce6aee58e7b99359ec2dfd9",
"0x5a9c16dc00d6ef18b7933a6f8dc65ccb55667138776f7dea101070dc8796e377",
"0x4df84f40ae0c8229d0d6069e5c8f39a7c299677a09d367fc7b05e3bc380ee652",
"0xcdc72595f74c7b1043d0e1ffbab734648c838dfb0527d971b602bc216c9619ef",
"0x0abf5ac974a1ed57f4050aa510dd9c74f508277b39d7973bb2dfccc5eeb0618d",
"0xb8cd74046ff337f0a7bf2c8e03e10f642c1886798d71806ab1e888d9e5ee87d0",
"0x838c5655cb21c6cb83313b5a631175dff4963772cce9108188b34ac87c81c41e",
"0x662ee4dd2dd7b2bc707961b1e646c4047669dcb6584f0d8d770daf5d7e7deb2e",
"0x388ab20e2573d171a88108e79d820e98f26c0b84aa8b2f4aa4968dbb818ea322",
"0x93237c50ba75ee485f4c22adf2f741400bdf8d6a9cc7df7ecae576221665d735",
"0x8448818bb4ae4562849e949e17ac16e0be16688e156b5cf15e098c627c0056a9"
]
}
Loading
Loading