Skip to content

Commit

Permalink
refactor!: make lengths of master tables' rows compile-time known
Browse files Browse the repository at this point in the history
  • Loading branch information
jan-ferdinand committed Feb 8, 2024
1 parent b03064d commit e52f4cf
Show file tree
Hide file tree
Showing 8 changed files with 141 additions and 74 deletions.
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -52,7 +52,7 @@ strum = { version = "0.26", features = ["derive"] }
syn = "2.0"
test-strategy = "0.3.1"
thiserror = "1.0"
twenty-first = { git = "https://github.com/Neptune-Crypto/twenty-first", rev = "e708b305" }
twenty-first = { git = "https://github.com/Neptune-Crypto/twenty-first", rev = "8bee834e" }
unicode-width = "0.1"

[workspace.dependencies.cargo-husky]
Expand Down
6 changes: 6 additions & 0 deletions triton-vm/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -218,6 +218,12 @@ pub enum ProvingError {
#[error(transparent)]
CanonicalRepresentationError(#[from] CanonicalRepresentationError),

#[error("expected row of length {expected_len} but got {actual_len}")]
TableRowConversionError {
expected_len: usize,
actual_len: usize,
},

#[error(transparent)]
MerkleTreeError(#[from] MerkleTreeError),

Expand Down
1 change: 1 addition & 0 deletions triton-vm/src/prelude.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ pub use twenty_first::prelude::BFieldElement;
pub use twenty_first::prelude::Digest;
pub use twenty_first::prelude::Tip5;
pub use twenty_first::prelude::XFieldElement;
pub use twenty_first::shared_math::traits::FiniteField;

pub use crate::error::InstructionError;
pub use crate::instruction::LabelledInstruction;
Expand Down
18 changes: 9 additions & 9 deletions triton-vm/src/proof_item.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,9 @@ use twenty_first::prelude::*;
use crate::error::ProofStreamError;
use crate::error::ProofStreamError::UnexpectedItem;
use crate::fri::AuthenticationStructure;
use crate::stark::NUM_QUOTIENT_SEGMENTS;
use crate::table::BaseRow;
use crate::table::ExtensionRow;
use crate::table::QuotientSegments;

/// A `FriResponse` is an `AuthenticationStructure` together with the values of the
/// revealed leaves of the Merkle tree. Together, they correspond to the
Expand Down Expand Up @@ -97,18 +99,16 @@ macro_rules! proof_items {

proof_items!(
MerkleRoot(Digest) => true, try_into_merkle_root,
OutOfDomainBaseRow(Vec<XFieldElement>) => true, try_into_out_of_domain_base_row,
OutOfDomainExtRow(Vec<XFieldElement>) => true, try_into_out_of_domain_ext_row,
OutOfDomainQuotientSegments([XFieldElement; NUM_QUOTIENT_SEGMENTS]) => true,
try_into_out_of_domain_quot_segments,
OutOfDomainBaseRow(Box<BaseRow<XFieldElement>>) => true, try_into_out_of_domain_base_row,
OutOfDomainExtRow(Box<ExtensionRow>) => true, try_into_out_of_domain_ext_row,
OutOfDomainQuotientSegments(QuotientSegments) => true, try_into_out_of_domain_quot_segments,

// the following are implied by some Merkle root, thus not included in the Fiat-Shamir heuristic
AuthenticationStructure(AuthenticationStructure) => false, try_into_authentication_structure,
MasterBaseTableRows(Vec<Vec<BFieldElement>>) => false, try_into_master_base_table_rows,
MasterExtTableRows(Vec<Vec<XFieldElement>>) => false, try_into_master_ext_table_rows,
MasterBaseTableRows(Vec<BaseRow<BFieldElement>>) => false, try_into_master_base_table_rows,
MasterExtTableRows(Vec<ExtensionRow>) => false, try_into_master_ext_table_rows,
Log2PaddedHeight(u32) => false, try_into_log2_padded_height,
QuotientSegmentsElements(Vec<[XFieldElement; NUM_QUOTIENT_SEGMENTS]>) => false,
try_into_quot_segments_elements,
QuotientSegmentsElements(Vec<QuotientSegments>) => false, try_into_quot_segments_elements,
FriCodeword(Vec<XFieldElement>) => false, try_into_fri_codeword,
FriResponse(FriResponse) => false, try_into_fri_response,
);
Expand Down
16 changes: 8 additions & 8 deletions triton-vm/src/proof_stream.rs
Original file line number Diff line number Diff line change
Expand Up @@ -144,19 +144,19 @@ mod tests {
use crate::proof_item::ProofItem;
use crate::shared_tests::LeavedMerkleTreeTestData;
use crate::stark::MTMaker;
use crate::stark::NUM_QUOTIENT_SEGMENTS;
use crate::table::master_table::NUM_BASE_COLUMNS;
use crate::table::master_table::NUM_EXT_COLUMNS;
use crate::table::BaseRow;
use crate::table::ExtensionRow;
use crate::table::QuotientSegments;

use super::*;

#[proptest]
fn serialize_proof_with_fiat_shamir(
#[strategy(vec(vec(arb(), NUM_BASE_COLUMNS), 2..100))] base_rows: Vec<Vec<BFieldElement>>,
#[strategy(vec(vec(arb(), NUM_EXT_COLUMNS), 2..100))] ext_rows: Vec<Vec<XFieldElement>>,
#[strategy(vec(arb(), NUM_BASE_COLUMNS))] ood_base_row: Vec<XFieldElement>,
#[strategy(vec(arb(), NUM_EXT_COLUMNS))] ood_ext_row: Vec<XFieldElement>,
#[strategy(arb())] quot_elements: Vec<[XFieldElement; NUM_QUOTIENT_SEGMENTS]>,
#[strategy(vec(arb(), 2..100))] base_rows: Vec<BaseRow<BFieldElement>>,
#[strategy(vec(arb(), 2..100))] ext_rows: Vec<ExtensionRow>,
#[strategy(arb())] ood_base_row: Box<BaseRow<XFieldElement>>,
#[strategy(arb())] ood_ext_row: Box<ExtensionRow>,
#[strategy(arb())] quot_elements: Vec<QuotientSegments>,
leaved_merkle_tree: LeavedMerkleTreeTestData,
) {
let auth_structure = leaved_merkle_tree.auth_structure.clone();
Expand Down
73 changes: 40 additions & 33 deletions triton-vm/src/stark.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ use crate::proof_stream::ProofStream;
use crate::table::challenges::Challenges;
use crate::table::extension_table::Evaluable;
use crate::table::master_table::*;
use crate::table::QuotientSegments;

pub type StarkHasher = Tip5;
pub type StarkProofStream = ProofStream<StarkHasher>;
Expand All @@ -43,7 +44,7 @@ pub type MTMaker = CpuParallel;

/// The number of segments the quotient polynomial is split into.
/// Helps keeping the FRI domain small.
pub(crate) const NUM_QUOTIENT_SEGMENTS: usize = AIR_TARGET_DEGREE as usize;
pub const NUM_QUOTIENT_SEGMENTS: usize = AIR_TARGET_DEGREE as usize;

const NUM_DEEP_CODEWORD_COMPONENTS: usize = 3;

Expand Down Expand Up @@ -268,18 +269,21 @@ impl Stark {
let out_of_domain_point_curr_row = proof_stream.sample_scalars(1)[0];
let out_of_domain_point_next_row = trace_domain_generator * out_of_domain_point_curr_row;

proof_stream.enqueue(ProofItem::OutOfDomainBaseRow(
master_base_table.row(out_of_domain_point_curr_row).to_vec(),
));
proof_stream.enqueue(ProofItem::OutOfDomainExtRow(
master_ext_table.row(out_of_domain_point_curr_row).to_vec(),
));
proof_stream.enqueue(ProofItem::OutOfDomainBaseRow(
master_base_table.row(out_of_domain_point_next_row).to_vec(),
));
proof_stream.enqueue(ProofItem::OutOfDomainExtRow(
master_ext_table.row(out_of_domain_point_next_row).to_vec(),
));
let ood_base_row = master_base_table.row(out_of_domain_point_curr_row);
let ood_base_row = MasterBaseTable::try_to_base_row(ood_base_row)?;
proof_stream.enqueue(ProofItem::OutOfDomainBaseRow(Box::new(ood_base_row)));

let ood_ext_row = master_ext_table.row(out_of_domain_point_curr_row);
let ood_ext_row = MasterExtTable::try_to_ext_row(ood_ext_row)?;
proof_stream.enqueue(ProofItem::OutOfDomainExtRow(Box::new(ood_ext_row)));

let ood_next_base_row = master_base_table.row(out_of_domain_point_next_row);
let ood_next_base_row = MasterBaseTable::try_to_base_row(ood_next_base_row)?;
proof_stream.enqueue(ProofItem::OutOfDomainBaseRow(Box::new(ood_next_base_row)));

let ood_next_ext_row = master_ext_table.row(out_of_domain_point_next_row);
let ood_next_ext_row = MasterExtTable::try_to_ext_row(ood_next_ext_row)?;
proof_stream.enqueue(ProofItem::OutOfDomainExtRow(Box::new(ood_next_ext_row)));

let out_of_domain_point_curr_row_pow_num_segments =
out_of_domain_point_curr_row.mod_pow_u32(NUM_QUOTIENT_SEGMENTS as u32);
Expand Down Expand Up @@ -441,7 +445,7 @@ impl Stark {
let revealed_base_elems = Self::get_revealed_elements(
master_base_table.fri_domain_table(),
&revealed_current_row_indices,
);
)?;
let base_authentication_structure =
base_merkle_tree.authentication_structure(&revealed_current_row_indices)?;
proof_stream.enqueue(ProofItem::MasterBaseTableRows(revealed_base_elems));
Expand All @@ -452,7 +456,7 @@ impl Stark {
let revealed_ext_elems = Self::get_revealed_elements(
master_ext_table.fri_domain_table(),
&revealed_current_row_indices,
);
)?;
let ext_authentication_structure =
ext_merkle_tree.authentication_structure(&revealed_current_row_indices)?;
proof_stream.enqueue(ProofItem::MasterExtTableRows(revealed_ext_elems));
Expand All @@ -462,7 +466,7 @@ impl Stark {

// Open quotient & combination codewords at the same positions as base & ext codewords.
let into_fixed_width_row =
|row: ArrayView1<_>| -> [_; NUM_QUOTIENT_SEGMENTS] { row.to_vec().try_into().unwrap() };
|row: ArrayView1<_>| -> QuotientSegments { row.to_vec().try_into().unwrap() };
let revealed_quotient_segments_rows = revealed_current_row_indices
.iter()
.map(|&i| fri_domain_quotient_segment_codewords.row(i))
Expand Down Expand Up @@ -631,14 +635,20 @@ impl Stark {
)
}

fn get_revealed_elements<FF: FiniteField>(
fn get_revealed_elements<const N: usize, FF: FiniteField>(
fri_domain_table: ArrayView2<FF>,
revealed_indices: &[usize],
) -> Vec<Vec<FF>> {
revealed_indices
.iter()
.map(|&idx| fri_domain_table.row(idx).to_vec())
.collect_vec()
) -> Result<Vec<[FF; N]>, ProvingError> {
let err = || ProvingError::TableRowConversionError {
expected_len: N,
actual_len: fri_domain_table.ncols(),
};
let row = |&row_idx| {
let row = fri_domain_table.row(row_idx).to_vec();
row.try_into().map_err(|_| err())
};

revealed_indices.iter().map(row).collect()
}

/// Apply the [DEEP update](Self::deep_update) to a polynomial in value form, _i.e._, to a
Expand Down Expand Up @@ -760,10 +770,10 @@ impl Stark {
.dequeue()?
.try_into_out_of_domain_quot_segments()?;

let out_of_domain_curr_base_row = Array1::from(out_of_domain_curr_base_row);
let out_of_domain_curr_ext_row = Array1::from(out_of_domain_curr_ext_row);
let out_of_domain_next_base_row = Array1::from(out_of_domain_next_base_row);
let out_of_domain_next_ext_row = Array1::from(out_of_domain_next_ext_row);
let out_of_domain_curr_base_row = Array1::from(out_of_domain_curr_base_row.to_vec());
let out_of_domain_curr_ext_row = Array1::from(out_of_domain_curr_ext_row.to_vec());
let out_of_domain_next_base_row = Array1::from(out_of_domain_next_base_row.to_vec());
let out_of_domain_next_ext_row = Array1::from(out_of_domain_next_ext_row.to_vec());
let out_of_domain_curr_row_quot_segments =
Array1::from(out_of_domain_curr_row_quot_segments.to_vec());
prof_stop!(maybe_profiler, "dequeue ood point and rows");
Expand Down Expand Up @@ -983,7 +993,7 @@ impl Stark {
) {
prof_itr0!(maybe_profiler, "main loop");
let (current_ext_row, randomizer_row) = ext_row.split_at(NUM_EXT_COLUMNS);
let base_row = Array1::from(base_row);
let base_row = Array1::from(base_row.to_vec());
let ext_row = Array1::from(current_ext_row.to_vec());
let randomizer_row = Array1::from(randomizer_row.to_vec());
let current_fri_domain_value = fri.domain.domain_value(row_idx as u32);
Expand Down Expand Up @@ -1038,12 +1048,9 @@ impl Stark {
Ok(())
}

fn hash_quotient_segment_elements(
quotient_segment_rows: &[[XFieldElement; NUM_QUOTIENT_SEGMENTS]],
) -> Vec<Digest> {
fn hash_quotient_segment_elements(quotient_segment_rows: &[QuotientSegments]) -> Vec<Digest> {
let interpret_xfe_as_bfes = |xfe: XFieldElement| xfe.coefficients.to_vec();
let collect_row_as_bfes =
|row: &[_; NUM_QUOTIENT_SEGMENTS]| row.map(interpret_xfe_as_bfes).concat();
let collect_row_as_bfes = |row: &QuotientSegments| row.map(interpret_xfe_as_bfes).concat();
quotient_segment_rows
.par_iter()
.map(collect_row_as_bfes)
Expand Down Expand Up @@ -1078,7 +1085,6 @@ impl Stark {

#[cfg(test)]
pub(crate) mod tests {
use crate::error::InstructionError;
use assert2::assert;
use assert2::check;
use assert2::let_assert;
Expand All @@ -1091,6 +1097,7 @@ pub(crate) mod tests {
use test_strategy::proptest;
use twenty_first::shared_math::other::random_elements;

use crate::error::InstructionError;
use crate::example_programs::*;
use crate::instruction::Instruction;
use crate::op_stack::OpStackElement;
Expand Down
26 changes: 26 additions & 0 deletions triton-vm/src/table.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,9 @@
use twenty_first::prelude::XFieldElement;

pub use crate::stark::NUM_QUOTIENT_SEGMENTS;
pub use crate::table::master_table::NUM_BASE_COLUMNS;
pub use crate::table::master_table::NUM_EXT_COLUMNS;

pub mod cascade_table;
pub mod challenges;
pub mod constraint_circuit;
Expand All @@ -17,3 +23,23 @@ pub mod program_table;
pub mod ram_table;
pub mod table_column;
pub mod u32_table;

/// A single row of a [`MasterBaseTable`][table].
///
/// Usually, the elements in the table are [`BFieldElement`][bfe]s. For out-of-domain rows, which is
/// relevant for “Domain Extension to Eliminate Pretenders” (DEEP), the elements are
/// [`XFieldElement`]s.
///
/// [table]: master_table::MasterBaseTable
/// [bfe]: crate::prelude::BFieldElement
pub type BaseRow<T> = [T; NUM_BASE_COLUMNS];

/// A single row of a [`MasterExtensionTable`][table].
///
/// [table]: master_table::MasterExtTable
pub type ExtensionRow = [XFieldElement; NUM_EXT_COLUMNS];

/// An element of the split-up quotient polynomial.
///
/// See also [`NUM_QUOTIENT_SEGMENTS`].
pub type QuotientSegments = [XFieldElement; NUM_QUOTIENT_SEGMENTS];
Loading

0 comments on commit e52f4cf

Please sign in to comment.