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

Keccak precompiled #205

Draft
wants to merge 22 commits into
base: develop
Choose a base branch
from
Draft
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
39 changes: 39 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ members = [
"state-machines/std",
"witness-computation",
"ziskos/entrypoint",
"precompiles/zisk_precompiles",
"precompiles/common",
]

resolver = "2"
Expand Down
4 changes: 2 additions & 2 deletions core/src/riscv2zisk_context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1699,8 +1699,8 @@ pub fn add_entry_exit_jmp(rom: &mut ZiskRom, addr: u64) {
// :0044
// Call the keccak precompiled opcode
let mut zib = ZiskInstBuilder::new(rom.next_init_inst_addr);
zib.src_a("reg", 11, false);
zib.src_b("imm", 0, false);
zib.src_a("step", 0, false);
zib.src_b("reg", 10, false);
zib.op("keccak").unwrap();
zib.j(4, 4);
zib.verbose("keccak");
Expand Down
137 changes: 137 additions & 0 deletions data-bus/src/data_bus_file.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
//! A module for reading and writing DataBus information to a file.
//!
//! The `DataBusFileReader` struct provides a utility for reading DataBus information from a plain
//! text file. The `DataBusFileWriter` struct provides a utility for writing DataBus information to
//! a file.

use std::{
fs::File,
io::{self, Read, Write},
str::FromStr,
};

pub struct DataBusFileReader;

impl DataBusFileReader {
/// Reads data from a plain text file and returns a vector of `(BusId, Payload)` tuples.
///
/// # File Format
/// Each line in the file should be formatted as:
/// ```text
/// <BusId> <Payload1> <Payload2> ...
/// ```
/// - `<BusId>`: A 16-bit unsigned integer representing the bus ID.
/// - `<PayloadN>`: A list of payload values convertible to the type `D`.
///
/// # Arguments
/// * `file_path` - The path to the plain text file.
///
/// # Returns
/// * `Result<Vec<(u16, Vec<D>)>, io::Error>`: A vector of `(BusId, Payload)` tuples or an error
/// if the file cannot be read or the data format is invalid.
///
/// # Errors
/// - Returns an error if the file cannot be opened or read.
/// - Returns an error if any line is malformed (missing `BusId` or invalid payload values).
pub fn read_from_file<D: FromStr>(file_path: &str) -> Result<Vec<(u16, Vec<D>)>, io::Error>
where
D::Err: std::fmt::Display,
{
let mut file = File::open(file_path)?;
let mut content = String::new();
file.read_to_string(&mut content)?;

// Estimate the number of lines for pre-allocation
let estimated_lines = content.lines().count();
let mut data = Vec::with_capacity(estimated_lines);

for (line_number, line) in content.lines().enumerate() {
let mut parts = line.split_whitespace();

// Parse the BusId (first token)
let bus_id = parts
.next()
.ok_or_else(|| {
io::Error::new(
io::ErrorKind::InvalidData,
format!("Missing BusId on line {}", line_number + 1),
)
})?
.parse::<u16>()
.map_err(|err| {
io::Error::new(
io::ErrorKind::InvalidData,
format!("Invalid BusId on line {}: {}", line_number + 1, err),
)
})?;

// Pre-allocate payload size if possible
let mut payload = Vec::with_capacity(parts.clone().count());

for token in parts {
let value = token.parse::<D>().map_err(|err| {
io::Error::new(
io::ErrorKind::InvalidData,
format!("Invalid payload on line {}: {}", line_number + 1, err),
)
})?;
payload.push(value);
}

// Push the parsed data into the pre-allocated vector
data.push((bus_id, payload));
}

Ok(data)
}
}

/// A utility struct for writing DataBus information to a file.
pub struct DataBusFileWriter {
file: Option<File>,
}

impl DataBusFileWriter {
/// Creates a new `DataBusFileWriter` and opens the specified file for writing.
///
/// # Arguments
/// * `file_path` - The path to the file where data will be written.
///
/// # Returns
/// A new instance of `DataBusFileWriter`.
pub fn new(file_path: &str) -> Result<Self, io::Error> {
let file = File::create(file_path)?;
Ok(Self { file: Some(file) })
}

/// Writes a single `(BusId, Payload)` line to the file.
///
/// # Arguments
/// * `bus_id` - The BusId to write.
/// * `payload` - A vector of payload items to write.
pub fn write<D: ToString>(&mut self, bus_id: u16, payload: &[D]) -> Result<(), io::Error> {
if let Some(file) = self.file.as_mut() {
let payload_str: String =
payload.iter().map(|item| item.to_string()).collect::<Vec<_>>().join(" ");
writeln!(file, "{} {}", bus_id, payload_str)?;
Ok(())
} else {
Err(io::Error::new(io::ErrorKind::Other, "Attempted to write to a closed file."))
}
}

/// Closes the file, ensuring all data is flushed to disk.
pub fn close(&mut self) -> Result<(), io::Error> {
if let Some(mut file) = self.file.take() {
file.flush()?; // Ensure all buffered data is written
}
Ok(())
}
}

impl Drop for DataBusFileWriter {
/// Ensures the file is closed when the `DataBusFileWriter` is dropped.
fn drop(&mut self) {
let _ = self.close(); // Silently ignore any errors during drop
}
}
40 changes: 40 additions & 0 deletions data-bus/src/data_bus_player.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
//! A player for replaying data on the `DataBus`.

use std::{io, str::FromStr};

use crate::{BusDevice, DataBus, DataBusFileReader};

pub struct DataBusPlayer;

impl DataBusPlayer {
/// Plays data on the `DataBus` from a provided data vector.
///
/// # Arguments
/// * `data_bus` - The `DataBus` to which the data is sent.
/// * `data` - A vector of `(BusId, Payload)` tuples.
pub fn play<D, BD: BusDevice<D>>(data_bus: &mut DataBus<D, BD>, data: Vec<(u16, Vec<D>)>) {
for (bus_id, payload) in data {
data_bus.write_to_bus(bus_id, payload);
}
}

/// Plays data on the `DataBus` from a file using `DataBusFileReader`.
///
/// # Arguments
/// * `file_path` - The path to the file containing the data.
/// * `data_bus` - The `DataBus` to which the data is sent.
///
/// # Returns
/// * `Result<(), io::Error>` indicating success or failure during file reading and playing.
pub fn play_from_file<D: FromStr, BD: BusDevice<D>>(
data_bus: &mut DataBus<D, BD>,
file_path: &str,
) -> Result<(), io::Error>
where
D::Err: std::fmt::Display,
{
let data = DataBusFileReader::read_from_file::<D>(file_path)?;
Self::play(data_bus, data);
Ok(())
}
}
4 changes: 4 additions & 0 deletions data-bus/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,13 @@
mod data_bus;
mod data_bus_file;
mod data_bus_mem;
mod data_bus_operation;
mod data_bus_player;
mod data_bus_rom;

pub use data_bus::*;
pub use data_bus_file::*;
pub use data_bus_mem::*;
pub use data_bus_operation::*;
pub use data_bus_player::*;
pub use data_bus_rom::*;
4 changes: 2 additions & 2 deletions executor/src/executor.rs
Original file line number Diff line number Diff line change
Expand Up @@ -283,7 +283,7 @@ impl<F: PrimeField> ZiskExecutor<F> {
}
}

