Certified Minecraft redstone
redstone-verify takes a redstone layout and a Verilog spec. It accepts the layout only if it is proved equal to the spec for every input, the proof is checked by independent programs, and the layout behaves the same on two MCHPRS engines. AI agents or search may propose layouts. The funnel decides.

Browse all 92 layouts. Each has a card with its verdict, and 92 of them open in a viewer where you can flip levers and watch the signal.
Read the paper (PDF) · Source code on GitHub
The funnel
A layout is ACCEPTED only if all eight stages pass. The rejection counts are from the shipped mutants: broken copies of accepted layouts, all of which must be rejected.
- 1. extract
- The layout is built as a world and turned into a component graph. Unbuildable layouts are rejected: floating wires, torches without a block, duplicate port names.
- 2. subset
- The graph must use only components with a frozen meaning: levers, wires, torches, repeaters, comparators, lamps, constants. No feedback loops.
- 3. ports
- The spec's ports are 1-bit and match the layout's levers (inputs) and lamps or observed blocks (outputs) by name.
- 4. prove
- The graph is turned into Verilog and compared with the spec by a miter. The solver must show that no input separates them.
- 5. certify
- The same claim is redone from an unoptimised AIGER file with a plain CNF encoder. CaDiCaL writes an LRAT proof; rup_check, lrat-check and the verified cake_lpr must all accept it.
- 6. lean
- An independent route: the spec and the layout become Lean definitions and a Lean theorem says they implement each other.
- 7. cosim
- The layout runs on the MCHPRS engine and on redpiler. Both must equal the model and the spec: every input up to 16 inputs, else structured plus 4,096 random vectors.
- 8. metrics
- Blocks, volume, components, critical path, settle ticks and glitches are recorded.
Benchmark
25 circuits from a NOT gate to a 15-bit adder, a 16-bit comparator and a multiplier. Blocks count every block including levers, lamps and floor. "Best" is the smallest accepted candidate in this table (hand-designed, agent and hill-climb candidates); a later ShinkaEvolve search found a 10-block AND that is not listed here. Time is prove plus certify of the best layout, from one run on an idle AWS server. Mutants: rejected / shipped, and in parentheses how many of the rejected still pass co-simulation. Components, critical path and glitches are seed/best. Click a circuit to see its layouts.
| circuit | in/out | seed | best | comp. | crit. rt | glitches | prove+cert s | CNF vars/cl. | LRAT kB | mutants (tests pass) |
|---|---|---|---|---|---|---|---|---|---|---|
| not | 1/1 | 9 | 4 | 1/1 | 1/1 | 0/0 | 0.09 | 86/254 | 4 | - |
| and2 | 2/1 | 25 | 16 | 3/2 | 2/2 | 0/0 | 0.10 | 248/701 | 11 | 1/1 (0) |
| nand2 | 2/1 | 21 | 7 | 2/2 | 1/1 | 0/0 | 0.10 | 212/593 | 9 | - |
| xor2 | 2/1 | 51 | 31 | 3/4 | 2/2 | 0/0 | 0.13 | 798/2231 | 37 | - |
| xnor2 | 2/1 | 53 | 32 | 4/5 | 3/3 | 0/0 | 0.14 | 825/2312 | 39 | - |
| imply2 | 2/1 | 23 | 5 | 1/1 | 1/1 | 0/0 | 0.10 | 185/512 | 7 | - |
| mux2 | 3/1 | 43 | 18 | 4/5 | 3/3 | 1/0 | 0.12 | 550/1532 | 25 | - |
| maj3 | 3/1 | 89 | 29 | 4/9 | 2/3 | 0/0 | 0.15 | 1010/2816 | 48 | - |
| half_adder | 2/2 | 96 | 34 | 6/7 | 2/4 | 0/1 | 0.15 | 988/2753 | 50 | - |
| full_adder | 3/2 | 236 | 71 | 14/13 | 5/7 | 2/8 | 0.21 | 1932/5342 | 95 | - |
| dec2to4 | 2/4 | 124 | 27 | 8/7 | 2/3 | 0/1 | 0.14 | 934/2651 | 47 | - |
| c17 | 5/2 | 162 | 41 | 12/7 | 3/4 | 6/8 | 0.17 | 1294/3602 | 60 | - |
| mul2 | 4/4 | 504 | - | 44 | 13 | 7 | 0.74 | 8845/24950 | 566 | 4/4 (0) |
| add4 | 9/5 | 699 | - | 60 | 12 | 769 | 1.20 | 14697/41327 | 812 | 5/5 (0) |
| add8 | 17/9 | 1399 | - | 120 | 20 | 12858 | 2.53 | 29323/82445 | 1824 | 5/5 (0) |
| add12 | 25/13 | 2099 | - | 180 | 28 | 19658 | 4.02 | 43949/123563 | 3085 | 5/5 (0) |
| add15 | 31/16 | 2624 | - | 225 | 34 | 24756 | 5.25 | 54911/154379 | 4275 | 5/5 (0) |
| eq8 | 16/1 | 481 | - | 37 | 7 | 0 | 0.76 | 9535/26600 | 497 | 4/4 (0) |
| eq12 | 24/1 | 721 | - | 55 | 9 | 0 | 1.14 | 14381/40106 | 779 | 4/4 (0) |
| eq16 | 32/1 | 961 | - | 73 | 11 | 0 | 1.58 | 19227/53612 | 1073 | 4/4 (0) |
| or17 | 17/1 | 73 | 56 | 1/0 | 1/0 | 0/0 | 0.36 | 4091/11237 | 208 | 1/1 (0) |
| or24 | 24/1 | 99 | - | 1 | 1 | 0 | 0.46 | 5675/15572 | 253 | 1/1 (0) |
| or32 | 32/1 | 131 | - | 2 | 2 | 0 | 0.61 | 7502/20573 | 393 | 2/2 (0) |
| and24 | 24/1 | 245 | - | 28 | 5 | 0 | 0.52 | 6548/18167 | 283 | 3/3 (0) |
| and32 | 32/1 | 325 | - | 37 | 6 | 0 | 0.68 | 8735/24224 | 383 | 4/4 (0) |
Viewer
The viewer covers layouts up to 1,000 blocks. It has an isometric and a plan view with a layer slider. Clicking a lever flips its input.
graph2v.py). It shows where the signal ends up. It is not vanilla Minecraft and has no timing. Tick playback replays a recorded run of the MCHPRS engine, one redstone tick per step, for layouts with at most 6 inputs. It has no torch burnout. Before a layout gets a viewer, the JavaScript evaluator must agree with both engines on every checked vector and with the engine's block states, block by block (results/site_check.json).Additional experiments
Multipliers: proof search and proof checking
A separate three-seed campaign extends certificate measurements: at 22 inputs, median CaDiCaL
time is 1825 s against a*b, versus 10.4 s against the layout's array architecture.
Checker time scales approximately with LRAT size (empirical log-log slopes 0.86–1.00), while
proof search and size grow sharply across architectures. Bit-parallel enumeration is faster
throughout the measured 10–22-input cross-architecture range, but yields no checked proof.
These are certificate-route results, not full-gate ACCEPTs; timings use a shared host.
Weak carry chains: faults missed by generic tests
A separate carry-skip adder experiment exposes faults missed by the tests. At widths 12–14, 20 of 45 faulty layouts pass the gate's co-simulation and both generic structured suites. The proof refutes all 45, with counterexamples confirmed on the engine; all 6 fault-free controls receive full ACCEPT. ABC also finds every fault, as do a fault-specific structured suite and 106 random model vectors. At widths 15–24, 107 random model vectors miss 3 of 24 faults; above 15 bits the engine's 32-input limit prevents replay and full ACCEPT.
Independent encoding and mutation checks
A separately written Rust encoder agrees on 62 accepted and 116 refuted miters, with all 62 independent UNSAT certificates checked by cake_lpr. Translator mutation tests exercise 314 single-site and 10 paired faults, with no observed false ACCEPT: 227 are detected (20 only by differential regressions outside the gate), 68 change no layout of the test pool, and 29 are noticed by nothing. A separate wire/timing generator produces 748 mutants, including 510 proof refutations and 224 steady-state equivalences; co-simulation misses 4 refuted wide-layout mutants.
Third-party compilers
We imported layouts from three public redstone compilers and ran them through the same funnel. 504 layouts were imported and 470 were accepted. 99 came from a compiler run and 65 of those were accepted. The rest are the compilers' own shipped example files. Every rejection has a located cause.
| tool | circuit | blocks (ours) | verdict | LRAT |
|---|---|---|---|---|
| REDA d8f3af0 | not / and2 / nand2 / imply2 | 12 / 54 / 54 / 44 (4 / 16 / 7 / 5) | ACCEPT | 10–60 KB |
| REDA | mux2, half_adder, maj3, full_adder, dec2to4, c17 | 174, 208, 792, 1,636, 648, 1,086 (18, 34, 29, 71, 27, 41) | ACCEPT | 0.1–0.7 MB |
| REDA | mul2, mul3, eq8, eq12 | 1,880, 12,426, 13,806, 28,954 | ACCEPT (eq8 exhaustive, 65,536 vectors) | up to 56 MB |
| REDA | eq16 | 51,436 | REJECT at Lean: simp step limit exceeded (SAT, LRAT and co-simulation pass); ACCEPT with --lean-long (Lean 851 s) | 56 MB |
| REDA | or24, or32, and24, and32, add4 | 8,250–23,516; add4 16,872 (699) | ACCEPT | up to 18 MB |
| REDA | add8, add12, add15 | 52,016, 93,086, 147,868 (1,399–2,624) | REJECT at Lean (simp step limit exceeded); also not settled within 200 ticks on redpiler. With --max-ticks 600 and --lean-long: add8 ACCEPT (Lean 790 s); add12 and add15 REJECT, bv_decide does not finish (add12: compile error after 2,505 s with a 7200 s budget; add15: timeout after 7200 s) | 59–167 MB |
| REDA | xor2, xnor2, or17 | 193*, 193*, 1,761* | REJECT unbuildable (F3) | – |
| Redstone-Compiler cc99773, final world | not / imply2 | 3 (4) / 21 (5) | ACCEPT | 2.5 / 19.5 KB |
| Redstone-Compiler, final world | and2 / nand2 | 32* / 31* | REJECT oscillates (F1) | – |
| Redstone-Compiler, all 64 candidates | and2 / nand2 / imply2 / not | – | 6, 11, 11, 16 of 16 ACCEPT | – |
| Redstone-Compiler | xor2, xnor2, half_adder, mux2, maj3, dec2to4, c17, full_adder, mul2, add4, eq8, or17 | – | no layout from the tool (F5) | – |
| Redstone-Compiler, its own shipped files (405) | half adder, xor-generated, full-adder, 3-input XOR, and-gate, 400 sampled tiles | 36 (34), 25 (31), 59 (71), 70, 17, tiles 19–70 | all ACCEPT | – |
| rtl2mc cbe416d | and2, xor2, half_adder, full_adder, mux2 | 2,224–17,044* | REJECT outside the subset (redstone_block) | – |
Findings in the compilers' output
Reproducers have been reported to Redstone-Compiler, REDA and MCHPRS. The separate certificate-checker finding is reported to drat-trim.
F1. Redstone-Compiler: input ports that feed back into the logic
In its exported and2 the torch that computes NOT a powers a block that touches a's own input wire. That is a one-torch ring oscillator. Source inspection suggests that candidate testing with levers, followed by export with wire at the ports, explains the discrepancy; we have not instrumented that execution path. With levers at the port cells the same world is accepted with a certificate.
We placed the raw layouts in vanilla Minecraft 1.21.1. The ring runs with period 4 for eight pulses, then the torch burns out and the ring stays dead. So vanilla does not oscillate forever, but the world is still not a working gate: nand2 gives the wrong output at a=0, b=1, and and2 matches its table only after the burnout. The tool's own simulator calls and2 wrong at a=0, b=1 (y=1, spec 0).


F3. REDA: redstone dust with nothing to stand on
REDA places dust on top of dust (xor2, xnor2) or on a repeater (or17). Its own simulator calls these layouts correct. Vanilla removes that dust when the layout is placed. The outputs then equal the dust-removed engine variant on every probed vector and differ from the spec exactly where the proof says: xor2 gives y=1 and xnor2 gives y=0 at a=b=0, and or17 gives y=0 with only i15 or only i16 on. For or17 all 4,096 random co-simulation vectors pass. Only the proof finds the bug.


Also found: Redstone-Compiler's interface.json lacks the placement offset and the outputs (F2). rtl2mc uses a redstone block that is outside our subset (F4). Redstone-Compiler cannot compile most of the benchmark (F5).
What this does not show
- The proof is about steady state. Timing, glitches and torch burnout are outside it. Glitches are measured, not proved.
- Only combinational layouts are in the subset. Latches and clocks are not.
- The vanilla Minecraft oracle is a spot check on a sample of vectors, not a proof.