Repository navigation
Conversation
Each wrong way to write logic in an o1js circuit is a test that shows the failure, and each right way is a test that shows it works: constants and variables, Provable.if and a JavaScript if, loop bounds, finding a value in a list, unconstrained witnesses, toBigInt()/toString(), and assertions against returned Bools. Messages are from o1js 3.0.0. Part of #1249 (6.7). Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Open
27 of 46 tasks
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
New page Tutorial 14: Logic in a Circuit (
docs/zkapps/tutorials/14-circuit-logic.mdx) and its example projectexamples/zkapps/14-circuit-logic. The page is built test-first: each "how not to" is a test that proves the failure, and each "how to" is a test that proves the fix. Each error message on the page is the real text from o1js3.0.0. All code on the page comes from the example through#include_code.Also:
sidebars.js: page 14 after 13.pagination_next: zkapps/tutorials/circuit-logic. Page 14 haspagination_prevto 13.docs/zkapps/tutorials/index.mdx: page 14 in the list..github/workflows/test-tutorials.yml: example in the run, test and canary matrices.static/llms.txt,static/llms-full.txtregenerated.Topics, claims and tests (34 tests)
Constants and variables (
constants.test.ts, real proofs)adds no constraints for arithmetic on constantsadds no constraints for a variable times a constant plus a constantisConstant()—marks a Field made from a JavaScript value as a constant, and a witness as a variableproves a secret more than the minimum that was compiled in,cannot prove a secret that is not more than the minimumcompile()→the proof could not be constructed: rest of division by vanishing polynomial—cannot prove after the JavaScript value changes, until the program is compiled againgives a different verification key for a different constantproves against different minimums with one verification key,cannot prove a secret that is not more than the minimum inputProvable.ifand a JavaScriptif(branching.test.ts)ifon aBoolcompiles with no error and always takes the true branch (aBoolis an object) —compiles with no error,always takes the true branch, so a score of 5 gets the bonus.toBoolean()→b.toBoolean() was called on a variable Bool `b` in provable code.at compile —fails at compile time with toBoolean()Provable.if—selects the bonus in the proof for each scoreProvable.ifcomputes both branches:x.div(0)in the unselected branch →Constraint unsatisfied—computes both branches, so a division by 0 in the branch that is not selected fails,gives 0 for y = 0 and x / y otherwise when each branch is safeLoops (
loops.test.ts)x.toBigInt() was called on a variable field element `x` in provable code.at compile —fails at compile time when the loop bound depends on a variableanalyzeMethods()rows double when the steps double (4/8/16 steps → 2/4/8 rows) —unrolls a JavaScript loop: twice the steps give twice the rowsProvable.if, one circuit —sums the first n items for n from 0 to MAX_LENGTH, with one circuit,cannot prove for n more than MAX_LENGTHFind a value in a list (#892's
array.includes()case,includes.test.ts)Array.includes()is false for a value in the list (reference equality) —is not found by Array.includes(), although the list has itArray.some(e => e.equals(x))is true for a value not in the list (Bool is truthy) —is found by Array.some() with equals(), although the list does not have itreducewithequals()/or()—is found by includes() with or() only when the list has itWitnesses (
witness.test.ts, real proofs)gives an honest prover a square rootverify()is true —accepts any witness when there is no constraint: ...does not put the witness code in the verification keyy.mul(y).assertEquals(x, ...)the same witness fails —rejects the same malicious witness when a constraint checks ittoBigInt()/toString()and debugging (conversions.test.ts)fails at compile time with toBigInt(),fails at compile time with toString()toBits()instead —proves if a number is even with constrained bitsProvable.asProverruns only when proving —runs Provable.asProver only when proving, with the valuesasProver/Provable.logadd 0 rows —adds no constraints for Provable.asProver and Provable.logAssertions and returned Bools (
assertions.test.ts, real proofs)Boolgives a valid proof of a false result —gives a valid proof for an age of 12 when the method returns a Bool: the output is falsecannot prove an age of 12 when the method asserts,proves an age of 30 when the method assertsChecks run locally (Node 22)
npm startandnpm test(34/34 pass; about 11 minutes with the default jest workers).npm run build,npm run test:scripts,npm run check-llms-txt,npm run check-o1labs-linkspass. Each o1Labs link on the page returns HTTP 200.Part of #1249 (6.7). Closes #892, #240.
🤖 Generated with Claude Code