Skip to content
Open
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
146 changes: 112 additions & 34 deletions crates/miden-agglayer/asm/agglayer/bridge/bridge_in.masm
Original file line number Diff line number Diff line change
Expand Up @@ -15,35 +15,40 @@ 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"

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

# Memory pointers for proof data layout
# Memory layout for proof data (loaded from advice map via pipe_preimage_to_memory).
# The proof data occupies addresses [PROOF_DATA_PTR .. PROOF_DATA_PTR + 535]:
# [0..255] smtProofLocalExitRoot (256 felts = 32 Keccak256 nodes)
# [256..511] smtProofRollupExitRoot (256 felts = 32 Keccak256 nodes)
# [512..519] globalIndex (8 felts)
# [520..527] mainnetExitRoot (8 felts)
# [528..535] rollupExitRoot (8 felts)
const PROOF_DATA_PTR = 0
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

# the memory address where leaf data is stored for get_leaf_value
const SMT_PROOF_LOCAL_EXIT_ROOT_PTR = PROOF_DATA_PTR
const SMT_PROOF_ROLLUP_EXIT_ROOT_PTR = SMT_PROOF_LOCAL_EXIT_ROOT_PTR + 256
const GLOBAL_INDEX_PTR = SMT_PROOF_ROLLUP_EXIT_ROOT_PTR + 256
const EXIT_ROOTS_PTR = GLOBAL_INDEX_PTR + 8
const MAINNET_EXIT_ROOT_PTR = EXIT_ROOTS_PTR
const ROLLUP_EXIT_ROOT_PTR = EXIT_ROOTS_PTR + 8

# Memory layout for leaf data (loaded separately via get_leaf_value)
const LEAF_DATA_START_PTR = 0

# The offset of the first half of the current Keccak256 hash value in the local memory of the
# `calculate_root` procedure.
# Local memory offsets for the `calculate_root` procedure's current hash
const CUR_HASH_LO_LOCAL = 0

# The offset of the second half of the current Keccak256 hash value in the local memory of the
# `calculate_root` procedure.
const CUR_HASH_HI_LOCAL = 4

# Data sizes
const PROOF_DATA_WORD_LEN = 134
# the number of words (4 felts each) in the advice map leaf data
const LEAF_DATA_NUM_WORDS = 8

# PUBLIC INTERFACE
Expand Down Expand Up @@ -116,17 +121,16 @@ end
#!
#! Invocation: exec
pub proc process_global_index_mainnet
# 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 +139,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 +299,69 @@ 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]]
# 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 stack position 5.

# 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]]
# 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]]

# 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]
u32lt.2 assert.err=ERR_MAINNET_FLAG_INVALID
# => [mainnet_flag, GLOBAL_INDEX[8], LEAF_VALUE[8]]

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

# 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
# => []
# 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
# => []
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
# calculate_root expects: [LEAF_VALUE_LO, LEAF_VALUE_HI, merkle_path_ptr, leaf_index]
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 movdn.9
# => [LOCAL_EXIT_ROOT_LO, LOCAL_EXIT_ROOT_HI, rollup_index, rollup_exit_root_ptr]
push.SMT_PROOF_ROLLUP_EXIT_ROOT_PTR movdn.8

# => [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