diff --git a/Cargo.lock b/Cargo.lock index 00c04ae3a..8208ccf7c 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1891,27 +1891,6 @@ dependencies = [ "transcript", ] -[[package]] -name = "singer-pro" -version = "0.1.0" -dependencies = [ - "ark-std", - "ff", - "ff_ext", - "gkr", - "gkr-graph", - "goldilocks", - "itertools 0.12.1", - "paste", - "rayon", - "serde", - "simple-frontend", - "singer-utils", - "strum 0.25.0", - "strum_macros 0.25.3", - "transcript", -] - [[package]] name = "singer-utils" version = "0.1.0" diff --git a/Cargo.toml b/Cargo.toml index 1dc70c4bf..5aa326e44 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -9,7 +9,6 @@ members = [ "multilinear_extensions", "simple-frontend", "singer", - "singer-pro", "singer-utils", "sumcheck", "transcript", diff --git a/Makefile.toml b/Makefile.toml index a13525936..74e5f0cac 100644 --- a/Makefile.toml +++ b/Makefile.toml @@ -23,8 +23,6 @@ args = [ "--workspace", "--exclude", "ceno_rt", - "--exclude", - "singer-pro", ] [tasks.fmt-all-check] diff --git a/singer-pro/Cargo.toml b/singer-pro/Cargo.toml deleted file mode 100644 index 3e03b29ff..000000000 --- a/singer-pro/Cargo.toml +++ /dev/null @@ -1,27 +0,0 @@ -[package] -name = "singer-pro" -version.workspace = true -edition.workspace = true -license.workspace = true - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[dependencies] -ark-std.workspace = true -ff.workspace = true -gkr = { version = "0.1.0", path = "../gkr", features = ["parallel"] } -gkr-graph = { version = "0.1.0", path = "../gkr-graph" } -goldilocks.workspace = true -itertools = "0.12.1" -paste = "1.0.15" -rayon.workspace = true -serde.workspace = true -simple-frontend = { version = "0.1.0", path = "../simple-frontend" } -singer-utils = { version = "0.1.0", path = "../singer-utils" } -strum = "0.25.0" -strum_macros = "0.25.3" -transcript = { version = "0.1.0", path = "../transcript" } -ff_ext = { path = "../ff_ext" } - -[features] -debug_wenqing = [] diff --git a/singer-pro/examples/simple.rs b/singer-pro/examples/simple.rs deleted file mode 100644 index 58fa4cdb4..000000000 --- a/singer-pro/examples/simple.rs +++ /dev/null @@ -1,69 +0,0 @@ -use goldilocks::GoldilocksExt2; -use itertools::Itertools; -use singer_pro::{ - instructions::SingerInstCircuitBuilder, - scheme::{prover::prove, verifier::verify}, - SingerAuxInfo, SingerGraphBuilder, SingerParams, SingerWiresIn, -}; -use singer_utils::structs::ChipChallenges; -use transcript::Transcript; - -fn main() { - let chip_challenges = ChipChallenges::default(); - let circuit_builder = SingerInstCircuitBuilder::::new(chip_challenges) - .expect("circuit builder failed"); - - let bytecode = vec![vec![0x60 as u8, 0x01, 0x50]]; - let singer_builder = SingerGraphBuilder::::new( - circuit_builder.clone(), - &bytecode, - chip_challenges, - ) - .expect("graph builder failed"); - - let mut prover_transcript = Transcript::new(b"Singer pro"); - - // TODO: Generate the following items. - let singer_wires_in = SingerWiresIn::default(); - let real_challenges = vec![]; - let singer_params = SingerParams::default(); - - let (proof, singer_aux_info) = { - let real_n_instances = singer_wires_in - .basic_blocks - .iter() - .map(|x| x.real_n_instance) - .collect_vec(); - let (circuit, witness, wires_out_id) = singer_builder - .construct_graph_and_witness(singer_wires_in, &[], &real_challenges, &singer_params) - .expect("construct failed"); - - let (proof, graph_aux_info) = - prove(&circuit, &witness, &wires_out_id, &mut prover_transcript).expect("prove failed"); - let aux_info = SingerAuxInfo { - graph_aux_info, - real_n_instances, - singer_params, - bytecode_len: bytecode.len(), - ..Default::default() - }; - (proof, aux_info) - }; - - // 4. Verify. - let mut verifier_transcript = Transcript::new(b"Singer pro"); - let singer_builder = - SingerGraphBuilder::::new(circuit_builder, &bytecode, chip_challenges) - .expect("graph builder failed"); - let circuit = singer_builder - .construct_graph(&singer_aux_info) - .expect("construct failed"); - verify( - &circuit, - proof, - &singer_aux_info, - &real_challenges, - &mut verifier_transcript, - ) - .expect("verify failed"); -} diff --git a/singer-pro/src/basic_block.rs b/singer-pro/src/basic_block.rs deleted file mode 100644 index 5842eec22..000000000 --- a/singer-pro/src/basic_block.rs +++ /dev/null @@ -1,620 +0,0 @@ -use std::{collections::HashSet, mem}; - -use ff_ext::ExtensionField; -use gkr_graph::structs::{CircuitGraphBuilder, NodeOutputType, PredType}; -use itertools::{izip, Itertools}; -use singer_utils::{chips::SingerChipBuilder, constants::OpcodeType, structs::ChipChallenges}; - -use crate::{ - basic_block::bb_ret::{BBReturnRestMemLoad, BBReturnRestMemStore}, - component::{AccessoryCircuit, BBFinalCircuit, BBStartCircuit}, - error::ZKVMError, - instructions::{ - construct_inst_graph, construct_inst_graph_and_witness, SingerInstCircuitBuilder, - }, - BasicBlockWiresIn, SingerParams, -}; - -use self::{ - bb_final::BasicBlockFinal, - bb_ret::{BBReturnRestStackPop, BasicBlockReturn}, - bb_start::BasicBlockStart, - utils::{lower_bound, BasicBlockStack, StackOpMode}, -}; - -// basic block -pub mod bb_final; -pub mod bb_ret; -pub mod bb_start; -pub mod utils; - -pub struct SingerBasicBlockBuilder { - inst_builder: SingerInstCircuitBuilder, - basic_blocks: Vec>, - pub(crate) challenges: ChipChallenges, -} - -impl SingerBasicBlockBuilder { - pub fn new( - inst_builder: SingerInstCircuitBuilder, - bytecode: &[Vec], - challenges: ChipChallenges, - ) -> Result { - let mut basic_blocks = Vec::new(); - let mut pc_start = 0; - for b in bytecode { - let len = b.len(); - basic_blocks.push(BasicBlock::new(b, pc_start, challenges)?); - pc_start += len as u64; - } - Ok(SingerBasicBlockBuilder { - basic_blocks, - inst_builder, - challenges, - }) - } - - pub fn construct_graph_and_witness( - &self, - graph_builder: &mut CircuitGraphBuilder, - chip_builder: &mut SingerChipBuilder, - mut bbs_wires_in: Vec>, - real_challenges: &[E], - params: &SingerParams, - ) -> Result, ZKVMError> { - let mut pub_out_id = None; - for (bb, bb_wires_in) in self.basic_blocks.iter().zip(bbs_wires_in.iter_mut()) { - let bb_pub_out_id = bb.construct_graph_and_witness( - graph_builder, - chip_builder, - &self.inst_builder, - mem::take(bb_wires_in), - real_challenges, - params, - )?; - if bb_pub_out_id.is_some() { - pub_out_id = bb_pub_out_id; - } - } - Ok(pub_out_id) - } - - pub fn construct_graph( - &self, - graph_builder: &mut CircuitGraphBuilder, - chip_builder: &mut SingerChipBuilder, - real_n_instances: &[usize], - params: &SingerParams, - ) -> Result, ZKVMError> { - let mut pub_out_id = None; - for (bb, real_n_instances) in izip!(self.basic_blocks.iter(), real_n_instances.iter()) { - let bb_pub_out_id = bb.construct_graph( - graph_builder, - chip_builder, - &self.inst_builder, - *real_n_instances, - params, - )?; - if bb_pub_out_id.is_some() { - pub_out_id = bb_pub_out_id; - } - } - Ok(pub_out_id) - } - - pub(crate) fn basic_block_bytecode(&self) -> Vec> { - self.basic_blocks - .iter() - .map(|bb| bb.bytecode.clone()) - .collect() - } -} - -#[derive(Clone, Debug)] -pub struct BasicBlockInfo { - pub(crate) pc_start: u64, - pub(crate) bb_start_stack_top_offsets: Vec, - pub(crate) bb_final_stack_top_offsets: Vec, - pub(crate) delta_stack_top: i64, -} - -#[derive(Clone, Debug)] -pub struct BasicBlock { - pub bytecode: Vec, - pub info: BasicBlockInfo, - - bb_start_circuit: BBStartCircuit, - bb_final_circuit: BBFinalCircuit, - bb_acc_circuits: Vec>, -} - -impl BasicBlock { - pub(crate) fn new( - bytecode: &[u8], - pc_start: u64, - challenges: ChipChallenges, - ) -> Result { - let mut stack_top = 0 as i64; - let mut pc = pc_start; - let mut stack_offsets = HashSet::new(); - - while pc < bytecode.len() as u64 { - let opcode = bytecode[pc as usize]; - match StackOpMode::from(opcode) { - StackOpMode::PopPush(a, b) => { - let a = a as i64; - let b = b as i64; - stack_offsets.extend((stack_top - a..stack_top).collect_vec()); - stack_offsets.extend((stack_top - a..stack_top - a + b).collect_vec()); - stack_top = stack_top - a + b; - pc += 1; - } - StackOpMode::Swap(n) => { - let n = n as i64; - stack_offsets.extend([stack_top - n - 1, stack_top - 1]); - pc += 1; - } - StackOpMode::Dup(n) => { - let n = n as i64; - stack_offsets.extend([stack_top - n, stack_top]); - stack_top += 1; - pc += 1; - } - } - if opcode == OpcodeType::RETURN as u8 { - break; - } - } - - let mut stack_offsets = stack_offsets.into_iter().collect_vec(); - stack_offsets.sort(); - - let bb_start_stack_top_offsets = stack_offsets[0..=lower_bound(&stack_offsets, 0)].to_vec(); - let bb_final_stack_top_offsets = - stack_offsets[0..=lower_bound(&stack_offsets, stack_top)].to_vec(); - - let info = BasicBlockInfo { - pc_start, - bb_start_stack_top_offsets, - bb_final_stack_top_offsets, - delta_stack_top: stack_top, - }; - - let bb_start_circuit = BasicBlockStart::construct_circuit(&info, challenges)?; - let (bb_final_circuit, bb_acc_circuits) = - if bytecode.last() == Some(&(OpcodeType::RETURN as u8)) { - ( - BasicBlockReturn::construct_circuit(&info, challenges)?, - vec![ - BBReturnRestMemLoad::construct_circuit(challenges)?, - BBReturnRestMemStore::construct_circuit(challenges)?, - BBReturnRestStackPop::construct_circuit(challenges)?, - ], - ) - } else { - ( - BasicBlockFinal::construct_circuit(&info, challenges)?, - vec![], - ) - }; - - Ok(BasicBlock { - bytecode: bytecode.to_vec(), - info, - bb_start_circuit, - bb_final_circuit, - bb_acc_circuits, - }) - } - - /// Construct the graph and witness for the basic block. Return the - /// `NodeOutputType` of the public output size, which is generated by Return - /// instruction. - pub(crate) fn construct_graph_and_witness( - &self, - graph_builder: &mut CircuitGraphBuilder, - chip_builder: &mut SingerChipBuilder, - inst_builder: &SingerInstCircuitBuilder, - mut bb_wires_in: BasicBlockWiresIn, - real_challenges: &[E], - params: &SingerParams, - ) -> Result, ZKVMError> { - let bb_start_circuit = &self.bb_start_circuit; - let bb_final_circuit = &self.bb_final_circuit; - let bb_acc_circuits = &self.bb_acc_circuits; - let real_n_instances = bb_wires_in.real_n_instance; - - let bb_start_node_id = graph_builder.add_node_with_witness( - "BB start", - &bb_start_circuit.circuit, - vec![PredType::Source; bb_start_circuit.circuit.n_witness_in], - real_challenges.to_vec(), - mem::take(&mut bb_wires_in.bb_start), - real_n_instances, - )?; - - // The instances wire in values are padded to the power of two, but we - // need the real number of instances here. - chip_builder.construct_chip_check_graph_and_witness( - graph_builder, - bb_start_node_id, - &bb_start_circuit.layout.to_chip_ids, - real_challenges, - real_n_instances, - )?; - - let mut to_succ = &bb_start_circuit.layout.to_succ_inst; - let mut next_pc = None; - let mut local_stack = - BasicBlockStack::initialize(self.info.clone(), bb_start_node_id, to_succ); - let mut pred_node_id = bb_start_node_id; - - // The return instruction will return the size of the public output. We - // should leak this to the verifier. - let mut public_output_size = None; - - for (&opcode, opcode_wires_in) in self.bytecode.iter().zip(bb_wires_in.opcodes.iter_mut()) { - let (inst_circuit, acc_circuits) = &inst_builder.insts_circuits.get(&opcode).unwrap(); - let opcode_wires_in = mem::take(opcode_wires_in); - - let mode = StackOpMode::from(opcode); - let stack = local_stack.pop_node_outputs(mode); - let memory_ts = NodeOutputType::WireOut(pred_node_id, to_succ.next_memory_ts_id); - let preds = inst_circuit.layout.input( - inst_circuit.circuit.n_witness_in, - opcode, - stack, - memory_ts, - ); - let (node_id, stack, po) = construct_inst_graph_and_witness( - opcode, - graph_builder, - chip_builder, - inst_circuit, - acc_circuits, - preds, - opcode_wires_in, - real_challenges, - real_n_instances, - params, - )?; - if po.is_some() { - public_output_size = po; - } - pred_node_id = node_id[0]; - to_succ = &inst_circuit.layout.to_succ_inst; - if let Some(to_bb_final) = inst_circuit.layout.to_bb_final { - next_pc = Some(NodeOutputType::WireOut(pred_node_id, to_bb_final)); - } - local_stack.push_node_outputs(stack, mode); - } - - let stack = local_stack.finalize(); - let stack_ts = NodeOutputType::WireOut( - bb_start_node_id, - bb_start_circuit.layout.to_bb_final.stack_ts_id, - ); - let memory_ts = NodeOutputType::WireOut(pred_node_id, to_succ.next_memory_ts_id); - let stack_top = NodeOutputType::WireOut( - bb_start_node_id, - bb_start_circuit.layout.to_bb_final.stack_top_id, - ); - let clk = - NodeOutputType::WireOut(bb_start_node_id, bb_start_circuit.layout.to_bb_final.clk_id); - let preds = bb_final_circuit.layout.input( - bb_final_circuit.circuit.n_witness_in, - stack, - stack_ts, - memory_ts, - stack_top, - clk, - next_pc, - ); - let bb_final_node_id = graph_builder.add_node_with_witness( - "BB final", - &bb_final_circuit.circuit, - preds, - real_challenges.to_vec(), - mem::take(&mut bb_wires_in.bb_final), - real_n_instances, - )?; - chip_builder.construct_chip_check_graph_and_witness( - graph_builder, - bb_final_node_id, - &bb_final_circuit.layout.to_chip_ids, - real_challenges, - real_n_instances, - )?; - - let real_n_instances_bb_accs = vec![ - params.n_mem_finalize, - params.n_mem_initialize, - params.n_stack_finalize, - ]; - for ((acc, acc_wires_in), real_n_instances) in bb_acc_circuits - .iter() - .zip(bb_wires_in.bb_accs.iter_mut()) - .zip(real_n_instances_bb_accs) - { - let acc_node_id = graph_builder.add_node_with_witness( - "BB acc", - &acc.circuit, - vec![PredType::Source; acc.circuit.n_witness_in], - real_challenges.to_vec(), - mem::take(acc_wires_in), - real_n_instances, - )?; - chip_builder.construct_chip_check_graph_and_witness( - graph_builder, - acc_node_id, - &acc.layout.to_chip_ids, - real_challenges, - real_n_instances, - )?; - } - Ok(public_output_size) - } - - pub(crate) fn construct_graph( - &self, - graph_builder: &mut CircuitGraphBuilder, - chip_builder: &mut SingerChipBuilder, - inst_builder: &SingerInstCircuitBuilder, - real_n_instances: usize, - params: &SingerParams, - ) -> Result, ZKVMError> { - let bb_start_circuit = &self.bb_start_circuit; - let bb_final_circuit = &self.bb_final_circuit; - let bb_acc_circuits = &self.bb_acc_circuits; - - let bb_start_node_id = graph_builder.add_node( - "BB start", - &bb_start_circuit.circuit, - vec![PredType::Source; bb_start_circuit.circuit.n_witness_in], - )?; - - // The instances wire in values are padded to the power of two, but we - // need the real number of instances here. - chip_builder.construct_chip_check_graph( - graph_builder, - bb_start_node_id, - &bb_start_circuit.layout.to_chip_ids, - real_n_instances, - )?; - - let mut to_succ = &bb_start_circuit.layout.to_succ_inst; - let mut next_pc = None; - let mut local_stack = - BasicBlockStack::initialize(self.info.clone(), bb_start_node_id, to_succ); - let mut pred_node_id = bb_start_node_id; - - // The return instruction will return the size of the public output. We - // should leak this to the verifier. - let mut public_output_size = None; - - for opcode in self.bytecode.iter() { - let (inst_circuit, acc_circuits) = &inst_builder.insts_circuits.get(&opcode).unwrap(); - - let mode = StackOpMode::from(*opcode); - let stack = local_stack.pop_node_outputs(mode); - let memory_ts = NodeOutputType::WireOut(pred_node_id, to_succ.next_memory_ts_id); - let preds = inst_circuit.layout.input( - inst_circuit.circuit.n_witness_in, - *opcode, - stack, - memory_ts, - ); - let (node_id, stack, po) = construct_inst_graph( - *opcode, - graph_builder, - chip_builder, - inst_circuit, - acc_circuits, - preds, - real_n_instances, - params, - )?; - if let Some(po) = po { - public_output_size = Some(po); - } - pred_node_id = node_id[0]; - to_succ = &inst_circuit.layout.to_succ_inst; - if let Some(op_to_bb_final) = inst_circuit.layout.to_bb_final { - next_pc = Some(NodeOutputType::WireOut(pred_node_id, op_to_bb_final)); - } - local_stack.push_node_outputs(stack, mode); - } - - let stack = local_stack.finalize(); - let stack_ts = NodeOutputType::WireOut( - bb_start_node_id, - bb_start_circuit.layout.to_bb_final.stack_ts_id, - ); - let memory_ts = NodeOutputType::WireOut(pred_node_id, to_succ.next_memory_ts_id); - let stack_top = NodeOutputType::WireOut( - bb_start_node_id, - bb_start_circuit.layout.to_bb_final.stack_top_id, - ); - let clk = - NodeOutputType::WireOut(bb_start_node_id, bb_start_circuit.layout.to_bb_final.clk_id); - let preds = bb_final_circuit.layout.input( - bb_final_circuit.circuit.n_witness_in, - stack, - stack_ts, - memory_ts, - stack_top, - clk, - next_pc, - ); - let bb_final_node_id = - graph_builder.add_node("BB final", &bb_final_circuit.circuit, preds)?; - chip_builder.construct_chip_check_graph( - graph_builder, - bb_final_node_id, - &bb_final_circuit.layout.to_chip_ids, - real_n_instances, - )?; - - let real_n_instances_bb_accs = vec![ - params.n_mem_finalize, - params.n_mem_initialize, - params.n_stack_finalize, - ]; - for (acc, real_n_instances) in bb_acc_circuits.iter().zip(real_n_instances_bb_accs) { - let acc_node_id = graph_builder.add_node( - "BB acc", - &acc.circuit, - vec![PredType::Source; acc.circuit.n_witness_in], - )?; - chip_builder.construct_chip_check_graph( - graph_builder, - acc_node_id, - &acc.layout.to_chip_ids, - real_n_instances, - )?; - } - Ok(public_output_size) - } -} - -#[cfg(test)] -mod test { - use crate::{ - basic_block::{ - bb_final::BasicBlockFinal, bb_start::BasicBlockStart, BasicBlock, BasicBlockInfo, - }, - instructions::{add::AddInstruction, SingerInstCircuitBuilder}, - scheme::GKRGraphProverState, - BasicBlockWiresIn, SingerParams, - }; - use ark_std::test_rng; - use ff::Field; - use ff_ext::ExtensionField; - use gkr::structs::LayerWitness; - use gkr_graph::structs::CircuitGraphBuilder; - use goldilocks::GoldilocksExt2; - use itertools::Itertools; - use singer_utils::{ - chips::SingerChipBuilder, - constants::OpcodeType, - structs::{ChipChallenges, PCUInt}, - }; - use std::time::Instant; - use transcript::Transcript; - - // A benchmark containing `n_adds_in_bb` ADD instructions in a basic block. - #[cfg(not(debug_assertions))] - fn bench_bb_helper(instance_num_vars: usize, n_adds_in_bb: usize) { - let chip_challenges = ChipChallenges::default(); - let circuit_builder = - SingerInstCircuitBuilder::::new(chip_challenges).expect("circuit builder failed"); - - let bytecode = vec![vec![OpcodeType::ADD as u8; n_adds_in_bb]]; - - let mut rng = test_rng(); - let real_challenges = vec![E::random(&mut rng), E::random(&mut rng)]; - let n_instances = 1 << instance_num_vars; - - let timer = Instant::now(); - - let mut random_matrix = |n, m| { - (0..n) - .map(|_| (0..m).map(|_| E::BaseField::random(&mut rng)).collect()) - .collect() - }; - let bb_witness = BasicBlockWiresIn { - bb_start: vec![LayerWitness { - instances: random_matrix( - n_instances, - BasicBlockStart::phase0_size(n_adds_in_bb + 1), - ), - }], - bb_final: vec![ - LayerWitness { - instances: random_matrix(n_instances, BasicBlockFinal::phase0_size()), - }, - LayerWitness::default(), - LayerWitness::default(), - LayerWitness::default(), - LayerWitness { - instances: random_matrix(n_instances, PCUInt::N_OPERAND_CELLS), - }, - LayerWitness::default(), - LayerWitness::default(), - ], - bb_accs: vec![], - opcodes: (0..n_adds_in_bb) - .map(|_| { - vec![vec![ - LayerWitness { - instances: random_matrix(n_instances, AddInstruction::phase0_size()), - }, - LayerWitness::default(), - LayerWitness::default(), - LayerWitness::default(), - ]] - }) - .collect_vec(), - real_n_instance: n_instances, - }; - - let info = BasicBlockInfo { - pc_start: 0, - bb_start_stack_top_offsets: (-((n_adds_in_bb + 1) as i64)..0).collect_vec(), - bb_final_stack_top_offsets: vec![-1], - delta_stack_top: -(n_adds_in_bb as i64), - }; - let bb_start_circuit = BasicBlockStart::construct_circuit(&info, chip_challenges) - .expect("construct circuit failed"); - let bb_final_circuit = BasicBlockFinal::construct_circuit(&info, chip_challenges) - .expect("construct circuit failed"); - let bb = BasicBlock { - bytecode: bytecode[0].clone(), - info, - bb_start_circuit, - bb_final_circuit, - bb_acc_circuits: vec![], - }; - - let mut graph_builder = CircuitGraphBuilder::::new(); - let mut chip_builder = SingerChipBuilder::::new(); - let _ = bb - .construct_graph_and_witness( - &mut graph_builder, - &mut chip_builder, - &circuit_builder, - bb_witness, - &real_challenges, - &SingerParams::default(), - ) - .expect("gkr graph construction failed"); - - let (graph, wit) = graph_builder.finalize_graph_and_witness(); - - println!( - "AddInstruction::construct_graph_and_witness, instance_num_vars = {}, time = {}s", - instance_num_vars, - timer.elapsed().as_secs_f64() - ); - - let point = (0..20).map(|_| E::random(&mut rng)).collect_vec(); - let target_evals = graph.target_evals(&wit, &point); - - let mut prover_transcript = &mut Transcript::new(b"Singer"); - - let timer = Instant::now(); - let _ = GKRGraphProverState::prove(&graph, &wit, &target_evals, &mut prover_transcript, 1) - .expect("prove failed"); - println!( - "AddInstruction::prove, instance_num_vars = {}, time = {}s", - instance_num_vars, - timer.elapsed().as_secs_f64() - ); - } - - #[test] - #[cfg(not(debug_assertions))] - fn bench_bb() { - bench_bb_helper::(10, 5); - } -} diff --git a/singer-pro/src/basic_block/bb_final.rs b/singer-pro/src/basic_block/bb_final.rs deleted file mode 100644 index d4672dbfe..000000000 --- a/singer-pro/src/basic_block/bb_final.rs +++ /dev/null @@ -1,140 +0,0 @@ -use ff::Field; -use ff_ext::ExtensionField; -use gkr::structs::Circuit; -use itertools::Itertools; -use paste::paste; -use simple_frontend::structs::{CircuitBuilder, MixedCell}; -use singer_utils::{ - chip_handler::{ - bytecode::BytecodeChip, global_state::GlobalStateChip, ram_handler::RAMHandler, - range::RangeChip, rom_handler::ROMHandler, stack::StackChip, ChipHandler, - }, - chips::IntoEnumIterator, - register_witness, - structs::{ChipChallenges, InstOutChipType, PCUInt, StackUInt, TSUInt}, - uint::constants::AddSubConstants, -}; -use std::{cell::RefCell, collections::BTreeMap, rc::Rc, sync::Arc}; - -use crate::{ - component::{BBFinalCircuit, BBFinalLayout, FromBBStart, FromPredInst, FromWitness}, - error::ZKVMError, - utils::i64_to_base_field, -}; - -use super::BasicBlockInfo; - -pub struct BasicBlockFinal; - -register_witness!(BasicBlockFinal, phase0 { - // State in related - stack_ts_add => AddSubConstants::::N_WITNESS_CELLS_NO_CARRY_OVERFLOW -}); - -impl BasicBlockFinal { - pub(crate) fn construct_circuit( - params: &BasicBlockInfo, - challenges: ChipChallenges, - ) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - let BasicBlockInfo { - delta_stack_top, - pc_start: _, - bb_start_stack_top_offsets: _, - bb_final_stack_top_offsets: stack_top_offsets, - } = params.clone(); - let n_stack_items = stack_top_offsets.len(); - - // From witness - let (phase0_wire_id, phase0) = circuit_builder.create_witness_in(Self::phase0_size()); - - // From BB start - let (stack_ts_id, stack_ts) = circuit_builder.create_witness_in(TSUInt::N_OPERAND_CELLS); - let (stack_top_id, stack_top) = circuit_builder.create_witness_in(1); - let (clk_id, clk) = circuit_builder.create_witness_in(1); - - // From inst pc. - let (next_pc_id, next_pc) = circuit_builder.create_witness_in(PCUInt::N_OPERAND_CELLS); - - let mut chip_handler = ChipHandler::new(challenges.clone()); - - let stack_ts = TSUInt::try_from(stack_ts)?; - let stack_ts_add_witness = &phase0[Self::phase0_stack_ts_add()]; - let next_stack_ts = RangeChip::add_ts_with_const( - &mut chip_handler, - &mut circuit_builder, - &stack_ts, - 1, - stack_ts_add_witness, - )?; - - let (memory_ts_id, memory_ts) = circuit_builder.create_witness_in(TSUInt::N_OPERAND_CELLS); - let stack_top_expr = MixedCell::Cell(stack_top[0]); - let clk_expr = MixedCell::Cell(clk[0]); - GlobalStateChip::state_out( - &mut chip_handler, - &mut circuit_builder, - &next_pc, - next_stack_ts.values(), - &memory_ts, - stack_top_expr.add(i64_to_base_field::(delta_stack_top)), - clk_expr.add(E::BaseField::ONE), - ); - - // Check the of stack_top + offset. - let stack_top_l = stack_top_expr.add(i64_to_base_field::(stack_top_offsets[0])); - RangeChip::range_check_stack_top(&mut chip_handler, &mut circuit_builder, stack_top_l)?; - let stack_top_r = - stack_top_expr.add(i64_to_base_field::(stack_top_offsets[n_stack_items - 1])); - RangeChip::range_check_stack_top(&mut chip_handler, &mut circuit_builder, stack_top_r)?; - - // From predesessor instruction - let stack_operand_ids = stack_top_offsets - .iter() - .map(|offset| { - let (stack_from_insts_id, stack_from_insts) = - circuit_builder.create_witness_in(StackUInt::N_OPERAND_CELLS); - StackChip::push( - &mut chip_handler, - &mut circuit_builder, - stack_top_expr.add(i64_to_base_field::(*offset)), - stack_ts.values(), - &stack_from_insts, - ); - stack_from_insts_id - }) - .collect_vec(); - - // To chips - let (ram_load_id, ram_store_id, rom_id) = chip_handler.finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::RAMLoad as usize] = ram_load_id; - to_chip_ids[InstOutChipType::RAMStore as usize] = ram_store_id; - to_chip_ids[InstOutChipType::ROMInput as usize] = rom_id; - - circuit_builder.configure(); - - // TODO other wire in ids. - Ok(BBFinalCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: BBFinalLayout { - to_chip_ids, - from_witness: FromWitness { - phase_ids: vec![phase0_wire_id], - }, - from_bb_start: FromBBStart { - stack_top_id, - stack_ts_id, - clk_id, - }, - from_pred_inst: FromPredInst { - memory_ts_id, - stack_operand_ids, - }, - next_pc_id: Some(next_pc_id), - }, - }) - } -} diff --git a/singer-pro/src/basic_block/bb_ret.rs b/singer-pro/src/basic_block/bb_ret.rs deleted file mode 100644 index 7ae5a3288..000000000 --- a/singer-pro/src/basic_block/bb_ret.rs +++ /dev/null @@ -1,265 +0,0 @@ -use ff_ext::ExtensionField; -use gkr::structs::Circuit; -use itertools::Itertools; -use paste::paste; -use simple_frontend::structs::{CircuitBuilder, MixedCell}; -use singer_utils::{ - chip_handler::{ - ram_handler::RAMHandler, range::RangeChip, rom_handler::ROMHandler, stack::StackChip, - ChipHandler, - }, - chips::IntoEnumIterator, - register_witness, - structs::{ChipChallenges, InstOutChipType, StackUInt, TSUInt}, -}; -use std::{cell::RefCell, collections::BTreeMap, rc::Rc, sync::Arc}; - -use crate::{ - component::{ - AccessoryCircuit, AccessoryLayout, BBFinalCircuit, BBFinalLayout, FromBBStart, - FromPredInst, FromWitness, - }, - error::ZKVMError, - utils::i64_to_base_field, -}; - -use super::BasicBlockInfo; - -pub struct BasicBlockReturn; -/// This circuit is to load the remaining elmeents after the program execution -/// from memory, which is a data-parallel circuit load one element in each -/// sub-circuit. -pub struct BBReturnRestMemLoad; -/// This circuit is to initialize the memory with 0 at the beginning. It can -/// only touch the used addresses. -pub struct BBReturnRestMemStore; - -impl BasicBlockReturn { - pub(crate) fn construct_circuit( - params: &BasicBlockInfo, - challenges: ChipChallenges, - ) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - let BasicBlockInfo { - delta_stack_top: _, - pc_start: _, - bb_start_stack_top_offsets: _, - bb_final_stack_top_offsets: stack_top_offsets, - } = params.clone(); - let n_stack_items = stack_top_offsets.len(); - - // From BB Start - let (stack_ts_id, stack_ts) = circuit_builder.create_witness_in(TSUInt::N_OPERAND_CELLS); - let (stack_top_id, stack_top) = circuit_builder.create_witness_in(1); - let (clk_id, _) = circuit_builder.create_witness_in(1); - - let mut chip_handler = ChipHandler::new(challenges.clone()); - - // Check the of stack_top + offset. - let stack_top_expr = MixedCell::Cell(stack_top[0]); - let stack_top_l = stack_top_expr.add(i64_to_base_field::(stack_top_offsets[0])); - RangeChip::range_check_stack_top(&mut chip_handler, &mut circuit_builder, stack_top_l)?; - let stack_top_r = - stack_top_expr.add(i64_to_base_field::(stack_top_offsets[n_stack_items - 1])); - RangeChip::range_check_stack_top(&mut chip_handler, &mut circuit_builder, stack_top_r)?; - - // From predesessor instruction - let (memory_ts_id, _) = circuit_builder.create_witness_in(TSUInt::N_OPERAND_CELLS); - let stack_operand_ids = stack_top_offsets - .iter() - .map(|offset| { - let (stack_from_insts_id, stack_from_insts) = circuit_builder.create_witness_in(1); - StackChip::push( - &mut chip_handler, - &mut circuit_builder, - stack_top_expr.add(i64_to_base_field::(*offset)), - &stack_ts, - &stack_from_insts, - ); - stack_from_insts_id - }) - .collect_vec(); - - // To chips. - let (ram_load_id, ram_store_id, rom_id) = chip_handler.finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::RAMLoad as usize] = ram_load_id; - to_chip_ids[InstOutChipType::RAMStore as usize] = ram_store_id; - to_chip_ids[InstOutChipType::ROMInput as usize] = rom_id; - - circuit_builder.configure(); - - Ok(BBFinalCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: BBFinalLayout { - to_chip_ids, - from_witness: FromWitness { phase_ids: vec![] }, - from_bb_start: FromBBStart { - stack_top_id, - stack_ts_id, - clk_id, - }, - from_pred_inst: FromPredInst { - stack_operand_ids, - memory_ts_id, - }, - next_pc_id: None, - }, - }) - } -} - -register_witness!( - BBReturnRestMemLoad, - phase0 { - mem_byte => 1, - old_memory_ts => TSUInt::N_OPERAND_CELLS, - offset => StackUInt::N_OPERAND_CELLS - } -); - -impl BBReturnRestMemLoad { - pub(crate) fn construct_circuit( - challenges: ChipChallenges, - ) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - let (phase0_wire_id, phase0) = circuit_builder.create_witness_in(Self::phase0_size()); - - let mut ram_handler = Rc::new(RefCell::new(RAMHandler::new(challenges.clone()))); - - // Load from memory - let offset = &phase0[Self::phase0_offset()]; - let mem_byte = phase0[Self::phase0_mem_byte().start]; - let old_memory_ts = &phase0[Self::phase0_old_memory_ts()]; - ram_handler - .borrow_mut() - .read_oam(&mut circuit_builder, offset, old_memory_ts, &[mem_byte]); - - let (ram_load_id, ram_store_id) = ram_handler.borrow_mut().finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::RAMLoad as usize] = ram_load_id; - to_chip_ids[InstOutChipType::RAMStore as usize] = ram_store_id; - to_chip_ids[InstOutChipType::ROMInput as usize] = None; - - circuit_builder.configure(); - - Ok(AccessoryCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: AccessoryLayout { - to_chip_ids, - from_witness: FromWitness { - phase_ids: vec![phase0_wire_id], - }, - from_pred_ooo: None, - from_pred_dup: None, - }, - }) - } -} - -register_witness!( - BBReturnRestMemStore, - phase0 { - mem_byte => 1, - offset => StackUInt::N_OPERAND_CELLS - } -); - -impl BBReturnRestMemStore { - pub(crate) fn construct_circuit( - challenges: ChipChallenges, - ) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - let (phase0_wire_id, phase0) = circuit_builder.create_witness_in(Self::phase0_size()); - - let mut ram_handler = Rc::new(RefCell::new(RAMHandler::new(challenges.clone()))); - - // Load from memory - let offset = &phase0[Self::phase0_offset()]; - let mem_byte = phase0[Self::phase0_mem_byte().start]; - // memory_ts is zero. - let memory_ts = circuit_builder.create_cells(StackUInt::N_OPERAND_CELLS); - ram_handler - .borrow_mut() - .write_oam(&mut circuit_builder, offset, &memory_ts, &[mem_byte]); - - let (ram_load_id, ram_store_id) = ram_handler.borrow_mut().finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::RAMLoad as usize] = ram_load_id; - to_chip_ids[InstOutChipType::RAMStore as usize] = ram_store_id; - to_chip_ids[InstOutChipType::ROMInput as usize] = None; - - Ok(AccessoryCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: AccessoryLayout { - to_chip_ids, - from_witness: FromWitness { - phase_ids: vec![phase0_wire_id], - }, - from_pred_ooo: None, - from_pred_dup: None, - }, - }) - } -} - -pub struct BBReturnRestStackPop; - -register_witness!( - BBReturnRestStackPop, - phase0 { - old_stack_ts => TSUInt::N_OPERAND_CELLS, - stack_values => StackUInt::N_OPERAND_CELLS - } -); - -impl BBReturnRestStackPop { - pub(crate) fn construct_circuit( - challenges: ChipChallenges, - ) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - let (phase0_wire_id, phase0) = circuit_builder.create_witness_in(Self::phase0_size()); - - let mut chip_handler = ChipHandler::new(challenges.clone()); - - // Pop from stack - let stack_top = circuit_builder.create_counter_in(0); - let stack_values = &phase0[Self::phase0_stack_values()]; - let old_stack_ts = &phase0[Self::phase0_old_stack_ts()]; - StackChip::pop( - &mut chip_handler, - &mut circuit_builder, - stack_top[0].into(), - old_stack_ts, - stack_values, - ); - - let (ram_load_id, ram_store_id, _) = chip_handler.finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::RAMLoad as usize] = ram_load_id; - to_chip_ids[InstOutChipType::RAMStore as usize] = ram_store_id; - to_chip_ids[InstOutChipType::ROMInput as usize] = None; - - circuit_builder.configure(); - - Ok(AccessoryCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: AccessoryLayout { - to_chip_ids, - from_witness: FromWitness { - phase_ids: vec![phase0_wire_id], - }, - from_pred_ooo: None, - from_pred_dup: None, - }, - }) - } -} diff --git a/singer-pro/src/basic_block/bb_start.rs b/singer-pro/src/basic_block/bb_start.rs deleted file mode 100644 index c4d68339f..000000000 --- a/singer-pro/src/basic_block/bb_start.rs +++ /dev/null @@ -1,154 +0,0 @@ -use ff::Field; -use ff_ext::ExtensionField; -use gkr::structs::Circuit; -use paste::paste; -use simple_frontend::structs::{CircuitBuilder, MixedCell}; -use singer_utils::{ - chip_handler::{ - global_state::GlobalStateChip, ram_handler::RAMHandler, range::RangeChip, - rom_handler::ROMHandler, stack::StackChip, ChipHandler, - }, - chips::IntoEnumIterator, - register_multi_witness, - structs::{ChipChallenges, InstOutChipType, PCUInt, StackUInt, TSUInt}, - uint::constants::AddSubConstants, -}; -use std::{cell::RefCell, rc::Rc, sync::Arc}; - -use crate::{ - component::{BBStartCircuit, BBStartLayout, FromWitness, ToBBFinal, ToSuccInst}, - error::ZKVMError, - utils::{add_assign_each_cell, i64_to_base_field}, -}; - -use super::BasicBlockInfo; - -pub(crate) struct BasicBlockStart; - -register_multi_witness!(BasicBlockStart, phase0(n_stack_items) { - // State in related - pc => PCUInt::N_OPERAND_CELLS, - stack_ts => TSUInt::N_OPERAND_CELLS, - memory_ts => TSUInt::N_OPERAND_CELLS, - stack_top => 1, - clk => 1, - - // Stack values - old_stack_values(n_stack_items) => StackUInt::N_OPERAND_CELLS, - old_stack_ts(n_stack_items) => TSUInt::N_OPERAND_CELLS, - old_stack_ts_lt(n_stack_items) => AddSubConstants::::N_WITNESS_CELLS_NO_CARRY_OVERFLOW -}); - -impl BasicBlockStart { - pub(crate) fn construct_circuit( - params: &BasicBlockInfo, - challenges: ChipChallenges, - ) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - let stack_top_offsets = ¶ms.bb_start_stack_top_offsets; - let n_stack_items = stack_top_offsets.len(); - - // From witness - let (phase0_wire_id, phase0) = - circuit_builder.create_witness_in(Self::phase0_size(n_stack_items)); - - let mut chip_handler = ChipHandler::new(challenges.clone()); - - // State update - let pc = &phase0[Self::phase0_pc(n_stack_items)]; - let stack_ts = &phase0[Self::phase0_stack_ts(n_stack_items)]; - let memory_ts = &phase0[Self::phase0_memory_ts(n_stack_items)]; - let stack_top = phase0[Self::phase0_stack_top(n_stack_items).start]; - let stack_top_expr = MixedCell::Cell(stack_top); - let clk = phase0[Self::phase0_clk(n_stack_items).start]; - GlobalStateChip::state_in( - &mut chip_handler, - &mut circuit_builder, - pc, - stack_ts, - memory_ts, - stack_top, - clk, - ); - - // Check the of stack_top + offset. - let stack_top_l = stack_top_expr.add(i64_to_base_field::(stack_top_offsets[0])); - RangeChip::range_check_stack_top(&mut chip_handler, &mut circuit_builder, stack_top_l)?; - let stack_top_r = - stack_top_expr.add(i64_to_base_field::(stack_top_offsets[n_stack_items - 1])); - RangeChip::range_check_stack_top(&mut chip_handler, &mut circuit_builder, stack_top_r)?; - - // pop all elements from the stack. - let stack_ts = TSUInt::try_from(stack_ts)?; - for (i, offset) in stack_top_offsets.iter().enumerate() { - let old_stack_ts = - TSUInt::try_from(&phase0[Self::phase0_old_stack_ts(i, n_stack_items)])?; - TSUInt::assert_lt( - &mut circuit_builder, - &mut chip_handler, - &old_stack_ts, - &stack_ts, - &phase0[Self::phase0_old_stack_ts_lt(i, n_stack_items)], - )?; - StackChip::pop( - &mut chip_handler, - &mut circuit_builder, - stack_top_expr.add(i64_to_base_field::(*offset)), - old_stack_ts.values(), - &phase0[Self::phase0_old_stack_values(i, n_stack_items)], - ); - } - - // To successor instruction - let mut stack_result_ids = Vec::with_capacity(n_stack_items); - for i in 0..n_stack_items { - let (stack_operand_id, stack_operand) = - circuit_builder.create_witness_out(StackUInt::N_OPERAND_CELLS); - let old_stack = &phase0[Self::phase0_old_stack_values(i, n_stack_items)]; - for j in 0..StackUInt::N_OPERAND_CELLS { - circuit_builder.add(stack_operand[j], old_stack[j], E::BaseField::ONE); - } - stack_result_ids.push(stack_operand_id); - } - let (out_memory_ts_id, out_memory_ts) = circuit_builder.create_witness_out(memory_ts.len()); - add_assign_each_cell(&mut circuit_builder, &out_memory_ts, &memory_ts); - - // To BB final - let (out_stack_ts_id, out_stack_ts) = - circuit_builder.create_witness_out(TSUInt::N_OPERAND_CELLS); - add_assign_each_cell(&mut circuit_builder, &out_stack_ts, stack_ts.values()); - let (out_stack_top_id, out_stack_top) = circuit_builder.create_witness_out(1); - circuit_builder.add(out_stack_top[0], stack_top, E::BaseField::ONE); - let (out_clk_id, out_clk) = circuit_builder.create_witness_out(1); - circuit_builder.add(out_clk[0], clk, E::BaseField::ONE); - - // To chips - let (ram_load_id, ram_store_id, rom_id) = chip_handler.finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::RAMLoad as usize] = ram_load_id; - to_chip_ids[InstOutChipType::RAMStore as usize] = ram_store_id; - to_chip_ids[InstOutChipType::ROMInput as usize] = rom_id; - - circuit_builder.configure(); - Ok(BBStartCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: BBStartLayout { - from_witness: FromWitness { - phase_ids: vec![phase0_wire_id], - }, - to_chip_ids, - to_succ_inst: ToSuccInst { - next_memory_ts_id: out_memory_ts_id, - stack_result_ids, - }, - to_bb_final: ToBBFinal { - stack_ts_id: out_stack_ts_id, - stack_top_id: out_stack_top_id, - clk_id: out_clk_id, - }, - }, - }) - } -} diff --git a/singer-pro/src/basic_block/utils.rs b/singer-pro/src/basic_block/utils.rs deleted file mode 100644 index be29c1ad2..000000000 --- a/singer-pro/src/basic_block/utils.rs +++ /dev/null @@ -1,113 +0,0 @@ -use gkr_graph::structs::NodeOutputType; -use itertools::Itertools; - -use crate::component::ToSuccInst; - -use super::BasicBlockInfo; - -pub(super) struct BasicBlockStack { - pub(super) stack: Vec, - pub(super) info: BasicBlockInfo, -} - -impl BasicBlockStack { - pub(super) fn initialize( - info: BasicBlockInfo, - bb_start_node_id: usize, - bb_to_succ: &ToSuccInst, - ) -> Self { - let mut stack = - vec![NodeOutputType::OutputLayer(0); -info.bb_start_stack_top_offsets[0] as usize]; - let stack_top = stack.len() as i64; - bb_to_succ - .stack_result_ids - .iter() - .zip(info.bb_start_stack_top_offsets.iter().rev()) - .for_each(|(&wire_id, &offset)| { - stack[(stack_top + offset) as usize] = - NodeOutputType::WireOut(bb_start_node_id, wire_id); - }); - Self { stack, info } - } - - pub(super) fn finalize(self) -> Vec { - let stack_top = self.stack.len() as i64; - self.info - .bb_final_stack_top_offsets - .iter() - .rev() - .map(|&offset| self.stack[(stack_top + offset) as usize]) - .collect() - } - - pub(super) fn pop_node_outputs(&mut self, mode: StackOpMode) -> Vec { - match mode { - StackOpMode::PopPush(n, _) => (0..n).map(|_| self.stack.pop().unwrap()).collect_vec(), - StackOpMode::Swap(n) => { - vec![ - self.stack[self.stack.len() - 1], - self.stack[self.stack.len() - n - 1], - ] - } - StackOpMode::Dup(n) => { - vec![self.stack[self.stack.len() - n]] - } - } - } - - pub(super) fn push_node_outputs(&mut self, curr: Vec, mode: StackOpMode) { - let stack_top = self.stack.len(); - match mode { - StackOpMode::PopPush(_, n) => { - assert_eq!(curr.len(), n); - curr.into_iter().for_each(|pred| { - self.stack.push(pred); - }); - } - StackOpMode::Swap(n) => { - assert_eq!(curr.len(), 2); - self.stack.swap(stack_top - 1, stack_top - n - 1); - } - StackOpMode::Dup(n) => { - assert_eq!(curr.len(), 2); - self.stack[stack_top - n] = curr[1]; - self.stack.push(curr[0]); - } - } - } -} - -#[derive(Clone, Copy, Debug)] -pub(super) enum StackOpMode { - PopPush(usize, usize), - Swap(usize), - Dup(usize), -} - -// implement From from u8 -impl From for StackOpMode { - fn from(opcode: u8) -> Self { - match opcode { - 0x01 => Self::PopPush(2, 1), // ADD - 0x11 => Self::PopPush(2, 1), // GT - 0x35 => Self::PopPush(1, 1), // CALLDATALOAD - 0x50 => Self::PopPush(1, 0), // POP - 0x52 => Self::PopPush(2, 0), // MSTORE - 0x56 => Self::PopPush(1, 0), // JUMP - 0x57 => Self::PopPush(2, 0), // JUMPI - 0x80 => Self::Dup(1), // DUP1 - 0x81 => Self::Dup(2), // DUP2 - 0x91 => Self::Swap(2), // SWAP2 - 0x93 => Self::Swap(4), // SWAP4 - 0xF3 => Self::PopPush(2, 0), // RETURN - _ => unimplemented!(), - } - } -} - -pub(crate) fn lower_bound(sorted_vec: &[i64], target: i64) -> usize { - match sorted_vec.binary_search(&target) { - Ok(index) => index, - Err(index) => index, - } -} diff --git a/singer-pro/src/component.rs b/singer-pro/src/component.rs deleted file mode 100644 index 12492f855..000000000 --- a/singer-pro/src/component.rs +++ /dev/null @@ -1,194 +0,0 @@ -use ff_ext::ExtensionField; -use gkr::structs::Circuit; -use gkr_graph::structs::{NodeOutputType, PredType}; -use simple_frontend::structs::WitnessId; -use singer_utils::constants::OpcodeType; -use std::sync::Arc; - -#[derive(Clone, Debug)] -pub struct InstCircuit { - pub(crate) circuit: Arc>, - pub(crate) layout: InstLayout, -} - -pub(crate) type ToChipsWires = Vec>; - -#[derive(Clone, Debug, Default)] -pub struct InstLayout { - // Input and output wires. - pub(crate) from_witness: FromWitness, - pub(crate) from_pred_inst: FromPredInst, - pub(crate) from_public_io: Option, - - pub(crate) to_succ_inst: ToSuccInst, - pub(crate) to_chip_ids: ToChipsWires, - pub(crate) to_bb_final: Option, - - pub(crate) to_acc_ooo: Option, - pub(crate) to_acc_dup: Option, -} - -impl InstLayout { - pub fn input( - &self, - n_wires_in: usize, - opcode: u8, - stack: Vec, - memory_ts: NodeOutputType, - ) -> Vec { - let mut input = vec![PredType::Source; n_wires_in]; - if opcode == OpcodeType::RETURN as u8 { - self.from_pred_inst - .stack_operand_ids - .iter() - .enumerate() - .for_each(|(i, &wire_id)| { - input[wire_id as usize] = PredType::PredWireDup(stack[i]); - }); - input[self.from_pred_inst.memory_ts_id as usize] = PredType::PredWireDup(memory_ts); - } else { - self.from_pred_inst - .stack_operand_ids - .iter() - .enumerate() - .for_each(|(i, &wire_id)| { - input[wire_id as usize] = PredType::PredWire(stack[i]); - }); - input[self.from_pred_inst.memory_ts_id as usize] = PredType::PredWire(memory_ts); - } - input - } -} - -#[derive(Clone, Debug)] -pub struct BBStartCircuit { - pub(crate) circuit: Arc>, - pub(crate) layout: BBStartLayout, -} - -#[derive(Clone, Debug)] -pub struct BBStartLayout { - pub(crate) from_witness: FromWitness, - - pub(crate) to_succ_inst: ToSuccInst, - pub(crate) to_bb_final: ToBBFinal, - pub(crate) to_chip_ids: ToChipsWires, -} - -#[derive(Clone, Debug)] -pub struct BBFinalCircuit { - pub(crate) circuit: Arc>, - pub(crate) layout: BBFinalLayout, -} - -#[derive(Clone, Debug)] -pub struct BBFinalLayout { - pub(crate) from_witness: FromWitness, - pub(crate) from_bb_start: FromBBStart, - pub(crate) from_pred_inst: FromPredInst, - pub(crate) next_pc_id: Option, - - pub(crate) to_chip_ids: ToChipsWires, -} - -impl BBFinalLayout { - pub fn input( - &self, - n_wires_in: usize, - stack: Vec, - stack_ts: NodeOutputType, - memory_ts: NodeOutputType, - stack_top: NodeOutputType, - clk: NodeOutputType, - next_pc: Option, - ) -> Vec { - let mut input = vec![PredType::Source; n_wires_in]; - self.from_pred_inst - .stack_operand_ids - .iter() - .enumerate() - .for_each(|(i, &wire_id)| { - input[wire_id as usize] = PredType::PredWire(stack[i]); - }); - input[self.from_bb_start.stack_ts_id as usize] = PredType::PredWire(stack_ts); - input[self.from_pred_inst.memory_ts_id as usize] = PredType::PredWire(memory_ts); - input[self.from_bb_start.stack_top_id as usize] = PredType::PredWire(stack_top); - input[self.from_bb_start.clk_id as usize] = PredType::PredWire(clk); - // TODO: Incorrect - if let (Some(next_pc_id), Some(next_pc)) = (self.next_pc_id.as_ref(), next_pc) { - input[*next_pc_id as usize] = PredType::PredWire(next_pc); - } - input - } -} - -#[derive(Clone, Debug)] -pub struct AccessoryCircuit { - pub(crate) circuit: Arc>, - pub(crate) layout: AccessoryLayout, -} - -#[derive(Clone, Debug)] -pub struct AccessoryLayout { - pub(crate) from_witness: FromWitness, - pub(crate) from_pred_ooo: Option, - pub(crate) from_pred_dup: Option, - pub(crate) to_chip_ids: ToChipsWires, -} - -impl AccessoryLayout { - pub fn input( - &self, - from_pred_ooo_id: Option, - from_pred_dup_id: Option, - ) -> Vec { - let n_wires_in = self.from_witness.phase_ids.len() - + self.from_pred_ooo.map_or(0, |_| 1) - + self.from_pred_dup.map_or(0, |_| 1); - let mut input = vec![PredType::Source; n_wires_in]; - if let Some(wire_id) = self.from_pred_ooo { - input[wire_id as usize] = PredType::PredWire(from_pred_ooo_id.unwrap()); - } - if let Some(wire_id) = self.from_pred_dup { - input[wire_id as usize] = PredType::PredWireDup(from_pred_dup_id.unwrap()); - } - input - } -} - -#[derive(Clone, Debug, Default)] -pub(crate) struct FromWitness { - pub(crate) phase_ids: Vec, -} - -#[derive(Clone, Copy, Debug, Default)] -pub(crate) struct FromBBStart { - pub(crate) stack_top_id: WitnessId, - pub(crate) stack_ts_id: WitnessId, - pub(crate) clk_id: WitnessId, -} - -#[derive(Clone, Debug, Default)] -pub(crate) struct FromPredInst { - pub(crate) memory_ts_id: WitnessId, - pub(crate) stack_operand_ids: Vec, -} - -/// From public output. This is used in the return instruction. -#[derive(Clone, Debug, Default)] -pub(crate) struct FromPublicIO { - pub(crate) public_output_id: WitnessId, -} - -#[derive(Clone, Debug, Default)] -pub(crate) struct ToSuccInst { - pub(crate) next_memory_ts_id: WitnessId, - pub(crate) stack_result_ids: Vec, -} - -#[derive(Clone, Debug, Default)] -pub(crate) struct ToBBFinal { - pub(crate) stack_ts_id: WitnessId, - pub(crate) stack_top_id: WitnessId, - pub(crate) clk_id: WitnessId, -} diff --git a/singer-pro/src/error.rs b/singer-pro/src/error.rs deleted file mode 100644 index 2cca597a9..000000000 --- a/singer-pro/src/error.rs +++ /dev/null @@ -1,22 +0,0 @@ -use gkr_graph::error::GKRGraphError; -use singer_utils::error::UtilError; - -#[derive(Debug)] -pub enum ZKVMError { - CircuitError, - GKRGraphError(GKRGraphError), - VerifyError, - UtilError(UtilError), -} - -impl From for ZKVMError { - fn from(error: GKRGraphError) -> Self { - Self::GKRGraphError(error) - } -} - -impl From for ZKVMError { - fn from(error: UtilError) -> Self { - Self::UtilError(error) - } -} diff --git a/singer-pro/src/instructions.rs b/singer-pro/src/instructions.rs deleted file mode 100644 index 9a55475a5..000000000 --- a/singer-pro/src/instructions.rs +++ /dev/null @@ -1,218 +0,0 @@ -use std::{collections::HashMap, mem}; - -use ff_ext::ExtensionField; -use gkr_graph::structs::{CircuitGraphBuilder, NodeOutputType, PredType}; -use itertools::Itertools; -use singer_utils::{chips::SingerChipBuilder, constants::OpcodeType, structs::ChipChallenges}; - -use crate::{ - component::{AccessoryCircuit, InstCircuit}, - error::ZKVMError, - CircuitWitnessIn, SingerParams, -}; - -use self::{ - add::AddInstruction, calldataload::CalldataloadInstruction, gt::GtInstruction, - jump::JumpInstruction, jumpi::JumpiInstruction, mstore::MstoreInstruction, -}; - -// arithmetic -pub mod add; - -// bitwise -pub mod gt; - -// control -pub mod jump; -pub mod jumpi; - -// memory -pub mod mstore; - -// system -pub mod calldataload; -pub mod ret; - -pub mod unknown; - -#[derive(Clone, Debug)] -pub struct SingerInstCircuitBuilder { - /// Opcode circuits - pub(crate) insts_circuits: HashMap, Vec>)>, - pub(crate) challenges: ChipChallenges, -} - -impl SingerInstCircuitBuilder { - pub fn new(challenges: ChipChallenges) -> Result { - let mut insts_circuits = HashMap::new(); - insts_circuits.insert(0x01, AddInstruction::construct_circuits(challenges)?); - insts_circuits.insert(0x11, GtInstruction::construct_circuits(challenges)?); - insts_circuits.insert( - 0x35, - CalldataloadInstruction::construct_circuits(challenges)?, - ); - insts_circuits.insert(0x52, MstoreInstruction::construct_circuits(challenges)?); - insts_circuits.insert(0x56, JumpInstruction::construct_circuits(challenges)?); - insts_circuits.insert(0x57, JumpiInstruction::construct_circuits(challenges)?); - - Ok(Self { - insts_circuits, - challenges, - }) - } -} - -pub(crate) fn construct_inst_graph_and_witness( - opcode: u8, - graph_builder: &mut CircuitGraphBuilder, - chip_builder: &mut SingerChipBuilder, - inst_circuit: &InstCircuit, - acc_circuits: &[AccessoryCircuit], - preds: Vec, - sources: Vec>, - real_challenges: &[E], - real_n_instances: usize, - params: &SingerParams, -) -> Result<(Vec, Vec, Option), ZKVMError> { - let method = match opcode { - 0x01 => AddInstruction::construct_graph_and_witness, - 0x11 => GtInstruction::construct_graph_and_witness, - 0x35 => CalldataloadInstruction::construct_graph_and_witness, - 0x52 => MstoreInstruction::construct_graph_and_witness, - 0x56 => JumpInstruction::construct_graph_and_witness, - 0x57 => JumpiInstruction::construct_graph_and_witness, - _ => unknown::UnknownInstruction::construct_graph_and_witness, - }; - method( - graph_builder, - chip_builder, - inst_circuit, - acc_circuits, - preds, - sources, - real_challenges, - real_n_instances, - params, - ) -} - -pub(crate) fn construct_inst_graph( - opcode: u8, - graph_builder: &mut CircuitGraphBuilder, - chip_builder: &mut SingerChipBuilder, - inst_circuit: &InstCircuit, - acc_circuits: &[AccessoryCircuit], - preds: Vec, - real_n_instances: usize, - params: &SingerParams, -) -> Result<(Vec, Vec, Option), ZKVMError> { - let method = match opcode { - 0x01 => AddInstruction::construct_graph, - 0x11 => GtInstruction::construct_graph, - 0x35 => CalldataloadInstruction::construct_graph, - 0x52 => MstoreInstruction::construct_graph, - 0x56 => JumpInstruction::construct_graph, - 0x57 => JumpiInstruction::construct_graph, - _ => unknown::UnknownInstruction::construct_graph, - }; - method( - graph_builder, - chip_builder, - inst_circuit, - acc_circuits, - preds, - real_n_instances, - params, - ) -} - -pub(crate) trait Instruction { - const OPCODE: OpcodeType; - const NAME: &'static str; - fn construct_circuit(challenges: ChipChallenges) -> Result, ZKVMError>; -} - -/// Construct the part of the circuit graph for an instruction. -pub(crate) trait InstructionGraph { - type InstType: Instruction; - - /// Construct instruction circuits and its extensions. Mostly there is no - /// extensions. - fn construct_circuits( - challenges: ChipChallenges, - ) -> Result<(InstCircuit, Vec>), ZKVMError> { - Ok((Self::InstType::construct_circuit(challenges)?, vec![])) - } - - /// Add instruction circuits, accessories and witnesses to the graph. - /// Besides, Generate the tree-structured circuit to compute the product or - /// fraction summation of the chip check wires. - fn construct_graph_and_witness( - graph_builder: &mut CircuitGraphBuilder, - chip_builder: &mut SingerChipBuilder, - inst_circuit: &InstCircuit, - _acc_circuits: &[AccessoryCircuit], - preds: Vec, - mut sources: Vec>, - real_challenges: &[E], - real_n_instances: usize, - _params: &SingerParams, - ) -> Result<(Vec, Vec, Option), ZKVMError> { - let node_id = graph_builder.add_node_with_witness( - >::NAME, - &inst_circuit.circuit, - preds, - real_challenges.to_vec(), - mem::take(&mut sources[0]), - real_n_instances.next_power_of_two(), - )?; - let stack = inst_circuit - .layout - .to_succ_inst - .stack_result_ids - .iter() - .map(|&wire_id| NodeOutputType::WireOut(node_id, wire_id)) - .collect_vec(); - chip_builder.construct_chip_check_graph_and_witness( - graph_builder, - node_id, - &inst_circuit.layout.to_chip_ids, - real_challenges, - real_n_instances, - )?; - Ok((vec![node_id], stack, None)) - } - - /// Add instruction circuits and accessories to the graph. Besides, Generate - /// the tree-structured circuit to compute the product or fraction summation - /// of the chip check wires. - fn construct_graph( - graph_builder: &mut CircuitGraphBuilder, - chip_builder: &mut SingerChipBuilder, - inst_circuit: &InstCircuit, - _acc_circuits: &[AccessoryCircuit], - preds: Vec, - real_n_instances: usize, - _params: &SingerParams, - ) -> Result<(Vec, Vec, Option), ZKVMError> { - let node_id = graph_builder.add_node( - >::NAME, - &inst_circuit.circuit, - preds, - )?; - let stack = inst_circuit - .layout - .to_succ_inst - .stack_result_ids - .iter() - .map(|&wire_id| NodeOutputType::WireOut(node_id, wire_id)) - .collect_vec(); - chip_builder.construct_chip_check_graph( - graph_builder, - node_id, - &inst_circuit.layout.to_chip_ids, - real_n_instances, - )?; - Ok((vec![node_id], stack, None)) - } -} diff --git a/singer-pro/src/instructions/add.rs b/singer-pro/src/instructions/add.rs deleted file mode 100644 index 386c94d72..000000000 --- a/singer-pro/src/instructions/add.rs +++ /dev/null @@ -1,102 +0,0 @@ -use ff_ext::ExtensionField; -use gkr::structs::Circuit; -use paste::paste; -use simple_frontend::structs::CircuitBuilder; -use singer_utils::{ - chip_handler::{ - bytecode::BytecodeChip, global_state::GlobalStateChip, range::RangeChip, - rom_handler::ROMHandler, stack::StackChip, ChipHandler, - }, - chips::IntoEnumIterator, - constants::OpcodeType, - register_witness, - structs::{ChipChallenges, InstOutChipType, StackUInt, TSUInt}, - uint::constants::AddSubConstants, -}; -use std::{cell::RefCell, collections::BTreeMap, rc::Rc, sync::Arc}; - -use crate::{ - component::{FromPredInst, FromWitness, InstCircuit, InstLayout, ToSuccInst}, - error::ZKVMError, - utils::add_assign_each_cell, -}; - -use super::{Instruction, InstructionGraph}; - -pub struct AddInstruction; - -impl InstructionGraph for AddInstruction { - type InstType = Self; -} - -register_witness!( - AddInstruction, - phase0 { - // Witness for addend_0 + addend_1 - instruction_add => AddSubConstants::::N_WITNESS_CELLS - } -); - -impl Instruction for AddInstruction { - const OPCODE: OpcodeType = OpcodeType::ADD; - const NAME: &'static str = "ADD"; - fn construct_circuit(challenges: ChipChallenges) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - - // From witness - let (phase0_wire_id, phase0) = circuit_builder.create_witness_in(Self::phase0_size()); - - // From predesessor instruction - let (memory_ts_id, memory_ts) = circuit_builder.create_witness_in(TSUInt::N_OPERAND_CELLS); - let (addend_0_id, addend_0) = circuit_builder.create_witness_in(StackUInt::N_OPERAND_CELLS); - let (addend_1_id, addend_1) = circuit_builder.create_witness_in(StackUInt::N_OPERAND_CELLS); - - let mut chip_handler = ChipHandler::new(challenges.clone()); - - // Execution result = addend0 + addend1, with carry. - let addend_0 = addend_0.try_into()?; - let addend_1 = addend_1.try_into()?; - let result = StackUInt::add( - &mut circuit_builder, - &mut chip_handler, - &addend_0, - &addend_1, - &phase0[Self::phase0_instruction_add()], - )?; - // To successor instruction - let stack_result_id = circuit_builder.create_witness_out_from_cells(result.values()); - let (next_memory_ts_id, next_memory_ts) = - circuit_builder.create_witness_out(TSUInt::N_OPERAND_CELLS); - add_assign_each_cell(&mut circuit_builder, &next_memory_ts, &memory_ts); - - // To chips - let (_, _, rom_id) = chip_handler.finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::ROMInput as usize] = rom_id; - - Ok(InstCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: InstLayout { - from_pred_inst: FromPredInst { - memory_ts_id, - stack_operand_ids: vec![addend_0_id, addend_1_id], - }, - from_witness: FromWitness { - phase_ids: vec![phase0_wire_id], - }, - from_public_io: None, - - to_chip_ids, - to_succ_inst: ToSuccInst { - next_memory_ts_id, - stack_result_ids: vec![stack_result_id], - }, - to_bb_final: None, - to_acc_dup: None, - to_acc_ooo: None, - }, - }) - } -} diff --git a/singer-pro/src/instructions/calldataload.rs b/singer-pro/src/instructions/calldataload.rs deleted file mode 100644 index 70b77faef..000000000 --- a/singer-pro/src/instructions/calldataload.rs +++ /dev/null @@ -1,90 +0,0 @@ -use ff_ext::ExtensionField; -use gkr::structs::Circuit; -use paste::paste; -use simple_frontend::structs::CircuitBuilder; -use singer_utils::{ - chip_handler::{calldata::CalldataChip, ChipHandler}, - chips::IntoEnumIterator, - constants::OpcodeType, - register_witness, - structs::{ChipChallenges, InstOutChipType, StackUInt, TSUInt, UInt64}, -}; -use std::{cell::RefCell, collections::BTreeMap, rc::Rc, sync::Arc}; - -use crate::{ - component::{FromPredInst, FromWitness, InstCircuit, InstLayout, ToSuccInst}, - error::ZKVMError, - utils::add_assign_each_cell, -}; - -use super::{Instruction, InstructionGraph}; - -impl InstructionGraph for CalldataloadInstruction { - type InstType = Self; -} - -pub struct CalldataloadInstruction; - -register_witness!( - CalldataloadInstruction, - phase0 { - data => StackUInt::N_OPERAND_CELLS - } -); - -impl Instruction for CalldataloadInstruction { - const OPCODE: OpcodeType = OpcodeType::CALLDATALOAD; - const NAME: &'static str = "CALLDATALOAD"; - fn construct_circuit(challenges: ChipChallenges) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - - // From witness - let (phase0_wire_id, phase0) = circuit_builder.create_witness_in(Self::phase0_size()); - // From predesessor instruction - let (memory_ts_id, memory_ts) = circuit_builder.create_witness_in(TSUInt::N_OPERAND_CELLS); - let (offset_id, offset) = circuit_builder.create_witness_in(UInt64::N_OPERAND_CELLS); - - let mut chip_handler = ChipHandler::new(challenges.clone()); - - // CallDataLoad check (offset, data) - let data = &phase0[Self::phase0_data()]; - CalldataChip::load(&mut chip_handler, &mut circuit_builder, &offset, data); - - // To successor instruction - let (data_copy_id, data_copy) = circuit_builder.create_witness_out(data.len()); - add_assign_each_cell(&mut circuit_builder, &data_copy, &data); - let (next_memory_ts_id, next_memory_ts) = - circuit_builder.create_witness_out(TSUInt::N_OPERAND_CELLS); - add_assign_each_cell(&mut circuit_builder, &next_memory_ts, &memory_ts); - - // To chips - let (_, _, rom_id) = chip_handler.finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::ROMInput as usize] = rom_id; - - Ok(InstCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: InstLayout { - from_pred_inst: FromPredInst { - memory_ts_id, - stack_operand_ids: vec![offset_id], - }, - from_witness: FromWitness { - phase_ids: vec![phase0_wire_id], - }, - from_public_io: None, - - to_chip_ids, - to_succ_inst: ToSuccInst { - next_memory_ts_id, - stack_result_ids: vec![data_copy_id], - }, - to_bb_final: None, - to_acc_dup: None, - to_acc_ooo: None, - }, - }) - } -} diff --git a/singer-pro/src/instructions/gt.rs b/singer-pro/src/instructions/gt.rs deleted file mode 100644 index 5908b1bfd..000000000 --- a/singer-pro/src/instructions/gt.rs +++ /dev/null @@ -1,104 +0,0 @@ -use ff_ext::ExtensionField; -use gkr::structs::Circuit; -use paste::paste; -use simple_frontend::structs::CircuitBuilder; -use singer_utils::{ - chip_handler::{range::RangeChip, rom_handler::ROMHandler, ChipHandler}, - chips::IntoEnumIterator, - constants::OpcodeType, - register_witness, - structs::{ChipChallenges, InstOutChipType, StackUInt, TSUInt}, - uint::constants::AddSubConstants, -}; -use std::{cell::RefCell, collections::BTreeMap, rc::Rc, sync::Arc}; - -use crate::{ - component::{FromPredInst, FromWitness, InstCircuit, InstLayout, ToSuccInst}, - error::ZKVMError, - utils::add_assign_each_cell, -}; - -use super::{Instruction, InstructionGraph}; -pub struct GtInstruction; - -impl InstructionGraph for GtInstruction { - type InstType = Self; -} -register_witness!( - GtInstruction, - phase0 { - // Witness for operand_0 > operand_1 - instruction_gt => AddSubConstants::::N_WITNESS_CELLS - } -); - -impl Instruction for GtInstruction { - const OPCODE: OpcodeType = OpcodeType::GT; - const NAME: &'static str = "GT"; - fn construct_circuit(challenges: ChipChallenges) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - - // From witness - let (phase0_wire_id, phase0) = circuit_builder.create_witness_in(Self::phase0_size()); - - // From predesessor instruction - let (memory_ts_id, memory_ts) = circuit_builder.create_witness_in(TSUInt::N_OPERAND_CELLS); - let (operand_0_id, operand_0) = - circuit_builder.create_witness_in(StackUInt::N_OPERAND_CELLS); - let (operand_1_id, operand_1) = - circuit_builder.create_witness_in(StackUInt::N_OPERAND_CELLS); - - let mut chip_handler = ChipHandler::new(challenges.clone()); - - // Execution operand_1 > operand_0. - let operand_0 = operand_0.try_into()?; - let operand_1 = operand_1.try_into()?; - let (result, _) = StackUInt::lt( - &mut circuit_builder, - &mut chip_handler, - &operand_0, - &operand_1, - &phase0[Self::phase0_instruction_gt()], - )?; - let result = [ - vec![result], - circuit_builder.create_cells(StackUInt::N_OPERAND_CELLS - 1), - ] - .concat(); - // To successor instruction - let stack_result_id = circuit_builder.create_witness_out_from_cells(&result); - let (next_memory_ts_id, next_memory_ts) = - circuit_builder.create_witness_out(TSUInt::N_OPERAND_CELLS); - add_assign_each_cell(&mut circuit_builder, &next_memory_ts, &memory_ts); - - // To chips - let (_, _, rom_id) = chip_handler.finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::ROMInput as usize] = rom_id; - - Ok(InstCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: InstLayout { - from_pred_inst: FromPredInst { - memory_ts_id, - stack_operand_ids: vec![operand_0_id, operand_1_id], - }, - from_witness: FromWitness { - phase_ids: vec![phase0_wire_id], - }, - from_public_io: None, - - to_chip_ids, - to_succ_inst: ToSuccInst { - next_memory_ts_id, - stack_result_ids: vec![stack_result_id], - }, - to_bb_final: None, - to_acc_dup: None, - to_acc_ooo: None, - }, - }) - } -} diff --git a/singer-pro/src/instructions/jump.rs b/singer-pro/src/instructions/jump.rs deleted file mode 100644 index fd3919de9..000000000 --- a/singer-pro/src/instructions/jump.rs +++ /dev/null @@ -1,66 +0,0 @@ -use ff_ext::ExtensionField; -use gkr::structs::Circuit; -use simple_frontend::structs::CircuitBuilder; -use singer_utils::{ - chips::IntoEnumIterator, - constants::OpcodeType, - structs::{ChipChallenges, InstOutChipType, StackUInt, TSUInt}, -}; -use std::sync::Arc; - -use super::{Instruction, InstructionGraph}; -use crate::{ - component::{FromPredInst, FromWitness, InstCircuit, InstLayout, ToSuccInst}, - error::ZKVMError, - utils::add_assign_each_cell, -}; - -pub struct JumpInstruction; - -impl InstructionGraph for JumpInstruction { - type InstType = Self; -} - -impl Instruction for JumpInstruction { - const OPCODE: OpcodeType = OpcodeType::JUMP; - const NAME: &'static str = "JUMP"; - fn construct_circuit(_: ChipChallenges) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - // From predesessor instruction - let (memory_ts_id, memory_ts) = circuit_builder.create_witness_in(TSUInt::N_OPERAND_CELLS); - let (next_pc_id, next_pc) = circuit_builder.create_witness_in(StackUInt::N_OPERAND_CELLS); - - // To BB final - let (next_pc_copy_id, next_pc_copy) = circuit_builder.create_witness_out(next_pc.len()); - add_assign_each_cell(&mut circuit_builder, &next_pc_copy, &next_pc); - - // To Succesor instruction - let (next_memory_ts_id, next_memory_ts) = - circuit_builder.create_witness_out(TSUInt::N_OPERAND_CELLS); - add_assign_each_cell(&mut circuit_builder, &next_memory_ts, &memory_ts); - - // To chips - let to_chip_ids = vec![None; InstOutChipType::iter().count()]; - circuit_builder.configure(); - - Ok(InstCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: InstLayout { - from_pred_inst: FromPredInst { - memory_ts_id, - stack_operand_ids: vec![next_pc_id], - }, - from_witness: FromWitness { phase_ids: vec![] }, - from_public_io: None, - to_chip_ids, - to_succ_inst: ToSuccInst { - next_memory_ts_id, - stack_result_ids: vec![], - }, - to_bb_final: Some(next_pc_copy_id), - to_acc_dup: None, - to_acc_ooo: None, - }, - }) - } -} diff --git a/singer-pro/src/instructions/jumpi.rs b/singer-pro/src/instructions/jumpi.rs deleted file mode 100644 index 032ce7100..000000000 --- a/singer-pro/src/instructions/jumpi.rs +++ /dev/null @@ -1,145 +0,0 @@ -use ff::Field; -use ff_ext::ExtensionField; -use gkr::structs::Circuit; -use itertools::izip; -use paste::paste; -use simple_frontend::structs::{CircuitBuilder, MixedCell}; -use singer_utils::{ - chip_handler::{ - bytecode::BytecodeChip, range::RangeChip, rom_handler::ROMHandler, ChipHandler, - }, - chips::IntoEnumIterator, - constants::OpcodeType, - register_witness, - structs::{ChipChallenges, InstOutChipType, PCUInt, StackUInt, TSUInt}, -}; -use std::{cell::RefCell, collections::BTreeMap, rc::Rc, sync::Arc}; - -use crate::{ - component::{FromPredInst, FromWitness, InstCircuit, InstLayout, ToSuccInst}, - error::ZKVMError, - utils::add_assign_each_cell, -}; - -use super::{Instruction, InstructionGraph}; - -pub struct JumpiInstruction; - -impl InstructionGraph for JumpiInstruction { - type InstType = Self; -} - -register_witness!( - JumpiInstruction, - phase0 { - pc_plus_1 => PCUInt::N_OPERAND_CELLS, - pc_plus_1_opcode => 1, - cond_values_inv => StackUInt::N_OPERAND_CELLS, - cond_non_zero_or_inv => 1 - } -); - -impl Instruction for JumpiInstruction { - const OPCODE: OpcodeType = OpcodeType::JUMPI; - const NAME: &'static str = "JUMPI"; - fn construct_circuit(challenges: ChipChallenges) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - - // From witness - let (phase0_wire_id, phase0) = circuit_builder.create_witness_in(Self::phase0_size()); - - // From predesessor instruction - let (memory_ts_id, memory_ts) = circuit_builder.create_witness_in(TSUInt::N_OPERAND_CELLS); - let (dest_id, dest) = circuit_builder.create_witness_in(StackUInt::N_OPERAND_CELLS); - let (cond_values_id, cond_values) = - circuit_builder.create_witness_in(StackUInt::N_OPERAND_CELLS); - - let mut chip_handler = ChipHandler::new(challenges.clone()); - - // Execution, cond_values_non_zero[i] = [cond_values[i] != 0] - let cond_values_inv = &phase0[Self::phase0_cond_values_inv()]; - let mut cond_values_non_zero = Vec::new(); - for (val, wit) in izip!(cond_values, cond_values_inv) { - cond_values_non_zero.push(RangeChip::non_zero( - &mut chip_handler, - &mut circuit_builder, - val, - *wit, - )?); - } - // cond_non_zero = [summation of cond_values_non_zero[i] != 0] - let non_zero_or = circuit_builder.create_cell(); - cond_values_non_zero - .iter() - .for_each(|x| circuit_builder.add(non_zero_or, *x, E::BaseField::ONE)); - let cond_non_zero_or_inv = phase0[Self::phase0_cond_non_zero_or_inv().start]; - let cond_non_zero = RangeChip::non_zero( - &mut chip_handler, - &mut circuit_builder, - non_zero_or, - cond_non_zero_or_inv, - )?; - - // If cond_non_zero, next_pc = dest, otherwise, pc = pc + 1 - let pc_plus_1 = &phase0[Self::phase0_pc_plus_1()]; - let (next_pc_id, next_pc) = circuit_builder.create_witness_out(PCUInt::N_OPERAND_CELLS); - for i in 0..PCUInt::N_OPERAND_CELLS { - circuit_builder.select(next_pc[i], pc_plus_1[i], dest[i], cond_non_zero); - } - - // If cond_non_zero, next_opcode = JUMPDEST, otherwise, opcode = pc + 1 opcode - let pc_plus_1_opcode = phase0[Self::phase0_pc_plus_1_opcode().start]; - let next_opcode = circuit_builder.create_cell(); - circuit_builder.sel_mixed( - next_opcode, - pc_plus_1_opcode.into(), - MixedCell::Constant(E::BaseField::from(OpcodeType::JUMPDEST as u64)), - cond_non_zero, - ); - // Check (next_pc, next_opcode) is a valid instruction - BytecodeChip::bytecode_with_pc_byte( - &mut chip_handler, - &mut circuit_builder, - &next_pc, - next_opcode, - ); - - // To successor instruction - let (next_memory_ts_id, next_memory_ts) = - circuit_builder.create_witness_out(TSUInt::N_OPERAND_CELLS); - add_assign_each_cell(&mut circuit_builder, &next_memory_ts, &memory_ts); - - let (_, _, rom_id) = chip_handler.finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::RAMLoad as usize] = None; - to_chip_ids[InstOutChipType::RAMStore as usize] = None; - to_chip_ids[InstOutChipType::ROMInput as usize] = rom_id; - - circuit_builder.configure(); - - Ok(InstCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: InstLayout { - from_pred_inst: FromPredInst { - memory_ts_id, - stack_operand_ids: vec![dest_id, cond_values_id], - }, - from_witness: FromWitness { - phase_ids: vec![phase0_wire_id], - }, - from_public_io: None, - - to_chip_ids, - to_succ_inst: ToSuccInst { - next_memory_ts_id, - stack_result_ids: vec![], - }, - to_bb_final: Some(next_pc_id), - to_acc_dup: None, - to_acc_ooo: None, - }, - }) - } -} diff --git a/singer-pro/src/instructions/mstore.rs b/singer-pro/src/instructions/mstore.rs deleted file mode 100644 index a9e2fa648..000000000 --- a/singer-pro/src/instructions/mstore.rs +++ /dev/null @@ -1,302 +0,0 @@ -use ff_ext::ExtensionField; -use gkr::structs::Circuit; -use gkr_graph::structs::{CircuitGraphBuilder, NodeOutputType, PredType}; -use itertools::Itertools; -use paste::paste; -use simple_frontend::structs::CircuitBuilder; -use singer_utils::{ - chip_handler::{ - bytecode::BytecodeChip, global_state::GlobalStateChip, memory::MemoryChip, - ram_handler::RAMHandler, range::RangeChip, rom_handler::ROMHandler, stack::StackChip, - ChipHandler, - }, - chips::{IntoEnumIterator, SingerChipBuilder}, - constants::{OpcodeType, EVM_STACK_BYTE_WIDTH}, - register_witness, - structs::{ChipChallenges, InstOutChipType, StackUInt, TSUInt}, - uint::constants::AddSubConstants, -}; -use std::{cell::RefCell, collections::BTreeMap, mem, rc::Rc, sync::Arc}; - -use crate::{ - component::{ - AccessoryCircuit, AccessoryLayout, FromPredInst, FromWitness, InstCircuit, InstLayout, - ToSuccInst, - }, - error::ZKVMError, - utils::add_assign_each_cell, - CircuitWitnessIn, SingerParams, -}; - -use super::{Instruction, InstructionGraph}; - -pub struct MstoreInstruction; - -impl InstructionGraph for MstoreInstruction { - type InstType = Self; - - fn construct_circuits( - challenges: ChipChallenges, - ) -> Result<(InstCircuit, Vec>), ZKVMError> { - Ok(( - Self::InstType::construct_circuit(challenges)?, - vec![MstoreAccessory::construct_circuit(challenges)?], - )) - } - - fn construct_graph_and_witness( - graph_builder: &mut CircuitGraphBuilder, - chip_builder: &mut SingerChipBuilder, - inst_circuit: &InstCircuit, - acc_circuits: &[AccessoryCircuit], - preds: Vec, - mut sources: Vec>, - real_challenges: &[E], - real_n_instances: usize, - _: &SingerParams, - ) -> Result<(Vec, Vec, Option), ZKVMError> { - // Add the instruction circuit to the graph. - let node_id = graph_builder.add_node_with_witness( - stringify!(Self::InstType), - &inst_circuit.circuit, - preds, - real_challenges.to_vec(), - mem::take(&mut sources[0]), - real_n_instances, - )?; - let stack = inst_circuit - .layout - .to_succ_inst - .stack_result_ids - .iter() - .map(|&wire_id| NodeOutputType::WireOut(node_id, wire_id)) - .collect_vec(); - - chip_builder.construct_chip_check_graph_and_witness( - graph_builder, - node_id, - &inst_circuit.layout.to_chip_ids, - real_challenges, - real_n_instances, - )?; - - // Add the memory accessory circuit to the graph. - let preds = acc_circuits[0].layout.input( - inst_circuit - .layout - .to_acc_ooo - .map(|wire_id| NodeOutputType::WireOut(node_id, wire_id)), - inst_circuit - .layout - .to_acc_dup - .map(|wire_id| NodeOutputType::WireOut(node_id, wire_id)), - ); - let acc_node_id = graph_builder.add_node_with_witness( - stringify!(MstoreAccessory), - &acc_circuits[0].circuit, - preds, - real_challenges.to_vec(), - mem::take(&mut sources[1]), - real_n_instances * EVM_STACK_BYTE_WIDTH, - )?; - - chip_builder.construct_chip_check_graph_and_witness( - graph_builder, - acc_node_id, - &acc_circuits[0].layout.to_chip_ids, - real_challenges, - real_n_instances * EVM_STACK_BYTE_WIDTH, - )?; - - Ok((vec![node_id, acc_node_id], stack, None)) - } -} - -register_witness!( - MstoreInstruction, - phase0 { - memory_ts_add => AddSubConstants::::N_WITNESS_CELLS_NO_CARRY_OVERFLOW, - mem_bytes => EVM_STACK_BYTE_WIDTH - } -); - -impl Instruction for MstoreInstruction { - const OPCODE: OpcodeType = OpcodeType::MSTORE; - const NAME: &'static str = "MSTORE"; - fn construct_circuit(challenges: ChipChallenges) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::::new(); - // From witness - let (phase0_wire_id, phase0) = circuit_builder.create_witness_in(Self::phase0_size()); - - // From predesessor instruction - let (memory_ts_id, memory_ts) = circuit_builder.create_witness_in(TSUInt::N_OPERAND_CELLS); - let (offset_id, offset) = circuit_builder.create_witness_in(StackUInt::N_OPERAND_CELLS); - let (mem_value_id, mem_values) = - circuit_builder.create_witness_in(StackUInt::N_OPERAND_CELLS); - - let mut chip_handler = ChipHandler::new(challenges.clone()); - - // Update memory timestamp. - let memory_ts = TSUInt::try_from(memory_ts.as_slice())?; - let next_memory_ts = RangeChip::add_ts_with_const( - &mut chip_handler, - &mut circuit_builder, - &memory_ts, - 1, - &phase0[Self::phase0_memory_ts_add()], - )?; - // To successor instruction - let next_memory_ts_id = - circuit_builder.create_witness_out_from_cells(next_memory_ts.values()); - - // Pop mem_bytes from stack - let mem_bytes = &phase0[Self::phase0_mem_bytes()]; - RangeChip::range_check_bytes(&mut chip_handler, &mut circuit_builder, mem_bytes)?; - - let mem_values = StackUInt::try_from(mem_values.as_slice())?; - let mem_values_from_bytes = - StackUInt::from_bytes_big_endian(&mut circuit_builder, &mem_bytes)?; - StackUInt::assert_eq(&mut circuit_builder, &mem_values_from_bytes, &mem_values)?; - - // To chips. - let (_, _, rom_id) = chip_handler.finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::ROMInput as usize] = rom_id; - - // To accessory circuits. - let (to_acc_dup_id, to_acc_dup) = - circuit_builder.create_witness_out(MstoreAccessory::pred_dup_size()); - add_assign_each_cell( - &mut circuit_builder, - &to_acc_dup[MstoreAccessory::pred_dup_memory_ts()], - next_memory_ts.values(), - ); - add_assign_each_cell( - &mut circuit_builder, - &to_acc_dup[MstoreAccessory::pred_dup_offset()], - &offset, - ); - - let (to_acc_ooo_id, to_acc_ooo) = circuit_builder - .create_witness_out(MstoreAccessory::pred_ooo_size() * EVM_STACK_BYTE_WIDTH); - add_assign_each_cell(&mut circuit_builder, &to_acc_ooo, mem_bytes); - - circuit_builder.configure(); - - Ok(InstCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: InstLayout { - from_pred_inst: FromPredInst { - memory_ts_id, - stack_operand_ids: vec![offset_id, mem_value_id], - }, - - from_witness: FromWitness { - phase_ids: vec![phase0_wire_id], - }, - from_public_io: None, - - to_chip_ids, - to_succ_inst: ToSuccInst { - next_memory_ts_id, - stack_result_ids: vec![], - }, - to_bb_final: None, - to_acc_dup: Some(to_acc_dup_id), - to_acc_ooo: Some(to_acc_ooo_id), - }, - }) - } -} - -pub struct MstoreAccessory; - -register_witness!( - MstoreAccessory, - pred_dup { - memory_ts => TSUInt::N_OPERAND_CELLS, - offset => StackUInt::N_OPERAND_CELLS - }, - pred_ooo { - mem_byte => 1 - }, - phase0 { - old_memory_ts => TSUInt::N_OPERAND_CELLS, - old_memory_ts_lt => AddSubConstants::::N_WITNESS_CELLS, - - offset_add_delta => AddSubConstants::::N_WITNESS_CELLS, - prev_mem_byte => 1 - } -); - -impl MstoreAccessory { - pub fn construct_circuit( - challenges: ChipChallenges, - ) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - - // From predesessor circuit. - let (pred_dup_wire_id, pred_dup) = circuit_builder.create_witness_in(Self::pred_dup_size()); - let (pred_ooo_wire_id, pred_ooo) = circuit_builder.create_witness_in(Self::pred_ooo_size()); - - // From witness. - let (phase0_wire_id, phase0) = circuit_builder.create_witness_in(Self::phase0_size()); - - let mut chip_handler = ChipHandler::new(challenges.clone()); - - // Compute offset, offset + 1, ..., offset + EVM_STACK_BYTE_WIDTH - 1. - // Load previous memory bytes. - let memory_ts = TSUInt::try_from(&pred_dup[Self::pred_dup_memory_ts()])?; - let old_memory_ts = TSUInt::try_from(&phase0[Self::phase0_old_memory_ts()])?; - let old_memory_ts_lt = &phase0[Self::phase0_old_memory_ts_lt()]; - let offset = StackUInt::try_from(&pred_dup[Self::pred_dup_offset()])?; - let offset_add_delta = &phase0[Self::phase0_offset_add_delta()]; - let delta = circuit_builder.create_counter_in(0)[0]; - let offset_plus_delta = StackUInt::add_cell( - &mut circuit_builder, - &mut chip_handler, - &offset, - delta, - offset_add_delta, - )?; - TSUInt::assert_lt( - &mut circuit_builder, - &mut chip_handler, - &old_memory_ts, - &memory_ts, - old_memory_ts_lt, - )?; - - let mem_byte = pred_ooo[Self::pred_ooo_mem_byte().start]; - let prev_mem_byte = phase0[Self::phase0_prev_mem_byte().start]; - MemoryChip::write( - &mut chip_handler, - &mut circuit_builder, - offset_plus_delta.values(), - old_memory_ts.values(), - memory_ts.values(), - prev_mem_byte, - mem_byte, - ); - - let (_, _, rom_id) = chip_handler.finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::ROMInput as usize] = rom_id; - - Ok(AccessoryCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: AccessoryLayout { - from_witness: FromWitness { - phase_ids: vec![phase0_wire_id], - }, - from_pred_dup: Some(pred_dup_wire_id), - from_pred_ooo: Some(pred_ooo_wire_id), - to_chip_ids, - }, - }) - } -} diff --git a/singer-pro/src/instructions/ret.rs b/singer-pro/src/instructions/ret.rs deleted file mode 100644 index 0b5c79ca0..000000000 --- a/singer-pro/src/instructions/ret.rs +++ /dev/null @@ -1,200 +0,0 @@ -use ff_ext::ExtensionField; -use gkr::structs::Circuit; -use gkr_graph::structs::{CircuitGraphBuilder, NodeOutputType, PredType}; -use paste::paste; -use simple_frontend::structs::CircuitBuilder; -use singer_utils::{ - chip_handler::{ - bytecode::BytecodeChip, global_state::GlobalStateChip, ram_handler::RAMHandler, - range::RangeChip, rom_handler::ROMHandler, stack::StackChip, ChipHandler, - }, - chips::{IntoEnumIterator, SingerChipBuilder}, - constants::OpcodeType, - register_witness, - structs::{ChipChallenges, InstOutChipType, StackUInt, TSUInt}, - uint::constants::AddSubConstants, -}; -use std::{cell::RefCell, collections::BTreeMap, mem, rc::Rc, sync::Arc}; - -use crate::{ - component::{ - AccessoryCircuit, FromPredInst, FromPublicIO, FromWitness, InstCircuit, InstLayout, - ToSuccInst, - }, - error::ZKVMError, - utils::add_assign_each_cell, - CircuitWitnessIn, SingerParams, -}; - -use super::{Instruction, InstructionGraph}; -/// This circuit is to load public output from memory, which is a data-parallel -/// circuit load one element in each sub-circuit. -pub struct ReturnInstruction; - -impl InstructionGraph for ReturnInstruction { - type InstType = Self; - - fn construct_graph_and_witness( - graph_builder: &mut CircuitGraphBuilder, - chip_builder: &mut SingerChipBuilder, - inst_circuit: &InstCircuit, - _: &[AccessoryCircuit], - preds: Vec, - mut sources: Vec>, - real_challenges: &[E], - _: usize, - params: &SingerParams, - ) -> Result<(Vec, Vec, Option), ZKVMError> { - let public_output_size = - preds[inst_circuit.layout.from_pred_inst.stack_operand_ids[1] as usize].clone(); - - // Add the instruction circuit to the graph. - let node_id = graph_builder.add_node_with_witness( - >::NAME, - &inst_circuit.circuit, - preds, - real_challenges.to_vec(), - mem::take(&mut sources[0]), - 1, - )?; - - chip_builder.construct_chip_check_graph_and_witness( - graph_builder, - node_id, - &inst_circuit.layout.to_chip_ids, - real_challenges, - params.n_public_output_bytes, - )?; - - if let PredType::PredWire(out) = public_output_size { - Ok((vec![node_id], vec![], Some(out))) - } else { - Err(ZKVMError::CircuitError) - } - } - - fn construct_graph( - graph_builder: &mut CircuitGraphBuilder, - chip_builder: &mut SingerChipBuilder, - inst_circuit: &InstCircuit, - _acc_circuits: &[AccessoryCircuit], - preds: Vec, - real_n_instances: usize, - _: &SingerParams, - ) -> Result<(Vec, Vec, Option), ZKVMError> { - let public_output_size = - preds[inst_circuit.layout.from_pred_inst.stack_operand_ids[1] as usize].clone(); - - // Add the instruction circuit to the graph. - let node_id = graph_builder.add_node( - >::NAME, - &inst_circuit.circuit, - preds, - )?; - - chip_builder.construct_chip_check_graph( - graph_builder, - node_id, - &inst_circuit.layout.to_chip_ids, - real_n_instances, - )?; - - if let PredType::PredWire(out) = public_output_size { - Ok((vec![node_id], vec![], Some(out))) - } else { - Err(ZKVMError::CircuitError) - } - } -} - -register_witness!( - ReturnInstruction, - public_io { - byte => 1 - }, - phase0 { - old_memory_ts => TSUInt::N_OPERAND_CELLS, - offset_add => AddSubConstants::::N_WITNESS_CELLS - } -); - -impl Instruction for ReturnInstruction { - const OPCODE: OpcodeType = OpcodeType::RETURN; - const NAME: &'static str = "RETURN"; - fn construct_circuit(challenges: ChipChallenges) -> Result, ZKVMError> { - let mut circuit_builder = CircuitBuilder::new(); - - // From public io - let (public_io_id, public_io) = circuit_builder.create_witness_in(Self::public_io_size()); - - // From witness - let (phase0_wire_id, phase0) = circuit_builder.create_witness_in(Self::phase0_size()); - - // From predesessor instruction - let (memory_ts_id, memory_ts) = circuit_builder.create_witness_in(TSUInt::N_OPERAND_CELLS); - let (offset_id, offset) = circuit_builder.create_witness_in(StackUInt::N_OPERAND_CELLS); - - let mut chip_handler = ChipHandler::new(challenges.clone()); - - // Compute offset + counter - let delta = circuit_builder.create_counter_in(0)[0]; - let offset = StackUInt::try_from(offset.as_slice())?; - let offset_add_delta = &phase0[Self::phase0_offset_add()]; - let offset_plus_delta = StackUInt::add_cell( - &mut circuit_builder, - &mut chip_handler, - &offset, - delta, - offset_add_delta, - )?; - - // Load from memory - let mem_byte = public_io[Self::public_io_byte().start]; - let memory_ts = TSUInt::try_from(memory_ts.as_slice())?; - let old_memory_ts = TSUInt::try_from(&phase0[Self::phase0_old_memory_ts()])?; - - chip_handler.ram_handler.read_oam( - &mut circuit_builder, - offset_plus_delta.values(), - old_memory_ts.values(), - &[mem_byte], - ); - - // To successor instruction - let (next_memory_ts_id, next_memory_ts) = - circuit_builder.create_witness_out(TSUInt::N_OPERAND_CELLS); - add_assign_each_cell(&mut circuit_builder, &next_memory_ts, memory_ts.values()); - - let (ram_load_id, ram_store_id, rom_id) = chip_handler.finalize(&mut circuit_builder); - circuit_builder.configure(); - - let mut to_chip_ids = vec![None; InstOutChipType::iter().count()]; - to_chip_ids[InstOutChipType::RAMLoad as usize] = ram_load_id; - to_chip_ids[InstOutChipType::RAMStore as usize] = ram_store_id; - to_chip_ids[InstOutChipType::ROMInput as usize] = rom_id; - - Ok(InstCircuit { - circuit: Arc::new(Circuit::new(&circuit_builder)), - layout: InstLayout { - to_chip_ids, - from_pred_inst: FromPredInst { - memory_ts_id, - stack_operand_ids: vec![offset_id], - }, - to_succ_inst: ToSuccInst { - next_memory_ts_id, - stack_result_ids: vec![], - }, - from_witness: FromWitness { - phase_ids: vec![phase0_wire_id], - }, - from_public_io: Some(FromPublicIO { - public_output_id: public_io_id, - }), - to_bb_final: None, - to_acc_dup: None, - to_acc_ooo: None, - }, - }) - } -} diff --git a/singer-pro/src/instructions/unknown.rs b/singer-pro/src/instructions/unknown.rs deleted file mode 100644 index 42c1627ab..000000000 --- a/singer-pro/src/instructions/unknown.rs +++ /dev/null @@ -1,18 +0,0 @@ -use ff_ext::ExtensionField; -use singer_utils::{constants::OpcodeType, structs::ChipChallenges}; - -use crate::{component::InstCircuit, error::ZKVMError}; - -use super::{Instruction, InstructionGraph}; - -pub struct UnknownInstruction; -impl Instruction for UnknownInstruction { - const OPCODE: OpcodeType = OpcodeType::UNKNOWN; - const NAME: &'static str = "UNKNOWN"; - fn construct_circuit(_: ChipChallenges) -> Result, ZKVMError> { - Err(ZKVMError::CircuitError) - } -} -impl InstructionGraph for UnknownInstruction { - type InstType = Self; -} diff --git a/singer-pro/src/lib.rs b/singer-pro/src/lib.rs deleted file mode 100644 index 4191e202a..000000000 --- a/singer-pro/src/lib.rs +++ /dev/null @@ -1,245 +0,0 @@ -#![feature(generic_const_exprs)] -#![feature(const_trait_impl)] - -use basic_block::SingerBasicBlockBuilder; -use error::ZKVMError; -use ff_ext::ExtensionField; -use gkr::structs::LayerWitness; -use gkr_graph::structs::{ - CircuitGraph, CircuitGraphAuxInfo, CircuitGraphBuilder, CircuitGraphWitness, NodeOutputType, -}; -use goldilocks::SmallField; -use instructions::SingerInstCircuitBuilder; -use itertools::Itertools; -use singer_utils::{ - chips::SingerChipBuilder, - structs::{ChipChallenges, InstOutChipType}, -}; -use std::mem; - -pub mod basic_block; -pub mod component; -pub mod error; -pub mod instructions; -pub mod scheme; -pub(crate) mod utils; - -// Process sketch: -// 1. Construct instruction circuits and circuit gadgets => circuit gadgets -// 2. (bytecode + input) => Run revm interpreter, generate all wires in -// 2.1 phase 0 wire in + commitment -// 2.2 phase 1 wire in + commitment -// 2.3 phase 2 wire in + commitment -// 3. (circuit gadgets + wires in) => gkr graph + gkr witness -// 4. (gkr graph + gkr witness) => (gkr proof + point) -// 5. (commitments + point) => pcs proof - -/// Circuit graph builder for Singer pro. `output_wires_id` is indexed by -/// InstOutChipType, corresponding to the product of summation of the chip check -/// records. `public_output_size` is the wire id stores the size of public -/// output. -pub struct SingerGraphBuilder { - graph_builder: CircuitGraphBuilder, - bb_builder: SingerBasicBlockBuilder, - chip_builder: SingerChipBuilder, - public_output_size: Option, -} - -impl SingerGraphBuilder { - pub fn new( - inst_circuit_builder: SingerInstCircuitBuilder, - bytecode: &[Vec], - challenges: ChipChallenges, - ) -> Result { - Ok(Self { - graph_builder: CircuitGraphBuilder::new(), - bb_builder: SingerBasicBlockBuilder::new(inst_circuit_builder, bytecode, challenges)?, - chip_builder: SingerChipBuilder::new(), - public_output_size: None, - }) - } - - pub fn construct_graph_and_witness( - mut self, - singer_wires_in: SingerWiresIn, - program_input: &[u8], - real_challenges: &[E], - params: &SingerParams, - ) -> Result< - ( - SingerCircuit, - SingerWitness, - SingerWiresOutID, - ), - ZKVMError, - > { - let basic_blocks = self.bb_builder.basic_block_bytecode(); - // Construct tables for lookup arguments, including bytecode, range and - // calldata - let pub_out_id = self.bb_builder.construct_graph_and_witness( - &mut self.graph_builder, - &mut self.chip_builder, - singer_wires_in.basic_blocks, - real_challenges, - params, - )?; - if pub_out_id.is_some() { - self.public_output_size = pub_out_id; - } - - // Construct tables for lookup arguments, including bytecode, range and - // calldata. - let table_out_node_id = self.chip_builder.construct_lookup_table_graph_and_witness( - &mut self.graph_builder, - &basic_blocks.iter().cloned().flatten().collect_vec(), - program_input, - singer_wires_in.table_count_witnesses, - &self.bb_builder.challenges, - real_challenges, - )?; - - let SingerGraphBuilder { - graph_builder, - chip_builder, - public_output_size, - bb_builder: _, - } = self; - - let mut output_wires_id = chip_builder.output_wires_id; - - let singer_wire_out_id = SingerWiresOutID { - ram_load: mem::take(&mut output_wires_id[InstOutChipType::RAMLoad as usize]), - ram_store: mem::take(&mut output_wires_id[InstOutChipType::RAMStore as usize]), - rom_input: mem::take(&mut output_wires_id[InstOutChipType::ROMInput as usize]), - rom_table: table_out_node_id, - - public_output_size, - }; - - let (graph, graph_witness) = - graph_builder.finalize_graph_and_witness_with_targets(&singer_wire_out_id.to_vec()); - Ok(( - SingerCircuit(graph), - SingerWitness(graph_witness), - singer_wire_out_id, - )) - } - - pub fn construct_graph( - mut self, - aux_info: &SingerAuxInfo, - ) -> Result, ZKVMError> { - // Construct tables for lookup arguments, including bytecode, range and - // calldata - let pub_out_id = self.bb_builder.construct_graph( - &mut self.graph_builder, - &mut self.chip_builder, - &aux_info.real_n_instances, - &aux_info.singer_params, - )?; - if pub_out_id.is_some() { - self.public_output_size = pub_out_id; - } - let table_out_node_id = self.chip_builder.construct_lookup_table_graph( - &mut self.graph_builder, - aux_info.bytecode_len, - aux_info.program_input_len, - &self.bb_builder.challenges, - )?; - - let SingerGraphBuilder { - graph_builder, - chip_builder, - public_output_size, - bb_builder: _, - } = self; - - let mut output_wires_id = chip_builder.output_wires_id; - - let singer_wire_out_id = SingerWiresOutID { - ram_load: mem::take(&mut output_wires_id[InstOutChipType::RAMLoad as usize]), - ram_store: mem::take(&mut output_wires_id[InstOutChipType::RAMStore as usize]), - rom_input: mem::take(&mut output_wires_id[InstOutChipType::ROMInput as usize]), - rom_table: table_out_node_id, - - public_output_size, - }; - - let graph = graph_builder.finalize_graph_with_targets(&singer_wire_out_id.to_vec()); - Ok(SingerCircuit(graph)) - } -} - -pub struct SingerCircuit(CircuitGraph); - -pub struct SingerWitness(CircuitGraphWitness); - -#[derive(Clone, Copy, Debug, Default)] -pub struct SingerParams { - pub n_public_output_bytes: usize, - pub n_mem_initialize: usize, - pub n_mem_finalize: usize, - pub n_stack_finalize: usize, -} - -#[derive(Clone, Debug, Default)] -pub struct SingerWiresIn { - pub basic_blocks: Vec>, - pub table_count_witnesses: Vec>, -} - -#[derive(Clone, Debug)] -pub struct SingerWiresOutID { - pub ram_load: Vec, - pub ram_store: Vec, - pub rom_input: Vec, - pub rom_table: Vec, - - pub public_output_size: Option, -} - -impl SingerWiresOutID { - pub fn to_vec(&self) -> Vec { - let mut res = [ - self.ram_load.clone(), - self.ram_store.clone(), - self.rom_input.clone(), - ] - .concat(); - if let Some(public_output_size) = self.public_output_size { - res.push(public_output_size); - } - res - } -} - -#[derive(Clone, Debug)] -pub struct SingerWiresOutValues { - pub ram_load: Vec>, - pub ram_store: Vec>, - pub rom_input: Vec>, - pub rom_table: Vec>, - - pub public_output_size: Option>, -} - -pub(crate) type CircuitWitnessIn = Vec>; - -#[derive(Clone, Debug, Default)] -pub struct BasicBlockWiresIn { - pub real_n_instance: usize, - pub bb_start: CircuitWitnessIn, - pub opcodes: Vec>>, - pub bb_final: CircuitWitnessIn, - pub bb_accs: Vec>, -} - -#[derive(Clone, Debug, Default)] -pub struct SingerAuxInfo { - pub graph_aux_info: CircuitGraphAuxInfo, - pub real_n_instances: Vec, - pub singer_params: SingerParams, - pub bytecode_len: usize, - pub program_input_len: usize, - pub program_output_len: usize, -} diff --git a/singer-pro/src/scheme.rs b/singer-pro/src/scheme.rs deleted file mode 100644 index c1996ff66..000000000 --- a/singer-pro/src/scheme.rs +++ /dev/null @@ -1,42 +0,0 @@ -use ff_ext::ExtensionField; -use gkr::structs::GKRInputClaims; - -use crate::SingerWiresOutValues; - -// TODO: to be changed to a real PCS scheme. -type BatchedPCSProof = Vec>; -type Commitment = Vec; - -pub mod prover; -pub mod verifier; - -pub struct CommitPhaseProof { - commitments: Vec>, -} - -pub struct GKRPhaseProverState { - proved_input_claims: Vec>, -} - -pub struct GKRPhaseVerifierState { - proved_input_claims: Vec>, -} - -pub type GKRGraphProof = gkr_graph::structs::IOPProof; -pub type GKRGraphProverState = gkr_graph::structs::IOPProverState; -pub type GKRGraphVerifierState = gkr_graph::structs::IOPVerifierState; - -pub struct GKRPhaseProof { - gkr_proofs: Vec>, -} - -pub struct OpenPhaseProof { - pcs_proof: BatchedPCSProof, -} - -pub struct SingerProof { - // commitment_phase_proof: CommitPhaseProof, - gkr_phase_proof: GKRGraphProof, - // open_phase_proof: OpenPhaseProof, - singer_out_evals: SingerWiresOutValues, -} diff --git a/singer-pro/src/scheme/prover.rs b/singer-pro/src/scheme/prover.rs deleted file mode 100644 index 82f500aba..000000000 --- a/singer-pro/src/scheme/prover.rs +++ /dev/null @@ -1,88 +0,0 @@ -use std::mem; - -use ff_ext::ExtensionField; -use gkr_graph::structs::{CircuitGraphAuxInfo, NodeOutputType}; -use itertools::Itertools; -use transcript::Transcript; - -use crate::{ - error::ZKVMError, SingerCircuit, SingerWiresOutID, SingerWiresOutValues, SingerWitness, -}; - -use super::{GKRGraphProverState, SingerProof}; - -pub fn prove( - vm_circuit: &SingerCircuit, - vm_witness: &SingerWitness, - vm_out_id: &SingerWiresOutID, - transcript: &mut Transcript, -) -> Result<(SingerProof, CircuitGraphAuxInfo), ZKVMError> { - // TODO: Add PCS. - let point = (0..2 * ::DEGREE) - .map(|_| { - transcript - .get_and_append_challenge(b"output point") - .elements - }) - .collect_vec(); - - let singer_out_evals = { - let target_wits = |node_out_ids: &[NodeOutputType]| { - node_out_ids - .iter() - .map(|node| { - match node { - NodeOutputType::OutputLayer(node_id) => vm_witness.0.node_witnesses - [*node_id as usize] - .output_layer_witness_ref() - .instances - .iter() - .cloned() - .flatten(), - NodeOutputType::WireOut(node_id, wit_id) => vm_witness.0.node_witnesses - [*node_id as usize] - .witness_out_ref()[*wit_id as usize] - .instances - .iter() - .cloned() - .flatten(), - } - .collect_vec() - }) - .collect_vec() - }; - let ram_load = target_wits(&vm_out_id.ram_load); - let ram_store = target_wits(&vm_out_id.ram_store); - let rom_input = target_wits(&vm_out_id.rom_input); - let rom_table = target_wits(&vm_out_id.rom_table); - SingerWiresOutValues { - ram_load, - ram_store, - rom_input, - rom_table, - public_output_size: vm_out_id - .public_output_size - .map(|node| mem::take(&mut target_wits(&[node])[0])), - } - }; - - let aux_info = CircuitGraphAuxInfo { - instance_num_vars: vm_witness - .0 - .node_witnesses - .iter() - .map(|witness| witness.instance_num_vars()) - .collect(), - }; - - let target_evals = vm_circuit.0.target_evals(&vm_witness.0, &point); - let gkr_phase_proof = - GKRGraphProverState::prove(&vm_circuit.0, &vm_witness.0, &target_evals, transcript, 1)?; - Ok(( - SingerProof { - gkr_phase_proof, - singer_out_evals, - }, - aux_info, - )) -} diff --git a/singer-pro/src/scheme/verifier.rs b/singer-pro/src/scheme/verifier.rs deleted file mode 100644 index f47183cc3..000000000 --- a/singer-pro/src/scheme/verifier.rs +++ /dev/null @@ -1,99 +0,0 @@ -use ff_ext::ExtensionField; -use gkr::{structs::PointAndEval, utils::MultilinearExtensionFromVectors}; -use gkr_graph::structs::TargetEvaluations; -use itertools::{chain, Itertools}; -use transcript::Transcript; - -use crate::{error::ZKVMError, SingerAuxInfo, SingerCircuit, SingerWiresOutValues}; - -use super::{GKRGraphVerifierState, SingerProof}; - -pub fn verify( - vm_circuit: &SingerCircuit, - vm_proof: SingerProof, - aux_info: &SingerAuxInfo, - challenges: &[E], - transcript: &mut Transcript, -) -> Result<(), ZKVMError> { - // TODO: Add PCS. - let point = (0..2 * ::DEGREE) - .map(|_| { - transcript - .get_and_append_challenge(b"output point") - .elements - }) - .collect_vec(); - - let SingerWiresOutValues { - ram_load, - ram_store, - rom_input, - rom_table, - public_output_size, - } = vm_proof.singer_out_evals; - - let ram_load_product: E = ram_load.iter().map(|x| E::from_limbs(&x)).product(); - let ram_store_product = ram_store.iter().map(|x| E::from_limbs(&x)).product(); - if ram_load_product != ram_store_product { - return Err(ZKVMError::VerifyError); - } - - let rom_input_sum = rom_input - .iter() - .map(|x| { - let l = x.len(); - let (den, num) = x.split_at(l / 2); - (E::from_limbs(den), E::from_limbs(num)) - }) - .fold((E::ONE, E::ZERO), |acc, x| { - (acc.0 * x.0, acc.0 * x.1 + acc.1 * x.0) - }); - let rom_table_sum = rom_table - .iter() - .map(|x| { - let l = x.len(); - let (den, num) = x.split_at(l / 2); - (E::from_limbs(den), E::from_limbs(num)) - }) - .fold((E::ONE, E::ZERO), |acc, x| { - (acc.0 * x.0, acc.0 * x.1 + acc.1 * x.0) - }); - if rom_input_sum.0 * rom_table_sum.1 != rom_input_sum.1 * rom_table_sum.0 { - return Err(ZKVMError::VerifyError); - } - - let mut target_evals = TargetEvaluations( - chain![ram_load, ram_store, rom_input, rom_table] - .map(|x| { - let f = vec![x.to_vec()].as_slice().original_mle(); - PointAndEval::new( - point[..f.num_vars].to_vec(), - f.evaluate(&point[..f.num_vars]), - ) - }) - .collect_vec(), - ); - - if let Some(output) = public_output_size { - let f = vec![output.to_vec()].as_slice().original_mle(); - target_evals.0.push(PointAndEval::new( - point[..f.num_vars].to_vec(), - f.evaluate(&point[..f.num_vars]), - )); - assert_eq!( - output[0], - E::BaseField::from(aux_info.program_output_len as u64) - ) - } - - GKRGraphVerifierState::verify( - &vm_circuit.0, - &challenges, - &target_evals, - vm_proof.gkr_phase_proof, - &aux_info.graph_aux_info, - transcript, - )?; - - Ok(()) -} diff --git a/singer-pro/src/test.rs b/singer-pro/src/test.rs deleted file mode 100644 index 227133865..000000000 --- a/singer-pro/src/test.rs +++ /dev/null @@ -1,144 +0,0 @@ -use crate::instructions::InstCircuit; -use core::ops::Range; -use gkr::structs::CircuitWitness; -use goldilocks::SmallField; -use std::collections::BTreeMap; - -pub(crate) fn test_opcode_circuit( - inst_circuit: &InstCircuit, - phase0_idx_map: &BTreeMap>, - phase1_idx_map: &BTreeMap>, - phase0_witness_size: usize, - phase1_witness_size: usize, - phase0_values_map: &BTreeMap>, - phase1_values_map: &BTreeMap>, -) { - // configure circuit - let circuit = inst_circuit.circuit.as_ref(); - println!("{:?}", circuit); - - // get indexes for circuit inputs and wire_in - // they are divided into phase0 and phase1 - let inputs_idxes = inst_circuit.layout.phases_wire_id; - let phase0_input_idx = inputs_idxes[0].unwrap(); - let phase1_input_idx = inputs_idxes[1].unwrap(); - - // assign witnesses to circuit - let n_wires_in = circuit.n_wires_in; - let mut wires_in = vec![vec![]; n_wires_in]; - wires_in[phase0_input_idx as usize] = vec![F::from(0u64); phase0_witness_size]; - wires_in[phase1_input_idx as usize] = vec![F::from(0u64); phase1_witness_size]; - - for phase in 0..2 { - let idx_map = match phase { - 0 => phase0_idx_map, - 1 => phase1_idx_map, - other => panic!("invalid phase"), - }; - let values_map = match phase { - 0 => phase0_values_map, - 1 => phase1_values_map, - other => panic!("invalid phase"), - }; - let input_idx = match phase { - 0 => phase0_input_idx as usize, - 1 => phase1_input_idx as usize, - other => panic!("invalid phase"), - }; - for key in idx_map.keys() { - let range = idx_map.get(key).unwrap().clone().collect::>(); - let values = values_map.get(key).unwrap(); - for (value_idx, wire_in_idx) in range.into_iter().enumerate() { - if value_idx < values.len() { - wires_in[input_idx as usize][wire_in_idx] = values[value_idx]; - } - } - } - } - - println!("{:?}", wires_in); - - /* - let circuit_witness = { - let challenges = vec![F::from(2), F::from(1)]; - let mut circuit_witness = CircuitWitness::new(&circuit, challenges); - circuit_witness.add_instance(&circuit, &wires_in); - circuit_witness - }; - - println!("{:?}", circuit_witness); - */ - /* - //#[cfg(feature = "debug")] - circuit_witness.check_correctness(&circuit); - */ - - /* - let instance_num_vars = circuit_witness.instance_num_vars(); - - let (proof, output_num_vars, output_eval) = { - let mut prover_transcript = Transcript::::new(b"example"); - let output_num_vars = instance_num_vars + circuit.last_layer_ref().num_vars(); - - let output_point = (0..output_num_vars) - .map(|_| { - prover_transcript - .get_and_append_challenge(b"output point") - .elements - }) - .collect_vec(); - - let output_eval = circuit_witness - .layer_poly(0, circuit.last_layer_ref().num_vars()) - .evaluate(&output_point); - ( - IOPProverState::prove_parallel( - &circuit, - &circuit_witness, - &[(output_point, output_eval)], - &[], - &mut prover_transcript, - ), - output_num_vars, - output_eval, - ) - }; - - let gkr_input_claims = { - let mut verifier_transcript = &mut Transcript::::new(b"example"); - let output_point = (0..output_num_vars) - .map(|_| { - verifier_transcript - .get_and_append_challenge(b"output point") - .elements - }) - .collect_vec(); - IOPVerifierState::verify_parallel( - &circuit, - circuit_witness.challenges(), - &[(output_point, output_eval)], - &[], - &proof, - instance_num_vars, - &mut verifier_transcript, - ) - .expect("verification failed") - }; - - let expected_values = circuit_witness - .wires_in_ref() - .iter() - .map(|witness| { - witness - .as_slice() - .mle(circuit.max_wires_in_num_vars, instance_num_vars) - .evaluate(&gkr_input_claims.point) - }) - .collect_vec(); - for i in 0..gkr_input_claims.values.len() { - assert_eq!(expected_values[i], gkr_input_claims.values[i]); - } - - println!("verification succeeded"); - */ -} diff --git a/singer-pro/src/utils.rs b/singer-pro/src/utils.rs deleted file mode 100644 index d194edc8c..000000000 --- a/singer-pro/src/utils.rs +++ /dev/null @@ -1,23 +0,0 @@ -use ff::Field; -use ff_ext::ExtensionField; -use itertools::izip; -use simple_frontend::structs::{CellId, CircuitBuilder}; - -pub(crate) fn i64_to_base_field(x: i64) -> E::BaseField { - if x >= 0 { - E::BaseField::from(x as u64) - } else { - -E::BaseField::from((-x) as u64) - } -} - -pub(crate) fn add_assign_each_cell( - circuit_builder: &mut CircuitBuilder, - dest: &[CellId], - src: &[CellId], -) { - assert_eq!(dest.len(), src.len()); - for (dest, src) in izip!(dest, src) { - circuit_builder.add(*dest, *src, E::BaseField::ONE); - } -}