Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: add I/O lookup elements #129

Merged
merged 1 commit into from
Dec 11, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 8 additions & 1 deletion crates/brainfuck_prover/src/brainfuck_air/mod.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
use crate::components::{
io::table::IoElements,
memory::{
self,
component::{MemoryComponent, MemoryEval},
Expand Down Expand Up @@ -62,14 +63,20 @@ impl BrainfuckClaim {
/// All the interaction elements (drawn from the channel)
/// required by the various components during the interaction phase.
pub struct BrainfuckInteractionElements {
pub input_lookup_elements: IoElements,
pub output_lookup_elements: IoElements,
pub memory_lookup_elements: MemoryElements,
}

impl BrainfuckInteractionElements {
/// Draw all the interaction elements needed for
/// all the components of the Brainfuck ZK-VM.
pub fn draw(channel: &mut impl Channel) -> Self {
Self { memory_lookup_elements: MemoryElements::draw(channel) }
Self {
input_lookup_elements: IoElements::draw(channel),
output_lookup_elements: IoElements::draw(channel),
memory_lookup_elements: MemoryElements::draw(channel),
}
}
}

Expand Down
68 changes: 62 additions & 6 deletions crates/brainfuck_prover/src/components/io/table.rs
Original file line number Diff line number Diff line change
@@ -1,12 +1,16 @@
use crate::components::{IoClaim, TraceColumn, TraceEval};
use brainfuck_vm::{instruction::InstructionType, registers::Registers};
use stwo_prover::core::{
backend::{
simd::{column::BaseColumn, m31::LOG_N_LANES},
Column,
use stwo_prover::{
constraint_framework::{logup::LookupElements, Relation, RelationEFTraitBound},
core::{
backend::{
simd::{column::BaseColumn, m31::LOG_N_LANES},
Column,
},
channel::Channel,
fields::m31::BaseField,
poly::circle::{CanonicCoset, CircleEvaluation},
},
fields::m31::BaseField,
poly::circle::{CanonicCoset, CircleEvaluation},
};

/// Represents a single row in the I/O Table.
Expand Down Expand Up @@ -180,6 +184,58 @@ impl TraceColumn for IoColumn {
}
}

/// The number of random elements necessary for the I/O lookup arguments.
const IO_LOOKUP_ELEMENTS: usize = 1;

/// The interaction elements are drawn for the extension column of the I/O components.
///
/// The logUp protocol uses these elements to combine the values of the different
/// registers of the main trace to create a random linear combination
/// of them, and use it in the denominator of the fractions in the logUp protocol.
///
/// There is a single lookup element in the I/O component: `mv`.
#[derive(Clone, Debug, Eq, PartialEq)]
pub struct IoElements(LookupElements<IO_LOOKUP_ELEMENTS>);

impl IoElements {
/// Provides dummy lookup elements.
pub fn dummy() -> Self {
Self(LookupElements::dummy())
}

/// Draw random elements from the Fiat-Shamir [`Channel`].
///
/// These elements are randomly secured, and will be use
/// to generate the interaction trace with the logUp protocol.
pub fn draw(channel: &mut impl Channel) -> Self {
Self(LookupElements::draw(channel))
}
}

impl<F: Clone, EF: RelationEFTraitBound<F>> Relation<F, EF> for IoElements {
/// Combine multiple values from a basefield (e.g. [`BaseField`])
/// and combine them to a value from an extension field (e.g. [`PackedSecureField`])
///
/// This is used when computing the interaction values from the main trace values.
fn combine(&self, values: &[F]) -> EF {
values
.iter()
.zip(self.0.alpha_powers)
.fold(EF::zero(), |acc, (value, power)| acc + EF::from(power) * value.clone()) -
self.0.z.into()
}

/// Returns the name of the struct.
fn get_name(&self) -> &str {
stringify!(IoElements)
}

/// Returns the number interaction elements.
fn get_size(&self) -> usize {
IO_LOOKUP_ELEMENTS
}
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down
Loading