Skip to content
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
5 changes: 4 additions & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
[workspace.package]
name = "leanMultisig"
version = "0.1.0"
edition = "2024"
rust-version = "1.85"
Expand Down Expand Up @@ -36,3 +35,7 @@ cast_sign_loss = "allow"
lean-isa = { path = "crates/leanIsa" }
lean-snark = { path = "crates/leanSnark" }
lean-vm = { path = "crates/leanVm" }

p3-field = { git = "https://github.com/Plonky3/Plonky3.git", rev = "d0c4a36" }
p3-baby-bear = { git = "https://github.com/Plonky3/Plonky3.git", rev = "d0c4a36" }
p3-koala-bear = { git = "https://github.com/Plonky3/Plonky3.git", rev = "d0c4a36" }
2 changes: 1 addition & 1 deletion crates/leanIsa/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "leanIsa"
name = "lean-isa"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/leanIsa/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

3 changes: 0 additions & 3 deletions crates/leanIsa/src/main.rs

This file was deleted.

2 changes: 1 addition & 1 deletion crates/leanSig/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "leanSig"
name = "lean-sig"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/leanSig/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

3 changes: 0 additions & 3 deletions crates/leanSig/src/main.rs

This file was deleted.

2 changes: 1 addition & 1 deletion crates/leanSnark/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "leanSnark"
name = "lean-snark"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
Expand Down
1 change: 1 addition & 0 deletions crates/leanSnark/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

3 changes: 0 additions & 3 deletions crates/leanSnark/src/main.rs

This file was deleted.

5 changes: 4 additions & 1 deletion crates/leanVm/Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
[package]
name = "leanVm"
name = "lean-vm"
version.workspace = true
edition.workspace = true
rust-version.workspace = true
Expand All @@ -9,3 +9,6 @@ license.workspace = true
workspace = true

[dependencies]
p3-baby-bear.workspace = true
p3-koala-bear.workspace = true
p3-field.workspace = true
1 change: 1 addition & 0 deletions crates/leanVm/src/lib.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod memory;
3 changes: 0 additions & 3 deletions crates/leanVm/src/main.rs

This file was deleted.

139 changes: 139 additions & 0 deletions crates/leanVm/src/memory/cell.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,139 @@
use std::ops::{Deref, DerefMut};

use p3_field::PrimeField64;

/// A memory cell used by the VM for storing 64-bit field elements with metadata.
///
/// Internally, the cell holds a single `u64` value.
/// The two most significant bits are reserved as flags:
/// - `BIT63` (NONE_MASK): indicates the cell is empty.
/// - `BIT62` (ACCESS_MASK): marks whether the cell has been accessed.
///
/// The remaining 62 bits store the canonical representation of a field element.
///
/// This design favors simplicity and cache efficiency over expressive power.
#[derive(Copy, Clone, Eq, Ord, PartialEq, PartialOrd, Debug)]
pub(crate) struct MemoryCell(u64);

impl Deref for MemoryCell {
type Target = u64;

fn deref(&self) -> &Self::Target {
&self.0
}
}

impl DerefMut for MemoryCell {
fn deref_mut(&mut self) -> &mut Self::Target {
&mut self.0
}
}

impl MemoryCell {
/// Flag bit indicating the cell is empty (bit 63 set).
pub(crate) const NONE_MASK: u64 = 1 << 63;
/// Flag bit indicating the cell was accessed (bit 62 set).
pub(crate) const ACCESS_MASK: u64 = 1 << 62;
/// Constant representing an empty cell.
pub(crate) const NONE: Self = Self(Self::NONE_MASK);

/// Creates a `MemoryCell` from a field element, using its canonical `u64` representation.
///
/// This clears any flag bits and assumes the value is valid.
pub(crate) fn from_f<F>(value: F) -> Self
where
F: PrimeField64,
{
Self(value.as_canonical_u64())
}

/// Creates a raw `MemoryCell` from a `u64` value.
///
/// Caller is responsible for ensuring no flag bits are set unless intentional.
pub(crate) const fn from_u64(value: u64) -> Self {
Self(value)
}

/// Returns true if the cell is marked as empty (`NONE`).
pub(crate) const fn is_none(self) -> bool {
self.0 & Self::NONE_MASK == Self::NONE_MASK
}

/// Returns true if the cell is not marked as empty.
pub(crate) const fn is_some(self) -> bool {
!self.is_none()
}

/// Marks the cell as accessed by setting the access flag.
pub(crate) const fn mark_accessed(&mut self) {
self.0 |= Self::ACCESS_MASK;
}

/// Returns true if the cell is marked as accessed.
pub(crate) const fn is_accessed(self) -> bool {
self.0 & Self::ACCESS_MASK == Self::ACCESS_MASK
}
}

#[cfg(test)]
mod tests {
use p3_baby_bear::BabyBear;
use p3_field::PrimeCharacteristicRing;

use super::*;

type F = BabyBear;

#[test]
fn test_from_f_and_accessors() {
let f = F::from_u64(123);
let cell = MemoryCell::from_f(f);
assert_eq!(*cell, 123);
assert!(cell.is_some());
assert!(!cell.is_none());
assert!(!cell.is_accessed());
}

#[test]
fn test_from_u64_and_flags() {
let raw = 0xFFFF_FFFF;
let cell = MemoryCell::from_u64(raw);
assert_eq!(*cell, raw);
assert!(cell.is_some());
assert!(!cell.is_none());
}

#[test]
fn test_is_none_and_is_some() {
let none_cell = MemoryCell::NONE;
assert!(none_cell.is_none());
assert!(!none_cell.is_some());

let some_cell = MemoryCell::from_u64(42);
assert!(!some_cell.is_none());
assert!(some_cell.is_some());
}

#[test]
fn test_mark_accessed_and_is_accessed() {
let mut cell = MemoryCell::from_u64(7);
assert!(!cell.is_accessed());
cell.mark_accessed();
assert!(cell.is_accessed());

// Ensure value bits are still preserved
assert_eq!(*cell & 0x3FFF_FFFF_FFFF_FFFF, 7);
}

#[test]
fn test_none_and_access_bits_do_not_conflict() {
let mut cell = MemoryCell::NONE;
assert!(cell.is_none());
assert!(!cell.is_accessed());

// Mark accessed should not clear the NONE flag
cell.mark_accessed();
assert!(cell.is_none());
assert!(cell.is_accessed());
}
}
1 change: 1 addition & 0 deletions crates/leanVm/src/memory/mod.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
pub mod cell;
Loading