Skip to content

Commit b577acb

Browse files
authored
refactor sumcheck (#112)
* refactor sumcheck * fix ci * clean up
1 parent 9c4ef3b commit b577acb

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

61 files changed

+910
-195
lines changed

.github/workflows/ci.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,4 +85,4 @@ jobs:
8585
run: |
8686
python3 ./scripts/install.py
8787
cargo run --bin=dev-setup --release
88-
cargo run --release -- -t ${{ matrix.os == 'macos-latest' && 2 || 16 }} -f ${{ matrix.field }}
88+
cargo run --bin=gkr --release -- -t ${{ matrix.os == 'macos-latest' && 2 || 16 }} -f ${{ matrix.field }}

Cargo.toml

Lines changed: 7 additions & 78 deletions
Original file line numberDiff line numberDiff line change
@@ -1,65 +1,19 @@
1-
[package]
2-
name = "expander-rs"
3-
version = "0.1.0"
4-
edition = "2021"
5-
default-run = "expander-rs" # default
6-
7-
[dependencies]
8-
arith = { path = "arith" }
9-
gf2 = { path = "arith/gf2" }
10-
gf2_128 = { path = "arith/gf2_128" }
11-
mersenne31 = { path = "arith/mersenne31" }
12-
transcript = { path = "transcript" }
13-
14-
ark-std.workspace = true
15-
clap.workspace = true
16-
env_logger.workspace = true
17-
log.workspace = true
18-
mpi.workspace = true
19-
rand.workspace = true
20-
sha2.workspace = true
21-
halo2curves.workspace = true
22-
thiserror.workspace = true
23-
ethnum.workspace = true
24-
25-
# for the server
26-
bytes.workspace = true
27-
tokio.workspace = true
28-
warp.workspace = true
29-
chrono.workspace = true
30-
tynm.workspace = true
31-
tiny-keccak.workspace = true
32-
33-
[dev-dependencies]
34-
criterion = "0.5.1"
35-
36-
[[bin]]
37-
name = "expander-rs-mpi"
38-
path = "src/main_mpi.rs"
39-
40-
[[bin]]
41-
name = "expander-exec"
42-
path = "src/exec.rs"
43-
44-
[[bin]]
45-
name = "dev-setup"
46-
path = "src/utils.rs"
47-
48-
[features]
49-
default = []
50-
# default = [ "grinding" ]
51-
grinding = []
52-
531
[workspace]
542
members = [
553
"arith", # definitions of Field, Extensions, SIMDS
564
"arith/gf2",
575
"arith/gf2_128",
586
"arith/goldilocks",
597
"arith/mersenne31",
60-
"bi-kzg",
8+
"bi-kzg",
9+
"circuit",
10+
"config",
11+
"gkr",
12+
"sumcheck",
6113
"transcript"
6214
]
15+
resolver = "2"
16+
6317

6418
[workspace.dependencies]
6519
ark-std = "0.4"
@@ -86,28 +40,3 @@ tynm = { version = "0.1.6", default-features = false }
8640
warp = "0.3.7"
8741
thiserror = "1.0.63"
8842
ethnum = "1.5.0"
89-
90-
[[bench]]
91-
name = "bn254_fr"
92-
harness = false
93-
path = "arith/benches/fr.rs"
94-
95-
[[bench]]
96-
name = "gf2"
97-
harness = false
98-
path = "arith/gf2/benches/gf2.rs"
99-
100-
[[bench]]
101-
name = "gf2_128"
102-
harness = false
103-
path = "arith/gf2_128/benches/gf2_128.rs"
104-
105-
[[bench]]
106-
name = "m31"
107-
harness = false
108-
path = "arith/mersenne31/benches/m31.rs"
109-
110-
[[bench]]
111-
name = "gkr-hashes"
112-
harness = false
113-
path = "benches/gkr_hashes.rs"

bi-kzg/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,6 @@ harness = false
2626

2727
[features]
2828
default = [
29-
"ark-std/print-trace",
29+
# "ark-std/print-trace",
3030
"ark-ec/parallel",
3131
]

circuit/Cargo.toml

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "circuit"
3+
version = "0.1.0"
4+
edition = "2021"
5+
6+
[dependencies]
7+
arith = { path = "../arith" }
8+
config = { path = "../config" }
9+
transcript = { path = "../transcript" }
10+
11+
ark-std.workspace = true
12+
ethnum.workspace = true
13+
log.workspace = true
14+
thiserror.workspace = true

circuit/src/ecc_circuit.rs

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,145 @@
1+
use config::GKRConfig;
2+
use std::{cmp::max, collections::HashMap, fs, io::Cursor};
3+
4+
use crate::*;
5+
6+
// recursive format used in compiler
7+
pub type SegmentId = usize;
8+
9+
pub struct Allocation {
10+
pub i_offset: usize,
11+
pub o_offset: usize,
12+
}
13+
14+
#[derive(Default)]
15+
pub struct Segment<C: GKRConfig> {
16+
pub i_var_num: usize,
17+
pub o_var_num: usize,
18+
pub child_segs: Vec<(SegmentId, Vec<Allocation>)>,
19+
pub gate_muls: Vec<GateMul<C>>,
20+
pub gate_adds: Vec<GateAdd<C>>,
21+
pub gate_consts: Vec<GateConst<C>>,
22+
pub gate_uni: Vec<GateUni<C>>,
23+
}
24+
25+
impl<C: GKRConfig> Segment<C> {
26+
pub fn contain_gates(&self) -> bool {
27+
!self.gate_muls.is_empty()
28+
|| !self.gate_adds.is_empty()
29+
|| !self.gate_consts.is_empty()
30+
|| !self.gate_uni.is_empty()
31+
}
32+
33+
pub fn scan_leaf_segments(
34+
&self,
35+
rc: &RecursiveCircuit<C>,
36+
cur_id: SegmentId,
37+
) -> HashMap<SegmentId, Vec<Allocation>> {
38+
let mut ret = HashMap::new();
39+
if self.contain_gates() {
40+
ret.insert(
41+
cur_id,
42+
vec![Allocation {
43+
i_offset: 0,
44+
o_offset: 0,
45+
}],
46+
);
47+
}
48+
for (child_seg_id, child_allocs) in &self.child_segs {
49+
let leaves = rc.segments[*child_seg_id].scan_leaf_segments(rc, *child_seg_id);
50+
for (leaf_seg_id, leaf_allocs) in leaves {
51+
ret.entry(leaf_seg_id).or_insert_with(Vec::new);
52+
for child_alloc in child_allocs {
53+
for leaf_alloc in &leaf_allocs {
54+
ret.get_mut(&leaf_seg_id).unwrap().push(Allocation {
55+
i_offset: child_alloc.i_offset + leaf_alloc.i_offset,
56+
o_offset: child_alloc.o_offset + leaf_alloc.o_offset,
57+
});
58+
}
59+
}
60+
}
61+
}
62+
ret
63+
}
64+
}
65+
66+
#[derive(Default)]
67+
pub struct RecursiveCircuit<C: GKRConfig> {
68+
pub num_public_inputs: usize,
69+
pub num_outputs: usize,
70+
pub expected_num_output_zeros: usize,
71+
72+
pub segments: Vec<Segment<C>>,
73+
pub layers: Vec<SegmentId>,
74+
}
75+
76+
impl<C: GKRConfig> RecursiveCircuit<C> {
77+
pub fn load(filename: &str) -> std::result::Result<Self, CircuitError> {
78+
let file_bytes = fs::read(filename)?;
79+
let cursor = Cursor::new(file_bytes);
80+
81+
Ok(Self::deserialize_from(cursor))
82+
}
83+
84+
pub fn flatten(&self) -> Circuit<C> {
85+
let mut ret = Circuit::<C> {
86+
expected_num_output_zeros: self.expected_num_output_zeros,
87+
..Default::default()
88+
};
89+
// layer-by-layer conversion
90+
for layer_id in &self.layers {
91+
let layer_seg = &self.segments[*layer_id];
92+
let leaves = layer_seg.scan_leaf_segments(self, *layer_id);
93+
let mut ret_layer = CircuitLayer {
94+
input_var_num: max(layer_seg.i_var_num, 1), // var_num >= 1
95+
output_var_num: max(layer_seg.o_var_num, 1), // var_num >= 1
96+
..Default::default()
97+
};
98+
for (leaf_seg_id, leaf_allocs) in leaves {
99+
let leaf_seg = &self.segments[leaf_seg_id];
100+
for alloc in leaf_allocs {
101+
for gate in &leaf_seg.gate_muls {
102+
let mut gate = gate.clone();
103+
gate.i_ids[0] += alloc.i_offset;
104+
gate.i_ids[1] += alloc.i_offset;
105+
gate.o_id += alloc.o_offset;
106+
ret_layer.mul.push(gate);
107+
}
108+
for gate in &leaf_seg.gate_adds {
109+
let mut gate = gate.clone();
110+
gate.i_ids[0] += alloc.i_offset;
111+
gate.o_id += alloc.o_offset;
112+
ret_layer.add.push(gate);
113+
}
114+
for gate in &leaf_seg.gate_consts {
115+
let mut gate = gate.clone();
116+
gate.o_id += alloc.o_offset;
117+
ret_layer.const_.push(gate);
118+
}
119+
for gate in &leaf_seg.gate_uni {
120+
let mut gate = gate.clone();
121+
gate.i_ids[0] += alloc.i_offset;
122+
gate.o_id += alloc.o_offset;
123+
ret_layer.uni.push(gate);
124+
}
125+
}
126+
}
127+
// debug print layer
128+
log::trace!(
129+
"layer {} mul: {} add: {} const:{} uni:{} i_var_num: {} o_var_num: {}",
130+
ret.layers.len(),
131+
ret_layer.mul.len(),
132+
ret_layer.add.len(),
133+
ret_layer.const_.len(),
134+
ret_layer.uni.len(),
135+
ret_layer.input_var_num,
136+
ret_layer.output_var_num,
137+
);
138+
ret.layers.push(ret_layer);
139+
}
140+
141+
ret.identify_rnd_coefs();
142+
ret.identify_structure_info();
143+
ret
144+
}
145+
}

0 commit comments

Comments
 (0)