Skip to content

Commit 102f446

Browse files
committed
runtime-tables:include negative tests
1 parent 7d2fff1 commit 102f446

File tree

2 files changed

+48
-6
lines changed

2 files changed

+48
-6
lines changed

src/lib/provable/gadgets/runtime-table.ts

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,10 +38,14 @@ export {
3838
* should consider an optimized custom solution.
3939
* - **mutable data**: runtime tables are write-once only, so once inserted entries in table are
4040
* remain fixed. To represent changing data, consider using DynamicArrays.
41-
*
41+
* - **unknown bounded size**: runtime lookup tables require all possible `indices` to be preallocated
42+
* at construction time. If the set of possible indices is not known in advance, consider using
43+
* DynamicArrays instead.
44+
*
4245
* ## Invariants & constraints
4346
* - `id !== 0 && id !== 1`. (Reserved for XOR and range-check tables.)
4447
* - `indices` are **unique**. Duplicates are rejected.
48+
* - `indices` must be **known** at construction time.
4549
* - `lookup()` **batches** each 3 calls (for the same table) into **one** gate automatically.
4650
* - `check()` call is required for soundness to flush 1–2 pending pairs before the end of the circuit.
4751
*
@@ -180,4 +184,4 @@ class RuntimeTable {
180184
this.pairs = [];
181185
}
182186
}
183-
}
187+
}

src/lib/provable/test/runtime-table.unit-test.ts

Lines changed: 42 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,15 @@ import { RuntimeTable } from '../gadgets/runtime-table.js';
77
import { constraintSystem, contains } from '../../testing/constraint-system.js';
88
import { FeatureFlags } from '../../proof-system/feature-flags.js';
99
import { Cache } from '../../proof-system/cache.js';
10+
import { Provable } from '../provable.js';
1011

11-
let uint = (n: number | bigint): Spec<bigint, Field> => {
12-
return fieldWithRng(Random.bignat((1n << BigInt(n)) - 1n));
13-
};
1412

15-
// Runtime table tests
13+
// in-circuit unit tests
1614
{
15+
let uint = (n: number | bigint): Spec<bigint, Field> => {
16+
return fieldWithRng(Random.bignat((1n << BigInt(n)) - 1n));
17+
};
18+
1719
let RuntimeTableZkProgram = ZkProgram({
1820
name: 'runtime-table',
1921
methods: {
@@ -68,3 +70,39 @@ let uint = (n: number | bigint): Spec<bigint, Field> => {
6870
}
6971
);
7072
}
73+
74+
// off-circuit checks
75+
{
76+
function expectThrows(fn: () => void | Promise<void>, msg: string) {
77+
let threw = false;
78+
try {
79+
fn();
80+
} catch {
81+
threw = true;
82+
}
83+
assert(threw, msg);
84+
}
85+
86+
// Cannot create a table with reserved id
87+
expectThrows(() => {
88+
new RuntimeTable(0, [0n, 1n]);
89+
}, 'Table id 0 is reserved');
90+
91+
expectThrows(() => {
92+
new RuntimeTable(1, [0n, 1n]);
93+
}, 'Table id 1 is reserved');
94+
95+
// Cannot create a table with duplicate indices
96+
expectThrows(() => {
97+
new RuntimeTable(3, [0n, 1n, 2n, 2n]);
98+
}, 'Indices must be unique');
99+
100+
// Cannot insert pairs with indices not in the table
101+
await Provable.runAndCheck(async () => {
102+
let table = new RuntimeTable(42, [0n, 1n, 2n, 3n, 4n, 5n]);
103+
104+
expectThrows(() => {
105+
table.insert([[0n, new Field(1)], [6n, new Field(2)]]);
106+
}, 'Indices must be preallocated at creation of the runtime table');
107+
});
108+
}

0 commit comments

Comments
 (0)