From 9d21aa7a25ff9af896f0d5e277d3e3b1afceecaf Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Mon, 13 Jan 2025 23:25:32 -0800 Subject: [PATCH 01/20] added precompile code for common directory --- common/precompiles/bn254_add.rs | 15 +++++++++++ common/precompiles/mod.rs | 7 ++++++ common/src/attributes.rs | 15 ++++++++++- common/src/constants.rs | 2 ++ common/src/rv_trace.rs | 44 ++++++++++++++++++++++++++++++--- 5 files changed, 79 insertions(+), 4 deletions(-) create mode 100644 common/precompiles/bn254_add.rs create mode 100644 common/precompiles/mod.rs diff --git a/common/precompiles/bn254_add.rs b/common/precompiles/bn254_add.rs new file mode 100644 index 000000000..1c36a93ae --- /dev/null +++ b/common/precompiles/bn254_add.rs @@ -0,0 +1,15 @@ +pub fn bn254_add(input_1: [u8; 16], input_2: [u8; 16]) -> [u8; 16] { + // This is a placeholder for the actual implementation. + [0; 16] +} + +#[cfg(test)] +mod tests { + #[test] + fn test_bn254_add() { + let input_1 = [1; 16]; + let input_2 = [2; 16]; + let expected_output = [3; 16]; + assert_eq!(bn254_add(input_1, input_2), expected_output); + } +} diff --git a/common/precompiles/mod.rs b/common/precompiles/mod.rs new file mode 100644 index 000000000..857065c08 --- /dev/null +++ b/common/precompiles/mod.rs @@ -0,0 +1,7 @@ +pub mod bn254_add; + +enum Precompile { + Bn254_add, +} + +// trait to deserialize the raw input bytes and serialize the outputs diff --git a/common/src/attributes.rs b/common/src/attributes.rs index 455c9f87d..273df95c0 100644 --- a/common/src/attributes.rs +++ b/common/src/attributes.rs @@ -2,7 +2,8 @@ use std::collections::HashMap; use syn::{Lit, Meta, MetaNameValue, NestedMeta}; use crate::constants::{ - DEFAULT_MAX_INPUT_SIZE, DEFAULT_MAX_OUTPUT_SIZE, DEFAULT_MEMORY_SIZE, DEFAULT_STACK_SIZE, + DEFAULT_MAX_INPUT_SIZE, DEFAULT_MAX_OUTPUT_SIZE, DEFAULT_MEMORY_SIZE, DEFAULT_STACK_SIZE, + DEFAULT_MAX_PRECOMPILE_INPUT_SIZE, DEFAULT_MAX_PRECOMPILE_OUTPUT_SIZE, }; pub struct Attributes { @@ -11,6 +12,8 @@ pub struct Attributes { pub stack_size: u64, pub max_input_size: u64, pub max_output_size: u64, + pub max_precompile_input_size: u64, + pub max_precompile_output_size: u64, } pub fn parse_attributes(attr: &Vec) -> Attributes { @@ -30,6 +33,8 @@ pub fn parse_attributes(attr: &Vec) -> Attributes { "stack_size" => attributes.insert("stack_size", value), "max_input_size" => attributes.insert("max_input_size", value), "max_output_size" => attributes.insert("max_output_size", value), + "max_precompile_input_size" => attributes.insert("max_precompile_input_size", value), + "max_precompile_output_size" => attributes.insert("max_precompile_output_size", value), _ => panic!("invalid attribute"), }; } @@ -50,6 +55,12 @@ pub fn parse_attributes(attr: &Vec) -> Attributes { let max_output_size = *attributes .get("max_output_size") .unwrap_or(&DEFAULT_MAX_OUTPUT_SIZE); + let max_precompile_input_size = *attributes + .get("max_precompile_input_size") + .unwrap_or(&DEFAULT_MAX_PRECOMPILE_INPUT_SIZE); + let max_precompile_output_size = *attributes + .get("max_precompile_output_size") + .unwrap_or(&DEFAULT_MAX_PRECOMPILE_OUTPUT_SIZE); Attributes { wasm, @@ -57,5 +68,7 @@ pub fn parse_attributes(attr: &Vec) -> Attributes { stack_size, max_input_size, max_output_size, + max_precompile_input_size, + max_precompile_output_size, } } diff --git a/common/src/constants.rs b/common/src/constants.rs index e6bd335a0..aefa7ed02 100644 --- a/common/src/constants.rs +++ b/common/src/constants.rs @@ -11,6 +11,8 @@ pub const DEFAULT_MEMORY_SIZE: u64 = 10 * 1024 * 1024; pub const DEFAULT_STACK_SIZE: u64 = 4096; pub const DEFAULT_MAX_INPUT_SIZE: u64 = 4096; pub const DEFAULT_MAX_OUTPUT_SIZE: u64 = 4096; +pub const DEFAULT_MAX_PRECOMPILE_INPUT_SIZE: u64 = 512; +pub const DEFAULT_MAX_PRECOMPILE_OUTPUT_SIZE: u64 = 512; pub const fn virtual_register_index(index: u64) -> u64 { index + VIRTUAL_REGISTER_COUNT diff --git a/common/src/rv_trace.rs b/common/src/rv_trace.rs index b6088a6ea..eb3f32f05 100644 --- a/common/src/rv_trace.rs +++ b/common/src/rv_trace.rs @@ -203,6 +203,8 @@ pub enum CircuitFlags { Assert, /// Used in virtual sequences; the program counter should be the same for the full sequence. DoNotUpdatePC, + /// 1 if the instruction is an ecall/precompile + Precompile, } pub const NUM_CIRCUIT_FLAGS: usize = CircuitFlags::COUNT; @@ -429,6 +431,7 @@ pub enum RV32IM { VIRTUAL_ASSERT_EQ, VIRTUAL_ASSERT_VALID_DIV0, VIRTUAL_ASSERT_HALFWORD_ALIGNMENT, + VIRTUAL_PRECOMPILE, } impl FromStr for RV32IM { @@ -588,6 +591,8 @@ pub struct JoltDevice { pub outputs: Vec, pub panic: bool, pub memory_layout: MemoryLayout, + pub precompile_input: Vec, + pub precompile_output: Vec, } impl JoltDevice { @@ -597,6 +602,8 @@ impl JoltDevice { outputs: Vec::new(), panic: false, memory_layout: MemoryLayout::new(max_input_size, max_output_size), + precompile_input: Vec::new(), + precompile_output: Vec::new(), } } @@ -621,7 +628,15 @@ impl JoltDevice { } } else { 0 // zero-padding + } else if self.is_precompile_input(address) { + let internal_address = self.convert_read_address(address); + if self.precompile_inputs.len() <= internal_address { + 0 + } else { + self.precompile_inputs[internal_address] + } } + // Add conditional for loading precompile output } pub fn store(&mut self, address: u64, value: u8) { @@ -639,7 +654,11 @@ impl JoltDevice { if self.outputs.len() <= internal_address { self.outputs.resize(internal_address + 1, 0); } - + else if self.precompile_outputs(address) { + self.precompile_outputs[internal_address] = value; + return; + } + // add conditional for storing precompile input self.outputs[internal_address] = value; } @@ -655,6 +674,14 @@ impl JoltDevice { address >= self.memory_layout.output_start && address < self.memory_layout.termination } + pub fn is_precompile_input(&self, address: u64) -> bool { + address >= self.memory_layout.precompile_input_start && address < self.memory_layout.precompile_input_end + } + + pub fn is_precompile_output(&self, address: u64) -> bool { + address >= self.memory_layout.precompile_output_start && address < self.memory_layout.precompile_output_end + } + pub fn is_panic(&self, address: u64) -> bool { address == self.memory_layout.panic } @@ -682,10 +709,13 @@ pub struct MemoryLayout { pub input_end: u64, pub output_start: u64, pub output_end: u64, + pub precompile_input_start: u64, + pub precompile_input_end: u64, + pub precompile_output_start: u64, + pub precompile_output_end: u64, pub panic: u64, pub termination: u64, } - impl MemoryLayout { pub fn new(mut max_input_size: u64, mut max_output_size: u64) -> Self { // Must be word-aligned @@ -694,7 +724,7 @@ impl MemoryLayout { // Adds 8 to account for panic bit and termination bit // (they each occupy one full 4-byte word) - let io_region_num_bytes = max_input_size + max_output_size + 8; + let io_region_num_bytes = max_input_size + max_output_size + 8 + 32; // Padded so that the witness index corresponding to `RAM_START_ADDRESS` // is a power of 2 @@ -704,6 +734,10 @@ impl MemoryLayout { let input_end = input_start + max_input_size; let output_start = input_end; let output_end = output_start + max_output_size; + let precompile_input_start = output_end; + let precompile_input_end = precompile_input_start + 16; // 512 bits + let precompile_output_start = precompile_input_end; + let precompile_output_end = precompile_output_start + 16; // 512 bits let panic = output_end; let termination = panic + 4; @@ -714,6 +748,10 @@ impl MemoryLayout { input_end, output_start, output_end, + precompile_input_start, + precompile_input_end, + precompile_output_start, + precompile_output_end, panic, termination, } From e7e56aad1e4e51a9880f9282b8b1ec2b588b81d6 Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Mon, 13 Jan 2025 23:28:15 -0800 Subject: [PATCH 02/20] added comments for jolt-core/jolt/instruction/ecall.rs --- jolt-core/src/jolt/instruction/ecall.rs | 3 +++ 1 file changed, 3 insertions(+) create mode 100644 jolt-core/src/jolt/instruction/ecall.rs diff --git a/jolt-core/src/jolt/instruction/ecall.rs b/jolt-core/src/jolt/instruction/ecall.rs new file mode 100644 index 000000000..484a47573 --- /dev/null +++ b/jolt-core/src/jolt/instruction/ecall.rs @@ -0,0 +1,3 @@ +// Implementation of the ECALL instruction. +// Reuse existing advice instruction (16x for each precompile word in the precompile output). +// Last instruction is a call to the precompile based on t0 register. From c2d1abb301ef682a512f8cbfbe0b3c3b1a6a18ea Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Mon, 13 Jan 2025 23:44:35 -0800 Subject: [PATCH 03/20] added prcompile directory to jotl-core/jolt/ --- jolt-core/src/jolt/precompiles/bn254_add.rs | 1 + jolt-core/src/jolt/precompiles/mod.rs | 47 +++++++++++++++++++++ 2 files changed, 48 insertions(+) create mode 100644 jolt-core/src/jolt/precompiles/bn254_add.rs create mode 100644 jolt-core/src/jolt/precompiles/mod.rs diff --git a/jolt-core/src/jolt/precompiles/bn254_add.rs b/jolt-core/src/jolt/precompiles/bn254_add.rs new file mode 100644 index 000000000..492f57f17 --- /dev/null +++ b/jolt-core/src/jolt/precompiles/bn254_add.rs @@ -0,0 +1 @@ +// R1CS implementation of the addition operation for the BN254 curve. diff --git a/jolt-core/src/jolt/precompiles/mod.rs b/jolt-core/src/jolt/precompiles/mod.rs new file mode 100644 index 000000000..486c03df4 --- /dev/null +++ b/jolt-core/src/jolt/precompiles/mod.rs @@ -0,0 +1,47 @@ +pub mod bn254_add; + +enum Precompile { + Bn254_add, + Bn254_mul, + Sha256, +} + +pub struct PrecompileIO { + pub input:[u32; 16] // 512 bits + pub output:[u32; 16] // 512 bits +} +struct PrecompileWitness { + pub precompile: Precompile, + pub a0i: [u8; 32], + pub a1i: [u8; 32], + pub a2i: [u8; 32], + pub a3i: [u8; 32], + pub a4i: [u8; 32], + pub a5i: [u8; 32], + pub a6i: [u8; 32], + pub a7i: [u8; 32], + pub a8i: [u8; 32], + pub a9i: [u8; 32], + pub a10i: [u8; 32], + pub a11i: [u8; 32], + pub a12i: [u8; 32], + pub a13i: [u8; 32], + pub a14i: [u8; 32], + pub a15i: [u8; 32], + pub a0o: [u8; 32], + pub a1o: [u8; 32], + pub a2o: [u8; 32], + pub a3o: [u8; 32], + pub a4o: [u8; 32], + pub a5o: [u8; 32], + pub a6o: [u8; 32], + pub a7o: [u8; 32], + pub a8o: [u8; 32], + pub a9o: [u8; 32], + pub a10o: [u8; 32], + pub a11o: [u8; 32], + pub a12o: [u8; 32], + pub a13o: [u8; 32], + pub a14o: [u8; 32], + pub a15o: [u8; 32], +} From 337af2a70453aba1fe7c54ca5df11d75b422ee0e Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Mon, 13 Jan 2025 23:51:53 -0800 Subject: [PATCH 04/20] added precompile template code to jolt-sdk --- jolt-sdk/macros/src/lib.rs | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/jolt-sdk/macros/src/lib.rs b/jolt-sdk/macros/src/lib.rs index e47552b87..706e52fe7 100644 --- a/jolt-sdk/macros/src/lib.rs +++ b/jolt-sdk/macros/src/lib.rs @@ -284,6 +284,10 @@ impl MacroBuilder { let output_start = memory_layout.output_start; let max_input_len = attributes.max_input_size as usize; let max_output_len = attributes.max_output_size as usize; + let max_precompile_input_len = attributes.max_precompile_input_size as usize; + let max_precompile_output_len = attributes.max_precompile_output_size as usize; + let precompile_input_start = memory_layout.precompile_input_start; // empty if no precompile used, no option + let precompile_output_start = memory_layout.precompile_output_start; let termination_bit = memory_layout.termination as usize; let get_input_slice = quote! { @@ -319,6 +323,8 @@ impl MacroBuilder { }, }; + + let precompile_fn = self.make_precompile_fn(PrecompileEnum); // check with Michael let panic_fn = self.make_panic(memory_layout.panic); let declare_alloc = self.make_allocator(); @@ -416,6 +422,7 @@ impl MacroBuilder { MemoryOp, MemoryLayout, MEMORY_OPS_PER_INSTRUCTION, + Precompiles, instruction::add::ADDInstruction, tracer, }; @@ -564,4 +571,22 @@ impl MacroBuilder { } } } + + fn make_precompile_fn(&self, precompile_enum: PrecompileEnum) -> TokenStream2 { + // Iterate over the inputs + // Serialize the inputs from the array using correct type + asm!( + "ecall", + in("t0") PrecompileEnum::fn_name as u32, + ) + + // quote! { + // #[cfg(feature = "guest")] + // pub fn #fn_name(#inputs) #output { + // #body + // } + // } + + + } } From 379541c66c5e5f417103b59d904b719a1367296f Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Tue, 14 Jan 2025 23:44:18 -0800 Subject: [PATCH 05/20] added skeleton code for ecall.rs --- jolt-core/src/jolt/instruction/ecall.rs | 87 +++++++++++++++++++++++++ 1 file changed, 87 insertions(+) diff --git a/jolt-core/src/jolt/instruction/ecall.rs b/jolt-core/src/jolt/instruction/ecall.rs index 484a47573..8cb92c513 100644 --- a/jolt-core/src/jolt/instruction/ecall.rs +++ b/jolt-core/src/jolt/instruction/ecall.rs @@ -1,3 +1,90 @@ // Implementation of the ECALL instruction. // Reuse existing advice instruction (16x for each precompile word in the precompile output). // Last instruction is a call to the precompile based on t0 register. + +use common::constants::virtual_register_index; +use tracer::{ELFInstruction, RVTraceRow, RegisterState, RV32IM}; + +use super::VirtualInstructionSequence; +use crate::jolt::instruction::{ + virtual_advice::ADVICEInstruction, JoltInstruction, +}; +/// Call a precompile based on the value in to register, +/// fetch the input from the precompile input memory region, +/// and write the output to the precompile output memory region. +pub struct EcallInstruction; + +impl VirtualInstructionSequence for EcallInstruction { + const SEQUENCE_LENGTH: usize = 8; // needs change? + + fn virtual_trace(trace_row: RVTraceRow) -> Vec { + assert_eq!(trace_row.instruction.opcode, RV32IM::ECALL); + // Ecall source registers + let r_x = trace_row.instruction.rs1; + let r_y = trace_row.instruction.rs2; + // Virtual registers used in sequence + let v_0 = Some(virtual_register_index(0)); + let v_q: Option = Some(virtual_register_index(1)); + let v_r: Option = Some(virtual_register_index(2)); + let v_qy = Some(virtual_register_index(3)); + // Precompile input + let x = trace_row.register_state.rs1_val.unwrap(); + let y = trace_row.register_state.rs2_val.unwrap(); + + let mut virtual_trace = vec![]; + + let precompile_output = // compute precompile output based on t0 register + + let q = ADVICEInstruction::(precompile_output).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output), + }); + + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_MOVE, + rs1: v_q, + rs2: None, + rd: trace_row.instruction.rd, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: Some(q), + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: None, + }); + + virtual_trace + } +} + +#[cfg(test)] +mod test { + use super::*; + use crate::{jolt::instruction::JoltInstruction, jolt_virtual_sequence_test}; + + #[test] + fn ecall_virtual_sequence_32() { + jolt_virtual_sequence_test!(EcallInstruction::<32>, RV32IM::ECALL); + } +} From 8b15c334aec4560347f613e1a8c35ad3e26ce6b9 Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Tue, 14 Jan 2025 23:53:03 -0800 Subject: [PATCH 06/20] removed extra two virtual advice registers --- jolt-core/src/jolt/instruction/ecall.rs | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/jolt-core/src/jolt/instruction/ecall.rs b/jolt-core/src/jolt/instruction/ecall.rs index 8cb92c513..23b95c45b 100644 --- a/jolt-core/src/jolt/instruction/ecall.rs +++ b/jolt-core/src/jolt/instruction/ecall.rs @@ -25,8 +25,6 @@ impl VirtualInstructionSequence for EcallInstruction { // Virtual registers used in sequence let v_0 = Some(virtual_register_index(0)); let v_q: Option = Some(virtual_register_index(1)); - let v_r: Option = Some(virtual_register_index(2)); - let v_qy = Some(virtual_register_index(3)); // Precompile input let x = trace_row.register_state.rs1_val.unwrap(); let y = trace_row.register_state.rs2_val.unwrap(); @@ -85,6 +83,6 @@ mod test { #[test] fn ecall_virtual_sequence_32() { - jolt_virtual_sequence_test!(EcallInstruction::<32>, RV32IM::ECALL); + jolt_virtual_sequence_test!(EcallInstruction, RV32IM::ECALL); } } From ab4d42da7b317c208846f1ade4e04feaedf3e757 Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Wed, 15 Jan 2025 01:06:41 -0800 Subject: [PATCH 07/20] added prove and verify placeholder functions in jolt-sdk/macros/lib.rs --- jolt-sdk/macros/src/lib.rs | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/jolt-sdk/macros/src/lib.rs b/jolt-sdk/macros/src/lib.rs index 706e52fe7..48ee1ae27 100644 --- a/jolt-sdk/macros/src/lib.rs +++ b/jolt-sdk/macros/src/lib.rs @@ -589,4 +589,21 @@ impl MacroBuilder { } + + #[cfg(not(feature = "guest"))] + pub fn prove_precompile( + preprocessing: Self::Preprocessing, + witness: Self::Witness, + ) -> Self::Proof { + // This is a placeholder for the actual implementation. + } + + #[cfg(not(feature = "guest"))] + pub fn verify( + preprocessing: Self::Preprocessing, + proof: Self::Proof, + ) -> bool { + // This is a placeholder for the actual implementation. + } + } From 9d0231a85ff4b3b0269ffee1109bbbe045c6167b Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Wed, 15 Jan 2025 02:06:05 -0800 Subject: [PATCH 08/20] added skeleton code to tracer/src/emulator/cpu.rs --- tracer/src/emulator/cpu.rs | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/tracer/src/emulator/cpu.rs b/tracer/src/emulator/cpu.rs index ac2607636..54087df5b 100644 --- a/tracer/src/emulator/cpu.rs +++ b/tracer/src/emulator/cpu.rs @@ -2514,6 +2514,14 @@ pub const INSTRUCTIONS: [Instruction; INSTRUCTION_NUM] = [ data: 0x00000073, name: "ECALL", operation: |cpu, _word, address| { + let precompile_enum = cpu.read_register(5); + let precompile = Precompile::from_u64(precompile_enum); // implement + let input = cpu.mmu.get_precompile_input(); // need to implement in mmu + let output = precompile.execute(input); // need to implement + cpu.get_mut_mmu.set_precompile_output(output); // need to implement + + + let exception_type = match cpu.privilege_mode { PrivilegeMode::User => TrapType::EnvironmentCallFromUMode, PrivilegeMode::Supervisor => TrapType::EnvironmentCallFromSMode, From 053d7f3ad3ae3504b7ce20d9e90f5be3b1c87842 Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Wed, 15 Jan 2025 16:20:50 -0800 Subject: [PATCH 09/20] added set_precompile_output_word() to mmu.rs --- tracer/src/emulator/cpu.rs | 22 +++++++++++----------- tracer/src/emulator/mmu.rs | 8 ++++++++ 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/tracer/src/emulator/cpu.rs b/tracer/src/emulator/cpu.rs index 54087df5b..3eb40231d 100644 --- a/tracer/src/emulator/cpu.rs +++ b/tracer/src/emulator/cpu.rs @@ -2515,23 +2515,23 @@ pub const INSTRUCTIONS: [Instruction; INSTRUCTION_NUM] = [ name: "ECALL", operation: |cpu, _word, address| { let precompile_enum = cpu.read_register(5); - let precompile = Precompile::from_u64(precompile_enum); // implement + let precompile = Precompile::from_u64(precompile_enum); // nneed to implement let input = cpu.mmu.get_precompile_input(); // need to implement in mmu let output = precompile.execute(input); // need to implement cpu.get_mut_mmu.set_precompile_output(output); // need to implement - let exception_type = match cpu.privilege_mode { - PrivilegeMode::User => TrapType::EnvironmentCallFromUMode, - PrivilegeMode::Supervisor => TrapType::EnvironmentCallFromSMode, - PrivilegeMode::Machine => TrapType::EnvironmentCallFromMMode, - PrivilegeMode::Reserved => panic!("Unknown Privilege mode"), - }; - Err(Trap { - trap_type: exception_type, - value: address, - }) + // let exception_type = match cpu.privilege_mode { + // PrivilegeMode::User => TrapType::EnvironmentCallFromUMode, + // PrivilegeMode::Supervisor => TrapType::EnvironmentCallFromSMode, + // PrivilegeMode::Machine => TrapType::EnvironmentCallFromMMode, + // PrivilegeMode::Reserved => panic!("Unknown Privilege mode"), + // }; + // Err(Trap { + // trap_type: exception_type, + // value: address, + // }) }, disassemble: dump_empty, trace: None, diff --git a/tracer/src/emulator/mmu.rs b/tracer/src/emulator/mmu.rs index f8245b6cc..b26cfa994 100644 --- a/tracer/src/emulator/mmu.rs +++ b/tracer/src/emulator/mmu.rs @@ -1150,6 +1150,14 @@ impl Mmu { pub fn get_mut_uart(&mut self) -> &mut Uart { &mut self.uart } + + /// Sets the precompile output to the correct location in memory designated for precompile outputs. + pub fn set_precompile_output_word(&mut self, v_address: u64, p_address: u64) { + // Load the world from virtual memory. + let output_word = self.load_word(v_address); + // Store the word in the correct precompile output memory location + self.store_word(p_address, output_word); + } } /// [`Memory`](../memory/struct.Memory.html) wrapper. Converts physical address to the one in memory From da40ee39cfb4822a83f924b03a309aecbaf18f49 Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Wed, 15 Jan 2025 16:38:25 -0800 Subject: [PATCH 10/20] updated mmu precompile methods --- tracer/src/emulator/mmu.rs | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/tracer/src/emulator/mmu.rs b/tracer/src/emulator/mmu.rs index b26cfa994..ccfd52e78 100644 --- a/tracer/src/emulator/mmu.rs +++ b/tracer/src/emulator/mmu.rs @@ -1151,10 +1151,15 @@ impl Mmu { &mut self.uart } - /// Sets the precompile output to the correct location in memory designated for precompile outputs. - pub fn set_precompile_output_word(&mut self, v_address: u64, p_address: u64) { + /// Gets the precompile input from the correct location in memory designated for precompile inputs. + pub fn get_precompile_input_word(&mut self, v_address: u64) -> Result { // Load the world from virtual memory. - let output_word = self.load_word(v_address); + let input_word = self.load_word(v_address); + input_word + } + + /// Sets the precompile output to the correct location in memory designated for precompile outputs. + pub fn set_precompile_output_word(&mut self, output_word: u32, p_address: u64) { // Store the word in the correct precompile output memory location self.store_word(p_address, output_word); } From 3f38bd5e37e8d2e872c9f2fc10a9fa614799c06b Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Wed, 15 Jan 2025 17:25:02 -0800 Subject: [PATCH 11/20] updated cpu.rs --- common/precompiles/mod.rs | 17 ++++++++++++++++- tracer/src/emulator/cpu.rs | 16 ++++++++++------ 2 files changed, 26 insertions(+), 7 deletions(-) diff --git a/common/precompiles/mod.rs b/common/precompiles/mod.rs index 857065c08..73b760880 100644 --- a/common/precompiles/mod.rs +++ b/common/precompiles/mod.rs @@ -1,7 +1,22 @@ pub mod bn254_add; -enum Precompile { +pub enum Precompile { Bn254_add, } +impl Precompile { + pub fn from_u64(value: u64) -> Option { + match value { + 0 => None, + 1 => Some(Precompile::Bn254_add), + _ => None, + } + } + + pub fn execute(&self, inputs: &[u8]) -> Vec { + match self { + Precompile::Bn254_add => bn254_add::bn254_add(inputs), + } + } +} // trait to deserialize the raw input bytes and serialize the outputs diff --git a/tracer/src/emulator/cpu.rs b/tracer/src/emulator/cpu.rs index 3eb40231d..44e5637ad 100644 --- a/tracer/src/emulator/cpu.rs +++ b/tracer/src/emulator/cpu.rs @@ -8,6 +8,7 @@ use std::str::FromStr; use crate::trace::Tracer; use common::rv_trace::*; +use common::precompiles; use self::fnv::FnvHashMap; @@ -2513,14 +2514,17 @@ pub const INSTRUCTIONS: [Instruction; INSTRUCTION_NUM] = [ mask: 0xffffffff, data: 0x00000073, name: "ECALL", - operation: |cpu, _word, address| { + operation: |cpu, _word, _address| { + // make sure that the t0 register contains non zero value + assert_ne!(cpu.read_register(5), 0, "No precompile enum provided in t0 register."); let precompile_enum = cpu.read_register(5); - let precompile = Precompile::from_u64(precompile_enum); // nneed to implement - let input = cpu.mmu.get_precompile_input(); // need to implement in mmu - let output = precompile.execute(input); // need to implement - cpu.get_mut_mmu.set_precompile_output(output); // need to implement + let precompile = Precompile::from_u64(precompile_enum).expect("invalid precompile"); - + let precompile_input_address = 0_u64; // @TODO: which address should be supplied to fetch the input? + let inputs = cpu.mmu.get_precompile_input(precompile_input_address); // which address should be supplied to fetch the input? + let output = precompile.execute(input); + let precompile_output_address = 0_u64; // @TODO: which address should be supplied to store the output? + cpu.get_mut_mmu.set_precompile_output(output, precompile_output_address); // let exception_type = match cpu.privilege_mode { // PrivilegeMode::User => TrapType::EnvironmentCallFromUMode, From f65d5f3886f98b1c366559b969a9b79c8622b80b Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Wed, 15 Jan 2025 17:28:24 -0800 Subject: [PATCH 12/20] added ok(()) to ecall method --- tracer/src/emulator/cpu.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/tracer/src/emulator/cpu.rs b/tracer/src/emulator/cpu.rs index 44e5637ad..f668c0597 100644 --- a/tracer/src/emulator/cpu.rs +++ b/tracer/src/emulator/cpu.rs @@ -2525,6 +2525,7 @@ pub const INSTRUCTIONS: [Instruction; INSTRUCTION_NUM] = [ let output = precompile.execute(input); let precompile_output_address = 0_u64; // @TODO: which address should be supplied to store the output? cpu.get_mut_mmu.set_precompile_output(output, precompile_output_address); + Ok(()) // let exception_type = match cpu.privilege_mode { // PrivilegeMode::User => TrapType::EnvironmentCallFromUMode, From e85ddbe45c32d0a66e3280cd37cd6c2ceded03c7 Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Wed, 15 Jan 2025 17:45:14 -0800 Subject: [PATCH 13/20] updated precompile mod.rs for jolt-core --- jolt-core/src/jolt/precompiles/mod.rs | 50 +++++++++++++++++++++++---- 1 file changed, 44 insertions(+), 6 deletions(-) diff --git a/jolt-core/src/jolt/precompiles/mod.rs b/jolt-core/src/jolt/precompiles/mod.rs index 486c03df4..68727e810 100644 --- a/jolt-core/src/jolt/precompiles/mod.rs +++ b/jolt-core/src/jolt/precompiles/mod.rs @@ -1,11 +1,5 @@ pub mod bn254_add; -enum Precompile { - Bn254_add, - Bn254_mul, - Sha256, -} - pub struct PrecompileIO { pub input:[u32; 16] // 512 bits pub output:[u32; 16] // 512 bits @@ -45,3 +39,47 @@ struct PrecompileWitness { pub a14o: [u8; 32], pub a15o: [u8; 32], } + +trait Precompile { + pub fn format_io(&self, inputs: impl Serialize, outputs: impl Serialize) -> PrecompileIO; + pub fn generate_witness(&self, io: PrecompileIO) -> PrecompileWitness { + // This is a placeholder for the actual implementation. + PrecompileWitness { + precompile: self, + a0i: io.input[0], + a1i: io.input[1], + a2i: io.input[2], + a3i: io.input[3], + a4i: io.input[4], + a5i: io.input[5], + a6i: io.input[6], + a7i: io.input[7], + a8i: io.input[8], + a9i: io.input[9], + a10i: io.input[10], + a11i: io.input[11], + a12i: io.input[12], + a13i: io.input[13], + a14i: io.input[14], + a15i: io.input[15], + a0o: io.output[0], + a1o: io.output[1], + a2o: io.output[2], + a3o: io.output[3], + a4o: io.output[4], + a5o: io.output[5], + a6o: io.output[6], + a7o: io.output[7], + a8o: io.output[8], + a9o: io.output[9], + a10o: io.output[10], + a11o: io.output[11], + a12o: io.output[12], + a13o: io.output[13], + a14o: io.output[14], + a15o: io.output[15], + } + }; + pub fn prove(&self, witness: PrecompileWitness) -> JoltProof; // Need to include Preprocessing struct as an input? + pub fn verify(&self, proof: JoltProof) -> Result<(), ProofVerifyError>; +} From 691efe695ec46b9885733e1eb545f42a6f420e25 Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Wed, 15 Jan 2025 21:00:24 -0800 Subject: [PATCH 14/20] added 16 advice instruction to ecall.rs --- jolt-core/src/jolt/instruction/ecall.rs | 302 +++++++++++++++++++- jolt-core/src/jolt/precompiles/bn254_add.rs | 26 +- jolt-core/src/jolt/precompiles/mod.rs | 1 + jolt-sdk/macros/src/lib.rs | 16 +- 4 files changed, 332 insertions(+), 13 deletions(-) diff --git a/jolt-core/src/jolt/instruction/ecall.rs b/jolt-core/src/jolt/instruction/ecall.rs index 23b95c45b..4248ca8c8 100644 --- a/jolt-core/src/jolt/instruction/ecall.rs +++ b/jolt-core/src/jolt/instruction/ecall.rs @@ -15,7 +15,7 @@ use crate::jolt::instruction::{ pub struct EcallInstruction; impl VirtualInstructionSequence for EcallInstruction { - const SEQUENCE_LENGTH: usize = 8; // needs change? + const SEQUENCE_LENGTH: usize = 16; // 16 or 17? fn virtual_trace(trace_row: RVTraceRow) -> Vec { assert_eq!(trace_row.instruction.opcode, RV32IM::ECALL); @@ -31,9 +31,9 @@ impl VirtualInstructionSequence for EcallInstruction { let mut virtual_trace = vec![]; - let precompile_output = // compute precompile output based on t0 register + let precompile_output: &[u32; 16] = &[0u32; 16]; // compute precompile output based on t0 register - let q = ADVICEInstruction::(precompile_output).lookup_entry(); + let ao0 = ADVICEInstruction::(precompile_output[0]).lookup_entry(); virtual_trace.push(RVTraceRow { instruction: ELFInstruction { address: trace_row.instruction.address, @@ -50,28 +50,312 @@ impl VirtualInstructionSequence for EcallInstruction { rd_post_val: Some(q), }, memory_state: None, - advice_value: Some(precompile_output), + advice_value: Some(precompile_output[0]), }); + let ao1 = ADVICEInstruction::(precompile_output[1]).lookup_entry(); virtual_trace.push(RVTraceRow { instruction: ELFInstruction { address: trace_row.instruction.address, - opcode: RV32IM::VIRTUAL_MOVE, - rs1: v_q, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[1]), + }); + + let ao2 = ADVICEInstruction::(precompile_output[2]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[2]), + }); + + let ao3 = ADVICEInstruction::(precompile_output[3]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[3]), + }); + + let ao4 = ADVICEInstruction::(precompile_output[4]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[4]), + }); + + let ao5 = ADVICEInstruction::(precompile_output[5]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, rs2: None, - rd: trace_row.instruction.rd, + rd: v_q, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { - rs1_val: Some(q), + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[5]), + }); + + let ao6 = ADVICEInstruction::(precompile_output[6]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[6]), + }); + + let ao7 = ADVICEInstruction::(precompile_output[7]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[7]), + }); + + let ao8 = ADVICEInstruction::(precompile_output[8]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, rs2_val: None, rd_post_val: Some(q), }, memory_state: None, - advice_value: None, + advice_value: Some(precompile_output[8]), }); + let ao9 = ADVICEInstruction::(precompile_output[9]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[9]), + }); + + let ao10 = ADVICEInstruction::(precompile_output[10]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[10]), + }); + + let ao11 = ADVICEInstruction::(precompile_output[11]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[11]), + }); + + let ao12 = ADVICEInstruction::(precompile_output[12]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[12]), + }); + + let ao13 = ADVICEInstruction::(precompile_output[13]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[13]), + }); + + let ao14 = ADVICEInstruction::(precompile_output[14]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[14]), + }); + + let ao15 = ADVICEInstruction::(precompile_output[15]).lookup_entry(); + virtual_trace.push(RVTraceRow { + instruction: ELFInstruction { + address: trace_row.instruction.address, + opcode: RV32IM::VIRTUAL_ADVICE, + rs1: None, + rs2: None, + rd: v_q, + imm: None, + virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), + }, + register_state: RegisterState { + rs1_val: None, + rs2_val: None, + rd_post_val: Some(q), + }, + memory_state: None, + advice_value: Some(precompile_output[15]), + }); + + + + virtual_trace } } diff --git a/jolt-core/src/jolt/precompiles/bn254_add.rs b/jolt-core/src/jolt/precompiles/bn254_add.rs index 492f57f17..d9a20eac7 100644 --- a/jolt-core/src/jolt/precompiles/bn254_add.rs +++ b/jolt-core/src/jolt/precompiles/bn254_add.rs @@ -1 +1,25 @@ -// R1CS implementation of the addition operation for the BN254 curve. +use super::*; + +pub struct Bn254Add { + pub inputs: Vec, + pub outputs: Vec, +} + +impl Precompile for Bn254Add { + pub fn format_io(inputs: Vec, outputs: Vec) -> PrecompileIO { + // Todo(); + } + pub fn generate_witness(io: PrecompileIO) -> PrecompileWitness { + // Todo(); + } + pub fn execute(inputs: Vec) -> Vec { + // Todo(); + // import from common/precompiles/bn254_add.rs + } + pub fn prove(witness: PrecompileWitness) -> JoltProof { + // Todo(); + } + pub fn verify(proof: JoltProof) -> Result<(), ProofVerifyError> { + // Todo(); + } +} diff --git a/jolt-core/src/jolt/precompiles/mod.rs b/jolt-core/src/jolt/precompiles/mod.rs index 68727e810..81348e2f5 100644 --- a/jolt-core/src/jolt/precompiles/mod.rs +++ b/jolt-core/src/jolt/precompiles/mod.rs @@ -42,6 +42,7 @@ struct PrecompileWitness { trait Precompile { pub fn format_io(&self, inputs: impl Serialize, outputs: impl Serialize) -> PrecompileIO; + pub fn execute(&self, inputs: impl Serialize) -> Vec; pub fn generate_witness(&self, io: PrecompileIO) -> PrecompileWitness { // This is a placeholder for the actual implementation. PrecompileWitness { diff --git a/jolt-sdk/macros/src/lib.rs b/jolt-sdk/macros/src/lib.rs index 48ee1ae27..e6e6746ad 100644 --- a/jolt-sdk/macros/src/lib.rs +++ b/jolt-sdk/macros/src/lib.rs @@ -14,9 +14,12 @@ use syn::{parse_macro_input, AttributeArgs, Ident, ItemFn, PatType, ReturnType, static WASM_IMPORTS_INIT: Once = Once::new(); #[proc_macro_attribute] -pub fn provable(attr: TokenStream, item: TokenStream) -> TokenStream { +pub fn provable(attr: TokenStream, item: TokenStream, precompile: Option) -> TokenStream { let attr = parse_macro_input!(attr as AttributeArgs); let func = parse_macro_input!(item as ItemFn); + if let Some(precompile_func) = precompile.map(|precompile| { + parse_macro_input!(precompile as ItemFn) + }); let mut builder = MacroBuilder::new(attr, func); let mut token_stream = builder.build(); @@ -40,11 +43,16 @@ struct MacroBuilder { func: ItemFn, std: bool, func_args: Vec<(Ident, Box)>, + precompile_func: Option, + precompile_func_args: Option)>>, } impl MacroBuilder { - fn new(attr: AttributeArgs, func: ItemFn) -> Self { + fn new(attr: AttributeArgs, func: ItemFn, precompile_func: Option) -> Self { let func_args = Self::get_func_args(&func); + if let Some(precompile_func_args) = precompile_func.map(|precompile_func| { + Self::get_func_args(&precompile_func) + }); #[cfg(feature = "guest-std")] let std = true; #[cfg(not(feature = "guest-std"))] @@ -55,6 +63,8 @@ impl MacroBuilder { func, std, func_args, + precompile_func, + precompile_func_args, } } @@ -572,7 +582,7 @@ impl MacroBuilder { } } - fn make_precompile_fn(&self, precompile_enum: PrecompileEnum) -> TokenStream2 { + fn make_build_precompile_fn(&self, precompile_enum: PrecompileEnum) -> TokenStream2 { // Iterate over the inputs // Serialize the inputs from the array using correct type asm!( From b70ce3c32542994684fa912fa3a2262d71a215f2 Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Wed, 15 Jan 2025 23:48:46 -0800 Subject: [PATCH 15/20] added 16 advice instructions to ecall.rs --- jolt-core/src/jolt/instruction/ecall.rs | 86 ++++++++++++++----------- 1 file changed, 49 insertions(+), 37 deletions(-) diff --git a/jolt-core/src/jolt/instruction/ecall.rs b/jolt-core/src/jolt/instruction/ecall.rs index 4248ca8c8..a2d8c245f 100644 --- a/jolt-core/src/jolt/instruction/ecall.rs +++ b/jolt-core/src/jolt/instruction/ecall.rs @@ -24,10 +24,22 @@ impl VirtualInstructionSequence for EcallInstruction { let r_y = trace_row.instruction.rs2; // Virtual registers used in sequence let v_0 = Some(virtual_register_index(0)); - let v_q: Option = Some(virtual_register_index(1)); - // Precompile input - let x = trace_row.register_state.rs1_val.unwrap(); - let y = trace_row.register_state.rs2_val.unwrap(); + let v_ao0: Option = Some(virtual_register_index(1)); + let v_ao1: Option = Some(virtual_register_index(2)); + let v_ao2: Option = Some(virtual_register_index(3)); + let v_ao3: Option = Some(virtual_register_index(4)); + let v_ao4: Option = Some(virtual_register_index(5)); + let v_ao5: Option = Some(virtual_register_index(6)); + let v_ao6: Option = Some(virtual_register_index(7)); + let v_ao7: Option = Some(virtual_register_index(8)); + let v_ao8: Option = Some(virtual_register_index(9)); + let v_ao9: Option = Some(virtual_register_index(10)); + let v_ao10: Option = Some(virtual_register_index(11)); + let v_ao11: Option = Some(virtual_register_index(12)); + let v_ao12: Option = Some(virtual_register_index(13)); + let v_ao13: Option = Some(virtual_register_index(14)); + let v_ao14: Option = Some(virtual_register_index(15)); + let v_ao15: Option = Some(virtual_register_index(16)); let mut virtual_trace = vec![]; @@ -40,14 +52,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao0, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao0), }, memory_state: None, advice_value: Some(precompile_output[0]), @@ -60,14 +72,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao1, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao1), }, memory_state: None, advice_value: Some(precompile_output[1]), @@ -80,14 +92,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao2, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao2), }, memory_state: None, advice_value: Some(precompile_output[2]), @@ -100,14 +112,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao3, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao3), }, memory_state: None, advice_value: Some(precompile_output[3]), @@ -120,14 +132,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao4, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao4), }, memory_state: None, advice_value: Some(precompile_output[4]), @@ -140,14 +152,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao5, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao5), }, memory_state: None, advice_value: Some(precompile_output[5]), @@ -160,14 +172,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao6, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao6), }, memory_state: None, advice_value: Some(precompile_output[6]), @@ -180,14 +192,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao7, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao7), }, memory_state: None, advice_value: Some(precompile_output[7]), @@ -200,14 +212,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao8, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao8), }, memory_state: None, advice_value: Some(precompile_output[8]), @@ -220,14 +232,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao9, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao9), }, memory_state: None, advice_value: Some(precompile_output[9]), @@ -240,14 +252,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao10, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(a10), }, memory_state: None, advice_value: Some(precompile_output[10]), @@ -260,14 +272,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao11, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao11), }, memory_state: None, advice_value: Some(precompile_output[11]), @@ -280,14 +292,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_a012, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao12), }, memory_state: None, advice_value: Some(precompile_output[12]), @@ -300,14 +312,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao13, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao13), }, memory_state: None, advice_value: Some(precompile_output[13]), @@ -320,14 +332,14 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao14, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao14), }, memory_state: None, advice_value: Some(precompile_output[14]), @@ -340,21 +352,21 @@ impl VirtualInstructionSequence for EcallInstruction { opcode: RV32IM::VIRTUAL_ADVICE, rs1: None, rs2: None, - rd: v_q, + rd: v_ao15, imm: None, virtual_sequence_remaining: Some(Self::SEQUENCE_LENGTH - virtual_trace.len() - 1), }, register_state: RegisterState { rs1_val: None, rs2_val: None, - rd_post_val: Some(q), + rd_post_val: Some(ao15), }, memory_state: None, advice_value: Some(precompile_output[15]), }); - + // TODO: Implement the precompile call instruction virtual_trace } From 8f065793e3e771912120b1d1b7b0cc4ca02367be Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Thu, 16 Jan 2025 00:14:42 -0800 Subject: [PATCH 16/20] added conditional for precompile output to load method --- common/src/rv_trace.rs | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/common/src/rv_trace.rs b/common/src/rv_trace.rs index eb3f32f05..8a0c25f34 100644 --- a/common/src/rv_trace.rs +++ b/common/src/rv_trace.rs @@ -626,8 +626,6 @@ impl JoltDevice { } else { self.outputs[internal_address] } - } else { - 0 // zero-padding } else if self.is_precompile_input(address) { let internal_address = self.convert_read_address(address); if self.precompile_inputs.len() <= internal_address { @@ -635,8 +633,16 @@ impl JoltDevice { } else { self.precompile_inputs[internal_address] } + } else if self.is_precompile_output(address) { + let internal_address = self.convert_write_address(address); + if self.precompile_outputs.len() <= internal_address { + 0 + } else { + self.precompile_outputs[internal_address] + } + } else { + 0 // zero-padding } - // Add conditional for loading precompile output } pub fn store(&mut self, address: u64, value: u8) { From e813eac5123f24ac4fe692b024d0e80d5fee8db8 Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Thu, 16 Jan 2025 00:15:51 -0800 Subject: [PATCH 17/20] fixed typo --- common/src/rv_trace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/rv_trace.rs b/common/src/rv_trace.rs index 8a0c25f34..8685b9cff 100644 --- a/common/src/rv_trace.rs +++ b/common/src/rv_trace.rs @@ -634,7 +634,7 @@ impl JoltDevice { self.precompile_inputs[internal_address] } } else if self.is_precompile_output(address) { - let internal_address = self.convert_write_address(address); + let internal_address = self.convert_read_address(address); if self.precompile_outputs.len() <= internal_address { 0 } else { From b3b57ae2f29a9395dc42f00c93f33e442f01cf8a Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Thu, 16 Jan 2025 00:27:44 -0800 Subject: [PATCH 18/20] unsure of how to handle store() method in rv_trace.rs --- common/src/rv_trace.rs | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/common/src/rv_trace.rs b/common/src/rv_trace.rs index 8685b9cff..4ff229f2e 100644 --- a/common/src/rv_trace.rs +++ b/common/src/rv_trace.rs @@ -657,14 +657,19 @@ impl JoltDevice { } let internal_address = self.convert_write_address(address); + if self.outputs.len() <= internal_address { self.outputs.resize(internal_address + 1, 0); } - else if self.precompile_outputs(address) { - self.precompile_outputs[internal_address] = value; - return; + + if self.precompile_inputs(address) { + // todo() } - // add conditional for storing precompile input + + if self.precompile_outputs(address) { + //todo() + } + self.outputs[internal_address] = value; } From 9499b185362c44ac4c2a6459b5a27298ddc52380 Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Thu, 16 Jan 2025 10:32:34 -0800 Subject: [PATCH 19/20] refactored rv_trace.rs to include conditionals for precompiles in store method --- common/src/rv_trace.rs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/common/src/rv_trace.rs b/common/src/rv_trace.rs index 4ff229f2e..20509492e 100644 --- a/common/src/rv_trace.rs +++ b/common/src/rv_trace.rs @@ -662,12 +662,12 @@ impl JoltDevice { self.outputs.resize(internal_address + 1, 0); } - if self.precompile_inputs(address) { - // todo() + if self.precompile_outputs.len() <= internal_address { + self.precompile_outputs.resize(internal_address + 1, 0); } - if self.precompile_outputs(address) { - //todo() + if self.precompile_outputs.len() <= internal_address { + self.precompile_outputs.resize(internal_address + 1, 0); } self.outputs[internal_address] = value; From c972066b3b2ee11059f16f300f456d2f47c28a4e Mon Sep 17 00:00:00 2001 From: Roy Rotstein Date: Thu, 16 Jan 2025 10:36:51 -0800 Subject: [PATCH 20/20] added correct address for panic mem region --- common/src/rv_trace.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/common/src/rv_trace.rs b/common/src/rv_trace.rs index 20509492e..72fa6e1b7 100644 --- a/common/src/rv_trace.rs +++ b/common/src/rv_trace.rs @@ -749,7 +749,7 @@ impl MemoryLayout { let precompile_input_end = precompile_input_start + 16; // 512 bits let precompile_output_start = precompile_input_end; let precompile_output_end = precompile_output_start + 16; // 512 bits - let panic = output_end; + let panic = precompile_output_end; let termination = panic + 4; Self {