Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
135 commits
Select commit Hold shift + click to select a range
7a1a87f
feat: typeless `AddressMap` with typed APIs (#1559)
jonathanpwang Apr 14, 2025
01c028d
feat: `GuestMemory` trait (#1574)
jonathanpwang Apr 13, 2025
aef64c9
feat(new-execution): make vm segment executor generic (#1582)
shuklaayush Apr 15, 2025
e51d918
feat(new-execution): `TracingMemory` and removal of records/logs (#1584)
jonathanpwang Apr 17, 2025
13d6234
feat(new-execution): add execute functions for rv32im instructions (#…
shuklaayush Apr 18, 2025
b85bfc2
feat(new-execution): `AdapterTraceStep` trait and rv32 ALU refactor (…
jonathanpwang Apr 21, 2025
bcde3f8
feat(new-execution): rv32im tracegen and e1 execution (#1607)
shuklaayush Apr 29, 2025
ae9635c
fix(new-execution): fix some rv32im loadstore tests (#1611)
shuklaayush Apr 29, 2025
e885ec0
feat: access adapters (#1614)
jonathanpwang May 2, 2025
8c2d6af
fix(new-execution): make rv32im hintstore work (#1616)
jonathanpwang May 2, 2025
6c86876
fix(new-execution): don't override min block size (#1619)
shuklaayush May 1, 2025
4a2ac13
fix: auipc tracegen
jonathanpwang May 2, 2025
e9cabd2
chore: remove `OfflineMemory` (#1623)
jonathanpwang May 3, 2025
d12a24d
feat: make rv32im testing uniform accross all the chips (#1630)
arayikhalatyan May 7, 2025
5506f06
fix: divrem tests (#1633)
arayikhalatyan May 7, 2025
9695af7
feat: bigint circuit to compile (#1639)
arayikhalatyan May 12, 2025
9174577
feat(new-execution): add codspeed execution benchmark (#1643)
shuklaayush May 13, 2025
169d5bb
feat: memory access adapters, boundary chips, merkle chip E3 (#1640)
Golovanov399 May 13, 2025
65ab533
fix: Cargo lock & format (#1650)
nyunyunyunyu May 14, 2025
8c33445
fix: new block initialization in memory access adapters (#1651)
Golovanov399 May 14, 2025
164eb0e
feat(new-execution): trigger codspeed ci on branch pushes (#1654)
shuklaayush May 15, 2025
327fe86
feat: new execution remove redundant controller memory e1 (#1653)
Golovanov399 May 15, 2025
d603ad0
feat: mod builder rewrite (#1644)
arayikhalatyan May 15, 2025
cf8bcdc
feat(new-execution): measure walltime in codspeed ci job (#1656)
shuklaayush May 15, 2025
00bab47
feat: rv32im working execution + tracegen + prove (aka integration te…
Golovanov399 May 16, 2025
5da1c54
feat: e1, e3 implementation for sha2 + keccak extensions (#1657)
arayikhalatyan May 20, 2025
950320b
feat(new-execution): metered execution (#1652)
shuklaayush May 20, 2025
e8afdad
fix: handle keccak256 input/output not 4-byte aligned (#1671)
jonathanpwang May 21, 2025
15a9ae8
fix: misaligned calls to sha256 (#1674)
arayikhalatyan May 21, 2025
87e9e3f
fix: remove serialized_modulus and align modulus constant (#1678)
jonathanpwang May 21, 2025
cc1002c
feat(new-execution): port native chips (#1665)
shuklaayush May 22, 2025
b1387a3
fix: integration test (#1679)
arayikhalatyan May 22, 2025
ae501ac
feat(new-execution): add interfaces for running different execute fun…
shuklaayush May 22, 2025
a32e4be
feat: port public values chip and native adapter (#1681)
shuklaayush May 22, 2025
fe29323
chore: bump stark backend (#1682)
shuklaayush May 22, 2025
61913de
fix: add InsExecutorE1 to sdk vc executor (#1684)
luffykai May 22, 2025
f188a93
fix(new-execution): return final memory (#1685)
shuklaayush May 23, 2025
46e36b0
fix(new-execution): add missing pc increment (#1687)
shuklaayush May 23, 2025
cb2a533
fix(new-execution): properly calculate total max cells (#1688)
shuklaayush May 23, 2025
cc62f86
feat: Poseidon2 chip (#1672)
nyunyunyunyu May 23, 2025
e9bc13d
fix: Fix setting initial memory (#1690)
Golovanov399 May 24, 2025
c9c7240
refactor: VM Executor for E1/E2 (#1699)
nyunyunyunyu May 30, 2025
3f3147b
fix(new-execution): use unpadded height for segmentation (#1698)
shuklaayush May 30, 2025
9b217c5
fix: fixes to get e2e benchmark working (#1696)
jonathanpwang May 30, 2025
a7f81dc
refactor: Make InsExecutorE1 Stateless (#1700)
nyunyunyunyu May 30, 2025
82f7ff9
fix(new-execution): return segments in `execute_metered` (#1702)
shuklaayush Jun 2, 2025
69aa7a0
refactor: Move `Streams` into `VmStateMut` (#1707)
nyunyunyunyu Jun 4, 2025
e8f34f4
feat: make merkle tree finalization parallel in new execution (#1701)
Golovanov399 Jun 5, 2025
356162e
feat: Do not build a `BTreeMap` when we don't need to (#1718)
Golovanov399 Jun 5, 2025
e9d9a6a
fix(new-execution): remove hardcoded trace heights (#1715)
shuklaayush Jun 13, 2025
9364d65
chore: merge `main` branch (#1740)
jonathanpwang Jun 15, 2025
e8ded6c
chore: add serde to segment (#1749)
luffykai Jun 17, 2025
d5a267c
fix(new-execution): cleanup `vm.rs` (#1751)
shuklaayush Jun 18, 2025
2851dc5
chore(new-execution): clk/cycles -> instret/insns (#1755)
shuklaayush Jun 18, 2025
337f768
ci: add benches for `execute_metered` (#1752)
shuklaayush Jun 18, 2025
bc094fa
Merge branch 'main' into jpw/merge-main-again
jonathanpwang Jun 18, 2025
7d6f53a
fmt
jonathanpwang Jun 18, 2025
341cada
fix bad merge
jonathanpwang Jun 18, 2025
724ab98
fix again
jonathanpwang Jun 18, 2025
70ae977
chore: merge `main` (#1759)
jonathanpwang Jun 18, 2025
2fa8d0b
fix(new-execution): prevent segmentation in single segment executor (…
shuklaayush Jun 19, 2025
df0a38a
feat: generalize E3 with generic `RecordArena` (#1761)
jonathanpwang Jun 20, 2025
8730118
fix(new-execution): use `StdRng` for deterministic execution (#1769)
shuklaayush Jun 20, 2025
42d4dc7
chore: add execution insn/s logging (#1764)
jonathanpwang Jun 20, 2025
6cbe7d1
fix(ci): make codspeed instrumentation dispatch only (#1771)
shuklaayush Jun 20, 2025
b0b892f
chore(ci): fix REF_HASH calculation (#1776)
jonathanpwang Jun 23, 2025
5eba513
perf(new-execution): use page-based approach for merkle tree metering…
shuklaayush Jun 23, 2025
c5d731b
feat(sdk): derive Debug traits in config (#1777)
Qumeric Jun 23, 2025
2011411
feat: RecordArena implementation on DenseRecordArena for variable len…
arayikhalatyan Jun 24, 2025
d0399d7
chore: make testing ProgramDummyAir mod public (#1781)
stephenh-axiom-xyz Jun 24, 2025
29e11c3
chore: make RANGE_CHECKER_BUS pub (#1783)
stephenh-axiom-xyz Jun 24, 2025
9875e86
chore: add 'allocated' method to DenseRecordArena (#1785)
arayikhalatyan Jun 24, 2025
6446607
chore: fix last chore (#1786)
arayikhalatyan Jun 24, 2025
77983f5
feat: use memmap instead of paged_vecs on platforms that support it (…
pjabbarzade Jun 25, 2025
184b12e
chore: derive Clone for Segment
Qumeric Jun 25, 2025
ca2e67d
fix: proper memory access functions in `execute_e1_impl` in the nativ…
Golovanov399 Jun 25, 2025
bb20ff8
refactor(new-execution): make `ExecutionCtrl`s stateless (#1789)
shuklaayush Jun 25, 2025
d0f6585
chore(ci): make sdk and cli tests faster
jonathanpwang Jun 25, 2025
fc3d59e
chore: use tracing spans for metrics (#1791)
jonathanpwang Jun 25, 2025
9be060c
chore: make memory volatile and persistent boundary chips pub (#1792)
stephenh-axiom-xyz Jun 25, 2025
24786c5
fix(new-execution): no segmentation in single segment executor (#1796)
shuklaayush Jun 26, 2025
24dc65b
feat(new-execution): change default `PAGE_BITS` value in e2 to 6 (#1794)
shuklaayush Jun 26, 2025
b4cd1d7
refactor: use PagedVec for TracingMemory metadata storage (#1793)
jonathanpwang Jun 26, 2025
6169738
fix(new-execution): remove duplicate assignment (#1799)
shuklaayush Jun 26, 2025
054b336
ci(new-execution): run codspeed instrumentation on push (#1797)
shuklaayush Jun 26, 2025
6fce5ac
fix: account for E1 / E2 execution in metrics summary (#1800)
yi-sun Jun 27, 2025
68630ef
Add ColsRef macro
Avaneesh-axiom Apr 7, 2025
399a393
Rename crates/circuits/sha256-air/ to crates/circuits/sha2-air/
Avaneesh-axiom Apr 7, 2025
c714d13
Update SHA-256 subair to support SHA-512 and SHA_384
Avaneesh-axiom Apr 7, 2025
a3b73ca
Rename extensions/sha256 to extensions/sha2
Avaneesh-axiom Apr 7, 2025
6dffa9b
fix(new-execution): adapter offset should be boundary_idx + 1 (#1803)
shuklaayush Jun 27, 2025
96b3e5c
Update SHA-256 VM chip to support SHA-512 and SHA-384
Avaneesh-axiom Apr 7, 2025
f38d801
Rename examples/sha256 to examples/sha2
Avaneesh-axiom Apr 7, 2025
49c739d
Update SHA-256 examples
Avaneesh-axiom Apr 7, 2025
e62ed2c
Rename SHA-256 to SHA-2 in various places
Avaneesh-axiom Apr 7, 2025
aaef884
Update the docs
Avaneesh-axiom Apr 7, 2025
05d78e4
Rename book/src/custom-extensions/sha256.md to sha2.md
Avaneesh-axiom Apr 7, 2025
1d4bd1f
Update book
Avaneesh-axiom Apr 7, 2025
665237e
Fix lint
Avaneesh-axiom Jun 27, 2025
9fafdbb
chore(ci): fix the instance type for codspeed benches (#1811)
jonathanpwang Jul 2, 2025
ffdfbbc
feat: new execution e4 for memory adapters (#1733)
Golovanov399 Jul 2, 2025
040d653
chore: update `stark-backend` commit (#1812)
jonathanpwang Jul 2, 2025
3f2b5fc
feat: extract_layout implementation for native Poseidon2 (#1813)
stephenh-axiom-xyz Jul 3, 2025
25ecd07
chore: make plonky3 nightly-features optional (#1818)
jonathanpwang Jul 3, 2025
8638194
fix(new-execution): disable loads from address space 1 (#1802)
shuklaayush Jul 5, 2025
0ed7820
feat(new-execution): ignore register addr space for memory ops (#1798)
shuklaayush Jul 5, 2025
378e076
feat: modify fri records + tests (#1819)
arayikhalatyan Jul 7, 2025
4a2f95e
fix: native Poseidon2 record size should be in bytes instead of u32 (…
stephenh-axiom-xyz Jul 7, 2025
5f4bc59
Merge branch 'feat/sha-512' into feat/sha-512-new-execution
Avaneesh-axiom Jul 9, 2025
7396a2a
Merge branch 'feat/new-execution' into feat/sha-512-new-execution
Avaneesh-axiom Jul 9, 2025
1f3c4fa
Rename sha256 to sha2 (missed in the merge)
Avaneesh-axiom Jul 9, 2025
c4e2cb6
fix(openvm-prof): replace unwraps with better error strings (#1833)
shuklaayush Jul 9, 2025
dabf5d5
fix(new-execution): add register contribtions on `reset_segment` (#1843)
shuklaayush Jul 10, 2025
45c2403
Merge branch 'main' into feat/new-exec-merge-1.3
jonathanpwang Jul 10, 2025
ad5e7c2
chore: fix merge
jonathanpwang Jul 10, 2025
ac7576d
Merge branch 'main' into feat/new-exec-merge-1.3
jonathanpwang Jul 10, 2025
a7d1125
chore: merge `main` (#1844)
jonathanpwang Jul 10, 2025
4090d73
Enforce 4-byte alignment for input to SHA-512/384
Avaneesh-axiom Jul 10, 2025
a58f1c3
Move ShaChipConfig::VARIANT to Sha2Config
Avaneesh-axiom Jul 10, 2025
2138780
Fix double negative "should_panic" in sha subair unit tests
Avaneesh-axiom Jul 10, 2025
2e86a9e
Merge branch 'feat/new-execution' into feat/sha-512-new-execution
Avaneesh-axiom Jul 10, 2025
a8b79b5
Fix typos in spec
Avaneesh-axiom Jul 10, 2025
49e1eb4
Fix bug
Avaneesh-axiom Jul 10, 2025
32b66e5
fix: do multiple digest writes for e1 for sha512/384
Avaneesh-axiom Jul 11, 2025
2ed19d5
Rename ShaChipConfig to Sha2ChipConfig for consistency with Sha2Config
Avaneesh-axiom Jul 11, 2025
a6be3df
feat: use cached max trace heights in leaf/internal aggregation (#1839)
stephenh-axiom-xyz Jul 11, 2025
3735326
Fix lint
Avaneesh-axiom Jul 11, 2025
48c80d7
feat: Add pubs needed for gpu (#1860)
Golovanov399 Jul 14, 2025
9315f1a
feat: RecordSeeker::get_aligned_record_size (#1863)
arayikhalatyan Jul 14, 2025
e027992
refactor(new-execution): optimize E1/E2 implementation (#1827)
nyunyunyunyu Jul 15, 2025
1c43154
chore: General Sys phantom (#1867)
nyunyunyunyu Jul 15, 2025
97eaf48
fix(new-execution): don't pass total_widths to execute_metered (#1868)
shuklaayush Jul 15, 2025
616dfa2
Merge branch 'feat/new-execution' into feat/sha-512-new-execution
Avaneesh-axiom Jul 16, 2025
a31776d
Merge branch 'main' into feat/sha-512-new-execution-updated
Avaneesh-axiom Oct 17, 2025
475b2ed
WIP
Avaneesh-axiom Oct 28, 2025
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
244 changes: 147 additions & 97 deletions Cargo.lock

Large diffs are not rendered by default.

16 changes: 9 additions & 7 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,9 @@ members = [
"extensions/keccak256/circuit",
"extensions/keccak256/transpiler",
"extensions/keccak256/guest",
"extensions/sha256/circuit",
"extensions/sha256/transpiler",
"extensions/sha256/guest",
"extensions/sha2/circuit",
"extensions/sha2/transpiler",
"extensions/sha2/guest",
"extensions/ecc/circuit",
"extensions/ecc/transpiler",
"extensions/ecc/guest",
Expand Down Expand Up @@ -123,7 +123,7 @@ openvm-cuda-common = { git = "https://github.com/openvm-org/stark-backend.git",
openvm-sdk = { path = "crates/sdk", default-features = false }
openvm-mod-circuit-builder = { path = "crates/circuits/mod-builder", default-features = false }
openvm-poseidon2-air = { path = "crates/circuits/poseidon2-air", default-features = false }
openvm-sha256-air = { path = "crates/circuits/sha256-air", default-features = false }
openvm-sha2-air = { path = "crates/circuits/sha2-air", default-features = false }
openvm-circuit-primitives = { path = "crates/circuits/primitives", default-features = false }
openvm-circuit-primitives-derive = { path = "crates/circuits/primitives/derive", default-features = false }
openvm = { path = "crates/toolchain/openvm", default-features = false }
Expand Down Expand Up @@ -153,9 +153,9 @@ openvm-native-transpiler = { path = "extensions/native/transpiler", default-feat
openvm-keccak256-circuit = { path = "extensions/keccak256/circuit", default-features = false }
openvm-keccak256-transpiler = { path = "extensions/keccak256/transpiler", default-features = false }
openvm-keccak256-guest = { path = "extensions/keccak256/guest", default-features = false }
openvm-sha256-circuit = { path = "extensions/sha256/circuit", default-features = false }
openvm-sha256-transpiler = { path = "extensions/sha256/transpiler", default-features = false }
openvm-sha256-guest = { path = "extensions/sha256/guest", default-features = false }
openvm-sha2-circuit = { path = "extensions/sha2/circuit", default-features = false }
openvm-sha2-transpiler = { path = "extensions/sha2/transpiler", default-features = false }
openvm-sha2-guest = { path = "extensions/sha2/guest", default-features = false }
openvm-bigint-circuit = { path = "extensions/bigint/circuit", default-features = false }
openvm-bigint-transpiler = { path = "extensions/bigint/transpiler", default-features = false }
openvm-bigint-guest = { path = "extensions/bigint/guest", default-features = false }
Expand Down Expand Up @@ -234,6 +234,8 @@ memmap2 = "0.9.5"
libc = "0.2.175"
tracing-subscriber = { version = "0.3.20", features = ["std", "env-filter"] }
tokio = "1" # >=1.0.0 to allow downstream flexibility
ndarray = { version = "0.16.1", default-features = false }
num_enum = { version = "0.7.4", default-features = false }

# default-features = false for no_std for use in guest programs
itertools = { version = "0.14.0", default-features = false }
Expand Down
4 changes: 2 additions & 2 deletions benchmarks/execute/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ openvm-keccak256-circuit.workspace = true
openvm-keccak256-transpiler.workspace = true
openvm-rv32im-circuit.workspace = true
openvm-rv32im-transpiler.workspace = true
openvm-sha256-circuit.workspace = true
openvm-sha256-transpiler.workspace = true
openvm-sha2-circuit.workspace = true
openvm-sha2-transpiler.workspace = true
openvm-continuations = { workspace = true }
openvm-native-recursion = { workspace = true }
openvm-sdk = { workspace = true }
Expand Down
10 changes: 5 additions & 5 deletions benchmarks/execute/benches/execute.rs
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,8 @@ use openvm_sdk::{
commit::VmCommittedExe,
config::{AggregationConfig, DEFAULT_NUM_CHILDREN_INTERNAL, DEFAULT_NUM_CHILDREN_LEAF},
};
use openvm_sha256_circuit::{Sha256, Sha256Executor, Sha2CpuProverExt};
use openvm_sha256_transpiler::Sha256TranspilerExtension;
use openvm_sha2_circuit::{Sha2, Sha2CpuProverExt, Sha2Executor};
use openvm_sha2_transpiler::Sha2TranspilerExtension;
use openvm_stark_sdk::{
config::{baby_bear_poseidon2::BabyBearPoseidon2Engine, FriParameters},
engine::{StarkEngine, StarkFriEngine},
Expand Down Expand Up @@ -106,7 +106,7 @@ pub struct ExecuteConfig {
#[extension]
pub keccak: Keccak256,
#[extension]
pub sha256: Sha256,
pub sha2: Sha2,
#[extension]
pub modular: ModularExtension,
#[extension]
Expand All @@ -127,7 +127,7 @@ impl Default for ExecuteConfig {
io: Rv32Io,
bigint: Int256::default(),
keccak: Keccak256,
sha256: Sha256,
sha2: Sha2,
modular: ModularExtension::new(vec![
bn_config.modulus.clone(),
bn_config.scalar.clone(),
Expand Down Expand Up @@ -215,7 +215,7 @@ fn create_default_transpiler() -> Transpiler<BabyBear> {
.with_extension(Rv32MTranspilerExtension)
.with_extension(Int256TranspilerExtension)
.with_extension(Keccak256TranspilerExtension)
.with_extension(Sha256TranspilerExtension)
.with_extension(Sha2TranspilerExtension)
.with_extension(ModularTranspilerExtension)
.with_extension(Fp2TranspilerExtension)
.with_extension(EccTranspilerExtension)
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/guest/kitchen-sink/openvm.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
[app_vm_config.rv32m]
[app_vm_config.io]
[app_vm_config.keccak]
[app_vm_config.sha256]
[app_vm_config.sha2]
[app_vm_config.bigint]

[app_vm_config.modular]
Expand Down
2 changes: 1 addition & 1 deletion benchmarks/guest/sha256/openvm.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[app_vm_config.rv32i]
[app_vm_config.rv32m]
[app_vm_config.io]
[app_vm_config.sha256]
[app_vm_config.sha2]
2 changes: 1 addition & 1 deletion benchmarks/guest/sha256_iter/openvm.toml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
[app_vm_config.rv32i]
[app_vm_config.rv32m]
[app_vm_config.io]
[app_vm_config.sha256]
[app_vm_config.sha2]
57 changes: 57 additions & 0 deletions benchmarks/prove/src/bin/kitchen_sink.rs
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,63 @@ fn verify_native_max_trace_heights(
Ok(())
}

fn verify_native_max_trace_heights(
sdk: &Sdk,
app_pk: Arc<AppProvingKey<SdkVmConfig>>,
app_committed_exe: Arc<NonRootCommittedExe>,
leaf_vm_pk: Arc<VmProvingKey<SC, NativeConfig>>,
num_children_leaf: usize,
) -> Result<()> {
let app_proof =
sdk.generate_app_proof(app_pk.clone(), app_committed_exe.clone(), StdIn::default())?;
let leaf_inputs =
LeafVmVerifierInput::chunk_continuation_vm_proof(&app_proof, num_children_leaf);
let vm_vk = leaf_vm_pk.vm_pk.get_vk();

leaf_inputs.iter().for_each(|leaf_input| {
let executor = {
let mut executor = SingleSegmentVmExecutor::new(leaf_vm_pk.vm_config.clone());
executor
.set_trace_height_constraints(leaf_vm_pk.vm_pk.trace_height_constraints.clone());
executor
};
let max_trace_heights = executor
.execute_metered(
app_pk.leaf_committed_exe.exe.clone(),
leaf_input.write_to_stream(),
&vm_vk.num_interactions(),
)
.expect("execute_metered failed");
println!("max_trace_heights: {:?}", max_trace_heights);

let actual_trace_heights = executor
.execute_and_generate(
app_pk.leaf_committed_exe.clone(),
leaf_input.write_to_stream(),
&max_trace_heights,
)
.expect("execute_and_generate failed")
.per_air
.iter()
.map(|(_, air)| air.raw.height())
.collect::<Vec<usize>>();
println!("actual_trace_heights: {:?}", actual_trace_heights);

actual_trace_heights
.iter()
.zip(NATIVE_MAX_TRACE_HEIGHTS)
.for_each(|(&actual, &expected)| {
assert!(
actual <= (expected as usize),
"Actual trace height {} exceeds expected height {}",
actual,
expected
);
});
});
Ok(())
}

fn main() -> Result<()> {
let args = BenchmarkCli::parse();

Expand Down
11 changes: 9 additions & 2 deletions crates/circuits/primitives/derive/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,13 @@ license.workspace = true
proc-macro = true

[dependencies]
syn = { version = "2.0", features = ["parsing"] }
syn = { version = "2.0", features = ["full", "parsing", "extra-traits"] }
quote = "1.0"
itertools = { workspace = true }
itertools = { workspace = true, default-features = true }
proc-macro2 = "1.0"

[dev-dependencies]
ndarray.workspace = true

[package.metadata.cargo-shear]
ignored = ["ndarray"]
113 changes: 113 additions & 0 deletions crates/circuits/primitives/derive/src/cols_ref/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
# ColsRef macro

The `ColsRef` procedural macro is used in constraint generation to create column structs that have dynamic sizes.

Note: this macro was originally created for use in the SHA-2 VM extension, where we reuse the same constraint generation code for three different circuits (SHA-256, SHA-512, and SHA-384).
See the [SHA-2 VM extension](../../../../../../extensions/sha2/circuit/src/sha2_chip/air.rs) for an example of how to use the `ColsRef` macro to reuse constraint generation code over multiple circuits.

## Overview

As an illustrative example, consider the following columns struct:
```rust
struct ExampleCols<T, const N: usize> {
arr: [T; N],
sum: T,
}
```
Let's say we want to constrain `sum` to be the sum of the elements of `arr`, and `N` can be either 5 or 10.
We can define a trait that stores the config parameters.
```rust
pub trait ExampleConfig {
const N: usize;
}
```
and then implement it for the two different configs.
```rust
pub struct ExampleConfigImplA;
impl ExampleConfig for ExampleConfigImplA {
const N: usize = 5;
}
pub struct ExampleConfigImplB;
impl ExampleConfig for ExampleConfigImplB {
const N: usize = 10;
}
```
Then we can use the `ColsRef` macro like this
```rust
#[derive(ColsRef)]
#[config(ExampleConfig)]
struct ExampleCols<T, const N: usize> {
arr: [T; N],
sum: T,
}
```
which will generate a columns struct that uses references to the fields.
```rust
struct ExampleColsRef<'a, T, const N: usize> {
arr: ndarray::ArrayView1<'a, T>, // an n-dimensional view into the input slice (ArrayView2 for 2D arrays, etc.)
sum: &'a T,
}
```
The `ColsRef` macro will also generate a `from` method that takes a slice of the correct length and returns an instance of the columns struct.
The `from` method is parameterized by a struct that implements the `ExampleConfig` trait, and it uses the associated constants to determine how to split the input slice into the fields of the columns struct.

So, the constraint generation code can be written as
```rust
impl<AB: InteractionBuilder, C: ExampleConfig> Air<AB> for ExampleAir<C> {
fn eval(&self, builder: &mut AB) {
let main = builder.main();
let (local, _) = (main.row_slice(0), main.row_slice(1));
let local_cols = ExampleColsRef::<AB::Var>::from::<C>(&local[..C::N + 1]);
let sum = local_cols.arr.iter().sum();
builder.assert_eq(local_cols.sum, sum);
}
}
```
Notes:
- the `arr` and `sum` fields of `ExampleColsRef` are references to the elements of the `local` slice.
- the name, `N`, of the const generic parameter must match the name of the associated constant `N` in the `ExampleConfig` trait.

The `ColsRef` macro also generates a `ExampleColsRefMut` struct that stores mutable references to the fields, for use in trace generation.

The `ColsRef` macro supports more than just variable-length array fields.
The field types can also be:
- any type that derives `AlignedBorrow` via `#[derive(AlignedBorrow)]`
- any type that derives `ColsRef` via `#[derive(ColsRef)]`
- (possibly nested) arrays of `T` or (possibly nested) arrays of a type that derives `AlignedBorrow`

Note that we currently do not support arrays of types that derive `ColsRef`.

## Specification

Annotating a struct named `ExampleCols` with `#[derive(ColsRef)]` and `#[config(ExampleConfig)]` produces two structs, `ExampleColsRef` and `ExampleColsRefMut`.
- we assume `ExampleCols` has exactly one generic type parameter, typically named `T`, and any number of const generic parameters. Each const generic parameter must have a name that matches an associated constant in the `ExampleConfig` trait

The fields of `ExampleColsRef` have the same names as the fields of `ExampleCols`, but their types are transformed as follows:
- type `T` becomes `&T`
- type `[T; LEN]` becomes `&ArrayView1<T>` (see [ndarray](https://docs.rs/ndarray/latest/ndarray/index.html)) where `LEN` is an associated constant in `ExampleConfig`
- the `ExampleColsRef::from` method will correctly infer the length of the array from the config
- fields with names that end in `Cols` are assumed to be a columns struct that derives `ColsRef` and are transformed into the appropriate `ColsRef` type recursively
- one restriction is that any nested `ColsRef` type must have the same config as the outer `ColsRef` type
- fields that are annotated with `#[aligned_borrow]` are assumed to derive `AlignedBorrow` and are borrowed from the input slice. The new type is a reference to the `AlignedBorrow` type
- if a field whose name ends in `Cols` is annotated with `#[aligned_borrow]`, then the aligned borrow takes precedence, and the field is not transformed into an `ArrayView`
- nested arrays of `U` become `&ArrayViewX<U>` where `X` is the number of dimensions in the nested array type
- `U` can be either the generic type `T` or a type that derives `AlignedBorrow`. In the latter case, the field must be annotated with `#[aligned_borrow]`
- the `ArrayViewX` type provides a `X`-dimensional view into the row slice

The fields of `ExampleColsRefMut` are almost the same as the fields of `ExampleColsRef`, but they are mutable references.
- the `ArrayViewMutX` type is used instead of `ArrayViewX` for the array fields.
- fields that derive `ColsRef` are transformed into the appropriate `ColsRefMut` type recursively.

Each of the `ExampleColsRef` and `ExampleColsRefMut` types has the following methods implemented:
```rust
// Takes a slice of the correct length and returns an instance of the columns struct.
pub const fn from<C: ExampleConfig>(slice: &[T]) -> Self;
// Returns the number of cells in the struct
pub const fn width<C: ExampleConfig>() -> usize;
```
Note that the `width` method on both structs returns the same value.

Additionally, the `ExampleColsRef` struct has a `from_mut` method that takes a `ExampleColsRefMut` and returns a `ExampleColsRef`.
This may be useful in trace generation to pass a `ExampleColsRefMut` to a function that expects a `ExampleColsRef`.

See the [tests](../../tests/test_cols_ref.rs) for concrete examples of how the `ColsRef` macro handles each of the supported field types.
Loading