Skip to content

Commit 8a277fb

Browse files
committed
Flat FRI layers array
1 parent 2528ae3 commit 8a277fb

12 files changed

Lines changed: 1315 additions & 137 deletions

File tree

stwo-verifier/Makefile

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@ WIT_FILE=../target/proof.wit
44
test:
55
bash ../scripts/unit_tests.sh --debug
66

7-
proof-simf:
7+
proof-test:
88
python3 scripts/generate_simf.py tests/data/proof.json > ../target/proof.simf
99

10-
proof-wit:
10+
proof:
1111
python3 scripts/generate_wit.py tests/data/proof.json > $(WIT_FILE)
1212

1313
build:

stwo-verifier/scripts/generate_simf.py

Lines changed: 23 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -146,9 +146,18 @@ def main() -> None:
146146
# FRI config and commitments
147147
fri = data["fri_proof"]
148148
# n_queries defined above
149-
first_commitment_b = bytes32_from_list(fri["first_layer"]["commitment"]) if isinstance(fri["first_layer"]["commitment"], list) else bytes(fri["first_layer"]["commitment"])
150-
inner_layers = fri.get("inner_layers", [])
151-
inner_commitments_b = [bytes32_from_list(layer["commitment"]) for layer in inner_layers]
149+
layers = fri.get("layers")
150+
if layers is not None:
151+
layer_commitments_b = [
152+
bytes32_from_list(layer["commitment"]) if isinstance(layer["commitment"], list) else bytes(layer["commitment"]) # type: ignore[arg-type]
153+
for layer in layers
154+
]
155+
else:
156+
# Backward compatibility: separate first + inner
157+
first_commitment_b = bytes32_from_list(fri["first_layer"]["commitment"]) if isinstance(fri["first_layer"]["commitment"], list) else bytes(fri["first_layer"]["commitment"]) # type: ignore[arg-type]
158+
inner_layers = fri.get("inner_layers", [])
159+
inner_commitments_b = [bytes32_from_list(layer["commitment"]) for layer in inner_layers]
160+
layer_commitments_b = [first_commitment_b] + inner_commitments_b
152161

153162
# Last layer polynomial coefficients (QM31 list)
154163
last_layer_poly = fri["last_layer_poly"]
@@ -187,35 +196,27 @@ def main() -> None:
187196
cp_oods_str = "[" + ", ".join(fmt_qm31(q) for q in cp_oods_qm31) + "]"
188197
oods_evals_str = f"(\n {trace_oods_str},\n {cp_oods_str},\n )"
189198

190-
# FRI commitments (no alphas): (u256, List<u256, MAX_FRI_LAYERS>, LinePoly)
191-
first_commitment_str = u256_hex(u256_from_bytes_be(first_commitment_b))
192-
inner_commitments_str = "[" + ", ".join(u256_hex(u256_from_bytes_be(c_b)) for c_b in inner_commitments_b) + "]"
199+
# FRI commitments (unified): ([u256; NUM_FRI_LAYERS], LinePoly)
200+
commitments_arr_str = "[" + ", ".join(u256_hex(u256_from_bytes_be(c_b)) for c_b in layer_commitments_b) + "]"
193201
last_layer_str = fmt_qm31(last_coeffs_qm31)
194-
fri_commitments_str = f"(\n {first_commitment_str},\n {inner_commitments_str},\n {last_layer_str},\n )"
202+
fri_commitments_str = f"(\n {commitments_arr_str},\n {last_layer_str},\n )"
195203

