Commit graph

214 commits

Author SHA1 Message Date
Rob Knight
acab26e5c1
Remove batch splitting system (#475)
* First pass at removing batch splitting

* Refactor to separate module loading from request parsing

* Consolidate module functionality

* Tidy up comments

* Use array of modules instead of HashMap

* Formatting

* Use module hashes when importing modules
2026-02-09 10:31:47 +01:00
Rob Knight
5dab8195b4
Fix accidental inclusion of extra input PODs (#476) (#478)
* Fix issue with adding extra input PODs

* Panic if input PODs are missing
2026-02-06 17:18:35 +01:00
2bd99ef322
MultiPodBuilder improvements (#473)
- Export MultiPodBuilder Error
- Redefine MultiPodBuilder error to wrap the frontend Error (this way we get better formatting instead of an embedded string)
- handle initial wildcard values in `MultiPodBuilder.op` just like the `MainPodBuilder` does
2026-02-06 10:53:01 +01:00
arnaucube
b04560c362
merkletree: reduce gate amount (-23%) by custom poseidon to use flag as initial state (#472)
* merkletree: custom poseidon to use flag as initial state.

This allows to do the merkletree related hashing in 1 gate instead of 2,
reducing ~23% of gates per merkle proof.

| tree levels   | 10 | 16 | 32  | 40  | 64  | 128 | 130 | 250  | 256  |
|---------------|----|----|-----|-----|-----|-----|-----|------|------|
| old num gates | 50 | 76 | 144 | 178 | 280 | 554 | 564 | 1076 | 1102 |
| new num gates | 39 | 59 | 111 | 137 | 215 | 425 | 433 | 825  | 845  |

* update docs with new tree hashing approach

* add inline comment stating clear how the flag is used in the state permutation
2026-02-04 12:31:56 +01:00
641d8dabdd
Merkle tree for custom predicate batches (#471)
Resolve https://github.com/0xPARC/pod2/issues/466

Now batches are identified by the root of a merkle tree that contains all the predicates (using sequential indices as keys).  This means that the format to identify a custom predicate reference is still a hash + index, but the calculation of the hash is different.
The MainPod circuit now isn't limited by number of batches but instead number of custom predicates; and for each one we verify a merkle proof to verify the batch id.

I've removed a bunch of tests from lang that were testing splitting into multiple batches because there's no longer any need for that.  In a future PR we'll remove the code that handles batch splitting.

Each custom predicate needs 148.2 gates (which is very close to my estimate of 142.7 in https://github.com/0xPARC/pod2/issues/466#issuecomment-3823531286 where I actually made a mistake and considered 5 predicates per batch instead of 4 in the previous Params).
2026-02-04 11:12:32 +01:00
a7a30176a7
Split Params into base and developer-defined (#458)
I thought it would be nice to have a Predicate for the typed value so that the developer can work with predicates as values comfortably.  Then I noticed that hashing a predicate required `Params` which would have been annoying for converting a `TypedValue::Predicate` to `RawValue` and this led to a small refactor over how `Params` work.

We already had some fields in the `Params` struct that determine compatibility between encoded data.  They can be seen as determining a kind of ABI compatibility.  In general it's better if those parameters don't change so that different circuit configurations can still verify proofs from each other.  So I decided to force those parameters to be constant in the code base and not allow the user of our library to change them.  Many field element serialization/deserialization functions in our code depended on those parameters, and since now they are constant many functions get rid of the `Params` argument, which simplifies the code.  This includes the serialization of a `Predicate` which was required to calculate its hash.
2026-02-02 16:23:32 +01:00
498e946612
Feat/fst order pred part3 & part4 (#457)
* support wildcard predicates in frontend

* suport wildcard predicate in podlang

* add validation test

* test full flow and apply some fixes

* fix clippy

* fix merge issues

* use desugared predicate

* Fix parsing of intro statement templates inside custom predicates

* Tidy up comments

* lang: handle wildcard predicate

* add unreachable message

---------

Co-authored-by: Rob Knight <mail@robknight.org.uk>
2026-02-02 10:59:33 +01:00
Rob Knight
b66f5051b5
MultiPodBuilder fixes (#468)
* Remove CopyStatement constraints

* Use a constant objective, since the iterative approach already finds the minimum number of PODs

* Make solving/proving consume the builder

* Remove use of cached builder
2026-02-01 11:54:09 -08:00
Rob Knight
879c7201ad
Fix parsing of intro statement templates inside custom predicates (#467)
* Fix parsing of intro statement templates inside custom predicates

* Tidy up comments
2026-01-30 10:30:57 -08:00
337a51135e
make hash_verifier_data_gadget and dummy pub (#464)
These two functions are used by the VDF Pod (previously known as PoW
Pod)
2026-01-28 16:08:22 +01:00
Rob Knight
48aa004ae5
Create multiple PODs where resource limits for a single POD are exceeded (#444)
* Create multiple PODs where resource limits for a single POD are exceeded

* HashSet -> BTreeSet determinism fix

* Fixed incorrect assignment of input PODs and added test

* Ensure only a single output POD

* Return error when reveal() called with unknown statement

* Use unreachable! for presumed-impossible cases

* Use assert_eq! rather than debug_assert_eq

* Use FIFO for topological sort

* Simplify bounds calculation

* Some more simplifications/comments

* Enforce dep_idx < idx invariant

* Incrementally solve rather than estimating slack

* Fix tests to correctly test dependencies between private and public statements

* More tidying

* Note possible optimisation of MainPodBuilder cloning of input PODs

* Fix tracking of total input POD count

* Refactor tests

* Formatting

* Small optimisation: use Vec in place of BTreeSet

* Account for automatically-inserted Contains statements

* Formatting

* Fix possible issue with copied statements

* Simplify result type given only a single result MainPod

* Remove unnecessary POD count estimate functionality

* Simplify dependency ordering and tracking

* Remove notion of multiple output PODs from solver

* Minor simplifications

* Use add_constraint instead of with

* Remove unnecessary check following assertion

* Fix handling of anchored keys given that Contains statements are not auto-inserted if they already exist

* Fix confusing dependency graph test

* Remove prove_order

* Fix deduplication and possible double-counting of public but not copied statements

* Reorder so that the output POD is the final POD

* Add more detailed tests

* Remove redundant tests

* Simplify POD counting

* More docs

* Flag more branches as unreachable

* Formatting

* Fix for changed custom batch parsing
2026-01-28 07:44:04 +01:00
Rob Knight
d1b7b4d37e
Improved predicate splitting (#445)
* Multi-batch splitting

* Invoke split predicates by name, passing in full argument list

* Reorder batches to prevent failure of forward references where possible

* Rename APIs for clarity

* Simplify example

* Add more docs

* Review updates

* Remove duplicate code

* Comment topological sort algorithm
2026-01-27 21:54:21 -08:00
9c9a2c454c
Feat/fst order pred part1 & part2 (#454)
Implement support for first order predicates in the backend.
Now a statement template can have a predicate hash or a wildcard.

## predicate <-> predicate hash constraints

To build the custom predicate table we need to calculate the custom predicate batch id, which uses the serialization of the statement templates before normalization.  This serialization uses the predicate hash when the template uses a predicate (instead of a wildcard).  Then in normalization we recalculate the predicate hash if it was a Batch Self.

This means that the relation between hash and predicate must be checked before and after normalization when the template is not using a wildcard.  How this is achieved:
- Before normalization: the constructor of StatementTmplTarget forces that if we keep a predicate, it's hash must be equal to the pred_hash when the template has a predicate (and not a wildcard)
- After normalization: the predicate hash is calculated in the normalization and replaced in the case of the template using a predicate and it being a BatchSelf.  If it was a predicate but not batch self, the old value was used which was constrained via the constructor.

See `CircuitBuilder::add_virtual_statement_tmpl` and `normalize_st_tmpl_circuit`

## Wildcard predicate resolution

It is done via `make_predicate_from_template_circuit` and is fairly simple as it's contains similar logic to `make_statement_arg_from_template_circuit` but simpler.
2026-01-20 13:14:22 +01:00
1724e7b146
feat: in MainPodBuilder track literal contains in dict_contains (#456)
The MainPodBuilder automatically adds contains statements for operations
that are created from entries.  But if the contains statement was
already added manually there will be duplicates.  We now track manually
added contains statements so that we don't generate duplicates when
adding statements from entries that use them.
2026-01-19 16:50:02 +01:00
0fca00cc93
Use predicate hash in statements instead of the literal predicate
Resolve #448 

Previously a predicate was 6 elements.  Now it grows to 8 elements; and the hash is 4 elements.

Some parts of the circuit require only require equality checks with the predicate: that works with the predicate hash.  Other parts require inspecting or working with particular elements in the predicate, those need the preimage of the predicate hash.
Both `StatementTarget` and `StatementTmplTarget` have been updated to include the predicate hash and optionally the predicate.  When the predicate is included, constraints are automatically generated for `pred_hash = hash(pred)`.  We only include the predicate when needed.
2026-01-19 11:02:11 +01:00
arnaucube
2eb1daeb92
[docs] Port the example that @ax0 told me months ago about a theorem-ish perspective on predicates, and updates the signature section adding a note (& references) on the current signature scheme. (#443)
* Port the example that @ax0 told me months ago about a theorem-ish perspective on predicates, and updates the signature section adding a note (& references) on the current signature scheme.

* apply review corrections from @ed255

* update example with @artwyman IsComposite suggestion & transitive_eq example
2026-01-07 16:24:56 +01:00
813a86c670
Remove max_depth in native MerkleTree (#442)
This simplifies the MerkleTree (and container) API.
Defer the max depth check when assigning the witness (merkle proof siblings) to the merkle tree circuit.

In this implementation the native Merkle Tree branches grow as much as they needed.  There are no checks of max depth in the merkle tree.  All keys are 256 bits (I added a debug_assert for this); so in the worst case a path will have depth 256.  It can't have a longer depth because the `insert` method calls `prove_nonexistence` which errors if the key already exists; another one may exist which must be different and thus require a path <= 256 depth. 

Resolve #436
2025-12-16 13:18:49 +01:00
Ahmad Afuni
32dc85471d
Add max input POD check to MainPodBuilder (#440) 2025-12-08 23:23:51 +10:00
Rob Knight
42f979c408
Frontend AST for Podlang (#432)
* Basic frontend AST and semantic validation

* Intro statement support

* Simplify validator lifetime

* Fix arity validation

* Lowering and splitting

* Remove legacy processor and use frontend AST by default

* Use builders instead of creating middleware types directly

* Typos/formatting

* Improve error messages when overflowing a batch due to splitting

* Add FromStr implementation for NativePredicate

* Remove 'raw' fields, and switch HashHex representation to byte vector rather than string

* Simpler wrapper types for batch and intro predicate hashes

* Parse secret and public keys to their respective data structures earlier

* More detail around string escape validity

* Simplify native predicate arity handling and move  method to NativePredicate impl

* Store hashes using middleware::Hash, and simplify lowering by using pre-parsed values

* Simplify predicate building

* Formatting

* Better error messages/suggestions for cases where predicate splitting fails

* Formatting

* Clippy fix

* Return error if we get a too-large int
2025-11-13 01:23:21 -08:00
c382bf487c
allow manually setting wildcard values (#438)
* allow manually setting wildcard values

* check for duplicate assignment
2025-10-27 11:31:21 +01:00
Rob Knight
aa4b531ac7
New 'use' syntax with support for intro predicates (#431)
* New 'use' syntax with support for intro predicates

* Use empty statement in test

* Review feedback
2025-10-17 03:27:11 -07:00
ffed5b4fbd
fix: remove dup arg in template builder for SetDelete (#430)
* fix: remove dup arg in template builder for SetDelete

* fix typo

* remove dbg
2025-10-01 16:10:24 +02:00
352b1fdac1
Allow creation of opaque custom predicate batch (#427)
This is useful for a verifier that wants to verify a MainPod that
contains a custom predicate in a public statement without
knowledge of how the custom predicate is defined.
2025-09-26 20:47:00 +10:00
Evan Laufer
5a80fba618
Add cases to desugar function for container update ops (#425)
* Add cases to desugar function for container update ops

* Make point hashable
2025-09-19 13:22:21 -07:00
Ahmad Afuni
6dcd17cc37
Update dependencies (#429) 2025-09-18 17:47:39 +10:00
Daniel Gulotta
26548cf612
Fix for #413 (#415) 2025-09-15 07:14:24 -07:00
1d14338351
make cache pub (#418) 2025-09-15 11:43:59 +02:00
Andrew Twyman
5de08da32c
Wildcards without the ? prefix (#422) 2025-09-12 13:08:17 -07:00
Andrew Twyman
7e04eb51ff
Optional dot syntax for anchored keys (#423) 2025-09-11 12:23:46 -07:00
Andrew Twyman
f95a27b412
Allow block comments with /* */ (#421) 2025-09-11 12:17:32 -07:00
Daniel Gulotta
03db60d94c
fix cargo doc warnings (#417) 2025-09-10 10:29:01 -07:00
Daniel Gulotta
c6c78304a9
remove unused file backends/plonky2/primitives/ec/gates/generic.rs (#416) 2025-09-10 07:49:35 -07:00
arnaucube
3d098c3ce6
update to latest plonky2 & plonky2-u32 versions in Cargo.toml (#414) 2025-09-09 10:50:51 +02:00
Andrew Twyman
a8a8734cd5
DictNotContains doesn't take a value arg (#412) 2025-09-08 01:19:43 -07:00
e1f8a9ad8b
Adjust default parameters (#406)
- Update formula in `estimate_verif_num_gates` after the update in the recursive verification from https://github.com/0xPARC/pod2/pull/397
- Update the parameters to get better utilization of 2^16 rows
- Update metrics report to be more compact
2025-09-08 10:14:12 +02:00
Daniel Gulotta
a24bbf7a3b
add container operation support to parser (#408) 2025-09-04 13:15:23 -07:00
Daniel Gulotta
b02d0ec462
allow downstream crates to instantiate *CircuitDataSerializer (#405) 2025-09-03 10:13:54 -07:00
Ahmad Afuni
1479400555
feat(backend): use custom gate for Schnorr signature verification (#397)
* schnorr signature prover optimization. TODO: implemented eval_unfiltered_circuit, serialize

* Use new gate(s) in MainPod circuit

* Formatting

* Clean-up

* Code review

* Code review

* Code review

* Formatting

* Remove unnecessary elements

---------

Co-authored-by: Linus Tang <linust@mit.edu>
2025-09-04 00:47:59 +10:00
ca97d9edc4
update docs with no-pod-id (#403)
* update docs with no-pod-id

* Update book/src/anchoredkeys.md

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>

* Update book/src/custompred.md

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>

* Update book/src/statements.md

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>

* Update book/src/statements.md

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>

---------

Co-authored-by: Ahmad Afuni <root@ahmadafuni.com>
2025-09-02 13:34:19 +02:00
511efa8d44
rename some old id to sts_hash (#402) 2025-08-28 10:48:43 +10:00
0e2f7b756e
No Pod IDs (#394)
- middleware:
  - Add `Statement::Intro`
  - Add `SignedBy` native predicate and operation.  The signature is auxiliary data to the operation
  - Rename `PodSigner` to `Signer` with a new API (just for signing `RawValue`)
  - Removed `NewEntry` operation.  Use `ContainsFromEntries` instead
  - Remove `KEY_SIGNER` and `KEY_TYPE` which are no longer used
  - Merge `RecursivePod` and `Pod` traits
  - Change the `Pod::deserialize_data` method to use `Self` instead of `Box<dyn Pod>` 
  - Extend `Pod` trait with these methods:
    - `is_main`: when the pod is Main, in a (recursive) verification its vk will be checked to exist in the vd_set but not if it's intro pod
    - `is_mock`: skip some verifications in the recursive mock MainPod verification
    - `verifier_data_hash`
    - `pod_id` renamed to `statements_hash`
  - AnchoredKeys are now a pair of dictionary root and key
  - Entry statements are now defined as Contains with literal arguments
    - Operations that take Entries now use Contains statements with literal arguments
- frontend:
  - Rename `SignedPod` to `SignedDict` (which now contains the dict, public key and signature, and can still `verify(self)`ed)
  - The `SignedDict` keeps the method `get_statement` for convenience but now it returns a `Contains` statement that proves the existence of the key in the dict
  - The `MainPodBuilder` automatically inserts a `Contains` statement when an operation is added that uses an entry as argument that was not yet "opened".
  - Removed the `literal` methods from the `MainPodBuilder` that were loading literals to anchored keys: that was no longer needed after we introduced literal arguments
- backend
  - Only verify inclusion of the verifying key into the vd_set if the pod is MainPod.  A pod is not MainPod if the first statement is Intro.
  - Reject intro pods that have non-intro statements
  - Empty pod now returns an intro statement
  - Don't insert a type statement automatically in MainPod and MockMainPod.  We get rid of the type entry.
  - Implement `SignedBy` operation, which uses the muxed table to store signature verifications
- Rename `PodId` to `statements_hash` or `sts_hash` for short.  Now this is only used as a hash of the statements for the circuits public inputs.
- Refactor normalization of `self` statements:
  - Before: replace values that contain `SELF` by the given pod_id
  - After: place the verifying key hash into the Intro predicates
2025-08-27 13:19:40 +02:00
Daniel Gulotta
122f9c3cac
pad_circuit: use config to determine zk and check for underflow (#395) 2025-08-25 08:12:04 -07:00
Daniel Gulotta
f76197c602
Fix handling of Lt, LtEq (#393)
Changed the middleware to only allow comparison of integers and to
use the implementation of Ord for i64.  This matches the backend
behavior.

Also fixed a separate bug where LtEqFromEntries was producing a
NotEquals statement.
2025-08-18 07:54:20 -07:00
Ahmad Afuni
1508dd6126
feat: add container update ops (#390)
* Add container update ops

* Update src/middleware/operation.rs

Co-authored-by: Eduard S. <eduardsanou@posteo.net>

* Update src/backends/plonky2/mainpod/mod.rs

Co-authored-by: Eduard S. <eduardsanou@posteo.net>

* Code review

---------

Co-authored-by: Eduard S. <eduardsanou@posteo.net>
2025-08-13 06:34:45 +10:00
656cae77e0
Add versioning features (#387)
- Add a function to calculate the hash of the `CommonCircuitData`.  The hash uniquely identify the `CommonCircuitData` used for a circuit/proof.  Serializing the struct is not enough because the polynomial identities of the custom gates are not serialized (only their parameters are); so I made a function to extract "fingerprints" of the custom gates by evaluating them over a predefined list of uniform values, and then doing a random linear combination over the results.
- Store the full verifier only circuit data of a proof in the MainPod so that we can verify pods from old circuits in new circuits and code
- Store the hash of the `CommonCircuitData` in the MainPod so that we can reject verifying old pods that use a different `CommonCircuitData` than the current one.  This has two goals
  - If the `CommonCircuitData` changes it's very likely that the verification will fail, but it will be hard to debug.  Doing this early check helps identify the origin of the verification failure as early as possible
  - There's a chance that the verification could succeed when the `CommonCircuitData` changes, and that could be dangerous because the verification will be doing different checks than the ones intended for the original proof, so we may be skipping some constraints that could lead to exploiting the system.  For this reason, whenever the common circuit data hash changes, all previous verifying keys should be discarded (that is, not included in the VDSet)
    - The fingerprint only has ~64 bits and the "random evaluation point" is fixed.  The assumption is that the pod developers are not malicious and are not changing the gates such that different gates give the same fingerprint.  With this assumption, I find it reasonable to assume that with high probability if a gate changes, its fingerprint changes as well.
- Add a github action that updates a wiki page with a table that contains: date, commit, params hash (with a link to the actual params), verifier data only circuit data hash and common circuit data hash.  This will make it easy to track when the common circuit data changes as well as track the verifier data corresponding to various versions (identified by commit)
  - The edited page is this one https://github.com/0xPARC/pod2/wiki/MainPod-circuit-info
  
Resolve https://github.com/0xPARC/pod2/issues/386

Summary of breaking changes:
- The `RecursivePod` trait has a new method `common_hash` that needs to return the result of `hash_common_data` on the `CommonCircuitData` that the circuit uses.
2025-08-08 09:33:44 -07:00
Ahmad Afuni
594c4d2e63
feat(backend): add updates and deletions to Merkle tree state transition proofs (#383)
* Add updates and deletions to Merkle tree state transition proofs

* Code review
2025-08-06 12:19:21 +10:00
bcaef6c47a
Add table multiplexer (and use it for container, custom pred & PublicKeyOf ops) (#376)
- Extend the `Flattenable` trait to include a `size` method that returns the number of `Target`s the type requires.  This is used in the table to figure out the max length of an array that must fit all entry types.
- Move the circuit methods to precalculate hash states and do hashes started from a precomputed state to a new module
- Introduce `MuxTableTarget` which allows easy multiplexing of tables where each sub-table may have entries of different lengths.  The table access is done via hashing + unhashing automatically (via use of a generator)
- Use the `MuxTableTarget` to access merkle tree claims and custom predicate verification, which where previously in different tables and accessed with independent random accesses each
- Move the public key derivation for the PublicKeyOf operation check to the same multiplexed table.  Now we can choose how many of those operations a circuit supports.

Resolve https://github.com/0xPARC/pod2/issues/357
Resolve https://github.com/0xPARC/pod2/issues/361
2025-08-05 19:09:41 -07:00
Daniel Gulotta
0305a4de19
add missing constructors to frontend::Operation (#379) 2025-08-04 14:42:13 -07:00
Daniel Gulotta
fe8c4eceb3
remove op! macro (#378) 2025-08-01 09:52:06 -07:00
Daniel Gulotta
7f120f026d
fix frontend::Operation::new_entry + doc improvements (#370) 2025-07-30 16:55:15 -07:00