longfellow 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/CODE_OF_CONDUCT.md +10 -0
- data/LICENSE.txt +21 -0
- data/README.md +152 -0
- data/ext/longfellow/CMakeLists.txt +76 -0
- data/ext/longfellow/extconf.rb +77 -0
- data/lib/longfellow/attribute.rb +65 -0
- data/lib/longfellow/c.rb +105 -0
- data/lib/longfellow/errors.rb +78 -0
- data/lib/longfellow/version.rb +5 -0
- data/lib/longfellow/zk_spec.rb +40 -0
- data/lib/longfellow.rb +162 -0
- data/sig/longfellow.rbs +74 -0
- data/vendor/longfellow-zk/LICENSE +203 -0
- data/vendor/longfellow-zk/lib/algebra/blas.h +121 -0
- data/vendor/longfellow-zk/lib/algebra/bogorng.h +68 -0
- data/vendor/longfellow-zk/lib/algebra/compare.h +40 -0
- data/vendor/longfellow-zk/lib/algebra/convolution.h +219 -0
- data/vendor/longfellow-zk/lib/algebra/crt.cc +42 -0
- data/vendor/longfellow-zk/lib/algebra/crt.h +299 -0
- data/vendor/longfellow-zk/lib/algebra/crt_convolution.h +114 -0
- data/vendor/longfellow-zk/lib/algebra/crt_test.cc +371 -0
- data/vendor/longfellow-zk/lib/algebra/fft.h +104 -0
- data/vendor/longfellow-zk/lib/algebra/fft_interpolation.h +304 -0
- data/vendor/longfellow-zk/lib/algebra/fft_interpolation_test.cc +168 -0
- data/vendor/longfellow-zk/lib/algebra/fft_test.cc +257 -0
- data/vendor/longfellow-zk/lib/algebra/fp.h +59 -0
- data/vendor/longfellow-zk/lib/algebra/fp2.h +240 -0
- data/vendor/longfellow-zk/lib/algebra/fp24.h +342 -0
- data/vendor/longfellow-zk/lib/algebra/fp24_6.h +305 -0
- data/vendor/longfellow-zk/lib/algebra/fp24_6_test.cc +197 -0
- data/vendor/longfellow-zk/lib/algebra/fp2_test.cc +280 -0
- data/vendor/longfellow-zk/lib/algebra/fp_generic.h +533 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p128.h +91 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p256.h +68 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p256k1.h +123 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p384.h +65 -0
- data/vendor/longfellow-zk/lib/algebra/fp_p521.h +62 -0
- data/vendor/longfellow-zk/lib/algebra/fp_test.cc +522 -0
- data/vendor/longfellow-zk/lib/algebra/hash.h +39 -0
- data/vendor/longfellow-zk/lib/algebra/interpolation.h +117 -0
- data/vendor/longfellow-zk/lib/algebra/interpolation_test.cc +74 -0
- data/vendor/longfellow-zk/lib/algebra/limb.h +153 -0
- data/vendor/longfellow-zk/lib/algebra/limb_test.cc +75 -0
- data/vendor/longfellow-zk/lib/algebra/nat.cc +32 -0
- data/vendor/longfellow-zk/lib/algebra/nat.h +212 -0
- data/vendor/longfellow-zk/lib/algebra/nat_test.cc +183 -0
- data/vendor/longfellow-zk/lib/algebra/nussbaumer.h +400 -0
- data/vendor/longfellow-zk/lib/algebra/nussbaumer_test.cc +138 -0
- data/vendor/longfellow-zk/lib/algebra/nussbaumerfp2_test.cc +139 -0
- data/vendor/longfellow-zk/lib/algebra/permutations.h +79 -0
- data/vendor/longfellow-zk/lib/algebra/poly.h +240 -0
- data/vendor/longfellow-zk/lib/algebra/poly_test.cc +123 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon.h +150 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon_extension.h +108 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon_extension_test.cc +76 -0
- data/vendor/longfellow-zk/lib/algebra/reed_solomon_test.cc +473 -0
- data/vendor/longfellow-zk/lib/algebra/rfft.h +400 -0
- data/vendor/longfellow-zk/lib/algebra/rfft_test.cc +102 -0
- data/vendor/longfellow-zk/lib/algebra/static_string.h +29 -0
- data/vendor/longfellow-zk/lib/algebra/sysdep.h +495 -0
- data/vendor/longfellow-zk/lib/algebra/sysdep_test.cc +41 -0
- data/vendor/longfellow-zk/lib/algebra/twiddle.h +59 -0
- data/vendor/longfellow-zk/lib/algebra/utility.h +86 -0
- data/vendor/longfellow-zk/lib/algebra/utility_test.cc +86 -0
- data/vendor/longfellow-zk/lib/arrays/affine.h +56 -0
- data/vendor/longfellow-zk/lib/arrays/affine_test.cc +220 -0
- data/vendor/longfellow-zk/lib/arrays/dense.h +210 -0
- data/vendor/longfellow-zk/lib/arrays/eq.h +75 -0
- data/vendor/longfellow-zk/lib/arrays/eqs.h +137 -0
- data/vendor/longfellow-zk/lib/arrays/eqs_test.cc +151 -0
- data/vendor/longfellow-zk/lib/arrays/sparse.h +192 -0
- data/vendor/longfellow-zk/lib/cbor/host_decoder.h +323 -0
- data/vendor/longfellow-zk/lib/cbor/host_decoder_test.cc +541 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor.h +594 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_byte_decoder.h +150 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_byte_decoder_test.cc +147 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_constants.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_pluck.h +110 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_pluck_test.cc +55 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_test.cc +174 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_testing.h +98 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/cbor_witness.h +312 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/mso2_test.cc +662 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/mso_test.cc +485 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/scan.h +104 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser/scan_test.cc +137 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor.h +640 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_byte_decoder.h +150 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_byte_decoder_test.cc +147 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_constants.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_testing.h +99 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/cbor_witness.h +319 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/lexer_test.cc +120 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/mdoc_examples_test.cc +89 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_circuit_test.cc +506 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_size_test.cc +79 -0
- data/vendor/longfellow-zk/lib/circuits/cbor_parser_v2/parser_test.cc +473 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/canonicalization_test.cc +185 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/circuit_dump.h +65 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/compiler.h +471 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/compiler_test.cc +110 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/node.h +176 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/pdqhash.h +127 -0
- data/vendor/longfellow-zk/lib/circuits/compiler/schedule.h +435 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_circuit.h +371 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_external_test.cc +246 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_test.cc +587 -0
- data/vendor/longfellow-zk/lib/circuits/ecdsa/verify_witness.h +201 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_adder.h +140 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_adder_test.cc +64 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker.h +247 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_constants.h +35 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_encoder.h +72 -0
- data/vendor/longfellow-zk/lib/circuits/logic/bit_plucker_test.cc +183 -0
- data/vendor/longfellow-zk/lib/circuits/logic/compiler_backend.h +62 -0
- data/vendor/longfellow-zk/lib/circuits/logic/counter.h +171 -0
- data/vendor/longfellow-zk/lib/circuits/logic/counter_test.cc +102 -0
- data/vendor/longfellow-zk/lib/circuits/logic/evaluation_backend.h +94 -0
- data/vendor/longfellow-zk/lib/circuits/logic/logic.h +1232 -0
- data/vendor/longfellow-zk/lib/circuits/logic/logic_circuit_test.cc +310 -0
- data/vendor/longfellow-zk/lib/circuits/logic/logic_test.cc +521 -0
- data/vendor/longfellow-zk/lib/circuits/logic/memcmp.h +68 -0
- data/vendor/longfellow-zk/lib/circuits/logic/memcmp_test.cc +148 -0
- data/vendor/longfellow-zk/lib/circuits/logic/polynomial.h +94 -0
- data/vendor/longfellow-zk/lib/circuits/logic/polynomial_test.cc +62 -0
- data/vendor/longfellow-zk/lib/circuits/logic/routing.h +445 -0
- data/vendor/longfellow-zk/lib/circuits/logic/routing_test.cc +241 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary.h +55 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker.h +77 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker_constants.h +37 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_plucker_test.cc +53 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_size_test.cc +69 -0
- data/vendor/longfellow-zk/lib/circuits/logic/unary_test.cc +62 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_circuit.h +193 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_circuit_test.cc +223 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_reference.h +72 -0
- data/vendor/longfellow-zk/lib/circuits/mac/mac_witness.h +94 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/circuit_maker.cc +242 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_attribute_ids.h +311 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_attribute_test.cc +64 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_circuit_id.cc +85 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_constants.h +85 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_decompress.cc +41 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_decompress.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_examples.h +5232 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_generate_circuit.cc +199 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_hash.h +554 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_signature.h +143 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_signature_test.cc +444 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_test_attributes.h +157 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_witness.h +863 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk.cc +693 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk.h +216 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/mdoc_zk_test.cc +724 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/zk_spec.cc +100 -0
- data/vendor/longfellow-zk/lib/circuits/mdoc/zk_spec_test.cc +155 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_circuit.h +330 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_circuit_test.cc +607 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_io.h +26 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_witness.cc +163 -0
- data/vendor/longfellow-zk/lib/circuits/sha/flatsha256_witness.h +47 -0
- data/vendor/longfellow-zk/lib/circuits/sha/sha256_constants.cc +34 -0
- data/vendor/longfellow-zk/lib/circuits/sha/sha256_constants.h +27 -0
- data/vendor/longfellow-zk/lib/circuits/sha/sha256_test_values.h +389 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/ptrcred.h +171 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small.h +218 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_examples.h +118 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_io.h +25 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_test.cc +208 -0
- data/vendor/longfellow-zk/lib/circuits/tests/anoncred/small_witness.h +130 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode.h +508 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_circuit_test.cc +95 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_test.cc +119 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_util.cc +47 -0
- data/vendor/longfellow-zk/lib/circuits/tests/base64/decode_util.h +29 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_circuit.h +231 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_circuit_test.cc +428 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ec/pk_witness.h +102 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt.h +190 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_constants.h +26 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_test.cc +559 -0
- data/vendor/longfellow-zk/lib/circuits/tests/jwt/jwt_witness.h +315 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f.h +411 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_io.h +32 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_test.cc +364 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_1f_witness.h +278 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation.h +146 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_constants.h +25 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_test.cc +315 -0
- data/vendor/longfellow-zk/lib/circuits/tests/mdoc/mdoc_revocation_witness.h +136 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr.h +250 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr_test.cc +333 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/bitaddr/bitaddr_witness.h +152 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44.h +903 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_circuit_test.cc +274 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_eval_test.cc +440 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_examples.cc +8851 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_examples.h +93 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_types.cc +24 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_types.h +118 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_witness.h +453 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_44_witness_test.cc +49 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref.cc +458 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref.h +150 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test.cc +398 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors.inc +3618 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors_pkdecode.inc +689 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/ml_dsa_ref_test_vectors_sigdecode.inc +1501 -0
- data/vendor/longfellow-zk/lib/circuits/tests/pq/ml_dsa/sigdecode_test_vectors.inc +540 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_circuit.h +394 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_circuit_test.cc +577 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_constants.h +90 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_witness.cc +174 -0
- data/vendor/longfellow-zk/lib/circuits/tests/ripemd/ripemd_witness.h +140 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_circuit.h +351 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_circuit_test.cc +466 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference.cc +207 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference.h +59 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_reference_test.cc +153 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_round_constants.cc +39 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_round_constants.h +29 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_slicing.h +31 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_witness.cc +83 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/sha3_witness.h +72 -0
- data/vendor/longfellow-zk/lib/circuits/tests/sha3/shake_test_vectors.h +477 -0
- data/vendor/longfellow-zk/lib/ec/elliptic_curve.h +596 -0
- data/vendor/longfellow-zk/lib/ec/elliptic_curve_test.cc +548 -0
- data/vendor/longfellow-zk/lib/ec/p256.cc +36 -0
- data/vendor/longfellow-zk/lib/ec/p256.h +60 -0
- data/vendor/longfellow-zk/lib/ec/p256k1.cc +34 -0
- data/vendor/longfellow-zk/lib/ec/p256k1.h +60 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2_128.h +503 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2_128_bench.cc +48 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2_128_test.cc +416 -0
- data/vendor/longfellow-zk/lib/gf2k/gf2poly.h +74 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14.h +242 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_bench.cc +75 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_reed_solomon.h +127 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_reed_solomon_test.cc +110 -0
- data/vendor/longfellow-zk/lib/gf2k/lch14_test.cc +246 -0
- data/vendor/longfellow-zk/lib/gf2k/sysdep.h +329 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_param.h +449 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_prover.h +354 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_test.cc +136 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_transcript.h +67 -0
- data/vendor/longfellow-zk/lib/ligero/ligero_verifier.h +272 -0
- data/vendor/longfellow-zk/lib/merkle/merkle_commitment.h +104 -0
- data/vendor/longfellow-zk/lib/merkle/merkle_tree.h +216 -0
- data/vendor/longfellow-zk/lib/merkle/merkle_tree_test.cc +240 -0
- data/vendor/longfellow-zk/lib/proto/circuit.h +354 -0
- data/vendor/longfellow-zk/lib/proto/circuit_test.cc +202 -0
- data/vendor/longfellow-zk/lib/random/random.h +119 -0
- data/vendor/longfellow-zk/lib/random/random_test.cc +189 -0
- data/vendor/longfellow-zk/lib/random/secure_random_engine.h +37 -0
- data/vendor/longfellow-zk/lib/random/transcript.h +193 -0
- data/vendor/longfellow-zk/lib/random/transcript_test.cc +344 -0
- data/vendor/longfellow-zk/lib/sumcheck/circuit.h +148 -0
- data/vendor/longfellow-zk/lib/sumcheck/circuit_id.h +71 -0
- data/vendor/longfellow-zk/lib/sumcheck/equad.h +126 -0
- data/vendor/longfellow-zk/lib/sumcheck/hquad.h +115 -0
- data/vendor/longfellow-zk/lib/sumcheck/prover.h +59 -0
- data/vendor/longfellow-zk/lib/sumcheck/prover_layers.h +362 -0
- data/vendor/longfellow-zk/lib/sumcheck/quad.h +227 -0
- data/vendor/longfellow-zk/lib/sumcheck/quad_builder.h +211 -0
- data/vendor/longfellow-zk/lib/sumcheck/quad_test.cc +169 -0
- data/vendor/longfellow-zk/lib/sumcheck/sumcheck_test.cc +324 -0
- data/vendor/longfellow-zk/lib/sumcheck/testing.h +69 -0
- data/vendor/longfellow-zk/lib/sumcheck/transcript_sumcheck.h +85 -0
- data/vendor/longfellow-zk/lib/sumcheck/verifier.h +84 -0
- data/vendor/longfellow-zk/lib/sumcheck/verifier_layers.h +221 -0
- data/vendor/longfellow-zk/lib/testing/test_main.cc +50 -0
- data/vendor/longfellow-zk/lib/util/ceildiv.h +164 -0
- data/vendor/longfellow-zk/lib/util/ceildiv_test.cc +152 -0
- data/vendor/longfellow-zk/lib/util/crc64.h +45 -0
- data/vendor/longfellow-zk/lib/util/crypto.cc +39 -0
- data/vendor/longfellow-zk/lib/util/crypto.h +108 -0
- data/vendor/longfellow-zk/lib/util/log.cc +110 -0
- data/vendor/longfellow-zk/lib/util/log.h +33 -0
- data/vendor/longfellow-zk/lib/util/panic.h +40 -0
- data/vendor/longfellow-zk/lib/util/readbuffer.h +67 -0
- data/vendor/longfellow-zk/lib/util/serialization.h +54 -0
- data/vendor/longfellow-zk/lib/zk/zk_common.h +455 -0
- data/vendor/longfellow-zk/lib/zk/zk_proof.h +378 -0
- data/vendor/longfellow-zk/lib/zk/zk_prover.h +202 -0
- data/vendor/longfellow-zk/lib/zk/zk_test.cc +340 -0
- data/vendor/longfellow-zk/lib/zk/zk_testing.h +154 -0
- data/vendor/longfellow-zk/lib/zk/zk_verifier.h +109 -0
- metadata +347 -0
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
// Copyright 2026 Google LLC.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
#ifndef PRIVACY_PROOFS_ZK_LIB_CIRCUITS_COMPILER_CIRCUIT_DUMP_H_
|
|
16
|
+
#define PRIVACY_PROOFS_ZK_LIB_CIRCUITS_COMPILER_CIRCUIT_DUMP_H_
|
|
17
|
+
|
|
18
|
+
#include <stddef.h>
|
|
19
|
+
|
|
20
|
+
#include "circuits/compiler/compiler.h"
|
|
21
|
+
#include "util/log.h"
|
|
22
|
+
|
|
23
|
+
// Debug printing routines for circuit tests.
|
|
24
|
+
namespace proofs {
|
|
25
|
+
|
|
26
|
+
template <class Field>
|
|
27
|
+
inline void dump_info(const char* name, size_t size,
|
|
28
|
+
const QuadCircuit<Field>& Q) {
|
|
29
|
+
log(INFO, "Compiled circuit: %s[%zu]", name, size);
|
|
30
|
+
dump_q(Q);
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
template <class Field>
|
|
34
|
+
inline void dump_info(const char* name, size_t sz0, size_t sz1,
|
|
35
|
+
const QuadCircuit<Field>& Q) {
|
|
36
|
+
log(INFO, "Compiled circuit: %s[%zu][%zu]", name, sz0, sz1);
|
|
37
|
+
dump_q(Q);
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
template <class Field>
|
|
41
|
+
inline void dump_info(const char* name, size_t sz0, size_t sz1, size_t sz2,
|
|
42
|
+
const QuadCircuit<Field>& Q) {
|
|
43
|
+
log(INFO, "Compiled circuit: %s[%zu][%zu][%zu]", name, sz0, sz1, sz2);
|
|
44
|
+
dump_q(Q);
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
template <class Field>
|
|
48
|
+
inline void dump_info(const char* name, const QuadCircuit<Field>& Q) {
|
|
49
|
+
log(INFO, "Compiled circuit: %s", name);
|
|
50
|
+
dump_q(Q);
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
template <class Field>
|
|
54
|
+
inline void dump_q(const QuadCircuit<Field>& Q) {
|
|
55
|
+
log(INFO,
|
|
56
|
+
" depth: %zu wires: %zu in: %zu out:%zu use:%zu ovh:%zu t:%zu cse:%zu "
|
|
57
|
+
"notn:%zu",
|
|
58
|
+
Q.depth_, Q.nwires_, Q.ninput_, Q.noutput_,
|
|
59
|
+
Q.nwires_ - Q.nwires_overhead_, Q.nwires_overhead_, Q.nquad_terms_,
|
|
60
|
+
Q.nwires_cse_eliminated_, Q.nwires_not_needed_);
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
} // namespace proofs
|
|
64
|
+
|
|
65
|
+
#endif // PRIVACY_PROOFS_ZK_LIB_CIRCUITS_COMPILER_CIRCUIT_DUMP_H_
|
|
@@ -0,0 +1,471 @@
|
|
|
1
|
+
// Copyright 2026 Google LLC.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
#ifndef PRIVACY_PROOFS_ZK_LIB_CIRCUITS_COMPILER_COMPILER_H_
|
|
16
|
+
#define PRIVACY_PROOFS_ZK_LIB_CIRCUITS_COMPILER_COMPILER_H_
|
|
17
|
+
|
|
18
|
+
#include <stddef.h>
|
|
19
|
+
#include <stdint.h>
|
|
20
|
+
|
|
21
|
+
#include <algorithm>
|
|
22
|
+
#include <memory>
|
|
23
|
+
#include <vector>
|
|
24
|
+
|
|
25
|
+
#include "algebra/hash.h"
|
|
26
|
+
#include "circuits/compiler/node.h"
|
|
27
|
+
#include "circuits/compiler/pdqhash.h"
|
|
28
|
+
#include "circuits/compiler/schedule.h"
|
|
29
|
+
#include "sumcheck/circuit.h"
|
|
30
|
+
#include "sumcheck/circuit_id.h"
|
|
31
|
+
#include "sumcheck/quad.h"
|
|
32
|
+
#include "util/panic.h"
|
|
33
|
+
|
|
34
|
+
namespace proofs {
|
|
35
|
+
/*
|
|
36
|
+
QuadCircuit contains methods that facilitate defining circuits used to
|
|
37
|
+
express predicates that are to be proven or verified. This class allows one
|
|
38
|
+
to use basic arithmetic circuit operations (add, mul, input, assert0, ...)
|
|
39
|
+
to define the circuit on a set of abstract wire labels.
|
|
40
|
+
|
|
41
|
+
The "mkcircuit" compiler method than optimizes the circuit by applying all of
|
|
42
|
+
the basic tricks of constant propagation, common sub-expression elimination,
|
|
43
|
+
squashing layers into as few as possible, and grouping terms into quads.
|
|
44
|
+
|
|
45
|
+
Quads are a new form of gate (in contrast to the add and mul gates in most
|
|
46
|
+
sumcheck proof systems). Quads represent a "sum of quadratic terms" where
|
|
47
|
+
each term is w_l * w_r * v for two wire labels and a constant v.
|
|
48
|
+
*/
|
|
49
|
+
template <class Field>
|
|
50
|
+
class QuadCircuit {
|
|
51
|
+
public:
|
|
52
|
+
using Elt = typename Field::Elt;
|
|
53
|
+
using nodeinfo = NodeInfoF<Field>;
|
|
54
|
+
using node = NodeF<Field>;
|
|
55
|
+
using size_t_for_storage = term::size_t_for_storage;
|
|
56
|
+
using quad_corner_t = typename Quad<Field>::quad_corner_t;
|
|
57
|
+
|
|
58
|
+
const Field& f_;
|
|
59
|
+
|
|
60
|
+
public:
|
|
61
|
+
// Variables for informational purposes:
|
|
62
|
+
size_t ninput_;
|
|
63
|
+
size_t npub_input_; // number of public inputs, index of 1st private
|
|
64
|
+
size_t subfield_boundary_; // least wire not known to be in the subfield
|
|
65
|
+
size_t noutput_;
|
|
66
|
+
|
|
67
|
+
// set by the algebraic simplifiers in this file
|
|
68
|
+
size_t depth_;
|
|
69
|
+
size_t nwires_cse_eliminated_;
|
|
70
|
+
size_t nwires_not_needed_;
|
|
71
|
+
|
|
72
|
+
// set by the scheduler
|
|
73
|
+
size_t nwires_;
|
|
74
|
+
size_t nquad_terms_;
|
|
75
|
+
size_t nwires_overhead_;
|
|
76
|
+
|
|
77
|
+
explicit QuadCircuit(const Field& f)
|
|
78
|
+
: f_(f),
|
|
79
|
+
ninput_(0),
|
|
80
|
+
npub_input_(0),
|
|
81
|
+
subfield_boundary_(0),
|
|
82
|
+
noutput_(0),
|
|
83
|
+
depth_(0),
|
|
84
|
+
nwires_cse_eliminated_(0),
|
|
85
|
+
nwires_not_needed_(0),
|
|
86
|
+
nwires_(-1), // undefined until set in mkcircuit()
|
|
87
|
+
nquad_terms_(-1),
|
|
88
|
+
nwires_overhead_(-1) {
|
|
89
|
+
// make sure that Elt(0) is represented as index 0 in the constant
|
|
90
|
+
// table.
|
|
91
|
+
size_t ki0 = kstore(f.zero());
|
|
92
|
+
proofs::check(ki0 == 0, "ki0 == 0");
|
|
93
|
+
size_t ki1 = kstore(f.one());
|
|
94
|
+
proofs::check(ki1 == 1, "ki1 == 1");
|
|
95
|
+
|
|
96
|
+
// make sure node 0 exists, carrying input[0] = F.one()
|
|
97
|
+
input_wire();
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
// Produce a linear term 1 * op0 that the compiler will not
|
|
101
|
+
// attempt to optimize to op0. The reason for this function
|
|
102
|
+
// is to implement linear terms such as a*x in the quadratic form
|
|
103
|
+
// a*x+b*x*y. Left to its own devices, the compiler peeks into x,
|
|
104
|
+
// and if x=k*z*w, it produces a term (a*k)*z*w in the previous
|
|
105
|
+
// layer, possibly destroying common subexpressions. linear(op)
|
|
106
|
+
// introduces an explicit multiplication by wire 0, which the
|
|
107
|
+
// compiler does not attempt to optimize away.
|
|
108
|
+
size_t linear(size_t op0) { return mul(0, op0); }
|
|
109
|
+
size_t linear(const Elt& k, size_t op0) { return mul(k, 0, op0); }
|
|
110
|
+
|
|
111
|
+
size_t mul(const Elt& k, size_t op) {
|
|
112
|
+
if (k == f_.zero()) {
|
|
113
|
+
return konst(k);
|
|
114
|
+
} else if (k == f_.one() || nodes_[op].zero()) {
|
|
115
|
+
return op;
|
|
116
|
+
} else {
|
|
117
|
+
return push_node(scale(k, op));
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
size_t mul(size_t op0, size_t op1) { return mul(f_.one(), op0, op1); }
|
|
122
|
+
|
|
123
|
+
size_t mul(const Elt& k, size_t op0, size_t op1) {
|
|
124
|
+
const auto& n0 = nodes_[op0];
|
|
125
|
+
const auto& n1 = nodes_[op1];
|
|
126
|
+
|
|
127
|
+
if (n0.zero()) {
|
|
128
|
+
return op0;
|
|
129
|
+
} else if (n0.constant()) {
|
|
130
|
+
// k * (k1 * op1) -> (k * k1) * op1
|
|
131
|
+
return mul(f_.mulf(k, kload(n0.terms[0].ki)), op1);
|
|
132
|
+
} else if (n0.linearp()) {
|
|
133
|
+
// k * ((k1 * op0) * op1) -> (k * k1) * op0 * op1
|
|
134
|
+
return mul(f_.mulf(k, kload(n0.terms[0].ki)), n0.terms[0].op1, op1);
|
|
135
|
+
} else if (n1.zero() || n1.constant() || n1.linearp()) {
|
|
136
|
+
return mul(k, op1, op0);
|
|
137
|
+
} else {
|
|
138
|
+
// general term k * op0 * op1
|
|
139
|
+
return push_node(node(kstore(k), op0, op1));
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
size_t add(size_t op0, size_t op1) {
|
|
144
|
+
const auto& n0 = nodes_[op0];
|
|
145
|
+
const auto& n1 = nodes_[op1];
|
|
146
|
+
|
|
147
|
+
if (n0.zero()) {
|
|
148
|
+
return op1;
|
|
149
|
+
} else if (n1.zero()) {
|
|
150
|
+
return op0;
|
|
151
|
+
} else {
|
|
152
|
+
// If the two addends are of different depth, do not merge
|
|
153
|
+
// them, which is accomplished by multiplying the shallower
|
|
154
|
+
// node by 1 and treating it as a single term of the final
|
|
155
|
+
// sum.
|
|
156
|
+
//
|
|
157
|
+
// Like many other "optimizations", this is a heuristic
|
|
158
|
+
// that may or may not work, but it seems to be uniformly
|
|
159
|
+
// beneficial or at least not harmful for all our circuits
|
|
160
|
+
// as of 2023-11-15.
|
|
161
|
+
if (n0.info.depth < n1.info.depth) {
|
|
162
|
+
op0 = linear(op0);
|
|
163
|
+
} else if (n1.info.depth < n0.info.depth) {
|
|
164
|
+
op1 = linear(op1);
|
|
165
|
+
}
|
|
166
|
+
return push_node(merge(op0, op1));
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
size_t sub(size_t op0, size_t op1) { return add(op0, mul(f_.mone(), op1)); }
|
|
170
|
+
|
|
171
|
+
size_t konst(const Elt& k) { return push_node(node(kstore(k), 0, 0)); }
|
|
172
|
+
|
|
173
|
+
// Generate a special node that asserts that op == 0.
|
|
174
|
+
// The node has the form 0*(1*op), which does not normally
|
|
175
|
+
// appear in circuits.
|
|
176
|
+
size_t assert0(size_t op) {
|
|
177
|
+
const node* n = &nodes_[op];
|
|
178
|
+
if (n->zero()) {
|
|
179
|
+
// Identically zero, so nothing to generate.
|
|
180
|
+
// More importantly, we cannot multiply OP by 1,
|
|
181
|
+
// since OP doesn't really exist.
|
|
182
|
+
return op;
|
|
183
|
+
} else if (n->linearp()) {
|
|
184
|
+
// n = k * (1 * op1).
|
|
185
|
+
//
|
|
186
|
+
// Reduce to assert0(op1), but handle the screw case k==0,
|
|
187
|
+
// which shouldn't happen but just in case...
|
|
188
|
+
if (n->terms[0].ki == 0) {
|
|
189
|
+
return op;
|
|
190
|
+
} else {
|
|
191
|
+
return assert0(n->terms[0].op1);
|
|
192
|
+
}
|
|
193
|
+
} else {
|
|
194
|
+
typename term::assert0_type_hack hack;
|
|
195
|
+
std::vector<term> terms;
|
|
196
|
+
terms.push_back(term(op, hack));
|
|
197
|
+
size_t n1 = push_node(node(terms));
|
|
198
|
+
nodes_[n1].info.is_assert0 = true;
|
|
199
|
+
return n1;
|
|
200
|
+
}
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
// Wrappers to avoid creating unnecessary wires. The
|
|
204
|
+
// compiler will discard them anyway, but they still take
|
|
205
|
+
// time and space.
|
|
206
|
+
size_t axpy(size_t y, const Elt& a, size_t x) {
|
|
207
|
+
if (a == f_.zero()) {
|
|
208
|
+
return y;
|
|
209
|
+
}
|
|
210
|
+
return add(y, linear(a, x));
|
|
211
|
+
}
|
|
212
|
+
size_t apy(size_t y, const Elt& a) {
|
|
213
|
+
if (a == f_.zero()) {
|
|
214
|
+
return y;
|
|
215
|
+
}
|
|
216
|
+
return add(y, konst(a));
|
|
217
|
+
}
|
|
218
|
+
|
|
219
|
+
// Create an input wire.
|
|
220
|
+
//
|
|
221
|
+
// Most code should never call this function directly. Call
|
|
222
|
+
// Logic::eltw_input() instead.
|
|
223
|
+
size_t input_wire() { return push_node(node(quad_corner_t(ninput_++))); }
|
|
224
|
+
|
|
225
|
+
// This function demarcates the end of the public inputs and beginning of
|
|
226
|
+
// private inputs. It can only be called once.
|
|
227
|
+
void private_input() {
|
|
228
|
+
proofs::check(
|
|
229
|
+
npub_input_ == 0,
|
|
230
|
+
"private_input can only be called once after setting public inputs");
|
|
231
|
+
npub_input_ = ninput_;
|
|
232
|
+
}
|
|
233
|
+
|
|
234
|
+
// This function demarcates the end of the private inputs in the
|
|
235
|
+
// subfield and beginning of the full-field private inputs. It can
|
|
236
|
+
// only be called once.
|
|
237
|
+
void begin_full_field() {
|
|
238
|
+
proofs::check(subfield_boundary_ == 0,
|
|
239
|
+
"begin_full_field() can only be called once");
|
|
240
|
+
subfield_boundary_ = ninput_;
|
|
241
|
+
}
|
|
242
|
+
|
|
243
|
+
size_t ninput() const { return ninput_; }
|
|
244
|
+
|
|
245
|
+
void output_wire(size_t n, size_t wire_id) {
|
|
246
|
+
output_internal(n, quad_corner_t(wire_id));
|
|
247
|
+
}
|
|
248
|
+
|
|
249
|
+
std::unique_ptr<Circuit<Field>> mkcircuit(size_t nc) {
|
|
250
|
+
size_t depth_ub = compute_depth_ub();
|
|
251
|
+
fixup_last_layer_assertions(depth_ub);
|
|
252
|
+
compute_needed(depth_ub);
|
|
253
|
+
|
|
254
|
+
Scheduler<Field> sched(nodes_, f_);
|
|
255
|
+
std::unique_ptr<Circuit<Field>> c =
|
|
256
|
+
sched.mkcircuit(constants_, depth_ub, nc);
|
|
257
|
+
|
|
258
|
+
// re-export the scheduler telemetry
|
|
259
|
+
nwires_ = sched.nwires_;
|
|
260
|
+
nquad_terms_ = sched.nquad_terms_;
|
|
261
|
+
nwires_overhead_ = sched.nwires_overhead_;
|
|
262
|
+
|
|
263
|
+
c->ninputs = ninput();
|
|
264
|
+
c->npub_in = npub_input_;
|
|
265
|
+
c->subfield_boundary = subfield_boundary_;
|
|
266
|
+
|
|
267
|
+
circuit_id(c->id, *c, f_);
|
|
268
|
+
return c;
|
|
269
|
+
}
|
|
270
|
+
|
|
271
|
+
private:
|
|
272
|
+
void output_internal(size_t n, quad_corner_t wire_id) {
|
|
273
|
+
nodes_[n].info.is_output = true;
|
|
274
|
+
nodes_[n].info.desired_wire_id_for_output = wire_id;
|
|
275
|
+
noutput_++;
|
|
276
|
+
}
|
|
277
|
+
|
|
278
|
+
size_t push_node(node n) {
|
|
279
|
+
// common-subexpression elimination: if we have already seen a
|
|
280
|
+
// node equal to n, return that node.
|
|
281
|
+
uint64_t d = n.hash();
|
|
282
|
+
|
|
283
|
+
auto pred = [&](PdqHash::value_t op) { return n == nodes_[op]; };
|
|
284
|
+
if (size_t op = cse_.find(d, pred); op != PdqHash::kNil) {
|
|
285
|
+
// do not linear terms as eliminated by the CSE, since they are
|
|
286
|
+
// likely placeholder nodes absorbed by the next layer.
|
|
287
|
+
if (!n.linearp()) {
|
|
288
|
+
++nwires_cse_eliminated_;
|
|
289
|
+
}
|
|
290
|
+
return op;
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
// compute the node depth, which has been so far uninitialized
|
|
294
|
+
n.info.depth = 0;
|
|
295
|
+
for (const auto& t : n.terms) {
|
|
296
|
+
n.info.depth = std::max<size_t>(
|
|
297
|
+
n.info.depth, 1 + std::max<size_t>(nodes_[t.op0].info.depth,
|
|
298
|
+
nodes_[t.op1].info.depth));
|
|
299
|
+
}
|
|
300
|
+
|
|
301
|
+
size_t nid = nodes_.size();
|
|
302
|
+
nodes_.push_back(n);
|
|
303
|
+
|
|
304
|
+
// record NID into the common-subexpression elimination table
|
|
305
|
+
cse_.insert(d, nid);
|
|
306
|
+
|
|
307
|
+
return nid;
|
|
308
|
+
}
|
|
309
|
+
|
|
310
|
+
node materialize_input(size_t op) {
|
|
311
|
+
if (nodes_[op].info.is_input) {
|
|
312
|
+
return node(/*kstore(f.one())=*/1, 0, op);
|
|
313
|
+
} else {
|
|
314
|
+
return /*a copy of*/ nodes_[op];
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
node scale(const Elt& k, size_t op) {
|
|
319
|
+
node n = materialize_input(op);
|
|
320
|
+
for (auto& t : n.terms) {
|
|
321
|
+
t.ki = kstore(f_.mulf(kload(t.ki), k));
|
|
322
|
+
}
|
|
323
|
+
return n;
|
|
324
|
+
}
|
|
325
|
+
|
|
326
|
+
void push_back_unless_zero(std::vector<term>& terms, const term& t) const {
|
|
327
|
+
if (t.ki != 0) {
|
|
328
|
+
terms.push_back(t);
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
|
|
332
|
+
node merge(size_t op0, size_t op1) {
|
|
333
|
+
const node n0 = materialize_input(op0);
|
|
334
|
+
const node n1 = materialize_input(op1);
|
|
335
|
+
const std::vector<term>& t0 = n0.terms;
|
|
336
|
+
const std::vector<term>& t1 = n1.terms;
|
|
337
|
+
std::vector<term> terms;
|
|
338
|
+
size_t i0 = 0, i1 = 0;
|
|
339
|
+
while (i0 < t0.size() && i1 < t1.size()) {
|
|
340
|
+
term t;
|
|
341
|
+
if (t0[i0].eqndx(t1[i1])) {
|
|
342
|
+
t = t0[i0];
|
|
343
|
+
t.ki = kstore(f_.addf(kload(t.ki), kload(t1[i1].ki)));
|
|
344
|
+
i0++;
|
|
345
|
+
i1++;
|
|
346
|
+
} else if (t0[i0].ltndx(t1[i1])) {
|
|
347
|
+
t = t0[i0++];
|
|
348
|
+
} else {
|
|
349
|
+
t = t1[i1++];
|
|
350
|
+
}
|
|
351
|
+
push_back_unless_zero(terms, t);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
while (i0 < t0.size()) {
|
|
355
|
+
push_back_unless_zero(terms, t0[i0++]);
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
while (i1 < t1.size()) {
|
|
359
|
+
push_back_unless_zero(terms, t1[i1++]);
|
|
360
|
+
}
|
|
361
|
+
|
|
362
|
+
return node(terms);
|
|
363
|
+
}
|
|
364
|
+
|
|
365
|
+
// constants_[n] stores the n-th constant, once.
|
|
366
|
+
// Modulo collisions, constants_[constttab_[hash(k)]] == k
|
|
367
|
+
// for k \in Elt.
|
|
368
|
+
std::vector<Elt> constants_;
|
|
369
|
+
PdqHash consttab_;
|
|
370
|
+
|
|
371
|
+
std::vector<node> nodes_;
|
|
372
|
+
PdqHash cse_;
|
|
373
|
+
|
|
374
|
+
size_t kstore(const Elt& k) {
|
|
375
|
+
uint64_t d = elt_hash(k, f_);
|
|
376
|
+
auto pred = [&](PdqHash::value_t ki) { return k == constants_[ki]; };
|
|
377
|
+
size_t ki = consttab_.find(d, pred);
|
|
378
|
+
|
|
379
|
+
if (ki == PdqHash::kNil) {
|
|
380
|
+
ki = constants_.size();
|
|
381
|
+
constants_.push_back(k);
|
|
382
|
+
consttab_.insert(d, ki);
|
|
383
|
+
}
|
|
384
|
+
return ki;
|
|
385
|
+
}
|
|
386
|
+
Elt& kload(size_t ki) { return constants_[ki]; }
|
|
387
|
+
|
|
388
|
+
void mark_needed(size_t op, size_t depth_at_which_needed) {
|
|
389
|
+
nodeinfo* nfo = &nodes_[op].info;
|
|
390
|
+
nfo->is_needed = true;
|
|
391
|
+
nfo->max_needed_depth =
|
|
392
|
+
std::max<size_t>(depth_at_which_needed, nfo->max_needed_depth);
|
|
393
|
+
|
|
394
|
+
// If DEPTH_AT_WHICH_NEEDED > DEPTH + 1, we need a constant 1 at
|
|
395
|
+
// depth DEPTH_AT_WHICH_NEEDED-1 (and implicily any lower depths) in
|
|
396
|
+
// order to copy the node across levels.
|
|
397
|
+
if (depth_at_which_needed > nfo->depth + 1) {
|
|
398
|
+
nodeinfo* nfo0 = &nodes_[0].info;
|
|
399
|
+
nfo0->is_needed = true;
|
|
400
|
+
nfo0->max_needed_depth =
|
|
401
|
+
std::max<size_t>(depth_at_which_needed - 1, nfo0->max_needed_depth);
|
|
402
|
+
}
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
size_t compute_depth_ub() {
|
|
406
|
+
size_t r = 0;
|
|
407
|
+
for (auto& n : nodes_) {
|
|
408
|
+
if (n.info.is_output) {
|
|
409
|
+
r = std::max<size_t>(r, 1 + n.info.depth);
|
|
410
|
+
} else if (n.info.is_assert0) {
|
|
411
|
+
// Assertions of the form 0*(1*OP) contribute n.info.depth and
|
|
412
|
+
// not 1 + n.info.depth. If the assertion is in the last
|
|
413
|
+
// layer, it will be transformed in an output of OP at
|
|
414
|
+
// n.info.depth. If the assertion is not in the last layer,
|
|
415
|
+
// then it doesn't matter whether we use DEPTH or 1 + DEPTH.
|
|
416
|
+
if (n.linearp()) {
|
|
417
|
+
r = std::max<size_t>(r, n.info.depth);
|
|
418
|
+
} else {
|
|
419
|
+
r = std::max<size_t>(r, 1 + n.info.depth);
|
|
420
|
+
}
|
|
421
|
+
}
|
|
422
|
+
}
|
|
423
|
+
depth_ = r;
|
|
424
|
+
return r;
|
|
425
|
+
}
|
|
426
|
+
|
|
427
|
+
void fixup_last_layer_assertions(size_t depth_ub) {
|
|
428
|
+
// convert assertions in the last layer into outputs
|
|
429
|
+
for (auto& n : nodes_) {
|
|
430
|
+
if (!n.info.is_output && n.info.is_assert0 && n.info.depth == depth_ub &&
|
|
431
|
+
n.linearp()) {
|
|
432
|
+
n.info.is_assert0 = false;
|
|
433
|
+
output_internal(n.terms[0].op1, nodeinfo::kWireIdUndefined);
|
|
434
|
+
}
|
|
435
|
+
}
|
|
436
|
+
}
|
|
437
|
+
|
|
438
|
+
void compute_needed(size_t depth_ub) {
|
|
439
|
+
nwires_not_needed_ = 0;
|
|
440
|
+
for (size_t i = nodes_.size(); i-- > 0;) {
|
|
441
|
+
nodeinfo* nfo = &nodes_[i].info;
|
|
442
|
+
|
|
443
|
+
// mark all inputs as needed, to prevent ambiguity
|
|
444
|
+
// in the layout of the W[] vector.
|
|
445
|
+
if (nfo->is_input) {
|
|
446
|
+
mark_needed(i, 1);
|
|
447
|
+
}
|
|
448
|
+
// outputs are needed at depth_ub_
|
|
449
|
+
if (nfo->is_output) {
|
|
450
|
+
mark_needed(i, depth_ub);
|
|
451
|
+
}
|
|
452
|
+
// assertions are needed in the next layer
|
|
453
|
+
if (nfo->is_assert0) {
|
|
454
|
+
mark_needed(i, nfo->depth + 1);
|
|
455
|
+
}
|
|
456
|
+
|
|
457
|
+
if (nfo->is_needed) {
|
|
458
|
+
for (const auto& t : nodes_[i].terms) {
|
|
459
|
+
mark_needed(t.op0, nfo->depth);
|
|
460
|
+
mark_needed(t.op1, nfo->depth);
|
|
461
|
+
}
|
|
462
|
+
} else {
|
|
463
|
+
++nwires_not_needed_;
|
|
464
|
+
}
|
|
465
|
+
}
|
|
466
|
+
}
|
|
467
|
+
};
|
|
468
|
+
|
|
469
|
+
} // namespace proofs
|
|
470
|
+
|
|
471
|
+
#endif // PRIVACY_PROOFS_ZK_LIB_CIRCUITS_COMPILER_COMPILER_H_
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
// Copyright 2026 Google LLC.
|
|
2
|
+
//
|
|
3
|
+
// Licensed under the Apache License, Version 2.0 (the "License");
|
|
4
|
+
// you may not use this file except in compliance with the License.
|
|
5
|
+
// You may obtain a copy of the License at
|
|
6
|
+
//
|
|
7
|
+
// http://www.apache.org/licenses/LICENSE-2.0
|
|
8
|
+
//
|
|
9
|
+
// Unless required by applicable law or agreed to in writing, software
|
|
10
|
+
// distributed under the License is distributed on an "AS IS" BASIS,
|
|
11
|
+
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
12
|
+
// See the License for the specific language governing permissions and
|
|
13
|
+
// limitations under the License.
|
|
14
|
+
|
|
15
|
+
#include "circuits/compiler/compiler.h"
|
|
16
|
+
|
|
17
|
+
#include <stddef.h>
|
|
18
|
+
|
|
19
|
+
#include <memory>
|
|
20
|
+
|
|
21
|
+
#include "algebra/fp.h"
|
|
22
|
+
#include "arrays/dense.h"
|
|
23
|
+
#include "circuits/compiler/circuit_dump.h"
|
|
24
|
+
#include "sumcheck/circuit.h"
|
|
25
|
+
#include "sumcheck/testing.h"
|
|
26
|
+
#include "gtest/gtest.h"
|
|
27
|
+
|
|
28
|
+
namespace proofs {
|
|
29
|
+
namespace {
|
|
30
|
+
typedef Fp<1> Field;
|
|
31
|
+
const Field F("18446744073709551557");
|
|
32
|
+
|
|
33
|
+
TEST(Compiler, OutputAnInput) {
|
|
34
|
+
// screw case of outputting an input wire directly
|
|
35
|
+
QuadCircuit<Field> Q(F);
|
|
36
|
+
|
|
37
|
+
size_t a = Q.input_wire();
|
|
38
|
+
size_t b = Q.input_wire();
|
|
39
|
+
size_t c = Q.input_wire();
|
|
40
|
+
|
|
41
|
+
Q.output_wire(a, 0);
|
|
42
|
+
// add some depth
|
|
43
|
+
Q.output_wire(Q.mul(b, c), 1);
|
|
44
|
+
|
|
45
|
+
auto CIRCUIT = Q.mkcircuit(1);
|
|
46
|
+
EXPECT_EQ(Q.nwires_,
|
|
47
|
+
/*one=*/1u + /*inputs=*/3u + /*mul(b,c)=*/1u + /*copy(a)*/ 1u);
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
TEST(Compiler, AliasOfLinearAndCopyWire) {
|
|
51
|
+
// Screw case creating an explicit linear term 1*n
|
|
52
|
+
// at the same time as n is copied by the scheduler
|
|
53
|
+
QuadCircuit<Field> Q(F);
|
|
54
|
+
|
|
55
|
+
size_t a = Q.input_wire();
|
|
56
|
+
Q.output_wire(a, 0);
|
|
57
|
+
Q.output_wire(Q.linear(a), 1);
|
|
58
|
+
auto CIRCUIT = Q.mkcircuit(1);
|
|
59
|
+
dump_info<Field>("AliasOfLinearAndCopyWire", Q);
|
|
60
|
+
EXPECT_EQ(Q.nwires_,
|
|
61
|
+
/*one*/ 1u + /*a*/ 1u + /*copy of a at d=2*/ 1u + /*linear(a)=*/1u);
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
TEST(Compiler, Assert0) {
|
|
65
|
+
QuadCircuit<Field> Q(F);
|
|
66
|
+
|
|
67
|
+
// circuit verifies that a + b = c
|
|
68
|
+
size_t a = Q.input_wire();
|
|
69
|
+
size_t b = Q.input_wire();
|
|
70
|
+
size_t c = Q.input_wire();
|
|
71
|
+
|
|
72
|
+
Q.assert0(Q.sub(Q.add(a, b), c));
|
|
73
|
+
|
|
74
|
+
size_t nc = 1;
|
|
75
|
+
auto CIRCUIT = Q.mkcircuit(nc);
|
|
76
|
+
dump_info<Field>("assert0", Q);
|
|
77
|
+
|
|
78
|
+
Dense<Field> W(nc, 1 + 3);
|
|
79
|
+
W.v_[0] = F.one();
|
|
80
|
+
W.v_[1] = F.of_scalar(3);
|
|
81
|
+
W.v_[2] = F.of_scalar(5);
|
|
82
|
+
W.v_[3] = F.of_scalar(8);
|
|
83
|
+
|
|
84
|
+
// no outputs
|
|
85
|
+
Proof<Field> pr(CIRCUIT->nl);
|
|
86
|
+
run_prover<Field>(CIRCUIT.get(), W.clone(), &pr, F);
|
|
87
|
+
run_verifier<Field>(CIRCUIT.get(), W.clone(), pr, F);
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
TEST(Compiler, Output0) {
|
|
91
|
+
QuadCircuit<Field> Q(F);
|
|
92
|
+
|
|
93
|
+
size_t a = Q.konst(F.two());
|
|
94
|
+
size_t b = Q.konst(F.one());
|
|
95
|
+
size_t c = Q.mul(a, b);
|
|
96
|
+
size_t d = Q.sub(a, c);
|
|
97
|
+
Q.output_wire(d, 0);
|
|
98
|
+
|
|
99
|
+
size_t nc = 1;
|
|
100
|
+
auto CIRCUIT = Q.mkcircuit(nc);
|
|
101
|
+
dump_info<Field>("output0", Q);
|
|
102
|
+
|
|
103
|
+
EXPECT_EQ(Q.ninput_, 1u);
|
|
104
|
+
EXPECT_EQ(Q.noutput_, 1u);
|
|
105
|
+
EXPECT_EQ(Q.nwires_, 1u);
|
|
106
|
+
EXPECT_EQ(Q.nquad_terms_, 0u);
|
|
107
|
+
}
|
|
108
|
+
|
|
109
|
+
} // namespace
|
|
110
|
+
} // namespace proofs
|