196-
# FRI decommitments: (FriLayerDecommitment, [FriLayerDecommitment; NUM_FRI_LAYERS])
197-
first_layer = fri["first_layer"]
198-
first_layer_decommitment_str = indent(parse_fri_layer_decommitment(first_layer, n_queries), 8)
199-
inner_layer_decommitments_strs = [parse_fri_layer_decommitment(layer, n_queries) for layer in inner_layers]
200-
inner_layers_block = (
201-
"[\n"
202-
+ ",\n".join(indent(s, 8) for s in inner_layer_decommitments_strs)
203-
+ "\n ]"
204-
)
204+
# FRI decommitments (unified array)
205+
fri_layers_list = layers if layers is not None else [fri["first_layer"]] + inner_layers
206+
fri_layer_decommitments_strs = [parse_fri_layer_decommitment(layer, n_queries) for layer in fri_layers_list]
207+
fri_decommitments_inner = ",\n".join(indent(s, 8) for s in fri_layer_decommitments_strs)
205208
fri_decommitments_str = (
206-
"(\n"
207-
+ first_layer_decommitment_str
208-
+ ",\n"
209-
+ indent(inner_layers_block, 4)
210-
+ "\n )"
209+
"[\n"
210+
+ " " + fri_decommitments_inner + "\n"
211+
+ " ]"
211212
)
212213

213214
# PoW nonce
214215
pow_nonce = int(data.get("proof_of_work", 0))
215216