if let Some(air_instance) = secn_instance.compute_witness(pctx) {
if let Some(air_instance) = secn_instance.compute_witness(None) {
pctx.air_instance_repo.add_air_instance(air_instance, global_id);
}
})
Expand Down Expand Up @@ -321,7 +321,7 @@ impl<F: PrimeField> ZiskExecutor<F> {

instances.iter_mut().for_each(|(global_idx, sec_instance)| {
if sec_instance.instance_type() == InstanceType::Table {
if let Some(air_instance) = sec_instance.compute_witness(pctx) {
if let Some(air_instance) = sec_instance.compute_witness(Some(pctx)) {
if pctx.dctx_is_my_instance(*global_idx) {
pctx.air_instance_repo.add_air_instance(air_instance, *global_idx);
}
Expand Down
32 changes: 26 additions & 6 deletions pil/src/pil_helpers/traces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,11 +45,15 @@ pub const BINARY_EXTENSION_AIR_IDS: &[usize] = &[12];

pub const BINARY_EXTENSION_TABLE_AIR_IDS: &[usize] = &[13];

pub const SPECIFIED_RANGES_AIR_IDS: &[usize] = &[14];
pub const KECCAKF_AIR_IDS: &[usize] = &[14];

pub const U_8_AIR_AIR_IDS: &[usize] = &[15];
pub const KECCAKF_TABLE_AIR_IDS: &[usize] = &[15];

pub const U_16_AIR_AIR_IDS: &[usize] = &[16];
pub const SPECIFIED_RANGES_AIR_IDS: &[usize] = &[16];

pub const U_8_AIR_AIR_IDS: &[usize] = &[17];

pub const U_16_AIR_AIR_IDS: &[usize] = &[18];


//PUBLICS
Expand Down Expand Up @@ -126,17 +130,25 @@ trace!(BinaryExtensionTableTrace<F> {
multiplicity: F,
}, 0, 13, 4194304 );

trace!(KeccakfTrace<F> {
free_in_a: [F; 6], free_in_b: [F; 6], free_in_c: [F; 6], multiplicity: F, debug_main_step: F, step_input: F, addr_input: F, a_src_mem: F, mem_step: F, c_src_mem: F,
}, 0, 14, 2097152 );

trace!(KeccakfTableTrace<F> {
multiplicity: F,
}, 0, 15, 2097152 );

trace!(SpecifiedRangesTrace<F> {
mul: [F; 2],
}, 0, 14, 16777216 );
}, 0, 16, 16777216 );

trace!(U8AirTrace<F> {
mul: F,
}, 0, 15, 256 );
}, 0, 17, 256 );

trace!(U16AirTrace<F> {
mul: F,
}, 0, 16, 65536 );
}, 0, 18, 65536 );

