From aa403c0793129874098e3395964f5349c572008a Mon Sep 17 00:00:00 2001 From: Iluvmagick Date: Mon, 13 May 2024 13:44:36 +0400 Subject: [PATCH] Added real opcode numbers assignment. --- .../components/zkevm/circuits/bytecode.hpp | 10 +- include/nil/blueprint/zkevm/zkevm_circuit.hpp | 17 +- include/nil/blueprint/zkevm/zkevm_opcodes.hpp | 185 +++++++++++++++++- 3 files changed, 195 insertions(+), 17 deletions(-) diff --git a/include/nil/blueprint/components/zkevm/circuits/bytecode.hpp b/include/nil/blueprint/components/zkevm/circuits/bytecode.hpp index b9b5dbce9..26cd5c7df 100644 --- a/include/nil/blueprint/components/zkevm/circuits/bytecode.hpp +++ b/include/nil/blueprint/components/zkevm/circuits/bytecode.hpp @@ -21,11 +21,8 @@ // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. //---------------------------------------------------------------------------// -// @file Declaration of interfaces for FRI verification array swapping component. -//---------------------------------------------------------------------------// -#ifndef CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_ZKEVM_CIRCUITS_BYTECODE_HPP -#define CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_ZKEVM_CIRCUITS_BYTECODE_HPP +#pragma once #include @@ -194,9 +191,6 @@ namespace nil { static constexpr std::size_t VALUE_RLC = component_type::VALUE_RLC; static constexpr std::size_t RLC_CHALLENGE = component_type::RLC_CHALLENGE; - const std::size_t witness_amount = component.witness_amount(); - const std::size_t rows_amount = component.rows_amount; - value_type rlc_challenge = var_value(assignment, instance_input.rlc_challenge); std::size_t cur = 0; @@ -366,5 +360,3 @@ namespace nil { } // namespace components } // namespace blueprint } // namespace nil - -#endif // CRYPTO3_BLUEPRINT_COMPONENTS_PLONK_ZKEVM_CIRCUITS_BYTECODE_HPP \ No newline at end of file diff --git a/include/nil/blueprint/zkevm/zkevm_circuit.hpp b/include/nil/blueprint/zkevm/zkevm_circuit.hpp index dccfed192..11967580e 100644 --- a/include/nil/blueprint/zkevm/zkevm_circuit.hpp +++ b/include/nil/blueprint/zkevm/zkevm_circuit.hpp @@ -116,7 +116,7 @@ namespace nil { } zkevm_circuit(assignment_type &assignment_, circuit_type &circuit_, std::size_t start_row_index_ = 1) - :assignment(assignment_), circuit(circuit_), + :assignment(assignment_), circuit(circuit_), opcodes_info_instance(opcodes_info::instance()), selector_manager(assignment_, circuit_), curr_row(start_row_index_), start_row_index(start_row_index_) { @@ -162,9 +162,10 @@ namespace nil { void advance_rows(const zkevm_opcode opcode, std::size_t rows) { assignment.enable_selector(middle_selector, curr_row, curr_row + rows - 1); // TODO: figure out what is going to happen on state change + value_type opcode_val = opcodes_info_instance.get_opcode_value(opcode); for (std::size_t i = 0; i < rows; i++) { // TODO: switch to real bytecode - assignment.witness(state_selector->W(0), curr_row) = value_type(std::size_t(opcode)); + assignment.witness(state_selector->W(0), curr_row) = opcode_val; components::generate_assignments( *state_selector, assignment, {var(state_selector->W(0), curr_row, false, var::column_type::witness)}, curr_row); @@ -176,7 +177,7 @@ namespace nil { if (i == 0) { state.step_selection.value = 0; } - assignment.witness(state_selector->W(0), curr_row) = value_type(std::size_t(opcode)); + assignment.witness(state_selector->W(0), curr_row) = opcode_val; state.rows_until_next_op.value = state.rows_until_next_op.value - 1; state.rows_until_next_op_inv.value = state.rows_until_next_op.value == 0 ? 0 : 1 / state.rows_until_next_op.value; @@ -309,8 +310,8 @@ namespace nil { start_selector = selector_manager.add_gate(first_constraints); // TODO: proper end constraints end_selector = circuit.add_gate(last_constraints); - // TODO: proper calculation - const std::size_t opcodes_amount = LAST_ZKEVM_OPCODE + 1; + + const std::size_t opcodes_amount = opcodes_info_instance.get_opcodes_amount(); const std::size_t state_selector_cols_amount = state_selector_type::get_manifest(opcodes_amount).witness_amount->max_value_if_sat(); for (std::size_t i = 0; i < state_selector_cols_amount; i++) { @@ -350,8 +351,8 @@ namespace nil { if (opcode_height > max_opcode_height) { BOOST_ASSERT("Opcode height exceeds maximum, please update max_opcode_height constant."); } - // TODO: proper opcode table instead - std::size_t opcode_num = opcode_it.first; + + std::size_t opcode_num = opcodes_info_instance.get_opcode_value(opcode_it.first); auto curr_opt_constraint = state_selector->option_constraint(opcode_num); // force current height to be proper value at the start of the opcode if (opcode_height == 1) { @@ -414,6 +415,8 @@ namespace nil { // reference to the assignment/circuit objects assignment_type &assignment; circuit_type &circuit; + // information about opcode metadata (mapping, etc.) + const opcodes_info &opcodes_info_instance; selector_manager_type selector_manager; std::shared_ptr state_selector; std::shared_ptr opcode_row_selector; diff --git a/include/nil/blueprint/zkevm/zkevm_opcodes.hpp b/include/nil/blueprint/zkevm/zkevm_opcodes.hpp index 1fe71a93e..80ea81e30 100644 --- a/include/nil/blueprint/zkevm/zkevm_opcodes.hpp +++ b/include/nil/blueprint/zkevm/zkevm_opcodes.hpp @@ -26,6 +26,9 @@ #include +#include +#include + namespace nil { namespace blueprint { #define ZKEVM_OPCODE_ENUM(X) \ @@ -64,6 +67,8 @@ namespace nil { X(CALLDATALOAD) \ X(CALLDATASIZE) \ X(CALLDATACOPY) \ + X(CODESIZE) \ + X(CODECOPY) \ X(GASPRICE) \ X(EXTCODESIZE) \ X(EXTCODECOPY) \ @@ -183,7 +188,185 @@ namespace nil { #undef ENUM_DEF }; - zkevm_opcode LAST_ZKEVM_OPCODE = zkevm_opcode::SELFDESTRUCT; + // singleton class to hold opcode to byte mapping + struct opcodes_info { + public: + static const opcodes_info& instance() { + static opcodes_info instance; + return instance; + } + + std::size_t get_opcode_value(const zkevm_opcode& opcode) const { + auto it = opcode_to_byte_map.left.find(opcode); + BOOST_ASSERT(it != opcode_to_byte_map.left.end()); + return it->second; + } + + zkevm_opcode get_opcode_from_value(const std::size_t& value) const { + auto it = opcode_to_byte_map.right.find(value); + BOOST_ASSERT(it != opcode_to_byte_map.right.end()); + return it->second; + } + + std::size_t get_opcodes_amount() const { + return opcode_to_byte_map.size(); + } + + boost::bimap, boost::bimaps::set_of> + opcode_to_byte_map; + private: + opcodes_info() { + opcode_to_byte_map.insert({zkevm_opcode::STOP, 0x00}); + opcode_to_byte_map.insert({zkevm_opcode::ADD, 0x01}); + opcode_to_byte_map.insert({zkevm_opcode::MUL, 0x02}); + opcode_to_byte_map.insert({zkevm_opcode::SUB, 0x03}); + opcode_to_byte_map.insert({zkevm_opcode::DIV, 0x04}); + opcode_to_byte_map.insert({zkevm_opcode::SDIV, 0x05}); + opcode_to_byte_map.insert({zkevm_opcode::MOD, 0x06}); + opcode_to_byte_map.insert({zkevm_opcode::SMOD, 0x07}); + opcode_to_byte_map.insert({zkevm_opcode::ADDMOD, 0x08}); + opcode_to_byte_map.insert({zkevm_opcode::MULMOD, 0x09}); + opcode_to_byte_map.insert({zkevm_opcode::EXP, 0x0a}); + opcode_to_byte_map.insert({zkevm_opcode::SIGNEXTEND, 0x0b}); + opcode_to_byte_map.insert({zkevm_opcode::LT, 0x10}); + opcode_to_byte_map.insert({zkevm_opcode::GT, 0x11}); + opcode_to_byte_map.insert({zkevm_opcode::SLT, 0x12}); + opcode_to_byte_map.insert({zkevm_opcode::SGT, 0x13}); + opcode_to_byte_map.insert({zkevm_opcode::EQ, 0x14}); + opcode_to_byte_map.insert({zkevm_opcode::ISZERO, 0x15}); + opcode_to_byte_map.insert({zkevm_opcode::AND, 0x16}); + opcode_to_byte_map.insert({zkevm_opcode::OR, 0x17}); + opcode_to_byte_map.insert({zkevm_opcode::XOR, 0x18}); + opcode_to_byte_map.insert({zkevm_opcode::NOT, 0x19}); + opcode_to_byte_map.insert({zkevm_opcode::BYTE, 0x1a}); + opcode_to_byte_map.insert({zkevm_opcode::SHL, 0x1b}); + opcode_to_byte_map.insert({zkevm_opcode::SHR, 0x1c}); + opcode_to_byte_map.insert({zkevm_opcode::SAR, 0x1d}); + opcode_to_byte_map.insert({zkevm_opcode::KECCAK256, 0x20}); + opcode_to_byte_map.insert({zkevm_opcode::ADDRESS, 0x30}); + opcode_to_byte_map.insert({zkevm_opcode::BALANCE, 0x31}); + opcode_to_byte_map.insert({zkevm_opcode::ORIGIN, 0x32}); + opcode_to_byte_map.insert({zkevm_opcode::CALLER, 0x33}); + opcode_to_byte_map.insert({zkevm_opcode::CALLVALUE, 0x34}); + opcode_to_byte_map.insert({zkevm_opcode::CALLDATALOAD, 0x35}); + opcode_to_byte_map.insert({zkevm_opcode::CALLDATASIZE, 0x36}); + opcode_to_byte_map.insert({zkevm_opcode::CALLDATACOPY, 0x37}); + opcode_to_byte_map.insert({zkevm_opcode::CODESIZE, 0x38}); + opcode_to_byte_map.insert({zkevm_opcode::CODECOPY, 0x39}); + opcode_to_byte_map.insert({zkevm_opcode::GASPRICE, 0x3a}); + opcode_to_byte_map.insert({zkevm_opcode::EXTCODESIZE, 0x3b}); + opcode_to_byte_map.insert({zkevm_opcode::EXTCODECOPY, 0x3c}); + opcode_to_byte_map.insert({zkevm_opcode::RETURNDATASIZE, 0x3d}); + opcode_to_byte_map.insert({zkevm_opcode::RETURNDATACOPY, 0x3e}); + opcode_to_byte_map.insert({zkevm_opcode::EXTCODEHASH, 0x3f}); + opcode_to_byte_map.insert({zkevm_opcode::BLOCKHASH, 0x40}); + opcode_to_byte_map.insert({zkevm_opcode::COINBASE, 0x41}); + opcode_to_byte_map.insert({zkevm_opcode::TIMESTAMP, 0x42}); + opcode_to_byte_map.insert({zkevm_opcode::NUMBER, 0x43}); + opcode_to_byte_map.insert({zkevm_opcode::PREVRANDAO, 0x44}); + opcode_to_byte_map.insert({zkevm_opcode::GASLIMIT, 0x45}); + opcode_to_byte_map.insert({zkevm_opcode::CHAINID, 0x46}); + opcode_to_byte_map.insert({zkevm_opcode::SELFBALANCE, 0x47}); + opcode_to_byte_map.insert({zkevm_opcode::BASEFEE, 0x48}); + opcode_to_byte_map.insert({zkevm_opcode::BLOBHASH, 0x49}); + opcode_to_byte_map.insert({zkevm_opcode::BLOBBASEFEE, 0x4a}); + opcode_to_byte_map.insert({zkevm_opcode::POP, 0x50}); + opcode_to_byte_map.insert({zkevm_opcode::MLOAD, 0x51}); + opcode_to_byte_map.insert({zkevm_opcode::MSTORE, 0x52}); + opcode_to_byte_map.insert({zkevm_opcode::MSTORE8, 0x53}); + opcode_to_byte_map.insert({zkevm_opcode::SLOAD, 0x54}); + opcode_to_byte_map.insert({zkevm_opcode::SSTORE, 0x55}); + opcode_to_byte_map.insert({zkevm_opcode::JUMP, 0x56}); + opcode_to_byte_map.insert({zkevm_opcode::JUMPI, 0x57}); + opcode_to_byte_map.insert({zkevm_opcode::PC, 0x58}); + opcode_to_byte_map.insert({zkevm_opcode::MSIZE, 0x59}); + opcode_to_byte_map.insert({zkevm_opcode::GAS, 0x5a}); + opcode_to_byte_map.insert({zkevm_opcode::JUMPDEST, 0x5b}); + opcode_to_byte_map.insert({zkevm_opcode::TLOAD, 0x5c}); + opcode_to_byte_map.insert({zkevm_opcode::TSTORE, 0x5d}); + opcode_to_byte_map.insert({zkevm_opcode::MCOPY, 0x5e}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH0, 0x5f}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH1, 0x60}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH2, 0x61}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH3, 0x62}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH4, 0x63}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH5, 0x64}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH6, 0x65}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH7, 0x66}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH8, 0x67}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH9, 0x68}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH10, 0x69}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH11, 0x6a}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH12, 0x6b}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH13, 0x6c}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH14, 0x6d}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH15, 0x6e}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH16, 0x6f}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH17, 0x70}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH18, 0x71}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH19, 0x72}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH20, 0x73}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH21, 0x74}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH22, 0x75}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH23, 0x76}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH24, 0x77}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH25, 0x78}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH26, 0x79}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH27, 0x7a}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH28, 0x7b}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH29, 0x7c}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH30, 0x7d}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH31, 0x7e}); + opcode_to_byte_map.insert({zkevm_opcode::PUSH32, 0x7f}); + opcode_to_byte_map.insert({zkevm_opcode::DUP1, 0x80}); + opcode_to_byte_map.insert({zkevm_opcode::DUP2, 0x81}); + opcode_to_byte_map.insert({zkevm_opcode::DUP3, 0x82}); + opcode_to_byte_map.insert({zkevm_opcode::DUP4, 0x83}); + opcode_to_byte_map.insert({zkevm_opcode::DUP5, 0x84}); + opcode_to_byte_map.insert({zkevm_opcode::DUP6, 0x85}); + opcode_to_byte_map.insert({zkevm_opcode::DUP7, 0x86}); + opcode_to_byte_map.insert({zkevm_opcode::DUP8, 0x87}); + opcode_to_byte_map.insert({zkevm_opcode::DUP9, 0x88}); + opcode_to_byte_map.insert({zkevm_opcode::DUP10, 0x89}); + opcode_to_byte_map.insert({zkevm_opcode::DUP11, 0x8a}); + opcode_to_byte_map.insert({zkevm_opcode::DUP12, 0x8b}); + opcode_to_byte_map.insert({zkevm_opcode::DUP13, 0x8c}); + opcode_to_byte_map.insert({zkevm_opcode::DUP14, 0x8d}); + opcode_to_byte_map.insert({zkevm_opcode::DUP15, 0x8e}); + opcode_to_byte_map.insert({zkevm_opcode::DUP16, 0x8f}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP1, 0x90}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP2, 0x91}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP3, 0x92}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP4, 0x93}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP5, 0x94}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP6, 0x95}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP7, 0x96}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP8, 0x97}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP9, 0x98}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP10, 0x99}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP11, 0x9a}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP12, 0x9b}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP13, 0x9c}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP14, 0x9d}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP15, 0x9e}); + opcode_to_byte_map.insert({zkevm_opcode::SWAP16, 0x9f}); + opcode_to_byte_map.insert({zkevm_opcode::LOG0, 0xa0}); + opcode_to_byte_map.insert({zkevm_opcode::LOG1, 0xa1}); + opcode_to_byte_map.insert({zkevm_opcode::LOG2, 0xa2}); + opcode_to_byte_map.insert({zkevm_opcode::LOG3, 0xa3}); + opcode_to_byte_map.insert({zkevm_opcode::LOG4, 0xa4}); + opcode_to_byte_map.insert({zkevm_opcode::CREATE, 0xf0}); + opcode_to_byte_map.insert({zkevm_opcode::CALL, 0xf1}); + opcode_to_byte_map.insert({zkevm_opcode::CALLCODE, 0xf2}); + opcode_to_byte_map.insert({zkevm_opcode::RETURN, 0xf3}); + opcode_to_byte_map.insert({zkevm_opcode::DELEGATECALL, 0xf4}); + opcode_to_byte_map.insert({zkevm_opcode::CREATE2, 0xf5}); + opcode_to_byte_map.insert({zkevm_opcode::STATICCALL, 0xfa}); + opcode_to_byte_map.insert({zkevm_opcode::REVERT, 0xfd}); + opcode_to_byte_map.insert({zkevm_opcode::INVALID, 0xfe}); + opcode_to_byte_map.insert({zkevm_opcode::SELFDESTRUCT, 0xff}); + } + }; std::string opcode_to_string(const zkevm_opcode& opcode) { switch (opcode) {