216217
# Assemble final proof
217218
proof_str = (
218-
"let proof: Proof = (\n"
219+
"let proof: StarkProof = (\n"
219220
f" {commitments_str},\n"
220221
f" {decommitments_str},\n"
221222
f" {oods_evals_str},\n"

stwo-verifier/scripts/generate_wit.py

Lines changed: 24 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -87,9 +87,9 @@ def build_types(cols: int, col_offsets: int, cp_parts: int, n_queries: int, n_la
8787

8888
FriQueryDecommitment = f"({QM31}, {MerkleProof32})"
8989
FriLayerDecommitment = f"[{FriQueryDecommitment}; {n_queries}]"
90-
FriDecommitments = f"({FriLayerDecommitment}, [{FriLayerDecommitment}; {n_layers}])"
90+
FriDecommitments = f"[{FriLayerDecommitment}; {n_layers}]"
9191

92-
FriCommitments = f"(u256, [u256; {n_layers}], {QM31})"
92+
FriCommitments = f"([u256; {n_layers}], {QM31})"
9393

9494
Commitments = "(u256, u256, u256)"
9595

@@ -175,16 +175,25 @@ def build_witness_from_json(data: Dict[str, Any]) -> Dict[str, Dict[str, str]]:
175175
)
176176
decommitments_list_val = "[" + ", ".join(decommitment_items) + "]"
177177

178-
# FRI config and commitments
178+
# FRI config and commitments (unified layers array with fallback)
179179
fri = data["fri_proof"]
180-
# n_queries already determined above
181-
first_commitment_b = bytes32_from_list(fri["first_layer"]["commitment"]) if isinstance(fri["first_layer"]["commitment"], list) else bytes(fri["first_layer"]["commitment"])
182-
inner_layers = fri.get("inner_layers", [])
183-
n_layers: int = len(inner_layers)
184-
inner_commitments_b = [bytes32_from_list(layer["commitment"]) for layer in inner_layers]
185-
186-
first_commitment_val = u256_hex(u256_from_bytes_be(first_commitment_b))
187-
inner_commitments_val = "[" + ", ".join(u256_hex(u256_from_bytes_be(c_b)) for c_b in inner_commitments_b) + "]"
180+
layers = fri.get("layers")
181+
if layers is not None:
182+
n_layers: int = len(layers)
183+
layer_commitments_b = [
184+
bytes32_from_list(layer["commitment"]) if isinstance(layer["commitment"], list) else bytes(layer["commitment"]) # type: ignore[arg-type]
185+
for layer in layers
186+
]
187+
fri_layers_for_decomm = layers
188+
else:
189+
first_commitment_b = bytes32_from_list(fri["first_layer"]["commitment"]) if isinstance(fri["first_layer"]["commitment"], list) else bytes(fri["first_layer"]["commitment"]) # type: ignore[arg-type]
190+
inner_layers = fri.get("inner_layers", [])
191+
n_layers = 1 + len(inner_layers)
192+
inner_commitments_b = [bytes32_from_list(layer["commitment"]) for layer in inner_layers]
193+
layer_commitments_b = [first_commitment_b] + inner_commitments_b
194+
fri_layers_for_decomm = [fri["first_layer"]] + inner_layers
195+
196+
commitments_arr_val = "[" + ", ".join(u256_hex(u256_from_bytes_be(c_b)) for c_b in layer_commitments_b) + "]"
188197

189198
# Last layer polynomial coefficients (QM31 list of one)
190199
last_layer_poly = fri["last_layer_poly"]
@@ -193,14 +202,11 @@ def build_witness_from_json(data: Dict[str, Any]) -> Dict[str, Dict[str, str]]:
193202
last_coeffs_qm31 = parse_qm31_from_json(coeffs_json[0])
194203
last_layer_val = qm31_value_str(last_coeffs_qm31)
195204

196-
fri_commitments_val = f"({first_commitment_val}, {inner_commitments_val}, {last_layer_val})"
205+
fri_commitments_val = f"({commitments_arr_val}, {last_layer_val})"
197206

198-
# FRI decommitments: first + inner
199-
first_layer = fri["first_layer"]
200-
first_layer_decommitment_val = parse_fri_layer_decommitment(first_layer, n_queries)
201-
inner_layer_decommitments_vals = [parse_fri_layer_decommitment(layer, n_queries) for layer in inner_layers]
202-
inner_layers_block_val = "[" + ", ".join(inner_layer_decommitments_vals) + "]"
203-
fri_decommitments_val = f"({first_layer_decommitment_val}, {inner_layers_block_val})"
207+
# FRI decommitments: unified array over layers
208+
fri_layer_decommitments_vals = [parse_fri_layer_decommitment(layer, n_queries) for layer in fri_layers_for_decomm]
209+
fri_decommitments_val = "[" + ", ".join(fri_layer_decommitments_vals) + "]"
204210

205211
# PoW nonce
206212
pow_nonce = int(data.get("proof_of_work", 0))

stwo-verifier/src/config.simf

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -14,29 +14,29 @@
1414
#define NUM_COLUMNS 4
1515

1616
#ifdef TESTING
17-
#define TRACE_LOG_SIZE 3
17+
#define TRACE_LOG_SIZE 2
1818

1919
/// Log size of the extended evaluation domain.
2020
/// trace log size + log blowup factor
21-
#define LDE_LOG_SIZE 4
21+
#define LDE_LOG_SIZE 3
2222

2323
/// Number of FRI queries.
2424
/// NOTE: must be power of 2 (temporarily, because array macros work for power of 2 sizes only)
25-
#define NUM_FRI_QUERIES 1
25+
#define NUM_FRI_QUERIES 2
2626

27-
/// Number of FRI inner layers (depends on the trace size).
27+
/// Number of FRI layers except the last one (depends on the trace size).
2828
/// NOTE: must be power of 2 (temporarily, because array macros work for power of 2 sizes only)
2929
#define NUM_FRI_LAYERS 2
3030

3131
/// The target for the proof of work.
3232
#define POW_TARGET_64 0x07ffffffffffffff // 5 bits
3333

3434
#else
35-
#define TRACE_LOG_SIZE 9
35+
#define TRACE_LOG_SIZE 8
3636

3737
/// Log size of the extended evaluation domain.
3838
/// trace log size + log blowup factor
39-
#define LDE_LOG_SIZE 13
39+
#define LDE_LOG_SIZE 12
4040

4141
/// Number of FRI queries.
4242
/// NOTE: must be power of 2 (temporarily, because array macros work for power of 2 sizes only)

stwo-verifier/src/evals/verify.simf

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ DEFINE_ZIP_ARR(query_decommitments, u32, Decommitment, 16, 8)
8484
/// Zip queries with decommitments to get query decommitments (u32, Decommitment).
8585
fn query_decommitments_zip_arr(queries: [u32; NUM_FRI_QUERIES], decommitments: [Decommitment; NUM_FRI_QUERIES]) -> [QueryDecommitment; NUM_FRI_QUERIES] {
8686
#ifdef TESTING
87-
query_decommitments_zip_arr_1(queries, decommitments)
87+
query_decommitments_zip_arr_2(queries, decommitments)
8888
#else
8989
query_decommitments_zip_arr_16(queries, decommitments)
9090
#endif // TESTING
@@ -101,7 +101,7 @@ DEFINE_MAP_ARR(QueryDecommitment, QueryResponse, QueryDecommitmentCtx, verify_qu
101101
/// Map query decommitments to query responses.
102102
fn verify_query_map_arr(query_decommitments: [QueryDecommitment; NUM_FRI_QUERIES], ctx: QueryDecommitmentCtx) -> ([QueryResponse; NUM_FRI_QUERIES], QueryDecommitmentCtx) {
103103
#ifdef TESTING
104-
verify_query_map_arr_1(query_decommitments, ctx)
104+
verify_query_map_arr_2(query_decommitments, ctx)
105105
#else
106106
verify_query_map_arr_16(query_decommitments, ctx)
107107
#endif // TESTING

stwo-verifier/src/fri/answers.simf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ DEFINE_MAP_ARR(QueryResponse, FriAnswer, QueryResponseCtx, fri_answer, 16, 8)
140140
/// Map query responses to FRI answers.
141141
fn fri_answer_map_arr(responses: [QueryResponse; NUM_FRI_QUERIES], ctx: QueryResponseCtx) -> ([FriAnswer; NUM_FRI_QUERIES], QueryResponseCtx) {
142142
#ifdef TESTING
143-
fri_answer_map_arr_1(responses, ctx)
143+
fri_answer_map_arr_2(responses, ctx)
144144
#else
145145
fri_answer_map_arr_16(responses, ctx)
146146
#endif // TESTING

stwo-verifier/src/fri/commit.simf

Lines changed: 17 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,9 @@
1313
#include "macros/array_map.simf"
1414

1515
/// FRI commitments:
16-
/// * first layer commitment
17-
/// * inner layers commitments
16+
/// * first and inner layers commitments
1817
/// * last layer: line polynomial coefficient (always degree 0)
19-
type FriCommitments = (u256, [u256; NUM_FRI_LAYERS], QM31);
18+
type FriCommitments = ([u256; NUM_FRI_LAYERS], QM31);
2019

2120
/// FRI layer:
2221
/// * commitment
@@ -27,7 +26,7 @@ type FriLayer = (u256, QM31);
2726
/// * first layer
2827
/// * inner layers
2928
/// * last layer: line polynomial coefficient (always degree 0)
30-
type FriLayers = (FriLayer, [FriLayer; NUM_FRI_LAYERS], QM31);
29+
type FriLayers = ([FriLayer; NUM_FRI_LAYERS], QM31);
3130

3231
/// Reads the FRI layer commitment and samples a random coefficient.
3332
/// Fails if the computed FRI layer evaluation does not match the pre-sampled FRI layer evaluation.
@@ -43,12 +42,12 @@ fn fri_layer_commit(root: u256, state: ChannelState) -> (FriLayer, ChannelState)
4342
}
4443

4544
/// Mix line polynomial coefficients into the channel state.
46-
fn channel_mix_line_poly(state: ChannelState, last_layer: QM31) -> ChannelState {
45+
fn channel_mix_line_poly(state: ChannelState, line_poly_coeff: QM31) -> ChannelState {
4746
let (digest, _): ChannelState = state;
4847
let ctx: Ctx8 = jet::sha_256_ctx_8_init();
4948
let ctx: Ctx8 = jet::sha_256_ctx_8_add_32(ctx, digest);
5049
// Mix coefficients
51-
let ctx: Ctx8 = hasher_add_qm31(last_layer, ctx);
50+
let ctx: Ctx8 = hasher_add_qm31(line_poly_coeff, ctx);
5251
let res: u256 = jet::sha_256_ctx_8_finalize(ctx);
5352
// Reset the num_sent counter
5453
(res, 0)
@@ -70,38 +69,31 @@ fn fri_layer_commit_map_arr(commitments: [u256; NUM_FRI_LAYERS], state: ChannelS
7069

7170
/// Commits the FRI layers.
7271
fn fri_commit(state: ChannelState, fri_commitments: FriCommitments) -> (ChannelState, FriLayers) {
73-
let (first_commitment, inner_commitments, last_layer): FriCommitments = fri_commitments;
72+
let (commitments, line_poly_coeff): FriCommitments = fri_commitments;
7473

75-
// Commit first layer
76-
let (first_layer, state): (FriLayer, ChannelState) = fri_layer_commit(first_commitment, state);
77-
78-
// Commit inner layers
79-
let (inner_layers, state): ([FriLayer; NUM_FRI_LAYERS], ChannelState) = fri_layer_commit_map_arr(inner_commitments, state);
74+
// Commit first and inner layers
75+
let (layers, state): ([FriLayer; NUM_FRI_LAYERS], ChannelState) = fri_layer_commit_map_arr(commitments, state);
8076

8177
// Commit last layer (line polynomial coefficients)
82-
let state: ChannelState = channel_mix_line_poly(state, last_layer);
78+
let state: ChannelState = channel_mix_line_poly(state, line_poly_coeff);
8379

84-
(state, (first_layer, inner_layers, last_layer))
80+
(state, (layers, line_poly_coeff))
8581
}
8682

8783
#ifdef TESTING
8884

8985
fn test_fri_commit() {
90-
let state: ChannelState = (0x44dff4effae0be493c21672683c892b3baeaa7d251e5e7153bc0e0b2da8a9d96, 0);
86+
let state: ChannelState = (0x28583eb83f6fe4837a995243e8e5c2648edbfd9cdd06262edcbce47fe96e5e3c, 0);
9187
let fri_commitments: FriCommitments = (
92-
0x768a89291d8db4be401f5545f1cc7f25a1b00753773a4b3789592badc33ecf3f,
93-
[
94-
0x3f2a2cb1b0384b1ddd57c16bb40b67a0b011c1449606196e959fdbff885a0280,
95-
0xb03eededd1682fcab8c82d0d284ccf0f8ddc7d003708ecd12323adfd843f0f5f,
96-
],
97-
qm31(1462473176, 2065988908, 1080482792, 1497677558),
88+
[0x0bee0d98d63597a3b6725c885e77c23647585e29ae3ebd3b3b88bdba21f30f13, 0xd63312459c0bd0456789cce101ab292880c3bf103514eb22bd7457808388423e],
89+
qm31(502777192, 1639915013, 504572960, 826242631),
9890
);
9991
let ((digest, _), layers): (ChannelState, FriLayers) = fri_commit(state, fri_commitments);
100-
assert!(jet::eq_256(digest, 0xa906adfe1ac2b7cf283ae8a11e16a1c4c44834f259056eacd36d14044761266c));
92+
assert!(jet::eq_256(digest, 0x3532bad0c22ceae1a8c9e137dfde35b18e8bd4a08ce6c5e64ea3d9465a517f82));
10193

102-
let (first_layer, _, _): FriLayers = layers;
103-
let (_, first_alpha): FriLayer = first_layer;
104-
assert!(qm31_eq(first_alpha, qm31(299390734, 1867715474, 641071780, 899293580)));
94+
let (layers, _): FriLayers = layers;
95+
let ((_, first_alpha), _): (FriLayer, FriLayer) = <[FriLayer; NUM_FRI_LAYERS]>::into(layers);
96+
assert!(qm31_eq(first_alpha, qm31(766788992, 1201991280, 1148418600, 2122329945)));
10597
}
10698

10799
#endif // TESTING

stwo-verifier/src/fri/queries.simf

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ fn fri_generate_queries(state: ChannelState, log_size: u8) -> (ChannelState, [u3
3131
let (state, (q0, q1, q2, q3, q4, q5, q6, q7)): (ChannelState, U32x8) = channel_draw_queries_8(state, query_mask);
3232

3333
#ifdef TESTING
34-
let queries: [u32; NUM_FRI_QUERIES] = dbg!([q0]);
34+
let queries: [u32; NUM_FRI_QUERIES] = dbg!([q0, q1]);
3535
#else
3636
let (state, (q8, q9, q10, q11, q12, q13, q14, q15)): (ChannelState, U32x8) = channel_draw_queries_8(state, query_mask);
3737
// CONFIG: see NUM_FRI_QUERIES

0 commit comments

Comments
 (0)