trace!(RomRomTrace<F> {
line: F, a_offset_imm0: F, a_imm1: F, b_offset_imm0: F, b_imm1: F, ind_width: F, op: F, store_offset: F, jmp_offset1: F, jmp_offset2: F, flags: F,
Expand Down Expand Up @@ -214,6 +226,14 @@ values!(BinaryExtensionTableAirGroupValues<F> {
gsum_result: FieldExtension<F>,
});

values!(KeccakfAirGroupValues<F> {
gsum_result: FieldExtension<F>,
});

values!(KeccakfTableAirGroupValues<F> {
gsum_result: FieldExtension<F>,
});

values!(SpecifiedRangesAirGroupValues<F> {
gsum_result: FieldExtension<F>,
});
Expand Down
12 changes: 9 additions & 3 deletions pil/zisk.pil
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ require "binary/pil/binary_table.pil"
require "binary/pil/binary_extension.pil"
require "binary/pil/binary_extension_table.pil"
require "arith/pil/arith.pil"
require "keccakf/pil/keccakf.pil"
require "keccakf/pil/keccakf_table.pil"

const int OPERATION_BUS_ID = 5000;

Expand All @@ -23,13 +25,17 @@ airgroup Zisk {
Mem(N: 2**21, RC: 2, base_address: 0x9000_0000, free_input_mem: 1, enable_flag: enable_input_data) alias InputData;

MemAlign(N: 2**21);
MemAlignRom(disable_fixed: 0);
MemAlignRom();

Arith(N: 2**21, operation_bus_id: OPERATION_BUS_ID);
ArithTable();
ArithRangeTable();
Binary(N: 2**21, operation_bus_id: OPERATION_BUS_ID);
BinaryTable(disable_fixed: 0);
BinaryTable();
BinaryExtension(N: 2**21, operation_bus_id: OPERATION_BUS_ID);
BinaryExtensionTable(disable_fixed: 0);
BinaryExtensionTable();

const int KECCAKF_BITS = 10;
Keccakf(N: 2**22, RC: 2, chunks: 6, bits: KECCAKF_BITS, bits_reduced: KECCAKF_BITS, operation_bus_id: OPERATION_BUS_ID);
KeccakfTable(N: 2**21, chunks: 1, bits: KECCAKF_BITS, bits_reduced: KECCAKF_BITS);
}
7 changes: 7 additions & 0 deletions precompiles/common/Cargo.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
[package]
name = "precompiles-common"
version = "0.1.0"
edition = "2021"

[dependencies]
zisk-core = { path = "../../core" }
Loading
Loading