zorch.commit.smcs¶
SP1 single-matrix commitment (SMCS) over zorch's Merkle blocks.
Semantically SP1's CudaTcsProver::commit_tensors for one matrix of
power-of-two height: hash each row to a leaf, fold sibling pairs to a Merkle
root (zorch's MerkleTree over Sponge + Compression), then apply
SP1's domain separator (the single_layer.rs convention) binding the matrix
shape into the root:
commit = compress([merkle_root, sponge([log_height, width])])
The domain separator is SP1-specific and lives here, not in zorch — zorch's
MerkleTree is deliberately scheme-agnostic and adds no separator. The same
holds for the verifier error codes, the open/verify path, and the heap proof
layout (prove_openings_at_indices): all SP1 glue, all here.
VerifyCode ¶
Bases: IntEnum
SMCS verifier return codes.
Values mirror SP1's verify enum so the FFI byte-match returns identical codes;
1 (WRONG_BATCH_SIZE) is unreachable for a single-matrix scheme (no batch
dimension), so it is omitted. verify_batch returns one of these as a traced
int32 rather than raising, so verification runs inside a jit/fused region.
Source code in zorch/commit/smcs.py
32 33 34 35 36 37 38 39 40 41 42 43 44 | |
SingleMatrixCommitmentScheme ¶
SP1's single-matrix commitment, built on zorch's agnostic Merkle blocks.
Holds the leaf Sponge and the 2-to-1 Compression (both also drive the
internal MerkleTree); digest_elems is the compressor chunk size.
Source code in zorch/commit/smcs.py
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 | |
commit ¶
commit(
matrix: Array, *, column_major: bool = False
) -> tuple[Array, list[Array]]
Commit a base-field (height, width) matrix (power-of-two height).
column_major commits the transpose (width, height) by hashing its
columns (a leaf is a column), so the producer can hand a codeword in its
native encode layout without a transpose; the root is identical to a
row-major commit of the transpose. It is a per-call choice — the same
scheme also commits row-major leaves (the FRI fold) — so it is not a
constructor property; open/verify re-hash individually-extracted
leaf rows and are layout-independent.
Returns (commitment, digest_layers): the (digest_elems,)
commitment with SP1's domain separator applied, plus zorch's layered
digest tree (leaf digests -> ... -> root). digest_layers is the
prover data open_batch needs for sibling paths — zorch's
MerkleTree is stateless, so the caller threads it back in (along
with the matrix, which holds the openable rows) rather than holding a
tree object.
Extension-field matrices are not yet supported (SP1 commits each EF row as
width * degree base-field elements, a reinterpretation not wired through
zorch's blocks yet — the FFI byte-match slice). The
leaf hash's field guard raises TypeError on an EF matrix ("input dtype
... must match the sponge field ...").
Source code in zorch/commit/smcs.py
68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 | |
hash_leaves ¶
hash_leaves(
matrix: Array, *, column_major: bool = False
) -> Array
commit's leaf-hash half: each leaf of matrix (layout per
column_major, see commit) to its (num_leaves, digest_elems)
digest layer. With fold_leaf_digests + bind_root, lets a
consumer cut jit-zone boundaries through the commit — only this half's
shapes carry the leaf width (see zorch.pcs.jagged.commit).
Source code in zorch/commit/smcs.py
103 104 105 106 107 108 109 110 | |
fold_leaf_digests ¶
fold_leaf_digests(
leaf_digests: Array,
) -> tuple[Array, list[Array]]
commit's fold half: a hash_leaves layer to (raw_root,
digest_layers). Layout-independent (the fold only compresses digests),
so one method serves both leaf layouts.
Source code in zorch/commit/smcs.py
112 113 114 115 116 | |
bind_root ¶
bind_root(raw_root: Array, shape_params: Array) -> Array
Apply SP1's domain separator to a raw root: the single source of the
compress([root, sponge([log_height, width])]) formula, shared by
commit, verify_batch, the jagged verifier, and the stacked open
so they can never drift. shape_params is the [log_height, width]
preimage as a field vector — a vector rather than two ints so a jit zone
can pass the width as a traced value instead of a compile key (the
zone-split commit's K-free tail). width is the base-field width
(commit/verify both guard EF).
Source code in zorch/commit/smcs.py
118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 | |
bind_structure ¶
bind_structure(
commitment: Array,
row_counts: Array,
column_counts: Array,
) -> Array
Bind jagged row/column structure into an SMCS commitment.
SP1's jagged commit convention: hash [num_tables, row_counts...,
column_counts...] and compress with the (already shape-bound)
commitment, so the verifier's claimed chip layout is pinned by the
commitment itself.
Source code in zorch/commit/smcs.py
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 | |
open_batch ¶
open_batch(
indices: Array,
matrix: Array,
digest_layers: list[Array],
) -> tuple[Array, list[Array]]
Open the rows at indices and collect their Merkle sibling paths.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
indices
|
Array
|
1-D |
required |
matrix
|
Array
|
the committed |
required |
digest_layers
|
list[Array]
|
|
required |
Returns (rows, proofs): rows is (Q, width); proofs is a
list of length log_height whose i-th entry is (Q, digest_elems),
the level-i sibling digest of every query. The sibling gather is
zorch's single-index MerkleTree.open batched over the queries with
frx.vmap — the consumer keeps no Merkle path logic of its own.
Source code in zorch/commit/smcs.py
160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 | |
verify_batch ¶
verify_batch(
commitment: Array,
dims: tuple[int, int],
index: int,
row: Array,
proof: list[Array],
) -> Array
Verify one opened row against an SMCS commitment.
Reconstructs the raw root from row + sibling proof (zorch's
reconstruct_root), re-binds SP1's domain separator (via the same
bind_root the prover used), and compares against commitment.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
commitment
|
Array
|
the |
required |
dims
|
tuple[int, int]
|
|
required |
index
|
int
|
the opened row index. |
required |
row
|
Array
|
the opened |
required |
proof
|
list[Array]
|
|
required |
Returns an int32 :class:VerifyCode: OK iff the rebound root
equals commitment; WRONG_HEIGHT if proof has the wrong
length; INDEX_OUT_OF_BOUNDS if index >= height; else
ROOT_MISMATCH.
Source code in zorch/commit/smcs.py
183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 | |
heap_digests
staticmethod
¶
heap_digests(digest_layers: list[Array]) -> Array
Flatten zorch's layered digest tree into SP1's heap buffer.
zorch returns layers leaf-first ([leaves, ..., root]); SP1's path
kernel indexes a single (2N-1, digest_elems) array in heap order
(root at 0, children of i at 2i+1/2i+2, leaf m at
2^H-1+m). Concatenating the layers root-first lays the levels down in
exactly that order — the adapter is just the reversal + concat.
Source code in zorch/commit/smcs.py
229 230 231 232 233 234 235 236 237 238 239 | |
prove_openings_at_indices ¶
prove_openings_at_indices(
flat_digests: Array, indices: Array, tree_height: int
) -> Array
SP1's computePaths kernel: sibling authentication paths from a
heap-indexed digest buffer.
Sibling indices are pure arithmetic on the heap layout (sibling of node
j is ((j-1) ^ 1) + 1; parent is (j-1) >> 1), so no level
depends on the data of another — the whole path is one gather.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
flat_digests
|
Array
|
|
required |
indices
|
Array
|
1-D |
required |
tree_height
|
int
|
|
required |
Returns (Q, tree_height, digest_elems): per query, the sibling
digest at each level, leaf level first.
Source code in zorch/commit/smcs.py
241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 | |