From 2f48ba9d30bc525c4312b0cce1655f4401dea11a Mon Sep 17 00:00:00 2001 From: darth-cy Date: Tue, 26 Mar 2024 18:51:58 -0400 Subject: [PATCH 01/20] Remove debug flags --- zkevm-circuits/src/rlp_circuit_fsm/test.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm/test.rs b/zkevm-circuits/src/rlp_circuit_fsm/test.rs index 4b8c0f5403..06dc403291 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm/test.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm/test.rs @@ -107,7 +107,6 @@ fn test_l1_msg_tx() { mock_prover.assert_satisfied_par(); } -// 1559_debug #[test] fn test_eip1559_tx() { let test_bytes = vec![ From e28eb309e65ce463c0bc4e51c7180530baa205a8 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Tue, 26 Mar 2024 22:08:26 -0400 Subject: [PATCH 02/20] Add decoding table PUSH lookup correspondence --- zkevm-circuits/src/rlp_circuit_fsm.rs | 66 ++++++++++++++++++++++ zkevm-circuits/src/rlp_circuit_fsm/test.rs | 5 +- 2 files changed, 69 insertions(+), 2 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index 0e011a29c4..84dea4b9ab 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -489,6 +489,7 @@ impl RlpCircuitConfig { is_tag!(is_tag_end_vector, EndVector); is_tag!(is_access_list_address, AccessListAddress); is_tag!(is_access_list_storage_key, AccessListStorageKey); + is_tag!(is_chain_id, ChainId); ////////////////////////////////////////////////////////// //////////// data table checks. ////////////////////////// @@ -2265,6 +2266,71 @@ impl RlpCircuitConfig { debug_assert!(meta.degree() <= 9); + /////////////////////////////////////////////////////////////////// + /////// Rlp Decoding Table and RLP Circuit Correspondence ///////// + /////////////////////////////////////////////////////////////////// + + // RLP Decoding Table is sorted using an id = (tx_id, format, depth, access_list_idx, storage_key_idx) + // but bytes in the RLP circuit (rlp_table) is processed in order. Therefore, to prevent malicious injection of stack ops that + // don't correspond to actual bytes in the RLP circuit, lookups are added to ensure correct correspondence. + meta.lookup_any( + "PUSH op in decoding table", + |meta| { + let enable = meta.query_advice(rlp_decoding_table.is_stack_push, Rotation::cur()); + + let input_exprs = vec![ + meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), + meta.query_advice(rlp_decoding_table.format, Rotation::cur()), + meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()) + 1.expr(), // decoding table counts bytes from idx = 0 + + // List scenario on each depth. + // Sufficiency is achieved by listing all possible depth. + meta.query_advice(is_stack_depth_one, Rotation::cur()), + meta.query_advice(is_stack_depth_two, Rotation::cur()), + meta.query_advice(is_stack_depth_three, Rotation::cur()), + meta.query_advice(is_stack_depth_four, Rotation::cur()), + ]; + let table_exprs = vec![ + meta.query_advice(tx_id, Rotation::cur()), + meta.query_advice(format, Rotation::cur()), + meta.query_advice(byte_idx, Rotation::cur()), + + // Depth 1: Begin decoding actual payload (with out the tx type envelope). Starting at ChainId + and::expr([ + is_chain_id(meta), + is_decode_tag_start(meta), + ]), + + // Depth 2: Begin decoding an access list. + and::expr([ + is_tag_begin_object(meta), + is_decode_tag_start(meta), + ]), + + // Depth 3: A new access list address item + meta.query_advice(rlp_table.access_list_idx, Rotation::cur()) + - meta.query_advice(rlp_table.access_list_idx, Rotation::prev()), + + // Depth 4: The first storage key item. + // Only the first storage key corresponds to a PUSH op. The rest correspond to UPDATE ops. + + // The difference between current storage_key_idx (in rlp_table) and the previous one is either 0 or 1. + // By multiplying the difference with current storage_key_idx, it guarantees that storage_key_idx::cur = 1 + // (which indicates the first storage key in an access list addresses's storage key list) + (meta.query_advice(rlp_table.storage_key_idx, Rotation::cur()) + - meta.query_advice(rlp_table.storage_key_idx, Rotation::prev())) + * meta.query_advice(rlp_table.storage_key_idx, Rotation::cur()), + ]; + input_exprs + .into_iter() + .zip(table_exprs) + .map(|(input, table)| (input * enable.expr(), table)) + .collect() + }, + ); + + debug_assert!(meta.degree() <= 9); + Self { q_first, q_last, diff --git a/zkevm-circuits/src/rlp_circuit_fsm/test.rs b/zkevm-circuits/src/rlp_circuit_fsm/test.rs index 06dc403291..f67e802a4d 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm/test.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm/test.rs @@ -107,15 +107,16 @@ fn test_l1_msg_tx() { mock_prover.assert_satisfied_par(); } +// 1559_debug #[test] fn test_eip1559_tx() { let test_bytes = vec![ // empty access list - "02f8b1010a8404a75411850f705051f08301724b94dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000006c57d84c55b01f7022999f6c0f95daf0e319dc37000000000000000000000000000000000000000000000000000000003b9aca00c001a0634f6d4b3b4fc658c2c26c1ba0966bd39d7e993b815390f1e778af9cf28d2c22a05410b97e41240ea25eb6250e1af7554cda8991bc4159228c43cfb240503d9870", + // "02f8b1010a8404a75411850f705051f08301724b94dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000006c57d84c55b01f7022999f6c0f95daf0e319dc37000000000000000000000000000000000000000000000000000000003b9aca00c001a0634f6d4b3b4fc658c2c26c1ba0966bd39d7e993b815390f1e778af9cf28d2c22a05410b97e41240ea25eb6250e1af7554cda8991bc4159228c43cfb240503d9870", // same as third test but with abridged access list "02f9025d01825cb38520955af4328521cf92558d830a1bff9400fc00900000002c00be4ef8f49c000211000c43830cc4d0b9015504673a0b85b3000bef3e26e01428d1b525a532ea7513b8f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097020c532d1b995b7e3e37a1aa6369386e5939053779abd3597508b00129cd75b800073edec02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f21661d0d1d76d3ecb8e1b9f1c923dbfffae40970bb86c3dc790b0d7291f864244b559b59b30f850a8cfb40dc7c53760375530e5af29fded5e139893252993820686c92b000094b61ba302f01b0f027d40c80d8f70f77d3884776531f80b21d20e5a6b806300024b2c713b4502988e070f96cf3bea50b4811cd5844e13a81b61a8078c761b0b85b3000bef3e26e01428d1b525a532ea7513b80002594ea302f03b9eb369241e4270796e665ea1afac355cb99f0c32078ab8ba00013c08711b06ed871e5a66bebf0af6fb768d343b1d14a04b5b34ab10cf761b0b85b3000bef3e26e01428d1b525a532ea7513b8000143542ef893f7940b85b3000bef3e26e01428d1b525a532ea7513b8e1a00000000000000000000000000000000000000000000000000000000000000006f85994c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a0e1dd9768c9de657aca2536cf1cdd1c4536b13ec81ff764307ea8312aa7a8790da070bc879403c8b875e45ea7afbb591f1fd4bde469db47d5f0e879e44c6798d33e80a0d274986e36e16ec2d4846168d59422f68e4b8ec41690b80bdd2ee65819f238eea03d0394f6daae31ba5a276a3741cc2b3ba79b90024f80df865622a62078e72910", // unabridged access list - "02f90b7b01825cb38520955af4328521cf92558d830a1bff9400fc00900000002c00be4ef8f49c000211000c43830cc4d0b9015504673a0b85b3000bef3e26e01428d1b525a532ea7513b8f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097020c532d1b995b7e3e37a1aa6369386e5939053779abd3597508b00129cd75b800073edec02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f21661d0d1d76d3ecb8e1b9f1c923dbfffae40970bb86c3dc790b0d7291f864244b559b59b30f850a8cfb40dc7c53760375530e5af29fded5e139893252993820686c92b000094b61ba302f01b0f027d40c80d8f70f77d3884776531f80b21d20e5a6b806300024b2c713b4502988e070f96cf3bea50b4811cd5844e13a81b61a8078c761b0b85b3000bef3e26e01428d1b525a532ea7513b80002594ea302f03b9eb369241e4270796e665ea1afac355cb99f0c32078ab8ba00013c08711b06ed871e5a66bebf0af6fb768d343b1d14a04b5b34ab10cf761b0b85b3000bef3e26e01428d1b525a532ea7513b8000143542ef909b0f89b940b85b3000bef3e26e01428d1b525a532ea7513b8f884a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008f8dd94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f8c6a0e1dd9768c9de657aca2536cf1cdd1c4536b13ec81ff764307ea8312aa7a8790da070bc879403c8b875e45ea7afbb591f1fd4bde469db47d5f0e879e44c6798d33ea0f88aa3ad276c350a067c34b2bed705e1a2cd30c7c3154f62ece8ee00939bbd2ea0be11b0e2ba48478671bfcd8fd182e025c26fbfbcf4fdf6952051d6147955a36fa09a1a5a7ef77f3399dea2a1044425aaca7fec294fdfdcacd7a960c9c94d15f0a6a091828b9b711948523369ff1651b6332e98f75bcd940a551dc7247d5af88e71faf8bc945b7e3e37a1aa6369386e5939053779abd3597508f8a5a00000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000002a0697b2bd7bb2984c4e0dc14c79c987d37818484a62958b9c45a0e8b962f20650fa00000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000000f9018394c7c53760375530e5af29fded5e13989325299382f9016ba00000000000000000000000000000000000000000000000000000000000000010a0000000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000016a0000000000000000000000000000000000000000000000000000000000000000ea051d155e8243cd6886ab3b36f59778d90f3bbb4af820bc2d4536b23ca13814bfba00000000000000000000000000000000000000000000000000000000000000013a0a7609b0290b911c4b52861d3739b36793fd0e23d9ef78cf2fa96dd1b0cbc764da00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000ca0bda2b1a2a3e35ca431f3c4b50639098537d215591b9ca3db95c24c01795a9981a0000000000000000000000000000000000000000000000000000000000000000df89b94c790b0d7291f864244b559b59b30f850a8cfb40df884a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8dd9406ed871e5a66bebf0af6fb768d343b1d14a04b5bf8c6a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000af8bc94f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097f8a5a04d3eb812b43a439547ce41ef251d01e8ad3d0dad3fde6f2bed3d0c0e29dcdd7aa026644b9dbbd32f8882f3abce5ac1575313789ab081b0fe9f3f39c946527bfa27a072fd74a6edf1b99d41f2c81c57f871e198cb7a24fd9861e998221c4aeb776014a0a7609b0290b911c4b52861d3739b36793fd0e23d9ef78cf2fa96dd1b0cbc764da01a3159eb932a0bb66f4d5b9c1cb119796d815774e3c4904b36748d7870d915c2f8dd940f027d40c80d8f70f77d3884776531f80b21d20ef8c6a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8bc941a76bffd6d1fc1660e1d0e0552fde51ddbb120cff8a5a06d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6dfa030e699f4646032d62d40ca795ecffcb27a2d9d2859f21626b5a588210198e7a6a0c929f5ae32c0eabfbdd06198210bc49736d88e6501f814a66dd5b2fa59508b3ea0ea52bdd009b752a3e91262d66aae31638bc36b449d247d61d646b87a733d7d5da0877978b096db3b11862d0cdfe5f5b74f30fd7d5d29e8ce80626ed8a8bbef1beef8dd944502988e070f96cf3bea50b4811cd5844e13a81bf8c6a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8dd949eb369241e4270796e665ea1afac355cb99f0c32f8c6a00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000cf85994f9a2d7e60a3297e513317ad1d7ce101cc4c6c8f6f842a04b376a11d00750d42abab4d4e465d5dc4d9b1286d77cf0c819f028213ea08bdfa072fd74a6edf1b99d41f2c81c57f871e198cb7a24fd9861e998221c4aeb77601480a0d274986e36e16ec2d4846168d59422f68e4b8ec41690b80bdd2ee65819f238eea03d0394f6daae31ba5a276a3741cc2b3ba79b90024f80df865622a62078e72910", + // "02f90b7b01825cb38520955af4328521cf92558d830a1bff9400fc00900000002c00be4ef8f49c000211000c43830cc4d0b9015504673a0b85b3000bef3e26e01428d1b525a532ea7513b8f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097020c532d1b995b7e3e37a1aa6369386e5939053779abd3597508b00129cd75b800073edec02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f21661d0d1d76d3ecb8e1b9f1c923dbfffae40970bb86c3dc790b0d7291f864244b559b59b30f850a8cfb40dc7c53760375530e5af29fded5e139893252993820686c92b000094b61ba302f01b0f027d40c80d8f70f77d3884776531f80b21d20e5a6b806300024b2c713b4502988e070f96cf3bea50b4811cd5844e13a81b61a8078c761b0b85b3000bef3e26e01428d1b525a532ea7513b80002594ea302f03b9eb369241e4270796e665ea1afac355cb99f0c32078ab8ba00013c08711b06ed871e5a66bebf0af6fb768d343b1d14a04b5b34ab10cf761b0b85b3000bef3e26e01428d1b525a532ea7513b8000143542ef909b0f89b940b85b3000bef3e26e01428d1b525a532ea7513b8f884a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008f8dd94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f8c6a0e1dd9768c9de657aca2536cf1cdd1c4536b13ec81ff764307ea8312aa7a8790da070bc879403c8b875e45ea7afbb591f1fd4bde469db47d5f0e879e44c6798d33ea0f88aa3ad276c350a067c34b2bed705e1a2cd30c7c3154f62ece8ee00939bbd2ea0be11b0e2ba48478671bfcd8fd182e025c26fbfbcf4fdf6952051d6147955a36fa09a1a5a7ef77f3399dea2a1044425aaca7fec294fdfdcacd7a960c9c94d15f0a6a091828b9b711948523369ff1651b6332e98f75bcd940a551dc7247d5af88e71faf8bc945b7e3e37a1aa6369386e5939053779abd3597508f8a5a00000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000002a0697b2bd7bb2984c4e0dc14c79c987d37818484a62958b9c45a0e8b962f20650fa00000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000000f9018394c7c53760375530e5af29fded5e13989325299382f9016ba00000000000000000000000000000000000000000000000000000000000000010a0000000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000016a0000000000000000000000000000000000000000000000000000000000000000ea051d155e8243cd6886ab3b36f59778d90f3bbb4af820bc2d4536b23ca13814bfba00000000000000000000000000000000000000000000000000000000000000013a0a7609b0290b911c4b52861d3739b36793fd0e23d9ef78cf2fa96dd1b0cbc764da00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000ca0bda2b1a2a3e35ca431f3c4b50639098537d215591b9ca3db95c24c01795a9981a0000000000000000000000000000000000000000000000000000000000000000df89b94c790b0d7291f864244b559b59b30f850a8cfb40df884a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8dd9406ed871e5a66bebf0af6fb768d343b1d14a04b5bf8c6a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000af8bc94f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097f8a5a04d3eb812b43a439547ce41ef251d01e8ad3d0dad3fde6f2bed3d0c0e29dcdd7aa026644b9dbbd32f8882f3abce5ac1575313789ab081b0fe9f3f39c946527bfa27a072fd74a6edf1b99d41f2c81c57f871e198cb7a24fd9861e998221c4aeb776014a0a7609b0290b911c4b52861d3739b36793fd0e23d9ef78cf2fa96dd1b0cbc764da01a3159eb932a0bb66f4d5b9c1cb119796d815774e3c4904b36748d7870d915c2f8dd940f027d40c80d8f70f77d3884776531f80b21d20ef8c6a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8bc941a76bffd6d1fc1660e1d0e0552fde51ddbb120cff8a5a06d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6dfa030e699f4646032d62d40ca795ecffcb27a2d9d2859f21626b5a588210198e7a6a0c929f5ae32c0eabfbdd06198210bc49736d88e6501f814a66dd5b2fa59508b3ea0ea52bdd009b752a3e91262d66aae31638bc36b449d247d61d646b87a733d7d5da0877978b096db3b11862d0cdfe5f5b74f30fd7d5d29e8ce80626ed8a8bbef1beef8dd944502988e070f96cf3bea50b4811cd5844e13a81bf8c6a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8dd949eb369241e4270796e665ea1afac355cb99f0c32f8c6a00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000cf85994f9a2d7e60a3297e513317ad1d7ce101cc4c6c8f6f842a04b376a11d00750d42abab4d4e465d5dc4d9b1286d77cf0c819f028213ea08bdfa072fd74a6edf1b99d41f2c81c57f871e198cb7a24fd9861e998221c4aeb77601480a0d274986e36e16ec2d4846168d59422f68e4b8ec41690b80bdd2ee65819f238eea03d0394f6daae31ba5a276a3741cc2b3ba79b90024f80df865622a62078e72910", ]; let txs = test_bytes From 940ea111ff5fbc83bf03e83339acd625514cd966 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Wed, 27 Mar 2024 01:55:42 -0400 Subject: [PATCH 03/20] Complete Stack Op Correspondence --- zkevm-circuits/src/rlp_circuit_fsm.rs | 161 +++++++++++++++------ zkevm-circuits/src/rlp_circuit_fsm/test.rs | 5 +- 2 files changed, 116 insertions(+), 50 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index 84dea4b9ab..d14de271d9 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -489,7 +489,7 @@ impl RlpCircuitConfig { is_tag!(is_tag_end_vector, EndVector); is_tag!(is_access_list_address, AccessListAddress); is_tag!(is_access_list_storage_key, AccessListStorageKey); - is_tag!(is_chain_id, ChainId); + is_tag!(is_tag_chain_id, ChainId); ////////////////////////////////////////////////////////// //////////// data table checks. ////////////////////////// @@ -2150,48 +2150,6 @@ impl RlpCircuitConfig { ])) }); - meta.create_gate("Decoding table stack op INIT", |meta| { - let mut cb = BaseConstraintBuilder::default(); - - cb.require_equal( - "stack init pushes all remaining_bytes onto depth 0", - meta.query_advice(rlp_decoding_table.value, Rotation::cur()), - meta.query_advice(byte_rev_idx, Rotation::cur()), - ); - cb.require_equal( - "stack can only init once with the first byte", - meta.query_advice(byte_idx, Rotation::cur()), - 1.expr(), - ); - cb.require_zero( - "stack inits at depth 0", - meta.query_advice(rlp_decoding_table.depth, Rotation::cur()), - ); - cb.require_zero( - "stack inits with al_idx at 0", - meta.query_advice(rlp_decoding_table.al_idx, Rotation::cur()), - ); - cb.require_zero( - "stack inits with sk_idx at 0", - meta.query_advice(rlp_decoding_table.sk_idx, Rotation::cur()), - ); - cb.condition( - not::expr(meta.query_fixed(q_first, Rotation::cur())), - |cb| { - cb.require_boolean( - "tx_id can only stay the same or increment by 1", - meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()) - - meta.query_advice(rlp_decoding_table.tx_id, Rotation::prev()), - ); - }, - ); - - cb.gate(and::expr([ - meta.query_fixed(q_enabled, Rotation::cur()), - meta.query_advice(rlp_decoding_table.is_stack_init, Rotation::cur()), - ])) - }); - // Cross-depth stack constraints in the RlpDecodingTable // These two sets of lookups ensure exact correspondence of PUSH and POP records meta.lookup_any( @@ -2273,16 +2231,68 @@ impl RlpCircuitConfig { // RLP Decoding Table is sorted using an id = (tx_id, format, depth, access_list_idx, storage_key_idx) // but bytes in the RLP circuit (rlp_table) is processed in order. Therefore, to prevent malicious injection of stack ops that // don't correspond to actual bytes in the RLP circuit, lookups are added to ensure correct correspondence. + + // The Init Op is not affected by sorting and stays at first position in decoding table. + // For this reason, its correctness and correspondence is constrained using a gate instead of lookup. + meta.create_gate("Decoding table stack op INIT correspondence", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + cb.require_equal( + "stack init pushes all remaining_bytes onto depth 0", + meta.query_advice(rlp_decoding_table.value, Rotation::cur()), + meta.query_advice(byte_rev_idx, Rotation::cur()), + ); + cb.require_equal( + "stack can only init once with the first byte", + meta.query_advice(byte_idx, Rotation::cur()), + 1.expr(), + ); + cb.require_zero( + "stack inits at depth 0", + meta.query_advice(rlp_decoding_table.depth, Rotation::cur()), + ); + cb.require_zero( + "stack inits with al_idx at 0", + meta.query_advice(rlp_decoding_table.al_idx, Rotation::cur()), + ); + cb.require_zero( + "stack inits with sk_idx at 0", + meta.query_advice(rlp_decoding_table.sk_idx, Rotation::cur()), + ); + cb.condition( + not::expr(meta.query_fixed(q_first, Rotation::cur())), + |cb| { + cb.require_boolean( + "tx_id can only stay the same or increment by 1", + meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()) + - meta.query_advice(rlp_decoding_table.tx_id, Rotation::prev()), + ); + }, + ); + cb.require_equal( + "Init Op has DecodeTagStart in the state machine", + is_decode_tag_start(meta), + 1.expr(), + ); + + cb.gate(and::expr([ + meta.query_fixed(q_enabled, Rotation::cur()), + meta.query_advice(rlp_decoding_table.is_stack_init, Rotation::cur()), + ])) + }); + meta.lookup_any( - "PUSH op in decoding table", + "Decoding table stack op PUSH correspondence", |meta| { let enable = meta.query_advice(rlp_decoding_table.is_stack_push, Rotation::cur()); let input_exprs = vec![ meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), meta.query_advice(rlp_decoding_table.format, Rotation::cur()), - meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()) + 1.expr(), // decoding table counts bytes from idx = 0 - + // The byte_idx position that triggers the PUSH op is 1 position before the row denoting new state machine values. + meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()) + 1.expr(), + 1.expr(), // PUSH op increases depth + // List scenario on each depth. // Sufficiency is achieved by listing all possible depth. meta.query_advice(is_stack_depth_one, Rotation::cur()), @@ -2294,10 +2304,11 @@ impl RlpCircuitConfig { meta.query_advice(tx_id, Rotation::cur()), meta.query_advice(format, Rotation::cur()), meta.query_advice(byte_idx, Rotation::cur()), + meta.query_advice(depth, Rotation::cur()) - meta.query_advice(depth, Rotation::prev()), // Depth 1: Begin decoding actual payload (with out the tx type envelope). Starting at ChainId and::expr([ - is_chain_id(meta), + is_tag_chain_id(meta), is_decode_tag_start(meta), ]), @@ -2329,6 +2340,62 @@ impl RlpCircuitConfig { }, ); + meta.lookup_any( + "Decoding table stack op POP correspondence", + |meta| { + let enable = meta.query_advice(rlp_decoding_table.is_stack_pop, Rotation::cur()); + + let input_exprs = vec![ + meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), + meta.query_advice(rlp_decoding_table.format, Rotation::cur()), + // A POP op doesn't correspond to an actual byte, but only the end tag state + meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), + 1.expr(), // A POP op reduces depth level + // A POP follows an end state, either EndVector or EndObject + 1.expr(), + ]; + let table_exprs = vec![ + meta.query_advice(tx_id, Rotation::cur()), + meta.query_advice(format, Rotation::cur()), + meta.query_advice(byte_idx, Rotation::cur()), + meta.query_advice(depth, Rotation::cur()) - meta.query_advice(depth, Rotation::next()), + meta.query_advice(is_tag_end, Rotation::cur()), + ]; + input_exprs + .into_iter() + .zip(table_exprs) + .map(|(input, table)| (input * enable.expr(), table)) + .collect() + }, + ); + + meta.lookup_any( + "Decoding table stack op UPDATE correspondence", + |meta| { + let enable = meta.query_advice(rlp_decoding_table.is_stack_update, Rotation::cur()); + + let input_exprs = vec![ + meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), + meta.query_advice(rlp_decoding_table.format, Rotation::cur()), + meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), + 0.expr(), // UPDATE doesn't change depth level + 0.expr(), // UPDATE can't correspond to end states + ]; + let table_exprs = vec![ + meta.query_advice(tx_id, Rotation::cur()), + meta.query_advice(format, Rotation::cur()), + meta.query_advice(byte_idx, Rotation::cur()), + meta.query_advice(depth, Rotation::next()) - meta.query_advice(depth, Rotation::cur()), + meta.query_advice(is_tag_end, Rotation::cur()), + ]; + input_exprs + .into_iter() + .zip(table_exprs) + .map(|(input, table)| (input * enable.expr(), table)) + .collect() + }, + ); + debug_assert!(meta.degree() <= 9); Self { diff --git a/zkevm-circuits/src/rlp_circuit_fsm/test.rs b/zkevm-circuits/src/rlp_circuit_fsm/test.rs index f67e802a4d..06dc403291 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm/test.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm/test.rs @@ -107,16 +107,15 @@ fn test_l1_msg_tx() { mock_prover.assert_satisfied_par(); } -// 1559_debug #[test] fn test_eip1559_tx() { let test_bytes = vec![ // empty access list - // "02f8b1010a8404a75411850f705051f08301724b94dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000006c57d84c55b01f7022999f6c0f95daf0e319dc37000000000000000000000000000000000000000000000000000000003b9aca00c001a0634f6d4b3b4fc658c2c26c1ba0966bd39d7e993b815390f1e778af9cf28d2c22a05410b97e41240ea25eb6250e1af7554cda8991bc4159228c43cfb240503d9870", + "02f8b1010a8404a75411850f705051f08301724b94dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000006c57d84c55b01f7022999f6c0f95daf0e319dc37000000000000000000000000000000000000000000000000000000003b9aca00c001a0634f6d4b3b4fc658c2c26c1ba0966bd39d7e993b815390f1e778af9cf28d2c22a05410b97e41240ea25eb6250e1af7554cda8991bc4159228c43cfb240503d9870", // same as third test but with abridged access list "02f9025d01825cb38520955af4328521cf92558d830a1bff9400fc00900000002c00be4ef8f49c000211000c43830cc4d0b9015504673a0b85b3000bef3e26e01428d1b525a532ea7513b8f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097020c532d1b995b7e3e37a1aa6369386e5939053779abd3597508b00129cd75b800073edec02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f21661d0d1d76d3ecb8e1b9f1c923dbfffae40970bb86c3dc790b0d7291f864244b559b59b30f850a8cfb40dc7c53760375530e5af29fded5e139893252993820686c92b000094b61ba302f01b0f027d40c80d8f70f77d3884776531f80b21d20e5a6b806300024b2c713b4502988e070f96cf3bea50b4811cd5844e13a81b61a8078c761b0b85b3000bef3e26e01428d1b525a532ea7513b80002594ea302f03b9eb369241e4270796e665ea1afac355cb99f0c32078ab8ba00013c08711b06ed871e5a66bebf0af6fb768d343b1d14a04b5b34ab10cf761b0b85b3000bef3e26e01428d1b525a532ea7513b8000143542ef893f7940b85b3000bef3e26e01428d1b525a532ea7513b8e1a00000000000000000000000000000000000000000000000000000000000000006f85994c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a0e1dd9768c9de657aca2536cf1cdd1c4536b13ec81ff764307ea8312aa7a8790da070bc879403c8b875e45ea7afbb591f1fd4bde469db47d5f0e879e44c6798d33e80a0d274986e36e16ec2d4846168d59422f68e4b8ec41690b80bdd2ee65819f238eea03d0394f6daae31ba5a276a3741cc2b3ba79b90024f80df865622a62078e72910", // unabridged access list - // "02f90b7b01825cb38520955af4328521cf92558d830a1bff9400fc00900000002c00be4ef8f49c000211000c43830cc4d0b9015504673a0b85b3000bef3e26e01428d1b525a532ea7513b8f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097020c532d1b995b7e3e37a1aa6369386e5939053779abd3597508b00129cd75b800073edec02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f21661d0d1d76d3ecb8e1b9f1c923dbfffae40970bb86c3dc790b0d7291f864244b559b59b30f850a8cfb40dc7c53760375530e5af29fded5e139893252993820686c92b000094b61ba302f01b0f027d40c80d8f70f77d3884776531f80b21d20e5a6b806300024b2c713b4502988e070f96cf3bea50b4811cd5844e13a81b61a8078c761b0b85b3000bef3e26e01428d1b525a532ea7513b80002594ea302f03b9eb369241e4270796e665ea1afac355cb99f0c32078ab8ba00013c08711b06ed871e5a66bebf0af6fb768d343b1d14a04b5b34ab10cf761b0b85b3000bef3e26e01428d1b525a532ea7513b8000143542ef909b0f89b940b85b3000bef3e26e01428d1b525a532ea7513b8f884a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008f8dd94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f8c6a0e1dd9768c9de657aca2536cf1cdd1c4536b13ec81ff764307ea8312aa7a8790da070bc879403c8b875e45ea7afbb591f1fd4bde469db47d5f0e879e44c6798d33ea0f88aa3ad276c350a067c34b2bed705e1a2cd30c7c3154f62ece8ee00939bbd2ea0be11b0e2ba48478671bfcd8fd182e025c26fbfbcf4fdf6952051d6147955a36fa09a1a5a7ef77f3399dea2a1044425aaca7fec294fdfdcacd7a960c9c94d15f0a6a091828b9b711948523369ff1651b6332e98f75bcd940a551dc7247d5af88e71faf8bc945b7e3e37a1aa6369386e5939053779abd3597508f8a5a00000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000002a0697b2bd7bb2984c4e0dc14c79c987d37818484a62958b9c45a0e8b962f20650fa00000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000000f9018394c7c53760375530e5af29fded5e13989325299382f9016ba00000000000000000000000000000000000000000000000000000000000000010a0000000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000016a0000000000000000000000000000000000000000000000000000000000000000ea051d155e8243cd6886ab3b36f59778d90f3bbb4af820bc2d4536b23ca13814bfba00000000000000000000000000000000000000000000000000000000000000013a0a7609b0290b911c4b52861d3739b36793fd0e23d9ef78cf2fa96dd1b0cbc764da00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000ca0bda2b1a2a3e35ca431f3c4b50639098537d215591b9ca3db95c24c01795a9981a0000000000000000000000000000000000000000000000000000000000000000df89b94c790b0d7291f864244b559b59b30f850a8cfb40df884a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8dd9406ed871e5a66bebf0af6fb768d343b1d14a04b5bf8c6a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000af8bc94f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097f8a5a04d3eb812b43a439547ce41ef251d01e8ad3d0dad3fde6f2bed3d0c0e29dcdd7aa026644b9dbbd32f8882f3abce5ac1575313789ab081b0fe9f3f39c946527bfa27a072fd74a6edf1b99d41f2c81c57f871e198cb7a24fd9861e998221c4aeb776014a0a7609b0290b911c4b52861d3739b36793fd0e23d9ef78cf2fa96dd1b0cbc764da01a3159eb932a0bb66f4d5b9c1cb119796d815774e3c4904b36748d7870d915c2f8dd940f027d40c80d8f70f77d3884776531f80b21d20ef8c6a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8bc941a76bffd6d1fc1660e1d0e0552fde51ddbb120cff8a5a06d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6dfa030e699f4646032d62d40ca795ecffcb27a2d9d2859f21626b5a588210198e7a6a0c929f5ae32c0eabfbdd06198210bc49736d88e6501f814a66dd5b2fa59508b3ea0ea52bdd009b752a3e91262d66aae31638bc36b449d247d61d646b87a733d7d5da0877978b096db3b11862d0cdfe5f5b74f30fd7d5d29e8ce80626ed8a8bbef1beef8dd944502988e070f96cf3bea50b4811cd5844e13a81bf8c6a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8dd949eb369241e4270796e665ea1afac355cb99f0c32f8c6a00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000cf85994f9a2d7e60a3297e513317ad1d7ce101cc4c6c8f6f842a04b376a11d00750d42abab4d4e465d5dc4d9b1286d77cf0c819f028213ea08bdfa072fd74a6edf1b99d41f2c81c57f871e198cb7a24fd9861e998221c4aeb77601480a0d274986e36e16ec2d4846168d59422f68e4b8ec41690b80bdd2ee65819f238eea03d0394f6daae31ba5a276a3741cc2b3ba79b90024f80df865622a62078e72910", + "02f90b7b01825cb38520955af4328521cf92558d830a1bff9400fc00900000002c00be4ef8f49c000211000c43830cc4d0b9015504673a0b85b3000bef3e26e01428d1b525a532ea7513b8f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097020c532d1b995b7e3e37a1aa6369386e5939053779abd3597508b00129cd75b800073edec02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f21661d0d1d76d3ecb8e1b9f1c923dbfffae40970bb86c3dc790b0d7291f864244b559b59b30f850a8cfb40dc7c53760375530e5af29fded5e139893252993820686c92b000094b61ba302f01b0f027d40c80d8f70f77d3884776531f80b21d20e5a6b806300024b2c713b4502988e070f96cf3bea50b4811cd5844e13a81b61a8078c761b0b85b3000bef3e26e01428d1b525a532ea7513b80002594ea302f03b9eb369241e4270796e665ea1afac355cb99f0c32078ab8ba00013c08711b06ed871e5a66bebf0af6fb768d343b1d14a04b5b34ab10cf761b0b85b3000bef3e26e01428d1b525a532ea7513b8000143542ef909b0f89b940b85b3000bef3e26e01428d1b525a532ea7513b8f884a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008f8dd94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f8c6a0e1dd9768c9de657aca2536cf1cdd1c4536b13ec81ff764307ea8312aa7a8790da070bc879403c8b875e45ea7afbb591f1fd4bde469db47d5f0e879e44c6798d33ea0f88aa3ad276c350a067c34b2bed705e1a2cd30c7c3154f62ece8ee00939bbd2ea0be11b0e2ba48478671bfcd8fd182e025c26fbfbcf4fdf6952051d6147955a36fa09a1a5a7ef77f3399dea2a1044425aaca7fec294fdfdcacd7a960c9c94d15f0a6a091828b9b711948523369ff1651b6332e98f75bcd940a551dc7247d5af88e71faf8bc945b7e3e37a1aa6369386e5939053779abd3597508f8a5a00000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000002a0697b2bd7bb2984c4e0dc14c79c987d37818484a62958b9c45a0e8b962f20650fa00000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000000f9018394c7c53760375530e5af29fded5e13989325299382f9016ba00000000000000000000000000000000000000000000000000000000000000010a0000000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000016a0000000000000000000000000000000000000000000000000000000000000000ea051d155e8243cd6886ab3b36f59778d90f3bbb4af820bc2d4536b23ca13814bfba00000000000000000000000000000000000000000000000000000000000000013a0a7609b0290b911c4b52861d3739b36793fd0e23d9ef78cf2fa96dd1b0cbc764da00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000ca0bda2b1a2a3e35ca431f3c4b50639098537d215591b9ca3db95c24c01795a9981a0000000000000000000000000000000000000000000000000000000000000000df89b94c790b0d7291f864244b559b59b30f850a8cfb40df884a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8dd9406ed871e5a66bebf0af6fb768d343b1d14a04b5bf8c6a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000af8bc94f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097f8a5a04d3eb812b43a439547ce41ef251d01e8ad3d0dad3fde6f2bed3d0c0e29dcdd7aa026644b9dbbd32f8882f3abce5ac1575313789ab081b0fe9f3f39c946527bfa27a072fd74a6edf1b99d41f2c81c57f871e198cb7a24fd9861e998221c4aeb776014a0a7609b0290b911c4b52861d3739b36793fd0e23d9ef78cf2fa96dd1b0cbc764da01a3159eb932a0bb66f4d5b9c1cb119796d815774e3c4904b36748d7870d915c2f8dd940f027d40c80d8f70f77d3884776531f80b21d20ef8c6a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8bc941a76bffd6d1fc1660e1d0e0552fde51ddbb120cff8a5a06d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6dfa030e699f4646032d62d40ca795ecffcb27a2d9d2859f21626b5a588210198e7a6a0c929f5ae32c0eabfbdd06198210bc49736d88e6501f814a66dd5b2fa59508b3ea0ea52bdd009b752a3e91262d66aae31638bc36b449d247d61d646b87a733d7d5da0877978b096db3b11862d0cdfe5f5b74f30fd7d5d29e8ce80626ed8a8bbef1beef8dd944502988e070f96cf3bea50b4811cd5844e13a81bf8c6a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8dd949eb369241e4270796e665ea1afac355cb99f0c32f8c6a00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000cf85994f9a2d7e60a3297e513317ad1d7ce101cc4c6c8f6f842a04b376a11d00750d42abab4d4e465d5dc4d9b1286d77cf0c819f028213ea08bdfa072fd74a6edf1b99d41f2c81c57f871e198cb7a24fd9861e998221c4aeb77601480a0d274986e36e16ec2d4846168d59422f68e4b8ec41690b80bdd2ee65819f238eea03d0394f6daae31ba5a276a3741cc2b3ba79b90024f80df865622a62078e72910", ]; let txs = test_bytes From 541a328638d9a63afbfe832f59fa82b2eea64c84 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Wed, 3 Apr 2024 17:01:21 -0400 Subject: [PATCH 04/20] fmt --- zkevm-circuits/src/rlp_circuit_fsm.rs | 220 ++++++++++++-------------- 1 file changed, 105 insertions(+), 115 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index 82bfabf734..14a60ea1e6 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2225,12 +2225,14 @@ impl RlpCircuitConfig { /////// Rlp Decoding Table and RLP Circuit Correspondence ///////// /////////////////////////////////////////////////////////////////// - // RLP Decoding Table is sorted using an id = (tx_id, format, depth, access_list_idx, storage_key_idx) - // but bytes in the RLP circuit (rlp_table) is processed in order. Therefore, to prevent malicious injection of stack ops that - // don't correspond to actual bytes in the RLP circuit, lookups are added to ensure correct correspondence. - - // The Init Op is not affected by sorting and stays at first position in decoding table. - // For this reason, its correctness and correspondence is constrained using a gate instead of lookup. + // RLP Decoding Table is sorted using an id = (tx_id, format, depth, access_list_idx, + // storage_key_idx) but bytes in the RLP circuit (rlp_table) is processed in order. + // Therefore, to prevent malicious injection of stack ops that don't correspond to + // actual bytes in the RLP circuit, lookups are added to ensure correct correspondence. + + // The Init Op is not affected by sorting and stays at first position in decoding table. + // For this reason, its correctness and correspondence is constrained using a gate instead + // of lookup. meta.create_gate("Decoding table stack op INIT correspondence", |meta| { let mut cb = BaseConstraintBuilder::default(); @@ -2278,120 +2280,108 @@ impl RlpCircuitConfig { ])) }); - meta.lookup_any( - "Decoding table stack op PUSH correspondence", - |meta| { - let enable = meta.query_advice(rlp_decoding_table.is_stack_push, Rotation::cur()); - - let input_exprs = vec![ - meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), - meta.query_advice(rlp_decoding_table.format, Rotation::cur()), - // The byte_idx position that triggers the PUSH op is 1 position before the row denoting new state machine values. - meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()) + 1.expr(), - 1.expr(), // PUSH op increases depth - - // List scenario on each depth. - // Sufficiency is achieved by listing all possible depth. - meta.query_advice(is_stack_depth_one, Rotation::cur()), - meta.query_advice(is_stack_depth_two, Rotation::cur()), - meta.query_advice(is_stack_depth_three, Rotation::cur()), - meta.query_advice(is_stack_depth_four, Rotation::cur()), - ]; - let table_exprs = vec![ - meta.query_advice(tx_id, Rotation::cur()), - meta.query_advice(format, Rotation::cur()), - meta.query_advice(byte_idx, Rotation::cur()), - meta.query_advice(depth, Rotation::cur()) - meta.query_advice(depth, Rotation::prev()), + meta.lookup_any("Decoding table stack op PUSH correspondence", |meta| { + let enable = meta.query_advice(rlp_decoding_table.is_stack_push, Rotation::cur()); - // Depth 1: Begin decoding actual payload (with out the tx type envelope). Starting at ChainId - and::expr([ - is_tag_chain_id(meta), - is_decode_tag_start(meta), - ]), - - // Depth 2: Begin decoding an access list. - and::expr([ - is_tag_begin_object(meta), - is_decode_tag_start(meta), - ]), - - // Depth 3: A new access list address item - meta.query_advice(rlp_table.access_list_idx, Rotation::cur()) - - meta.query_advice(rlp_table.access_list_idx, Rotation::prev()), - - // Depth 4: The first storage key item. - // Only the first storage key corresponds to a PUSH op. The rest correspond to UPDATE ops. - - // The difference between current storage_key_idx (in rlp_table) and the previous one is either 0 or 1. - // By multiplying the difference with current storage_key_idx, it guarantees that storage_key_idx::cur = 1 - // (which indicates the first storage key in an access list addresses's storage key list) - (meta.query_advice(rlp_table.storage_key_idx, Rotation::cur()) - - meta.query_advice(rlp_table.storage_key_idx, Rotation::prev())) - * meta.query_advice(rlp_table.storage_key_idx, Rotation::cur()), - ]; - input_exprs - .into_iter() - .zip(table_exprs) - .map(|(input, table)| (input * enable.expr(), table)) - .collect() - }, - ); + let input_exprs = vec![ + meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), + meta.query_advice(rlp_decoding_table.format, Rotation::cur()), + // The byte_idx position that triggers the PUSH op is 1 position before the row + // denoting new state machine values. + meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()) + 1.expr(), + 1.expr(), // PUSH op increases depth + // List scenario on each depth. + // Sufficiency is achieved by listing all possible depth. + meta.query_advice(is_stack_depth_one, Rotation::cur()), + meta.query_advice(is_stack_depth_two, Rotation::cur()), + meta.query_advice(is_stack_depth_three, Rotation::cur()), + meta.query_advice(is_stack_depth_four, Rotation::cur()), + ]; + let table_exprs = vec![ + meta.query_advice(tx_id, Rotation::cur()), + meta.query_advice(format, Rotation::cur()), + meta.query_advice(byte_idx, Rotation::cur()), + meta.query_advice(depth, Rotation::cur()) + - meta.query_advice(depth, Rotation::prev()), + // Depth 1: Begin decoding actual payload (with out the tx type envelope). Starting + // at ChainId + and::expr([is_tag_chain_id(meta), is_decode_tag_start(meta)]), + // Depth 2: Begin decoding an access list. + and::expr([is_tag_begin_object(meta), is_decode_tag_start(meta)]), + // Depth 3: A new access list address item + meta.query_advice(rlp_table.access_list_idx, Rotation::cur()) + - meta.query_advice(rlp_table.access_list_idx, Rotation::prev()), + // Depth 4: The first storage key item. + // Only the first storage key corresponds to a PUSH op. The rest correspond to + // UPDATE ops. + + // The difference between current storage_key_idx (in rlp_table) and the previous + // one is either 0 or 1. By multiplying the difference with current + // storage_key_idx, it guarantees that storage_key_idx::cur = 1 + // (which indicates the first storage key in an access list addresses's storage key + // list) + (meta.query_advice(rlp_table.storage_key_idx, Rotation::cur()) + - meta.query_advice(rlp_table.storage_key_idx, Rotation::prev())) + * meta.query_advice(rlp_table.storage_key_idx, Rotation::cur()), + ]; + input_exprs + .into_iter() + .zip(table_exprs) + .map(|(input, table)| (input * enable.expr(), table)) + .collect() + }); - meta.lookup_any( - "Decoding table stack op POP correspondence", - |meta| { - let enable = meta.query_advice(rlp_decoding_table.is_stack_pop, Rotation::cur()); + meta.lookup_any("Decoding table stack op POP correspondence", |meta| { + let enable = meta.query_advice(rlp_decoding_table.is_stack_pop, Rotation::cur()); - let input_exprs = vec![ - meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), - meta.query_advice(rlp_decoding_table.format, Rotation::cur()), - // A POP op doesn't correspond to an actual byte, but only the end tag state - meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), - 1.expr(), // A POP op reduces depth level - // A POP follows an end state, either EndVector or EndObject - 1.expr(), - ]; - let table_exprs = vec![ - meta.query_advice(tx_id, Rotation::cur()), - meta.query_advice(format, Rotation::cur()), - meta.query_advice(byte_idx, Rotation::cur()), - meta.query_advice(depth, Rotation::cur()) - meta.query_advice(depth, Rotation::next()), - meta.query_advice(is_tag_end, Rotation::cur()), - ]; - input_exprs - .into_iter() - .zip(table_exprs) - .map(|(input, table)| (input * enable.expr(), table)) - .collect() - }, - ); + let input_exprs = vec![ + meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), + meta.query_advice(rlp_decoding_table.format, Rotation::cur()), + // A POP op doesn't correspond to an actual byte, but only the end tag state + meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), + 1.expr(), // A POP op reduces depth level + // A POP follows an end state, either EndVector or EndObject + 1.expr(), + ]; + let table_exprs = vec![ + meta.query_advice(tx_id, Rotation::cur()), + meta.query_advice(format, Rotation::cur()), + meta.query_advice(byte_idx, Rotation::cur()), + meta.query_advice(depth, Rotation::cur()) + - meta.query_advice(depth, Rotation::next()), + meta.query_advice(is_tag_end, Rotation::cur()), + ]; + input_exprs + .into_iter() + .zip(table_exprs) + .map(|(input, table)| (input * enable.expr(), table)) + .collect() + }); - meta.lookup_any( - "Decoding table stack op UPDATE correspondence", - |meta| { - let enable = meta.query_advice(rlp_decoding_table.is_stack_update, Rotation::cur()); + meta.lookup_any("Decoding table stack op UPDATE correspondence", |meta| { + let enable = meta.query_advice(rlp_decoding_table.is_stack_update, Rotation::cur()); - let input_exprs = vec![ - meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), - meta.query_advice(rlp_decoding_table.format, Rotation::cur()), - meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), - 0.expr(), // UPDATE doesn't change depth level - 0.expr(), // UPDATE can't correspond to end states - ]; - let table_exprs = vec![ - meta.query_advice(tx_id, Rotation::cur()), - meta.query_advice(format, Rotation::cur()), - meta.query_advice(byte_idx, Rotation::cur()), - meta.query_advice(depth, Rotation::next()) - meta.query_advice(depth, Rotation::cur()), - meta.query_advice(is_tag_end, Rotation::cur()), - ]; - input_exprs - .into_iter() - .zip(table_exprs) - .map(|(input, table)| (input * enable.expr(), table)) - .collect() - }, - ); + let input_exprs = vec![ + meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), + meta.query_advice(rlp_decoding_table.format, Rotation::cur()), + meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), + 0.expr(), // UPDATE doesn't change depth level + 0.expr(), // UPDATE can't correspond to end states + ]; + let table_exprs = vec![ + meta.query_advice(tx_id, Rotation::cur()), + meta.query_advice(format, Rotation::cur()), + meta.query_advice(byte_idx, Rotation::cur()), + meta.query_advice(depth, Rotation::next()) + - meta.query_advice(depth, Rotation::cur()), + meta.query_advice(is_tag_end, Rotation::cur()), + ]; + input_exprs + .into_iter() + .zip(table_exprs) + .map(|(input, table)| (input * enable.expr(), table)) + .collect() + }); debug_assert!(meta.degree() <= 9); From 5eff0e6676db559a58aba948be4244aef102218c Mon Sep 17 00:00:00 2001 From: darth-cy Date: Thu, 4 Apr 2024 17:42:29 -0400 Subject: [PATCH 05/20] Correct lookup constraint --- zkevm-circuits/src/rlp_circuit_fsm.rs | 39 ++++++++++++++++++--------- 1 file changed, 27 insertions(+), 12 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index 14a60ea1e6..b339964a5a 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2288,7 +2288,9 @@ impl RlpCircuitConfig { meta.query_advice(rlp_decoding_table.format, Rotation::cur()), // The byte_idx position that triggers the PUSH op is 1 position before the row // denoting new state machine values. - meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()) + 1.expr(), + // meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()) + 1.expr(), + meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), + 1.expr(), // PUSH op increases depth // List scenario on each depth. // Sufficiency is achieved by listing all possible depth. @@ -2301,28 +2303,41 @@ impl RlpCircuitConfig { meta.query_advice(tx_id, Rotation::cur()), meta.query_advice(format, Rotation::cur()), meta.query_advice(byte_idx, Rotation::cur()), - meta.query_advice(depth, Rotation::cur()) - - meta.query_advice(depth, Rotation::prev()), + meta.query_advice(depth, Rotation::next()) + - meta.query_advice(depth, Rotation::cur()), // Depth 1: Begin decoding actual payload (with out the tx type envelope). Starting // at ChainId - and::expr([is_tag_chain_id(meta), is_decode_tag_start(meta)]), + and::expr([ + // is_tag_chain_id(meta), + tag_bits.value_equals(Tag::ChainId, Rotation::next())(meta), + // is_decode_tag_start(meta), + state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta), + ]), // Depth 2: Begin decoding an access list. - and::expr([is_tag_begin_object(meta), is_decode_tag_start(meta)]), + and::expr([ + sum::expr([ + // Case 1: The access list is completely empty. The very first row after PUSH is EndVector. + tag_bits.value_equals(Tag::EndVector, Rotation::next())(meta), + // Case 2: A regular access list. + tag_bits.value_equals(Tag::BeginObject, Rotation::next())(meta), + ]), + state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta), + ]), // Depth 3: A new access list address item - meta.query_advice(rlp_table.access_list_idx, Rotation::cur()) - - meta.query_advice(rlp_table.access_list_idx, Rotation::prev()), + meta.query_advice(rlp_table.access_list_idx, Rotation::next()) + - meta.query_advice(rlp_table.access_list_idx, Rotation::cur()), // Depth 4: The first storage key item. // Only the first storage key corresponds to a PUSH op. The rest correspond to // UPDATE ops. // The difference between current storage_key_idx (in rlp_table) and the previous - // one is either 0 or 1. By multiplying the difference with current - // storage_key_idx, it guarantees that storage_key_idx::cur = 1 + // one is either 0 or 1. By multiplying the difference with the new + // storage_key_idx, it guarantees that storage_key_idx::next = 1 // (which indicates the first storage key in an access list addresses's storage key // list) - (meta.query_advice(rlp_table.storage_key_idx, Rotation::cur()) - - meta.query_advice(rlp_table.storage_key_idx, Rotation::prev())) - * meta.query_advice(rlp_table.storage_key_idx, Rotation::cur()), + (meta.query_advice(rlp_table.storage_key_idx, Rotation::next()) + - meta.query_advice(rlp_table.storage_key_idx, Rotation::cur())) + * meta.query_advice(rlp_table.storage_key_idx, Rotation::next()), ]; input_exprs .into_iter() From 2a07e58947f24f8f1172d68cd01997de7b00edcd Mon Sep 17 00:00:00 2001 From: darth-cy Date: Thu, 4 Apr 2024 17:43:53 -0400 Subject: [PATCH 06/20] Remove unused macro --- zkevm-circuits/src/rlp_circuit_fsm.rs | 1 - 1 file changed, 1 deletion(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index b339964a5a..779cd38bd6 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -489,7 +489,6 @@ impl RlpCircuitConfig { is_tag!(is_tag_end_vector, EndVector); is_tag!(is_access_list_address, AccessListAddress); is_tag!(is_access_list_storage_key, AccessListStorageKey); - is_tag!(is_tag_chain_id, ChainId); ////////////////////////////////////////////////////////// //////////// data table checks. ////////////////////////// From 35c6554392973035db94e265371791517a2c9e44 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Thu, 4 Apr 2024 17:45:28 -0400 Subject: [PATCH 07/20] fmt --- zkevm-circuits/src/rlp_circuit_fsm.rs | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index 779cd38bd6..4a00d9398a 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2289,7 +2289,6 @@ impl RlpCircuitConfig { // denoting new state machine values. // meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()) + 1.expr(), meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), - 1.expr(), // PUSH op increases depth // List scenario on each depth. // Sufficiency is achieved by listing all possible depth. @@ -2307,7 +2306,7 @@ impl RlpCircuitConfig { // Depth 1: Begin decoding actual payload (with out the tx type envelope). Starting // at ChainId and::expr([ - // is_tag_chain_id(meta), + // is_tag_chain_id(meta), tag_bits.value_equals(Tag::ChainId, Rotation::next())(meta), // is_decode_tag_start(meta), state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta), @@ -2315,7 +2314,8 @@ impl RlpCircuitConfig { // Depth 2: Begin decoding an access list. and::expr([ sum::expr([ - // Case 1: The access list is completely empty. The very first row after PUSH is EndVector. + // Case 1: The access list is completely empty. The very first row after + // PUSH is EndVector. tag_bits.value_equals(Tag::EndVector, Rotation::next())(meta), // Case 2: A regular access list. tag_bits.value_equals(Tag::BeginObject, Rotation::next())(meta), From ef7468b9ec0ec341c148fb91968c139b7b530fe6 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Thu, 4 Apr 2024 19:18:00 -0400 Subject: [PATCH 08/20] Correct lookup constraint for pre 2930 txs --- zkevm-circuits/src/rlp_circuit_fsm.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index 4a00d9398a..04387a3e35 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2306,9 +2306,12 @@ impl RlpCircuitConfig { // Depth 1: Begin decoding actual payload (with out the tx type envelope). Starting // at ChainId and::expr([ - // is_tag_chain_id(meta), - tag_bits.value_equals(Tag::ChainId, Rotation::next())(meta), - // is_decode_tag_start(meta), + sum::expr([ + // Case 1: For pre-EIP2930/1559 and L1 Tx, the first field is Nonce. + tag_bits.value_equals(Tag::Nonce, Rotation::next())(meta), + // Case 2: For EIP2930/1559, the first field is ChainId. + tag_bits.value_equals(Tag::ChainId, Rotation::next())(meta), + ]), state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta), ]), // Depth 2: Begin decoding an access list. From 4ace12f97c791d6f09e5d70e4bd3577a266e0be7 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Thu, 4 Apr 2024 19:18:39 -0400 Subject: [PATCH 09/20] fmt --- zkevm-circuits/src/rlp_circuit_fsm.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index 04387a3e35..0e0b927f2e 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2311,7 +2311,7 @@ impl RlpCircuitConfig { tag_bits.value_equals(Tag::Nonce, Rotation::next())(meta), // Case 2: For EIP2930/1559, the first field is ChainId. tag_bits.value_equals(Tag::ChainId, Rotation::next())(meta), - ]), + ]), state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta), ]), // Depth 2: Begin decoding an access list. From d512ff1a576af630161245fee2dd73b8bba084ab Mon Sep 17 00:00:00 2001 From: darth-cy Date: Wed, 10 Apr 2024 19:00:10 -0400 Subject: [PATCH 10/20] Adjust comments --- zkevm-circuits/src/rlp_circuit_fsm.rs | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index 0e0b927f2e..56500ab9b0 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2229,6 +2229,11 @@ impl RlpCircuitConfig { // Therefore, to prevent malicious injection of stack ops that don't correspond to // actual bytes in the RLP circuit, lookups are added to ensure correct correspondence. + // How to ensure that every row in the state machine is also present in the decoding table: + // For each decoding table row that's not padding, a stack op (INIT, PUSH, POP or UPDATE) must be present. + // Then for each stack op that's present, it must correspond to a row in the state machine by below constraint (for INIT) and lookups (for PUSH, POP, UPDATE). + // This two-way constraint system creates a one-to-one relationship between state machine and the decoding table. + // The Init Op is not affected by sorting and stays at first position in decoding table. // For this reason, its correctness and correspondence is constrained using a gate instead // of lookup. @@ -2279,15 +2284,16 @@ impl RlpCircuitConfig { ])) }); + // Lookup strategies for PUSH: + // 1. The input expressions include the indicators for each depth level. + // 2. For each active depth indicator, it's checked against the allowable transitional scenarios in the state machine for that depth. + // 3. The byte_idx and depth transition are included. meta.lookup_any("Decoding table stack op PUSH correspondence", |meta| { let enable = meta.query_advice(rlp_decoding_table.is_stack_push, Rotation::cur()); let input_exprs = vec![ meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), meta.query_advice(rlp_decoding_table.format, Rotation::cur()), - // The byte_idx position that triggers the PUSH op is 1 position before the row - // denoting new state machine values. - // meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()) + 1.expr(), meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), 1.expr(), // PUSH op increases depth // List scenario on each depth. @@ -2303,8 +2309,7 @@ impl RlpCircuitConfig { meta.query_advice(byte_idx, Rotation::cur()), meta.query_advice(depth, Rotation::next()) - meta.query_advice(depth, Rotation::cur()), - // Depth 1: Begin decoding actual payload (with out the tx type envelope). Starting - // at ChainId + // Depth 1: Begin decoding actual payload (with out the tx type envelope). and::expr([ sum::expr([ // Case 1: For pre-EIP2930/1559 and L1 Tx, the first field is Nonce. From d927fc638964e5ac977d59e9d44d4cd74e1a13c2 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Wed, 10 Apr 2024 19:01:35 -0400 Subject: [PATCH 11/20] fmt --- zkevm-circuits/src/rlp_circuit_fsm.rs | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index 56500ab9b0..d915e35f55 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2230,9 +2230,11 @@ impl RlpCircuitConfig { // actual bytes in the RLP circuit, lookups are added to ensure correct correspondence. // How to ensure that every row in the state machine is also present in the decoding table: - // For each decoding table row that's not padding, a stack op (INIT, PUSH, POP or UPDATE) must be present. - // Then for each stack op that's present, it must correspond to a row in the state machine by below constraint (for INIT) and lookups (for PUSH, POP, UPDATE). - // This two-way constraint system creates a one-to-one relationship between state machine and the decoding table. + // For each decoding table row that's not padding, a stack op (INIT, PUSH, POP or UPDATE) + // must be present. Then for each stack op that's present, it must correspond to a + // row in the state machine by below constraint (for INIT) and lookups (for PUSH, POP, + // UPDATE). This two-way constraint system creates a one-to-one relationship between + // state machine and the decoding table. // The Init Op is not affected by sorting and stays at first position in decoding table. // For this reason, its correctness and correspondence is constrained using a gate instead @@ -2286,7 +2288,8 @@ impl RlpCircuitConfig { // Lookup strategies for PUSH: // 1. The input expressions include the indicators for each depth level. - // 2. For each active depth indicator, it's checked against the allowable transitional scenarios in the state machine for that depth. + // 2. For each active depth indicator, it's checked against the allowable transitional + // scenarios in the state machine for that depth. // 3. The byte_idx and depth transition are included. meta.lookup_any("Decoding table stack op PUSH correspondence", |meta| { let enable = meta.query_advice(rlp_decoding_table.is_stack_push, Rotation::cur()); From c1414e71898fba0614ffd2dfb1431c293aef7e12 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Tue, 16 Apr 2024 16:39:56 -0400 Subject: [PATCH 12/20] Add lookup indicator column for state machine --- zkevm-circuits/src/rlp_circuit_fsm.rs | 426 ++++++++++++--------- zkevm-circuits/src/rlp_circuit_fsm/test.rs | 5 +- 2 files changed, 257 insertions(+), 174 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index d915e35f55..b817f3cbf6 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -338,6 +338,12 @@ pub struct RlpCircuitConfig { is_stack_al_idx_diff: Column, /// Decoding table key change indicator. storage key idx change. is_stack_sk_idx_diff: Column, + /// Indicator column (PUSH) for lookup op into the decoding table from state machine + is_push_op_lookup: Column, + /// Indicator column (POP) for lookup op into the decoding table from state machine + is_pop_op_lookup: Column, + /// Indicator column (UPDATE) for lookup op into the decoding table from state machine + is_update_op_lookup: Column, /// Check for byte_value <= 0x80 byte_value_lte_0x80: ComparatorConfig, /// Check for byte_value >= 0x80 @@ -417,6 +423,9 @@ impl RlpCircuitConfig { is_new_access_list_storage_key, is_access_list_end, is_storage_key_list_end, + is_push_op_lookup, + is_pop_op_lookup, + is_update_op_lookup, ) = ( meta.fixed_column(), meta.fixed_column(), @@ -440,6 +449,9 @@ impl RlpCircuitConfig { meta.advice_column(), meta.advice_column(), meta.advice_column(), + meta.advice_column(), + meta.advice_column(), + meta.advice_column(), ); let tag_value_acc = meta.advice_column_in(SecondPhase); @@ -2220,193 +2232,229 @@ impl RlpCircuitConfig { debug_assert!(meta.degree() <= 9); - /////////////////////////////////////////////////////////////////// - /////// Rlp Decoding Table and RLP Circuit Correspondence ///////// - /////////////////////////////////////////////////////////////////// - // RLP Decoding Table is sorted using an id = (tx_id, format, depth, access_list_idx, - // storage_key_idx) but bytes in the RLP circuit (rlp_table) is processed in order. - // Therefore, to prevent malicious injection of stack ops that don't correspond to - // actual bytes in the RLP circuit, lookups are added to ensure correct correspondence. - - // How to ensure that every row in the state machine is also present in the decoding table: - // For each decoding table row that's not padding, a stack op (INIT, PUSH, POP or UPDATE) - // must be present. Then for each stack op that's present, it must correspond to a - // row in the state machine by below constraint (for INIT) and lookups (for PUSH, POP, - // UPDATE). This two-way constraint system creates a one-to-one relationship between - // state machine and the decoding table. - - // The Init Op is not affected by sorting and stays at first position in decoding table. - // For this reason, its correctness and correspondence is constrained using a gate instead - // of lookup. - meta.create_gate("Decoding table stack op INIT correspondence", |meta| { + + + // /////////////////////////////////////////////////////////////////// + // /////// Rlp Decoding Table and RLP Circuit Correspondence ///////// + // /////////////////////////////////////////////////////////////////// + meta.create_gate("State machine lookup indicators into the decoding table", |meta| { let mut cb = BaseConstraintBuilder::default(); + // stack operation indicators cb.require_equal( - "stack init pushes all remaining_bytes onto depth 0", - meta.query_advice(rlp_decoding_table.value, Rotation::cur()), - meta.query_advice(byte_rev_idx, Rotation::cur()), - ); - cb.require_equal( - "stack can only init once with the first byte", - meta.query_advice(byte_idx, Rotation::cur()), + "each state machine row (not padding) must correspond to a stack op in the decoding table", + sum::expr([ + meta.query_advice(rlp_decoding_table.is_stack_init, Rotation::cur()), // INIT is not affected by sorting + meta.query_advice(is_push_op_lookup, Rotation::cur()), + meta.query_advice(is_pop_op_lookup, Rotation::cur()), + meta.query_advice(is_update_op_lookup, Rotation::cur()), + ]), 1.expr(), ); - cb.require_zero( - "stack inits at depth 0", - meta.query_advice(rlp_decoding_table.depth, Rotation::cur()), + + cb.require_boolean( + "is_push_op_lookup is binary", + meta.query_advice(is_push_op_lookup, Rotation::cur()), ); - cb.require_zero( - "stack inits with al_idx at 0", - meta.query_advice(rlp_decoding_table.al_idx, Rotation::cur()), + cb.require_boolean( + "is_pop_op_lookup is binary", + meta.query_advice(is_pop_op_lookup, Rotation::cur()), ); - cb.require_zero( - "stack inits with sk_idx at 0", - meta.query_advice(rlp_decoding_table.sk_idx, Rotation::cur()), - ); - cb.condition( - not::expr(meta.query_fixed(q_first, Rotation::cur())), - |cb| { - cb.require_boolean( - "tx_id can only stay the same or increment by 1", - meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()) - - meta.query_advice(rlp_decoding_table.tx_id, Rotation::prev()), - ); - }, - ); - cb.require_equal( - "Init Op has DecodeTagStart in the state machine", - is_decode_tag_start(meta), - 1.expr(), + cb.require_boolean( + "is_update_op_lookup is binary", + meta.query_advice(is_update_op_lookup, Rotation::cur()), ); cb.gate(and::expr([ meta.query_fixed(q_enabled, Rotation::cur()), - meta.query_advice(rlp_decoding_table.is_stack_init, Rotation::cur()), + not::expr(is_end(meta)), ])) }); - // Lookup strategies for PUSH: - // 1. The input expressions include the indicators for each depth level. - // 2. For each active depth indicator, it's checked against the allowable transitional - // scenarios in the state machine for that depth. - // 3. The byte_idx and depth transition are included. - meta.lookup_any("Decoding table stack op PUSH correspondence", |meta| { - let enable = meta.query_advice(rlp_decoding_table.is_stack_push, Rotation::cur()); - - let input_exprs = vec![ - meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), - meta.query_advice(rlp_decoding_table.format, Rotation::cur()), - meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), - 1.expr(), // PUSH op increases depth - // List scenario on each depth. - // Sufficiency is achieved by listing all possible depth. - meta.query_advice(is_stack_depth_one, Rotation::cur()), - meta.query_advice(is_stack_depth_two, Rotation::cur()), - meta.query_advice(is_stack_depth_three, Rotation::cur()), - meta.query_advice(is_stack_depth_four, Rotation::cur()), - ]; - let table_exprs = vec![ - meta.query_advice(tx_id, Rotation::cur()), - meta.query_advice(format, Rotation::cur()), - meta.query_advice(byte_idx, Rotation::cur()), - meta.query_advice(depth, Rotation::next()) - - meta.query_advice(depth, Rotation::cur()), - // Depth 1: Begin decoding actual payload (with out the tx type envelope). - and::expr([ - sum::expr([ - // Case 1: For pre-EIP2930/1559 and L1 Tx, the first field is Nonce. - tag_bits.value_equals(Tag::Nonce, Rotation::next())(meta), - // Case 2: For EIP2930/1559, the first field is ChainId. - tag_bits.value_equals(Tag::ChainId, Rotation::next())(meta), - ]), - state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta), - ]), - // Depth 2: Begin decoding an access list. - and::expr([ - sum::expr([ - // Case 1: The access list is completely empty. The very first row after - // PUSH is EndVector. - tag_bits.value_equals(Tag::EndVector, Rotation::next())(meta), - // Case 2: A regular access list. - tag_bits.value_equals(Tag::BeginObject, Rotation::next())(meta), - ]), - state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta), - ]), - // Depth 3: A new access list address item - meta.query_advice(rlp_table.access_list_idx, Rotation::next()) - - meta.query_advice(rlp_table.access_list_idx, Rotation::cur()), - // Depth 4: The first storage key item. - // Only the first storage key corresponds to a PUSH op. The rest correspond to - // UPDATE ops. - - // The difference between current storage_key_idx (in rlp_table) and the previous - // one is either 0 or 1. By multiplying the difference with the new - // storage_key_idx, it guarantees that storage_key_idx::next = 1 - // (which indicates the first storage key in an access list addresses's storage key - // list) - (meta.query_advice(rlp_table.storage_key_idx, Rotation::next()) - - meta.query_advice(rlp_table.storage_key_idx, Rotation::cur())) - * meta.query_advice(rlp_table.storage_key_idx, Rotation::next()), - ]; - input_exprs - .into_iter() - .zip(table_exprs) - .map(|(input, table)| (input * enable.expr(), table)) - .collect() - }); - - meta.lookup_any("Decoding table stack op POP correspondence", |meta| { - let enable = meta.query_advice(rlp_decoding_table.is_stack_pop, Rotation::cur()); - - let input_exprs = vec![ - meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), - meta.query_advice(rlp_decoding_table.format, Rotation::cur()), - // A POP op doesn't correspond to an actual byte, but only the end tag state - meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), - 1.expr(), // A POP op reduces depth level - // A POP follows an end state, either EndVector or EndObject - 1.expr(), - ]; - let table_exprs = vec![ - meta.query_advice(tx_id, Rotation::cur()), - meta.query_advice(format, Rotation::cur()), - meta.query_advice(byte_idx, Rotation::cur()), - meta.query_advice(depth, Rotation::cur()) - - meta.query_advice(depth, Rotation::next()), - meta.query_advice(is_tag_end, Rotation::cur()), - ]; - input_exprs - .into_iter() - .zip(table_exprs) - .map(|(input, table)| (input * enable.expr(), table)) - .collect() - }); - - meta.lookup_any("Decoding table stack op UPDATE correspondence", |meta| { - let enable = meta.query_advice(rlp_decoding_table.is_stack_update, Rotation::cur()); - - let input_exprs = vec![ - meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), - meta.query_advice(rlp_decoding_table.format, Rotation::cur()), - meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), - 0.expr(), // UPDATE doesn't change depth level - 0.expr(), // UPDATE can't correspond to end states - ]; - let table_exprs = vec![ - meta.query_advice(tx_id, Rotation::cur()), - meta.query_advice(format, Rotation::cur()), - meta.query_advice(byte_idx, Rotation::cur()), - meta.query_advice(depth, Rotation::next()) - - meta.query_advice(depth, Rotation::cur()), - meta.query_advice(is_tag_end, Rotation::cur()), - ]; - input_exprs - .into_iter() - .zip(table_exprs) - .map(|(input, table)| (input * enable.expr(), table)) - .collect() - }); + // // RLP Decoding Table is sorted using an id = (tx_id, format, depth, access_list_idx, + // // storage_key_idx) but bytes in the RLP circuit (rlp_table) is processed in order. + // // Therefore, to prevent malicious injection of stack ops that don't correspond to + // // actual bytes in the RLP circuit, lookups are added to ensure correct correspondence. + + // // How to ensure that every row in the state machine is also present in the decoding table: + // // For each decoding table row that's not padding, a stack op (INIT, PUSH, POP or UPDATE) + // // must be present. Then for each stack op that's present, it must correspond to a + // // row in the state machine by below constraint (for INIT) and lookups (for PUSH, POP, + // // UPDATE). This two-way constraint system creates a one-to-one relationship between + // // state machine and the decoding table. + + // // The Init Op is not affected by sorting and stays at first position in decoding table. + // // For this reason, its correctness and correspondence is constrained using a gate instead + // // of lookup. + // meta.create_gate("Decoding table stack op INIT correspondence", |meta| { + // let mut cb = BaseConstraintBuilder::default(); + + // cb.require_equal( + // "stack init pushes all remaining_bytes onto depth 0", + // meta.query_advice(rlp_decoding_table.value, Rotation::cur()), + // meta.query_advice(byte_rev_idx, Rotation::cur()), + // ); + // cb.require_equal( + // "stack can only init once with the first byte", + // meta.query_advice(byte_idx, Rotation::cur()), + // 1.expr(), + // ); + // cb.require_zero( + // "stack inits at depth 0", + // meta.query_advice(rlp_decoding_table.depth, Rotation::cur()), + // ); + // cb.require_zero( + // "stack inits with al_idx at 0", + // meta.query_advice(rlp_decoding_table.al_idx, Rotation::cur()), + // ); + // cb.require_zero( + // "stack inits with sk_idx at 0", + // meta.query_advice(rlp_decoding_table.sk_idx, Rotation::cur()), + // ); + // cb.condition( + // not::expr(meta.query_fixed(q_first, Rotation::cur())), + // |cb| { + // cb.require_boolean( + // "tx_id can only stay the same or increment by 1", + // meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()) + // - meta.query_advice(rlp_decoding_table.tx_id, Rotation::prev()), + // ); + // }, + // ); + // cb.require_equal( + // "Init Op has DecodeTagStart in the state machine", + // is_decode_tag_start(meta), + // 1.expr(), + // ); + + // cb.gate(and::expr([ + // meta.query_fixed(q_enabled, Rotation::cur()), + // meta.query_advice(rlp_decoding_table.is_stack_init, Rotation::cur()), + // ])) + // }); + + // // Lookup strategies for PUSH: + // // 1. The input expressions include the indicators for each depth level. + // // 2. For each active depth indicator, it's checked against the allowable transitional + // // scenarios in the state machine for that depth. + // // 3. The byte_idx and depth transition are included. + // meta.lookup_any("Decoding table stack op PUSH correspondence", |meta| { + // let enable = meta.query_advice(rlp_decoding_table.is_stack_push, Rotation::cur()); + + // let input_exprs = vec![ + // meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), + // meta.query_advice(rlp_decoding_table.format, Rotation::cur()), + // meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), + // 1.expr(), // PUSH op increases depth + // // List scenario on each depth. + // // Sufficiency is achieved by listing all possible depth. + // meta.query_advice(is_stack_depth_one, Rotation::cur()), + // meta.query_advice(is_stack_depth_two, Rotation::cur()), + // meta.query_advice(is_stack_depth_three, Rotation::cur()), + // meta.query_advice(is_stack_depth_four, Rotation::cur()), + // ]; + // let table_exprs = vec![ + // meta.query_advice(tx_id, Rotation::cur()), + // meta.query_advice(format, Rotation::cur()), + // meta.query_advice(byte_idx, Rotation::cur()), + // meta.query_advice(depth, Rotation::next()) + // - meta.query_advice(depth, Rotation::cur()), + // // Depth 1: Begin decoding actual payload (with out the tx type envelope). + // and::expr([ + // sum::expr([ + // // Case 1: For pre-EIP2930/1559 and L1 Tx, the first field is Nonce. + // tag_bits.value_equals(Tag::Nonce, Rotation::next())(meta), + // // Case 2: For EIP2930/1559, the first field is ChainId. + // tag_bits.value_equals(Tag::ChainId, Rotation::next())(meta), + // ]), + // state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta), + // ]), + // // Depth 2: Begin decoding an access list. + // and::expr([ + // sum::expr([ + // // Case 1: The access list is completely empty. The very first row after + // // PUSH is EndVector. + // tag_bits.value_equals(Tag::EndVector, Rotation::next())(meta), + // // Case 2: A regular access list. + // tag_bits.value_equals(Tag::BeginObject, Rotation::next())(meta), + // ]), + // state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta), + // ]), + // // Depth 3: A new access list address item + // meta.query_advice(rlp_table.access_list_idx, Rotation::next()) + // - meta.query_advice(rlp_table.access_list_idx, Rotation::cur()), + // // Depth 4: The first storage key item. + // // Only the first storage key corresponds to a PUSH op. The rest correspond to + // // UPDATE ops. + + // // The difference between current storage_key_idx (in rlp_table) and the previous + // // one is either 0 or 1. By multiplying the difference with the new + // // storage_key_idx, it guarantees that storage_key_idx::next = 1 + // // (which indicates the first storage key in an access list addresses's storage key + // // list) + // (meta.query_advice(rlp_table.storage_key_idx, Rotation::next()) + // - meta.query_advice(rlp_table.storage_key_idx, Rotation::cur())) + // * meta.query_advice(rlp_table.storage_key_idx, Rotation::next()), + // ]; + // input_exprs + // .into_iter() + // .zip(table_exprs) + // .map(|(input, table)| (input * enable.expr(), table)) + // .collect() + // }); + + // meta.lookup_any("Decoding table stack op POP correspondence", |meta| { + // let enable = meta.query_advice(rlp_decoding_table.is_stack_pop, Rotation::cur()); + + // let input_exprs = vec![ + // meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), + // meta.query_advice(rlp_decoding_table.format, Rotation::cur()), + // // A POP op doesn't correspond to an actual byte, but only the end tag state + // meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), + // 1.expr(), // A POP op reduces depth level + // // A POP follows an end state, either EndVector or EndObject + // 1.expr(), + // ]; + // let table_exprs = vec![ + // meta.query_advice(tx_id, Rotation::cur()), + // meta.query_advice(format, Rotation::cur()), + // meta.query_advice(byte_idx, Rotation::cur()), + // meta.query_advice(depth, Rotation::cur()) + // - meta.query_advice(depth, Rotation::next()), + // meta.query_advice(is_tag_end, Rotation::cur()), + // ]; + // input_exprs + // .into_iter() + // .zip(table_exprs) + // .map(|(input, table)| (input * enable.expr(), table)) + // .collect() + // }); + + // meta.lookup_any("Decoding table stack op UPDATE correspondence", |meta| { + // let enable = meta.query_advice(rlp_decoding_table.is_stack_update, Rotation::cur()); + + // let input_exprs = vec![ + // meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), + // meta.query_advice(rlp_decoding_table.format, Rotation::cur()), + // meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), + // 0.expr(), // UPDATE doesn't change depth level + // 0.expr(), // UPDATE can't correspond to end states + // ]; + // let table_exprs = vec![ + // meta.query_advice(tx_id, Rotation::cur()), + // meta.query_advice(format, Rotation::cur()), + // meta.query_advice(byte_idx, Rotation::cur()), + // meta.query_advice(depth, Rotation::next()) + // - meta.query_advice(depth, Rotation::cur()), + // meta.query_advice(is_tag_end, Rotation::cur()), + // ]; + // input_exprs + // .into_iter() + // .zip(table_exprs) + // .map(|(input, table)| (input * enable.expr(), table)) + // .collect() + // }); debug_assert!(meta.degree() <= 9); @@ -2453,6 +2501,9 @@ impl RlpCircuitConfig { is_stack_depth_diff, is_stack_al_idx_diff, is_stack_sk_idx_diff, + is_push_op_lookup, + is_pop_op_lookup, + is_update_op_lookup, byte_value_lte_0x80, byte_value_gte_0x80, byte_value_lte_0xb8, @@ -2513,6 +2564,37 @@ impl RlpCircuitConfig { )) }, )?; + + // Assign lookup indicators from state machine into decoding table + let is_init = matches!(witness.rlp_decoding_table.stack_op, StackOp::Init); + let is_begin = + witness.rlp_table.is_output && + (witness.state_machine.tag == Tag::BeginObject || + witness.state_machine.tag == Tag::BeginVector); + region.assign_advice( + || "is_push_op_lookup", + self.is_push_op_lookup, + row, + || Value::known(F::from(is_begin as u64)), + )?; + let is_end = + witness.rlp_table.is_output && + (witness.state_machine.tag == Tag::EndVector || + witness.state_machine.tag == Tag::EndObject); + region.assign_advice( + || "is_pop_op_lookup", + self.is_pop_op_lookup, + row, + || Value::known(F::from(is_end as u64)), + )?; + let is_update = !(is_init || is_begin || is_end); + region.assign_advice( + || "is_update_op_lookup", + self.is_update_op_lookup, + row, + || Value::known(F::from(is_update as u64)), + )?; + region.assign_advice( || "rlp_table.tag_value", self.rlp_table.tag_value, diff --git a/zkevm-circuits/src/rlp_circuit_fsm/test.rs b/zkevm-circuits/src/rlp_circuit_fsm/test.rs index 06dc403291..3a34090d6a 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm/test.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm/test.rs @@ -107,13 +107,14 @@ fn test_l1_msg_tx() { mock_prover.assert_satisfied_par(); } +// 1559_debug #[test] fn test_eip1559_tx() { let test_bytes = vec![ // empty access list - "02f8b1010a8404a75411850f705051f08301724b94dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000006c57d84c55b01f7022999f6c0f95daf0e319dc37000000000000000000000000000000000000000000000000000000003b9aca00c001a0634f6d4b3b4fc658c2c26c1ba0966bd39d7e993b815390f1e778af9cf28d2c22a05410b97e41240ea25eb6250e1af7554cda8991bc4159228c43cfb240503d9870", + // "02f8b1010a8404a75411850f705051f08301724b94dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000006c57d84c55b01f7022999f6c0f95daf0e319dc37000000000000000000000000000000000000000000000000000000003b9aca00c001a0634f6d4b3b4fc658c2c26c1ba0966bd39d7e993b815390f1e778af9cf28d2c22a05410b97e41240ea25eb6250e1af7554cda8991bc4159228c43cfb240503d9870", // same as third test but with abridged access list - "02f9025d01825cb38520955af4328521cf92558d830a1bff9400fc00900000002c00be4ef8f49c000211000c43830cc4d0b9015504673a0b85b3000bef3e26e01428d1b525a532ea7513b8f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097020c532d1b995b7e3e37a1aa6369386e5939053779abd3597508b00129cd75b800073edec02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f21661d0d1d76d3ecb8e1b9f1c923dbfffae40970bb86c3dc790b0d7291f864244b559b59b30f850a8cfb40dc7c53760375530e5af29fded5e139893252993820686c92b000094b61ba302f01b0f027d40c80d8f70f77d3884776531f80b21d20e5a6b806300024b2c713b4502988e070f96cf3bea50b4811cd5844e13a81b61a8078c761b0b85b3000bef3e26e01428d1b525a532ea7513b80002594ea302f03b9eb369241e4270796e665ea1afac355cb99f0c32078ab8ba00013c08711b06ed871e5a66bebf0af6fb768d343b1d14a04b5b34ab10cf761b0b85b3000bef3e26e01428d1b525a532ea7513b8000143542ef893f7940b85b3000bef3e26e01428d1b525a532ea7513b8e1a00000000000000000000000000000000000000000000000000000000000000006f85994c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a0e1dd9768c9de657aca2536cf1cdd1c4536b13ec81ff764307ea8312aa7a8790da070bc879403c8b875e45ea7afbb591f1fd4bde469db47d5f0e879e44c6798d33e80a0d274986e36e16ec2d4846168d59422f68e4b8ec41690b80bdd2ee65819f238eea03d0394f6daae31ba5a276a3741cc2b3ba79b90024f80df865622a62078e72910", + // "02f9025d01825cb38520955af4328521cf92558d830a1bff9400fc00900000002c00be4ef8f49c000211000c43830cc4d0b9015504673a0b85b3000bef3e26e01428d1b525a532ea7513b8f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097020c532d1b995b7e3e37a1aa6369386e5939053779abd3597508b00129cd75b800073edec02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f21661d0d1d76d3ecb8e1b9f1c923dbfffae40970bb86c3dc790b0d7291f864244b559b59b30f850a8cfb40dc7c53760375530e5af29fded5e139893252993820686c92b000094b61ba302f01b0f027d40c80d8f70f77d3884776531f80b21d20e5a6b806300024b2c713b4502988e070f96cf3bea50b4811cd5844e13a81b61a8078c761b0b85b3000bef3e26e01428d1b525a532ea7513b80002594ea302f03b9eb369241e4270796e665ea1afac355cb99f0c32078ab8ba00013c08711b06ed871e5a66bebf0af6fb768d343b1d14a04b5b34ab10cf761b0b85b3000bef3e26e01428d1b525a532ea7513b8000143542ef893f7940b85b3000bef3e26e01428d1b525a532ea7513b8e1a00000000000000000000000000000000000000000000000000000000000000006f85994c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a0e1dd9768c9de657aca2536cf1cdd1c4536b13ec81ff764307ea8312aa7a8790da070bc879403c8b875e45ea7afbb591f1fd4bde469db47d5f0e879e44c6798d33e80a0d274986e36e16ec2d4846168d59422f68e4b8ec41690b80bdd2ee65819f238eea03d0394f6daae31ba5a276a3741cc2b3ba79b90024f80df865622a62078e72910", // unabridged access list "02f90b7b01825cb38520955af4328521cf92558d830a1bff9400fc00900000002c00be4ef8f49c000211000c43830cc4d0b9015504673a0b85b3000bef3e26e01428d1b525a532ea7513b8f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097020c532d1b995b7e3e37a1aa6369386e5939053779abd3597508b00129cd75b800073edec02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f21661d0d1d76d3ecb8e1b9f1c923dbfffae40970bb86c3dc790b0d7291f864244b559b59b30f850a8cfb40dc7c53760375530e5af29fded5e139893252993820686c92b000094b61ba302f01b0f027d40c80d8f70f77d3884776531f80b21d20e5a6b806300024b2c713b4502988e070f96cf3bea50b4811cd5844e13a81b61a8078c761b0b85b3000bef3e26e01428d1b525a532ea7513b80002594ea302f03b9eb369241e4270796e665ea1afac355cb99f0c32078ab8ba00013c08711b06ed871e5a66bebf0af6fb768d343b1d14a04b5b34ab10cf761b0b85b3000bef3e26e01428d1b525a532ea7513b8000143542ef909b0f89b940b85b3000bef3e26e01428d1b525a532ea7513b8f884a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008f8dd94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f8c6a0e1dd9768c9de657aca2536cf1cdd1c4536b13ec81ff764307ea8312aa7a8790da070bc879403c8b875e45ea7afbb591f1fd4bde469db47d5f0e879e44c6798d33ea0f88aa3ad276c350a067c34b2bed705e1a2cd30c7c3154f62ece8ee00939bbd2ea0be11b0e2ba48478671bfcd8fd182e025c26fbfbcf4fdf6952051d6147955a36fa09a1a5a7ef77f3399dea2a1044425aaca7fec294fdfdcacd7a960c9c94d15f0a6a091828b9b711948523369ff1651b6332e98f75bcd940a551dc7247d5af88e71faf8bc945b7e3e37a1aa6369386e5939053779abd3597508f8a5a00000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000002a0697b2bd7bb2984c4e0dc14c79c987d37818484a62958b9c45a0e8b962f20650fa00000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000000f9018394c7c53760375530e5af29fded5e13989325299382f9016ba00000000000000000000000000000000000000000000000000000000000000010a0000000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000016a0000000000000000000000000000000000000000000000000000000000000000ea051d155e8243cd6886ab3b36f59778d90f3bbb4af820bc2d4536b23ca13814bfba00000000000000000000000000000000000000000000000000000000000000013a0a7609b0290b911c4b52861d3739b36793fd0e23d9ef78cf2fa96dd1b0cbc764da00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000ca0bda2b1a2a3e35ca431f3c4b50639098537d215591b9ca3db95c24c01795a9981a0000000000000000000000000000000000000000000000000000000000000000df89b94c790b0d7291f864244b559b59b30f850a8cfb40df884a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8dd9406ed871e5a66bebf0af6fb768d343b1d14a04b5bf8c6a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000af8bc94f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097f8a5a04d3eb812b43a439547ce41ef251d01e8ad3d0dad3fde6f2bed3d0c0e29dcdd7aa026644b9dbbd32f8882f3abce5ac1575313789ab081b0fe9f3f39c946527bfa27a072fd74a6edf1b99d41f2c81c57f871e198cb7a24fd9861e998221c4aeb776014a0a7609b0290b911c4b52861d3739b36793fd0e23d9ef78cf2fa96dd1b0cbc764da01a3159eb932a0bb66f4d5b9c1cb119796d815774e3c4904b36748d7870d915c2f8dd940f027d40c80d8f70f77d3884776531f80b21d20ef8c6a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8bc941a76bffd6d1fc1660e1d0e0552fde51ddbb120cff8a5a06d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6dfa030e699f4646032d62d40ca795ecffcb27a2d9d2859f21626b5a588210198e7a6a0c929f5ae32c0eabfbdd06198210bc49736d88e6501f814a66dd5b2fa59508b3ea0ea52bdd009b752a3e91262d66aae31638bc36b449d247d61d646b87a733d7d5da0877978b096db3b11862d0cdfe5f5b74f30fd7d5d29e8ce80626ed8a8bbef1beef8dd944502988e070f96cf3bea50b4811cd5844e13a81bf8c6a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8dd949eb369241e4270796e665ea1afac355cb99f0c32f8c6a00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000cf85994f9a2d7e60a3297e513317ad1d7ce101cc4c6c8f6f842a04b376a11d00750d42abab4d4e465d5dc4d9b1286d77cf0c819f028213ea08bdfa072fd74a6edf1b99d41f2c81c57f871e198cb7a24fd9861e998221c4aeb77601480a0d274986e36e16ec2d4846168d59422f68e4b8ec41690b80bdd2ee65819f238eea03d0394f6daae31ba5a276a3741cc2b3ba79b90024f80df865622a62078e72910", ]; From 62ed8c8eea8203ca6ab566ecea77a4f7ce473b85 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Tue, 16 Apr 2024 17:12:55 -0400 Subject: [PATCH 13/20] Add correct condition for stack op lookups --- zkevm-circuits/src/rlp_circuit_fsm.rs | 167 +++++++++++++++----------- 1 file changed, 100 insertions(+), 67 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index b817f3cbf6..3b6eed3374 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2232,9 +2232,6 @@ impl RlpCircuitConfig { debug_assert!(meta.degree() <= 9); - - - // /////////////////////////////////////////////////////////////////// // /////// Rlp Decoding Table and RLP Circuit Correspondence ///////// // /////////////////////////////////////////////////////////////////// @@ -2266,73 +2263,112 @@ impl RlpCircuitConfig { meta.query_advice(is_update_op_lookup, Rotation::cur()), ); + // Correct state machine condition for PUSH op + cb.require_equal( + "is_push_op_lookup is the last row of a begin tag", + meta.query_advice(is_push_op_lookup, Rotation::cur()), + and::expr([ + meta.query_advice(is_tag_begin, Rotation::cur()), + meta.query_advice(rlp_table.is_output, Rotation::cur()), + ]) + ); + cb.condition( + meta.query_advice(is_push_op_lookup, Rotation::cur()), |cb| { + cb.require_equal( + "PUSH op within state machine should increase depth", + meta.query_advice(depth, Rotation::cur()) + 1.expr(), + meta.query_advice(depth, Rotation::next()), + ); + }); + + // Correct state machine condition for POP op + cb.require_equal( + "is_pop_op_lookup is the last row of an end tag", + meta.query_advice(is_pop_op_lookup, Rotation::cur()), + meta.query_advice(is_tag_end, Rotation::cur()), + ); + cb.condition( + meta.query_advice(is_pop_op_lookup, Rotation::cur()), + |cb| { + cb.require_zero( + "POP op within state machine should decrease depth, except the last byte of an instance.", + ( + meta.query_advice(depth, Rotation::next()) + 1.expr() + - meta.query_advice(depth, Rotation::cur()) + ) * ( + meta.query_advice(byte_rev_idx, Rotation::cur()) - 1.expr() + ), + ); + }); + cb.gate(and::expr([ meta.query_fixed(q_enabled, Rotation::cur()), not::expr(is_end(meta)), ])) }); + meta.create_gate("Decoding table stack op INIT correspondence", |meta| { + let mut cb = BaseConstraintBuilder::default(); + + cb.require_equal( + "stack init pushes all remaining_bytes onto depth 0", + meta.query_advice(rlp_decoding_table.value, Rotation::cur()), + meta.query_advice(byte_rev_idx, Rotation::cur()), + ); + cb.require_equal( + "stack can only init once with the first byte", + meta.query_advice(byte_idx, Rotation::cur()), + 1.expr(), + ); + cb.require_zero( + "stack inits at depth 0", + meta.query_advice(rlp_decoding_table.depth, Rotation::cur()), + ); + cb.require_zero( + "stack inits with al_idx at 0", + meta.query_advice(rlp_decoding_table.al_idx, Rotation::cur()), + ); + cb.require_zero( + "stack inits with sk_idx at 0", + meta.query_advice(rlp_decoding_table.sk_idx, Rotation::cur()), + ); + cb.condition( + not::expr(meta.query_fixed(q_first, Rotation::cur())), + |cb| { + cb.require_boolean( + "tx_id can only stay the same or increment by 1", + meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()) + - meta.query_advice(rlp_decoding_table.tx_id, Rotation::prev()), + ); + }, + ); + cb.require_equal( + "Init Op has DecodeTagStart in the state machine", + is_decode_tag_start(meta), + 1.expr(), + ); + + cb.gate(and::expr([ + meta.query_fixed(q_enabled, Rotation::cur()), + meta.query_advice(rlp_decoding_table.is_stack_init, Rotation::cur()), + ])) + }); + // // RLP Decoding Table is sorted using an id = (tx_id, format, depth, access_list_idx, // // storage_key_idx) but bytes in the RLP circuit (rlp_table) is processed in order. // // Therefore, to prevent malicious injection of stack ops that don't correspond to // // actual bytes in the RLP circuit, lookups are added to ensure correct correspondence. - // // How to ensure that every row in the state machine is also present in the decoding table: - // // For each decoding table row that's not padding, a stack op (INIT, PUSH, POP or UPDATE) - // // must be present. Then for each stack op that's present, it must correspond to a - // // row in the state machine by below constraint (for INIT) and lookups (for PUSH, POP, - // // UPDATE). This two-way constraint system creates a one-to-one relationship between - // // state machine and the decoding table. + // // How to ensure that every row in the state machine is also present in the decoding + // table: // For each decoding table row that's not padding, a stack op (INIT, PUSH, + // POP or UPDATE) // must be present. Then for each stack op that's present, it must + // correspond to a // row in the state machine by below constraint (for INIT) and + // lookups (for PUSH, POP, // UPDATE). This two-way constraint system creates a + // one-to-one relationship between // state machine and the decoding table. // // The Init Op is not affected by sorting and stays at first position in decoding table. - // // For this reason, its correctness and correspondence is constrained using a gate instead - // // of lookup. - // meta.create_gate("Decoding table stack op INIT correspondence", |meta| { - // let mut cb = BaseConstraintBuilder::default(); - - // cb.require_equal( - // "stack init pushes all remaining_bytes onto depth 0", - // meta.query_advice(rlp_decoding_table.value, Rotation::cur()), - // meta.query_advice(byte_rev_idx, Rotation::cur()), - // ); - // cb.require_equal( - // "stack can only init once with the first byte", - // meta.query_advice(byte_idx, Rotation::cur()), - // 1.expr(), - // ); - // cb.require_zero( - // "stack inits at depth 0", - // meta.query_advice(rlp_decoding_table.depth, Rotation::cur()), - // ); - // cb.require_zero( - // "stack inits with al_idx at 0", - // meta.query_advice(rlp_decoding_table.al_idx, Rotation::cur()), - // ); - // cb.require_zero( - // "stack inits with sk_idx at 0", - // meta.query_advice(rlp_decoding_table.sk_idx, Rotation::cur()), - // ); - // cb.condition( - // not::expr(meta.query_fixed(q_first, Rotation::cur())), - // |cb| { - // cb.require_boolean( - // "tx_id can only stay the same or increment by 1", - // meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()) - // - meta.query_advice(rlp_decoding_table.tx_id, Rotation::prev()), - // ); - // }, - // ); - // cb.require_equal( - // "Init Op has DecodeTagStart in the state machine", - // is_decode_tag_start(meta), - // 1.expr(), - // ); - - // cb.gate(and::expr([ - // meta.query_fixed(q_enabled, Rotation::cur()), - // meta.query_advice(rlp_decoding_table.is_stack_init, Rotation::cur()), - // ])) - // }); + // // For this reason, its correctness and correspondence is constrained using a gate + // instead // of lookup. // // Lookup strategies for PUSH: // // 1. The input expressions include the indicators for each depth level. @@ -2391,8 +2427,8 @@ impl RlpCircuitConfig { // // The difference between current storage_key_idx (in rlp_table) and the previous // // one is either 0 or 1. By multiplying the difference with the new // // storage_key_idx, it guarantees that storage_key_idx::next = 1 - // // (which indicates the first storage key in an access list addresses's storage key - // // list) + // // (which indicates the first storage key in an access list addresses's storage + // key // list) // (meta.query_advice(rlp_table.storage_key_idx, Rotation::next()) // - meta.query_advice(rlp_table.storage_key_idx, Rotation::cur())) // * meta.query_advice(rlp_table.storage_key_idx, Rotation::next()), @@ -2567,20 +2603,17 @@ impl RlpCircuitConfig { // Assign lookup indicators from state machine into decoding table let is_init = matches!(witness.rlp_decoding_table.stack_op, StackOp::Init); - let is_begin = - witness.rlp_table.is_output && - (witness.state_machine.tag == Tag::BeginObject || - witness.state_machine.tag == Tag::BeginVector); + let is_begin = witness.rlp_table.is_output + && (witness.state_machine.tag == Tag::BeginObject + || witness.state_machine.tag == Tag::BeginVector); region.assign_advice( || "is_push_op_lookup", self.is_push_op_lookup, row, || Value::known(F::from(is_begin as u64)), )?; - let is_end = - witness.rlp_table.is_output && - (witness.state_machine.tag == Tag::EndVector || - witness.state_machine.tag == Tag::EndObject); + let is_end = witness.state_machine.tag == Tag::EndVector + || witness.state_machine.tag == Tag::EndObject; region.assign_advice( || "is_pop_op_lookup", self.is_pop_op_lookup, From ce56600dcf0c645446be2f0ceeb6ad3ee7dac022 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Tue, 16 Apr 2024 18:22:07 -0400 Subject: [PATCH 14/20] Complete PUSH op lookup --- zkevm-circuits/src/rlp_circuit_fsm.rs | 97 +++++++++------------------ 1 file changed, 33 insertions(+), 64 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index 3b6eed3374..fb813994dc 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2354,6 +2354,38 @@ impl RlpCircuitConfig { ])) }); + meta.lookup_any("Decoding table stack op PUSH correspondence", |meta| { + let enable = meta.query_advice(is_push_op_lookup, Rotation::cur()); + + let input_exprs = vec![ + meta.query_advice(tx_id, Rotation::cur()), + meta.query_advice(format, Rotation::cur()), + meta.query_advice(byte_idx, Rotation::cur()), + meta.query_advice(depth, Rotation::cur()) + 1.expr(), + 1.expr(), + select::expr( + is_decode_tag_start(meta), + meta.query_advice(byte_value, Rotation::cur()) - 248.expr(), + meta.query_advice(tag_value_acc, Rotation::cur()), + ), + 0.expr(), + ]; + let table_exprs = vec![ + meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), + meta.query_advice(rlp_decoding_table.format, Rotation::cur()), + meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), + meta.query_advice(rlp_decoding_table.depth, Rotation::cur()), + meta.query_advice(rlp_decoding_table.is_stack_push, Rotation::cur()), + meta.query_advice(rlp_decoding_table.value, Rotation::cur()), + meta.query_advice(rlp_decoding_table.value_prev, Rotation::cur()), + ]; + input_exprs + .into_iter() + .zip(table_exprs) + .map(|(input, table)| (input * enable.expr(), table)) + .collect() + }); + // // RLP Decoding Table is sorted using an id = (tx_id, format, depth, access_list_idx, // // storage_key_idx) but bytes in the RLP circuit (rlp_table) is processed in order. // // Therefore, to prevent malicious injection of stack ops that don't correspond to @@ -2375,70 +2407,7 @@ impl RlpCircuitConfig { // // 2. For each active depth indicator, it's checked against the allowable transitional // // scenarios in the state machine for that depth. // // 3. The byte_idx and depth transition are included. - // meta.lookup_any("Decoding table stack op PUSH correspondence", |meta| { - // let enable = meta.query_advice(rlp_decoding_table.is_stack_push, Rotation::cur()); - - // let input_exprs = vec![ - // meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), - // meta.query_advice(rlp_decoding_table.format, Rotation::cur()), - // meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), - // 1.expr(), // PUSH op increases depth - // // List scenario on each depth. - // // Sufficiency is achieved by listing all possible depth. - // meta.query_advice(is_stack_depth_one, Rotation::cur()), - // meta.query_advice(is_stack_depth_two, Rotation::cur()), - // meta.query_advice(is_stack_depth_three, Rotation::cur()), - // meta.query_advice(is_stack_depth_four, Rotation::cur()), - // ]; - // let table_exprs = vec![ - // meta.query_advice(tx_id, Rotation::cur()), - // meta.query_advice(format, Rotation::cur()), - // meta.query_advice(byte_idx, Rotation::cur()), - // meta.query_advice(depth, Rotation::next()) - // - meta.query_advice(depth, Rotation::cur()), - // // Depth 1: Begin decoding actual payload (with out the tx type envelope). - // and::expr([ - // sum::expr([ - // // Case 1: For pre-EIP2930/1559 and L1 Tx, the first field is Nonce. - // tag_bits.value_equals(Tag::Nonce, Rotation::next())(meta), - // // Case 2: For EIP2930/1559, the first field is ChainId. - // tag_bits.value_equals(Tag::ChainId, Rotation::next())(meta), - // ]), - // state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta), - // ]), - // // Depth 2: Begin decoding an access list. - // and::expr([ - // sum::expr([ - // // Case 1: The access list is completely empty. The very first row after - // // PUSH is EndVector. - // tag_bits.value_equals(Tag::EndVector, Rotation::next())(meta), - // // Case 2: A regular access list. - // tag_bits.value_equals(Tag::BeginObject, Rotation::next())(meta), - // ]), - // state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta), - // ]), - // // Depth 3: A new access list address item - // meta.query_advice(rlp_table.access_list_idx, Rotation::next()) - // - meta.query_advice(rlp_table.access_list_idx, Rotation::cur()), - // // Depth 4: The first storage key item. - // // Only the first storage key corresponds to a PUSH op. The rest correspond to - // // UPDATE ops. - - // // The difference between current storage_key_idx (in rlp_table) and the previous - // // one is either 0 or 1. By multiplying the difference with the new - // // storage_key_idx, it guarantees that storage_key_idx::next = 1 - // // (which indicates the first storage key in an access list addresses's storage - // key // list) - // (meta.query_advice(rlp_table.storage_key_idx, Rotation::next()) - // - meta.query_advice(rlp_table.storage_key_idx, Rotation::cur())) - // * meta.query_advice(rlp_table.storage_key_idx, Rotation::next()), - // ]; - // input_exprs - // .into_iter() - // .zip(table_exprs) - // .map(|(input, table)| (input * enable.expr(), table)) - // .collect() - // }); + // meta.lookup_any("Decoding table stack op POP correspondence", |meta| { // let enable = meta.query_advice(rlp_decoding_table.is_stack_pop, Rotation::cur()); From 3cea6c318a4cf01c7adbcf4bf13eea0585d38be0 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Tue, 16 Apr 2024 18:37:40 -0400 Subject: [PATCH 15/20] Correct POP op lookup --- zkevm-circuits/src/rlp_circuit_fsm.rs | 31 +++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index fb813994dc..a65222e9d8 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2386,6 +2386,37 @@ impl RlpCircuitConfig { .collect() }); + meta.lookup_any("Decoding table stack op POP correspondence", |meta| { + let enable = select::expr( + sum::expr([ + meta.query_advice(rlp_decoding_table.is_stack_init, Rotation::next()), + is_padding_in_dt.expr(Rotation::next())(meta), + ]), + 0.expr(), + meta.query_advice(is_pop_op_lookup, Rotation::cur()), + ); + + let input_exprs = vec![ + meta.query_advice(tx_id, Rotation::cur()), + meta.query_advice(format, Rotation::cur()), + meta.query_advice(byte_idx, Rotation::cur()), + meta.query_advice(depth, Rotation::cur()) - 1.expr(), + 1.expr(), + ]; + let table_exprs = vec![ + meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), + meta.query_advice(rlp_decoding_table.format, Rotation::cur()), + meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), + meta.query_advice(rlp_decoding_table.depth, Rotation::cur()), + meta.query_advice(rlp_decoding_table.is_stack_pop, Rotation::cur()), + ]; + input_exprs + .into_iter() + .zip(table_exprs) + .map(|(input, table)| (input * enable.expr(), table)) + .collect() + }); + // // RLP Decoding Table is sorted using an id = (tx_id, format, depth, access_list_idx, // // storage_key_idx) but bytes in the RLP circuit (rlp_table) is processed in order. // // Therefore, to prevent malicious injection of stack ops that don't correspond to From 4c93cc565fc9a816aab5036f2a9730ef3493e9df Mon Sep 17 00:00:00 2001 From: darth-cy Date: Tue, 16 Apr 2024 20:03:41 -0400 Subject: [PATCH 16/20] Correct PUSH lookup --- zkevm-circuits/src/rlp_circuit_fsm.rs | 119 +++++++-------------- zkevm-circuits/src/rlp_circuit_fsm/test.rs | 5 +- 2 files changed, 41 insertions(+), 83 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index a65222e9d8..db69298681 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2232,9 +2232,17 @@ impl RlpCircuitConfig { debug_assert!(meta.degree() <= 9); - // /////////////////////////////////////////////////////////////////// - // /////// Rlp Decoding Table and RLP Circuit Correspondence ///////// - // /////////////////////////////////////////////////////////////////// + ///////////////////////////////////////////////////////////////////// + ///////// Rlp Decoding Table and RLP Circuit Correspondence ///////// + ///////////////////////////////////////////////////////////////////// + // RLP Decoding Table is sorted using an id = (tx_id, format, depth, access_list_idx, + // storage_key_idx) but bytes in the RLP circuit (rlp_table) is processed in order. + // Therefore, to prevent malicious injection of stack ops that don't correspond to + // actual bytes in the RLP circuit, lookups are added to ensure correct correspondence. + + // The Init Op is not affected by sorting and stays at first position in decoding table. + // For this reason, its correctness and correspondence is constrained using a gate + // instead of lookup. meta.create_gate("State machine lookup indicators into the decoding table", |meta| { let mut cb = BaseConstraintBuilder::default(); @@ -2269,7 +2277,7 @@ impl RlpCircuitConfig { meta.query_advice(is_push_op_lookup, Rotation::cur()), and::expr([ meta.query_advice(is_tag_begin, Rotation::cur()), - meta.query_advice(rlp_table.is_output, Rotation::cur()), + state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta) ]) ); cb.condition( @@ -2365,7 +2373,7 @@ impl RlpCircuitConfig { 1.expr(), select::expr( is_decode_tag_start(meta), - meta.query_advice(byte_value, Rotation::cur()) - 248.expr(), + meta.query_advice(byte_value, Rotation::cur()) - 192.expr(), meta.query_advice(tag_value_acc, Rotation::cur()), ), 0.expr(), @@ -2417,80 +2425,29 @@ impl RlpCircuitConfig { .collect() }); - // // RLP Decoding Table is sorted using an id = (tx_id, format, depth, access_list_idx, - // // storage_key_idx) but bytes in the RLP circuit (rlp_table) is processed in order. - // // Therefore, to prevent malicious injection of stack ops that don't correspond to - // // actual bytes in the RLP circuit, lookups are added to ensure correct correspondence. - - // // How to ensure that every row in the state machine is also present in the decoding - // table: // For each decoding table row that's not padding, a stack op (INIT, PUSH, - // POP or UPDATE) // must be present. Then for each stack op that's present, it must - // correspond to a // row in the state machine by below constraint (for INIT) and - // lookups (for PUSH, POP, // UPDATE). This two-way constraint system creates a - // one-to-one relationship between // state machine and the decoding table. - - // // The Init Op is not affected by sorting and stays at first position in decoding table. - // // For this reason, its correctness and correspondence is constrained using a gate - // instead // of lookup. - - // // Lookup strategies for PUSH: - // // 1. The input expressions include the indicators for each depth level. - // // 2. For each active depth indicator, it's checked against the allowable transitional - // // scenarios in the state machine for that depth. - // // 3. The byte_idx and depth transition are included. - - - // meta.lookup_any("Decoding table stack op POP correspondence", |meta| { - // let enable = meta.query_advice(rlp_decoding_table.is_stack_pop, Rotation::cur()); - - // let input_exprs = vec![ - // meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), - // meta.query_advice(rlp_decoding_table.format, Rotation::cur()), - // // A POP op doesn't correspond to an actual byte, but only the end tag state - // meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), - // 1.expr(), // A POP op reduces depth level - // // A POP follows an end state, either EndVector or EndObject - // 1.expr(), - // ]; - // let table_exprs = vec![ - // meta.query_advice(tx_id, Rotation::cur()), - // meta.query_advice(format, Rotation::cur()), - // meta.query_advice(byte_idx, Rotation::cur()), - // meta.query_advice(depth, Rotation::cur()) - // - meta.query_advice(depth, Rotation::next()), - // meta.query_advice(is_tag_end, Rotation::cur()), - // ]; - // input_exprs - // .into_iter() - // .zip(table_exprs) - // .map(|(input, table)| (input * enable.expr(), table)) - // .collect() - // }); - - // meta.lookup_any("Decoding table stack op UPDATE correspondence", |meta| { - // let enable = meta.query_advice(rlp_decoding_table.is_stack_update, Rotation::cur()); - - // let input_exprs = vec![ - // meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), - // meta.query_advice(rlp_decoding_table.format, Rotation::cur()), - // meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), - // 0.expr(), // UPDATE doesn't change depth level - // 0.expr(), // UPDATE can't correspond to end states - // ]; - // let table_exprs = vec![ - // meta.query_advice(tx_id, Rotation::cur()), - // meta.query_advice(format, Rotation::cur()), - // meta.query_advice(byte_idx, Rotation::cur()), - // meta.query_advice(depth, Rotation::next()) - // - meta.query_advice(depth, Rotation::cur()), - // meta.query_advice(is_tag_end, Rotation::cur()), - // ]; - // input_exprs - // .into_iter() - // .zip(table_exprs) - // .map(|(input, table)| (input * enable.expr(), table)) - // .collect() - // }); + meta.lookup_any("Decoding table stack op UPDATE correspondence", |meta| { + let enable = meta.query_advice(is_update_op_lookup, Rotation::cur()); + + let input_exprs = vec![ + meta.query_advice(tx_id, Rotation::cur()), + meta.query_advice(format, Rotation::cur()), + meta.query_advice(byte_idx, Rotation::cur()), + meta.query_advice(depth, Rotation::cur()), + 1.expr(), + ]; + let table_exprs = vec![ + meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), + meta.query_advice(rlp_decoding_table.format, Rotation::cur()), + meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), + meta.query_advice(rlp_decoding_table.depth, Rotation::cur()), + meta.query_advice(rlp_decoding_table.is_stack_update, Rotation::cur()), + ]; + input_exprs + .into_iter() + .zip(table_exprs) + .map(|(input, table)| (input * enable.expr(), table)) + .collect() + }); debug_assert!(meta.degree() <= 9); @@ -2603,7 +2560,9 @@ impl RlpCircuitConfig { // Assign lookup indicators from state machine into decoding table let is_init = matches!(witness.rlp_decoding_table.stack_op, StackOp::Init); - let is_begin = witness.rlp_table.is_output + let is_begin = ( + witness_next.is_none() || witness_next.unwrap().state_machine.state == State::DecodeTagStart + ) && (witness.state_machine.tag == Tag::BeginObject || witness.state_machine.tag == Tag::BeginVector); region.assign_advice( diff --git a/zkevm-circuits/src/rlp_circuit_fsm/test.rs b/zkevm-circuits/src/rlp_circuit_fsm/test.rs index 3a34090d6a..06dc403291 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm/test.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm/test.rs @@ -107,14 +107,13 @@ fn test_l1_msg_tx() { mock_prover.assert_satisfied_par(); } -// 1559_debug #[test] fn test_eip1559_tx() { let test_bytes = vec![ // empty access list - // "02f8b1010a8404a75411850f705051f08301724b94dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000006c57d84c55b01f7022999f6c0f95daf0e319dc37000000000000000000000000000000000000000000000000000000003b9aca00c001a0634f6d4b3b4fc658c2c26c1ba0966bd39d7e993b815390f1e778af9cf28d2c22a05410b97e41240ea25eb6250e1af7554cda8991bc4159228c43cfb240503d9870", + "02f8b1010a8404a75411850f705051f08301724b94dac17f958d2ee523a2206206994597c13d831ec780b844a9059cbb0000000000000000000000006c57d84c55b01f7022999f6c0f95daf0e319dc37000000000000000000000000000000000000000000000000000000003b9aca00c001a0634f6d4b3b4fc658c2c26c1ba0966bd39d7e993b815390f1e778af9cf28d2c22a05410b97e41240ea25eb6250e1af7554cda8991bc4159228c43cfb240503d9870", // same as third test but with abridged access list - // "02f9025d01825cb38520955af4328521cf92558d830a1bff9400fc00900000002c00be4ef8f49c000211000c43830cc4d0b9015504673a0b85b3000bef3e26e01428d1b525a532ea7513b8f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097020c532d1b995b7e3e37a1aa6369386e5939053779abd3597508b00129cd75b800073edec02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f21661d0d1d76d3ecb8e1b9f1c923dbfffae40970bb86c3dc790b0d7291f864244b559b59b30f850a8cfb40dc7c53760375530e5af29fded5e139893252993820686c92b000094b61ba302f01b0f027d40c80d8f70f77d3884776531f80b21d20e5a6b806300024b2c713b4502988e070f96cf3bea50b4811cd5844e13a81b61a8078c761b0b85b3000bef3e26e01428d1b525a532ea7513b80002594ea302f03b9eb369241e4270796e665ea1afac355cb99f0c32078ab8ba00013c08711b06ed871e5a66bebf0af6fb768d343b1d14a04b5b34ab10cf761b0b85b3000bef3e26e01428d1b525a532ea7513b8000143542ef893f7940b85b3000bef3e26e01428d1b525a532ea7513b8e1a00000000000000000000000000000000000000000000000000000000000000006f85994c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a0e1dd9768c9de657aca2536cf1cdd1c4536b13ec81ff764307ea8312aa7a8790da070bc879403c8b875e45ea7afbb591f1fd4bde469db47d5f0e879e44c6798d33e80a0d274986e36e16ec2d4846168d59422f68e4b8ec41690b80bdd2ee65819f238eea03d0394f6daae31ba5a276a3741cc2b3ba79b90024f80df865622a62078e72910", + "02f9025d01825cb38520955af4328521cf92558d830a1bff9400fc00900000002c00be4ef8f49c000211000c43830cc4d0b9015504673a0b85b3000bef3e26e01428d1b525a532ea7513b8f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097020c532d1b995b7e3e37a1aa6369386e5939053779abd3597508b00129cd75b800073edec02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f21661d0d1d76d3ecb8e1b9f1c923dbfffae40970bb86c3dc790b0d7291f864244b559b59b30f850a8cfb40dc7c53760375530e5af29fded5e139893252993820686c92b000094b61ba302f01b0f027d40c80d8f70f77d3884776531f80b21d20e5a6b806300024b2c713b4502988e070f96cf3bea50b4811cd5844e13a81b61a8078c761b0b85b3000bef3e26e01428d1b525a532ea7513b80002594ea302f03b9eb369241e4270796e665ea1afac355cb99f0c32078ab8ba00013c08711b06ed871e5a66bebf0af6fb768d343b1d14a04b5b34ab10cf761b0b85b3000bef3e26e01428d1b525a532ea7513b8000143542ef893f7940b85b3000bef3e26e01428d1b525a532ea7513b8e1a00000000000000000000000000000000000000000000000000000000000000006f85994c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f842a0e1dd9768c9de657aca2536cf1cdd1c4536b13ec81ff764307ea8312aa7a8790da070bc879403c8b875e45ea7afbb591f1fd4bde469db47d5f0e879e44c6798d33e80a0d274986e36e16ec2d4846168d59422f68e4b8ec41690b80bdd2ee65819f238eea03d0394f6daae31ba5a276a3741cc2b3ba79b90024f80df865622a62078e72910", // unabridged access list "02f90b7b01825cb38520955af4328521cf92558d830a1bff9400fc00900000002c00be4ef8f49c000211000c43830cc4d0b9015504673a0b85b3000bef3e26e01428d1b525a532ea7513b8f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097020c532d1b995b7e3e37a1aa6369386e5939053779abd3597508b00129cd75b800073edec02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f21661d0d1d76d3ecb8e1b9f1c923dbfffae40970bb86c3dc790b0d7291f864244b559b59b30f850a8cfb40dc7c53760375530e5af29fded5e139893252993820686c92b000094b61ba302f01b0f027d40c80d8f70f77d3884776531f80b21d20e5a6b806300024b2c713b4502988e070f96cf3bea50b4811cd5844e13a81b61a8078c761b0b85b3000bef3e26e01428d1b525a532ea7513b80002594ea302f03b9eb369241e4270796e665ea1afac355cb99f0c32078ab8ba00013c08711b06ed871e5a66bebf0af6fb768d343b1d14a04b5b34ab10cf761b0b85b3000bef3e26e01428d1b525a532ea7513b8000143542ef909b0f89b940b85b3000bef3e26e01428d1b525a532ea7513b8f884a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008f8dd94c02aaa39b223fe8d0a0e5c4f27ead9083c756cc2f8c6a0e1dd9768c9de657aca2536cf1cdd1c4536b13ec81ff764307ea8312aa7a8790da070bc879403c8b875e45ea7afbb591f1fd4bde469db47d5f0e879e44c6798d33ea0f88aa3ad276c350a067c34b2bed705e1a2cd30c7c3154f62ece8ee00939bbd2ea0be11b0e2ba48478671bfcd8fd182e025c26fbfbcf4fdf6952051d6147955a36fa09a1a5a7ef77f3399dea2a1044425aaca7fec294fdfdcacd7a960c9c94d15f0a6a091828b9b711948523369ff1651b6332e98f75bcd940a551dc7247d5af88e71faf8bc945b7e3e37a1aa6369386e5939053779abd3597508f8a5a00000000000000000000000000000000000000000000000000000000000000004a00000000000000000000000000000000000000000000000000000000000000002a0697b2bd7bb2984c4e0dc14c79c987d37818484a62958b9c45a0e8b962f20650fa00000000000000000000000000000000000000000000000000000000000000009a00000000000000000000000000000000000000000000000000000000000000000f9018394c7c53760375530e5af29fded5e13989325299382f9016ba00000000000000000000000000000000000000000000000000000000000000010a0000000000000000000000000000000000000000000000000000000000000000ba00000000000000000000000000000000000000000000000000000000000000016a0000000000000000000000000000000000000000000000000000000000000000ea051d155e8243cd6886ab3b36f59778d90f3bbb4af820bc2d4536b23ca13814bfba00000000000000000000000000000000000000000000000000000000000000013a0a7609b0290b911c4b52861d3739b36793fd0e23d9ef78cf2fa96dd1b0cbc764da00000000000000000000000000000000000000000000000000000000000000000a0000000000000000000000000000000000000000000000000000000000000000ca0bda2b1a2a3e35ca431f3c4b50639098537d215591b9ca3db95c24c01795a9981a0000000000000000000000000000000000000000000000000000000000000000df89b94c790b0d7291f864244b559b59b30f850a8cfb40df884a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8dd9406ed871e5a66bebf0af6fb768d343b1d14a04b5bf8c6a0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000af8bc94f21661d0d1d76d3ecb8e1b9f1c923dbfffae4097f8a5a04d3eb812b43a439547ce41ef251d01e8ad3d0dad3fde6f2bed3d0c0e29dcdd7aa026644b9dbbd32f8882f3abce5ac1575313789ab081b0fe9f3f39c946527bfa27a072fd74a6edf1b99d41f2c81c57f871e198cb7a24fd9861e998221c4aeb776014a0a7609b0290b911c4b52861d3739b36793fd0e23d9ef78cf2fa96dd1b0cbc764da01a3159eb932a0bb66f4d5b9c1cb119796d815774e3c4904b36748d7870d915c2f8dd940f027d40c80d8f70f77d3884776531f80b21d20ef8c6a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8bc941a76bffd6d1fc1660e1d0e0552fde51ddbb120cff8a5a06d5257204ebe7d88fd91ae87941cb2dd9d8062b64ae5a2bd2d28ec40b9fbf6dfa030e699f4646032d62d40ca795ecffcb27a2d9d2859f21626b5a588210198e7a6a0c929f5ae32c0eabfbdd06198210bc49736d88e6501f814a66dd5b2fa59508b3ea0ea52bdd009b752a3e91262d66aae31638bc36b449d247d61d646b87a733d7d5da0877978b096db3b11862d0cdfe5f5b74f30fd7d5d29e8ce80626ed8a8bbef1beef8dd944502988e070f96cf3bea50b4811cd5844e13a81bf8c6a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000ca00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007f8dd949eb369241e4270796e665ea1afac355cb99f0c32f8c6a00000000000000000000000000000000000000000000000000000000000000008a00000000000000000000000000000000000000000000000000000000000000006a00000000000000000000000000000000000000000000000000000000000000007a00000000000000000000000000000000000000000000000000000000000000009a0000000000000000000000000000000000000000000000000000000000000000aa0000000000000000000000000000000000000000000000000000000000000000cf85994f9a2d7e60a3297e513317ad1d7ce101cc4c6c8f6f842a04b376a11d00750d42abab4d4e465d5dc4d9b1286d77cf0c819f028213ea08bdfa072fd74a6edf1b99d41f2c81c57f871e198cb7a24fd9861e998221c4aeb77601480a0d274986e36e16ec2d4846168d59422f68e4b8ec41690b80bdd2ee65819f238eea03d0394f6daae31ba5a276a3741cc2b3ba79b90024f80df865622a62078e72910", ]; From 6e0f4b81d9f1b4fad580628c4868b382c046b6f8 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Tue, 16 Apr 2024 20:04:42 -0400 Subject: [PATCH 17/20] fmt --- zkevm-circuits/src/rlp_circuit_fsm.rs | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index db69298681..2bac5a825e 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2560,9 +2560,8 @@ impl RlpCircuitConfig { // Assign lookup indicators from state machine into decoding table let is_init = matches!(witness.rlp_decoding_table.stack_op, StackOp::Init); - let is_begin = ( - witness_next.is_none() || witness_next.unwrap().state_machine.state == State::DecodeTagStart - ) + let is_begin = (witness_next.is_none() + || witness_next.unwrap().state_machine.state == State::DecodeTagStart) && (witness.state_machine.tag == Tag::BeginObject || witness.state_machine.tag == Tag::BeginVector); region.assign_advice( From 0b80c8d30d94d60d1aeff5f0720e7b6cc3f3eb99 Mon Sep 17 00:00:00 2001 From: darth-cy Date: Wed, 17 Apr 2024 18:20:06 -0400 Subject: [PATCH 18/20] Add backward compatibility for eip155 and pre155 --- zkevm-circuits/src/rlp_circuit_fsm.rs | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index 2bac5a825e..d19dd7dd94 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2277,7 +2277,9 @@ impl RlpCircuitConfig { meta.query_advice(is_push_op_lookup, Rotation::cur()), and::expr([ meta.query_advice(is_tag_begin, Rotation::cur()), - state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta) + state_bits.value_equals(State::DecodeTagStart, Rotation::next())(meta), + // Backward compatibility for EIP155 and pre-155 txs. The first begin tag corresponds to INIT + not::expr(meta.query_advice(rlp_decoding_table.is_stack_init, Rotation::cur())), ]) ); cb.condition( @@ -2560,8 +2562,9 @@ impl RlpCircuitConfig { // Assign lookup indicators from state machine into decoding table let is_init = matches!(witness.rlp_decoding_table.stack_op, StackOp::Init); - let is_begin = (witness_next.is_none() - || witness_next.unwrap().state_machine.state == State::DecodeTagStart) + let is_begin = !is_init + && (witness_next.is_none() + || witness_next.unwrap().state_machine.state == State::DecodeTagStart) && (witness.state_machine.tag == Tag::BeginObject || witness.state_machine.tag == Tag::BeginVector); region.assign_advice( From 4a6618f87e7fd3588705e4e5724ce90aa9a8b43b Mon Sep 17 00:00:00 2001 From: darth-cy Date: Thu, 18 Apr 2024 20:32:56 -0400 Subject: [PATCH 19/20] Add al_idx to input expression --- zkevm-circuits/src/rlp_circuit_fsm.rs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index aabb37a220..58f2a8f0fc 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2373,6 +2373,7 @@ impl RlpCircuitConfig { meta.query_advice(tag_value_acc, Rotation::cur()), ), 0.expr(), + ]; let table_exprs = vec![ meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), @@ -2430,6 +2431,7 @@ impl RlpCircuitConfig { meta.query_advice(byte_idx, Rotation::cur()), meta.query_advice(depth, Rotation::cur()), 1.expr(), + meta.query_advice(rlp_table.access_list_idx, Rotation::cur()), ]; let table_exprs = vec![ meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), @@ -2437,6 +2439,7 @@ impl RlpCircuitConfig { meta.query_advice(rlp_decoding_table.byte_idx, Rotation::cur()), meta.query_advice(rlp_decoding_table.depth, Rotation::cur()), meta.query_advice(rlp_decoding_table.is_stack_update, Rotation::cur()), + meta.query_advice(rlp_decoding_table.al_idx, Rotation::cur()), ]; input_exprs .into_iter() From 9896a5813d220ab1e7e351e3acb2e6cc00bebdaa Mon Sep 17 00:00:00 2001 From: darth-cy Date: Thu, 18 Apr 2024 20:46:05 -0400 Subject: [PATCH 20/20] Add access list idx to PUSH correspondence --- zkevm-circuits/src/rlp_circuit_fsm.rs | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/zkevm-circuits/src/rlp_circuit_fsm.rs b/zkevm-circuits/src/rlp_circuit_fsm.rs index 58f2a8f0fc..1b358573d3 100644 --- a/zkevm-circuits/src/rlp_circuit_fsm.rs +++ b/zkevm-circuits/src/rlp_circuit_fsm.rs @@ -2373,7 +2373,7 @@ impl RlpCircuitConfig { meta.query_advice(tag_value_acc, Rotation::cur()), ), 0.expr(), - + meta.query_advice(rlp_table.access_list_idx, Rotation::cur()), ]; let table_exprs = vec![ meta.query_advice(rlp_decoding_table.tx_id, Rotation::cur()), @@ -2383,6 +2383,11 @@ impl RlpCircuitConfig { meta.query_advice(rlp_decoding_table.is_stack_push, Rotation::cur()), meta.query_advice(rlp_decoding_table.value, Rotation::cur()), meta.query_advice(rlp_decoding_table.value_prev, Rotation::cur()), + select::expr( + meta.query_advice(is_stack_depth_three, Rotation::cur()), + meta.query_advice(rlp_decoding_table.al_idx, Rotation::cur()) - 1.expr(), + meta.query_advice(rlp_decoding_table.al_idx, Rotation::cur()), + ), ]; input_exprs .into_iter()