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,362 @@
|
|
|
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_SUMCHECK_PROVER_LAYERS_H_
|
|
16
|
+
#define PRIVACY_PROOFS_ZK_LIB_SUMCHECK_PROVER_LAYERS_H_
|
|
17
|
+
|
|
18
|
+
#include <cstddef>
|
|
19
|
+
#include <memory>
|
|
20
|
+
#include <vector>
|
|
21
|
+
|
|
22
|
+
#include "arrays/affine.h"
|
|
23
|
+
#include "arrays/dense.h"
|
|
24
|
+
#include "arrays/eqs.h"
|
|
25
|
+
#include "sumcheck/circuit.h"
|
|
26
|
+
#include "sumcheck/equad.h"
|
|
27
|
+
#include "sumcheck/hquad.h"
|
|
28
|
+
#include "sumcheck/quad.h"
|
|
29
|
+
#include "sumcheck/transcript_sumcheck.h"
|
|
30
|
+
#include "util/panic.h"
|
|
31
|
+
|
|
32
|
+
namespace proofs {
|
|
33
|
+
|
|
34
|
+
// A high level idea is partially described in chapter 4.6.7 "Leveraging Data
|
|
35
|
+
// Parallelism for Further Speedups" in the book "Proofs, Arguments, and
|
|
36
|
+
// Zero-Knowledge" by Justin Thaler.
|
|
37
|
+
template <class Field>
|
|
38
|
+
class ProverLayers {
|
|
39
|
+
using Elt = typename Field::Elt;
|
|
40
|
+
|
|
41
|
+
public:
|
|
42
|
+
using inputs = std::vector<std::unique_ptr<Dense<Field>>>;
|
|
43
|
+
|
|
44
|
+
explicit ProverLayers(const Field& f) : f_(f) {}
|
|
45
|
+
|
|
46
|
+
// Evaluate CIRCUIT on input wires W0. This function stores the
|
|
47
|
+
// input wires of each layer L into IN->at(L), and returns the
|
|
48
|
+
// final output. This asymmetry reflects the fact that for L
|
|
49
|
+
// layers there are L+1 meaningful sets of wires, and that the
|
|
50
|
+
// prover needs IN while the verifier needs the final output.
|
|
51
|
+
std::unique_ptr<Dense<Field>> eval_circuit(inputs* in,
|
|
52
|
+
const Circuit<Field>* circ,
|
|
53
|
+
std::unique_ptr<Dense<Field>> W0,
|
|
54
|
+
const Field& F) {
|
|
55
|
+
if (in == nullptr || circ == nullptr || W0 == nullptr) return nullptr;
|
|
56
|
+
|
|
57
|
+
std::unique_ptr<Dense<Field>> finalV;
|
|
58
|
+
size_t nl = circ->nl, nc = circ->nc;
|
|
59
|
+
check(nl >= 1, "nl >= 1");
|
|
60
|
+
check(nc >= 1, "nc >= 1");
|
|
61
|
+
|
|
62
|
+
Dense<Field>* W = W0.get();
|
|
63
|
+
|
|
64
|
+
in->resize(nl);
|
|
65
|
+
in->at(nl - 1).swap(W0);
|
|
66
|
+
|
|
67
|
+
// Allocate memory and evaluate layer on input W and output V
|
|
68
|
+
for (size_t l = nl; l-- > 0;) {
|
|
69
|
+
Dense<Field>* V;
|
|
70
|
+
if (l > 0) {
|
|
71
|
+
// input of layer l-1 = output of layer l
|
|
72
|
+
in->at(l - 1) = std::make_unique<Dense<Field>>(nc, circ->l[l - 1].nw);
|
|
73
|
+
V = in->at(l - 1).get();
|
|
74
|
+
} else {
|
|
75
|
+
// final output = output of layer 0
|
|
76
|
+
finalV = std::make_unique<Dense<Field>>(nc, circ->nv);
|
|
77
|
+
V = finalV.get();
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
bool ok = eval_quad(circ->l[l].quad.get(), V, W, F);
|
|
81
|
+
if (!ok) {
|
|
82
|
+
// Early exit in case of assertion failure.
|
|
83
|
+
// In this case IN is only partially allocated.
|
|
84
|
+
// To avoid ambiguities, free all memory that we may have allocated.
|
|
85
|
+
for (size_t i = 0; i < nl; ++i) {
|
|
86
|
+
in->at(i) = nullptr;
|
|
87
|
+
}
|
|
88
|
+
finalV = nullptr;
|
|
89
|
+
|
|
90
|
+
return /*finalV=*/nullptr;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
W = V;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
return finalV;
|
|
97
|
+
}
|
|
98
|
+
|
|
99
|
+
protected:
|
|
100
|
+
const Field& f_;
|
|
101
|
+
|
|
102
|
+
// A struct that collects the bindings generated while proving one
|
|
103
|
+
// layer, to serve as initial bindings for the next layer.
|
|
104
|
+
// This protected class must be defined before the public section.
|
|
105
|
+
struct bindings {
|
|
106
|
+
size_t logv;
|
|
107
|
+
Elt q[Proof<Field>::kMaxBindings];
|
|
108
|
+
Elt g[2][Proof<Field>::kMaxBindings];
|
|
109
|
+
};
|
|
110
|
+
|
|
111
|
+
// Generate proof for circuit, as a protected member, the caller must
|
|
112
|
+
// ensure that input parameters are valid.
|
|
113
|
+
void prove(Proof<Field>* pr, const Proof<Field>* pad,
|
|
114
|
+
const Circuit<Field>* circ, const inputs& in, ProofAux<Field>* aux,
|
|
115
|
+
bindings& bnd, TranscriptSumcheck<Field>& ts, const Field& F) {
|
|
116
|
+
size_t logc = circ->logc;
|
|
117
|
+
corner_t nc = circ->nc;
|
|
118
|
+
|
|
119
|
+
check(circ->logv <= Proof<Field>::kMaxBindings,
|
|
120
|
+
"CIRCUIT->logv <= kMaxBindings");
|
|
121
|
+
bnd.logv = circ->logv;
|
|
122
|
+
|
|
123
|
+
// obtain the initial Q and G[0] bindings from the verifier
|
|
124
|
+
ts.begin_circuit(bnd.q, bnd.g[0]);
|
|
125
|
+
|
|
126
|
+
// Duplicate the g[0] binding.
|
|
127
|
+
// In general, the prover step takes two claims G[0], G[1] on the output
|
|
128
|
+
// wires and reduces them to one claim on G[0] + alpha * G[1] for random
|
|
129
|
+
// alpha. However, in the first step, there is only one claim, so we
|
|
130
|
+
// need to make up G[1]. The code sets G[1] = G[0] and it doesn't affect
|
|
131
|
+
// soundness.
|
|
132
|
+
for (size_t i = 0; i < bnd.logv; ++i) {
|
|
133
|
+
bnd.g[1][i] = bnd.g[0][i];
|
|
134
|
+
}
|
|
135
|
+
|
|
136
|
+
for (size_t ly = 0; ly < circ->nl; ++ly) {
|
|
137
|
+
auto clr = &circ->l.at(ly);
|
|
138
|
+
Elt alpha, beta;
|
|
139
|
+
ts.begin_layer(alpha, beta, ly);
|
|
140
|
+
Eqs<Field> EQ(logc, nc, bnd.q, F);
|
|
141
|
+
auto EQUAD =
|
|
142
|
+
clr->quad->bind_g(bnd.logv, bnd.g[0], bnd.g[1], alpha, beta, F);
|
|
143
|
+
|
|
144
|
+
layer(pr, pad, ts, bnd, ly, logc, clr->logw, &EQ, EQUAD.get(),
|
|
145
|
+
in.at(ly).get(), F);
|
|
146
|
+
|
|
147
|
+
if (aux != nullptr) {
|
|
148
|
+
aux->bound_quad[ly] = EQUAD->scalar();
|
|
149
|
+
}
|
|
150
|
+
}
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
private:
|
|
154
|
+
using index_t = typename EQuad<Field>::index_t;
|
|
155
|
+
using CPoly = typename LayerProof<Field>::CPoly;
|
|
156
|
+
using WPoly = typename LayerProof<Field>::WPoly;
|
|
157
|
+
using FCPoly = typename LayerProof<Field>::FCPoly;
|
|
158
|
+
using FWPoly = typename LayerProof<Field>::FWPoly;
|
|
159
|
+
|
|
160
|
+
/*
|
|
161
|
+
Engage in single-layer sumcheck on
|
|
162
|
+
|
|
163
|
+
EQ[|c] QUAD[|r,l] W[r,c] W[l,c]
|
|
164
|
+
|
|
165
|
+
Bind c to C, r to R, and l to L (in that order). Store claims
|
|
166
|
+
W[R,C] and W[L,C] in the proof, and set BND to the new bindings for
|
|
167
|
+
the next layer.
|
|
168
|
+
|
|
169
|
+
logw: number of sumcheck rounds in r, l
|
|
170
|
+
logc: number of sumcheck rounds in c
|
|
171
|
+
*/
|
|
172
|
+
void layer(Proof<Field>* pr, const Proof<Field>* pad,
|
|
173
|
+
TranscriptSumcheck<Field>& ts, bindings& bnd, size_t layer,
|
|
174
|
+
size_t logc, size_t logw, Eqs<Field>* EQ, HQuad<Field>* EQUAD,
|
|
175
|
+
Dense<Field>* W, const Field& F) {
|
|
176
|
+
check(EQ->n() == W->n0_, "EQ->n() == W->n0_");
|
|
177
|
+
|
|
178
|
+
check(logw <= Proof<Field>::kMaxBindings, "logw <= kMaxBindings");
|
|
179
|
+
bnd.logv = logw;
|
|
180
|
+
|
|
181
|
+
// Bind the C variables to Q.
|
|
182
|
+
// Note that binding C variables takes O(number_of_copies * circuit_size)
|
|
183
|
+
// while binding R, L takes O(circuit_size * log(circuit_size)). In most
|
|
184
|
+
// cases number_of_copies > log(circuit_size), so we don't have to
|
|
185
|
+
// optimize binding R, L.
|
|
186
|
+
for (size_t round = 0; round < logc; ++round) {
|
|
187
|
+
CPoly sum{};
|
|
188
|
+
|
|
189
|
+
// sum over r,l: QUAD[|r,l] EQ[|c] W[r,c] W[l,c]
|
|
190
|
+
for (index_t i = 0; i < EQUAD->n_; i++) {
|
|
191
|
+
const corner_t r(EQUAD->hc_[i].h[0]);
|
|
192
|
+
const corner_t l(EQUAD->hc_[i].h[1]);
|
|
193
|
+
|
|
194
|
+
// sum over c: EQ[|c] W[r,c] W[l,c]
|
|
195
|
+
CPoly sumc{};
|
|
196
|
+
|
|
197
|
+
// n0_ is the copy dimension, n1_ is the wire dimension.
|
|
198
|
+
for (corner_t c = 0; c < W->n0_; c += 2) {
|
|
199
|
+
const CPoly poly = cpoly_at_dense(EQ, c, 0, F)
|
|
200
|
+
.mul(cpoly_at_dense(W, c, r, F), F)
|
|
201
|
+
.mul(cpoly_at_dense(W, c, l, F), F);
|
|
202
|
+
sumc.add(poly, F);
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
sumc.mul_scalar(EQUAD->vc_[i].v, F);
|
|
206
|
+
sum.add(sumc, F);
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
Elt rnd = round_c(pr, pad, ts, layer, round, sum, F);
|
|
210
|
+
bnd.q[round] = rnd;
|
|
211
|
+
|
|
212
|
+
// bind the c variable in both EQ and W
|
|
213
|
+
EQ->bind(rnd, F);
|
|
214
|
+
W->bind(rnd, F);
|
|
215
|
+
}
|
|
216
|
+
|
|
217
|
+
Elt eq0 = EQ->scalar();
|
|
218
|
+
|
|
219
|
+
W->reshape(W->n1_);
|
|
220
|
+
check(W->n1_ == 1, "W->n1_ == 1");
|
|
221
|
+
|
|
222
|
+
// To save memory, we avoid cloning W. Instead, we use a single temporary
|
|
223
|
+
// buffer Wtmp of size N/2 and start with both hand-pointers WH[0,1]
|
|
224
|
+
// pointing to W. In the first round of the loop, hand 0 is bound
|
|
225
|
+
// out-of-place from W into Wtmp, and we then update WH[0] to point to Wtmp.
|
|
226
|
+
// Hand 1 is then bound in-place in W. This strategy uses 1.5N space instead
|
|
227
|
+
// of 2N.
|
|
228
|
+
auto Wtmp = std::make_unique<Dense<Field>>((W->n0_ + 1) / 2, 1);
|
|
229
|
+
Dense<Field>* WH[2] = {W, W};
|
|
230
|
+
|
|
231
|
+
for (size_t round = 0; round < logw; ++round) {
|
|
232
|
+
for (size_t hand = 0; hand < 2; hand++) {
|
|
233
|
+
// In SUM_{l,r} Q[l,r] W[l] W[r], first precompute QW[l] =
|
|
234
|
+
// SUM_{r} Q[l,r] W[r] as a dense array, and then compute
|
|
235
|
+
// SUM_{l} QW[l] W[l].
|
|
236
|
+
Dense<Field> QW(WH[hand]->n0_, 1);
|
|
237
|
+
QW.clear(F);
|
|
238
|
+
size_t ohand = 1 - hand;
|
|
239
|
+
|
|
240
|
+
// QW[l] = SUM_{r} Q[l,r] W[r]
|
|
241
|
+
for (index_t i = 0; i < EQUAD->n_; ++i) {
|
|
242
|
+
const corner_t p0(EQUAD->hc_[i].h[hand]);
|
|
243
|
+
const corner_t p1(EQUAD->hc_[i].h[ohand]);
|
|
244
|
+
F.add(QW.v_[p0], F.mulf(EQUAD->vc_[i].v, WH[ohand]->v_[p1]));
|
|
245
|
+
}
|
|
246
|
+
|
|
247
|
+
// SUM_{l} QW[l] W[l].
|
|
248
|
+
WPoly sum{};
|
|
249
|
+
for (corner_t l = 0; l < QW.n0_; l += 2) {
|
|
250
|
+
WPoly poly = wpoly_at_dense(WH[hand], l, 0, F)
|
|
251
|
+
.mul(wpoly_at_dense(&QW, l, 0, F), F);
|
|
252
|
+
sum.add(poly, F);
|
|
253
|
+
}
|
|
254
|
+
|
|
255
|
+
sum.mul_scalar(eq0, F);
|
|
256
|
+
Elt rnd = round_h(pr, pad, ts, layer, hand, round, sum, F);
|
|
257
|
+
bnd.g[hand][round] = rnd;
|
|
258
|
+
|
|
259
|
+
// bind the r variable in W[hand] and QUAD
|
|
260
|
+
if (round == 0 && hand == 0) {
|
|
261
|
+
WH[0] = Wtmp.get();
|
|
262
|
+
WH[0]->bind(rnd, *W, F);
|
|
263
|
+
} else {
|
|
264
|
+
WH[hand]->bind(rnd, F);
|
|
265
|
+
}
|
|
266
|
+
EQUAD->bind_h(rnd, hand, F);
|
|
267
|
+
}
|
|
268
|
+
}
|
|
269
|
+
|
|
270
|
+
EQUAD->scalar(); // for the side effect of assertions
|
|
271
|
+
Elt WC[2] = {WH[0]->scalar(), WH[1]->scalar()};
|
|
272
|
+
end_layer(pr, pad, ts, layer, WC, F);
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Evaluate the quadratic form
|
|
276
|
+
//
|
|
277
|
+
// V[g,c] = QUAD[g|r,l] W[r,c] W[l,c]
|
|
278
|
+
//
|
|
279
|
+
// Returns false in the case the quad is an assert0 check that fails.
|
|
280
|
+
bool eval_quad(const Quad<Field>* quad, Dense<Field>* V,
|
|
281
|
+
const Dense<Field>* W, const Field& F) {
|
|
282
|
+
check(V->n0_ == W->n0_, "V->n0_ == W->n0_");
|
|
283
|
+
corner_t n0 = V->n0_;
|
|
284
|
+
|
|
285
|
+
V->clear(F);
|
|
286
|
+
for (const auto& ec : *quad) {
|
|
287
|
+
const corner_t g(ec.g);
|
|
288
|
+
const corner_t r(ec.h[0]);
|
|
289
|
+
const corner_t l(ec.h[1]);
|
|
290
|
+
for (corner_t c = 0; c < n0; ++c) {
|
|
291
|
+
if (ec.v == F.zero()) {
|
|
292
|
+
// assert that the computed W[l]W[r] is zero.
|
|
293
|
+
Elt y = W->v_[n0 * l + c];
|
|
294
|
+
F.mul(y, W->v_[n0 * r + c]);
|
|
295
|
+
if (y != F.zero()) {
|
|
296
|
+
return false;
|
|
297
|
+
}
|
|
298
|
+
} else {
|
|
299
|
+
Elt x = ec.v;
|
|
300
|
+
F.mul(x, W->v_[n0 * l + c]);
|
|
301
|
+
F.mul(x, W->v_[n0 * r + c]);
|
|
302
|
+
F.add(V->v_[n0 * g + c], x);
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
}
|
|
306
|
+
return true;
|
|
307
|
+
}
|
|
308
|
+
|
|
309
|
+
Elt /*R*/ round_c(Proof<Field>* pr, const Proof<Field>* pad,
|
|
310
|
+
TranscriptSumcheck<Field>& ts, size_t layer, size_t round,
|
|
311
|
+
CPoly poly, const Field& F) {
|
|
312
|
+
check(round <= Proof<Field>::kMaxBindings, "round <= kMaxBindings");
|
|
313
|
+
|
|
314
|
+
if (pad) {
|
|
315
|
+
poly.sub(pad->l[layer].cp[round], F);
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
pr->l[layer].cp[round] = poly;
|
|
319
|
+
return ts.round(poly);
|
|
320
|
+
}
|
|
321
|
+
|
|
322
|
+
Elt /*R*/ round_h(Proof<Field>* pr, const Proof<Field>* pad,
|
|
323
|
+
TranscriptSumcheck<Field>& ts, size_t layer, size_t hand,
|
|
324
|
+
size_t round, WPoly poly, const Field& F) {
|
|
325
|
+
check(round <= Proof<Field>::kMaxBindings, "round <= kMaxBindings");
|
|
326
|
+
if (pad) {
|
|
327
|
+
poly.sub(pad->l[layer].hp[hand][round], F);
|
|
328
|
+
}
|
|
329
|
+
pr->l[layer].hp[hand][round] = poly;
|
|
330
|
+
return ts.round(poly);
|
|
331
|
+
}
|
|
332
|
+
|
|
333
|
+
void end_layer(Proof<Field>* pr, const Proof<Field>* pad,
|
|
334
|
+
TranscriptSumcheck<Field>& ts, size_t layer, const Elt wc[2],
|
|
335
|
+
const Field& F) {
|
|
336
|
+
Elt tt[2] = {wc[0], wc[1]};
|
|
337
|
+
if (pad) {
|
|
338
|
+
F.sub(tt[0], pad->l[layer].wc[0]);
|
|
339
|
+
F.sub(tt[1], pad->l[layer].wc[1]);
|
|
340
|
+
}
|
|
341
|
+
|
|
342
|
+
pr->l[layer].wc[0] = tt[0];
|
|
343
|
+
pr->l[layer].wc[1] = tt[1];
|
|
344
|
+
|
|
345
|
+
ts.write(tt, 1, 2);
|
|
346
|
+
}
|
|
347
|
+
|
|
348
|
+
CPoly cpoly_at_dense(const Dense<Field>* D, corner_t p0, corner_t p1,
|
|
349
|
+
const Field& F) {
|
|
350
|
+
auto tmp = FCPoly::extend(D->t2_at_corners(p0, p1, F), F);
|
|
351
|
+
return CPoly(tmp);
|
|
352
|
+
}
|
|
353
|
+
|
|
354
|
+
WPoly wpoly_at_dense(const Dense<Field>* D, corner_t p0, corner_t p1,
|
|
355
|
+
const Field& F) {
|
|
356
|
+
auto tmp = FWPoly::extend(D->t2_at_corners(p0, p1, F), F);
|
|
357
|
+
return WPoly(tmp);
|
|
358
|
+
}
|
|
359
|
+
};
|
|
360
|
+
} // namespace proofs
|
|
361
|
+
|
|
362
|
+
#endif // PRIVACY_PROOFS_ZK_LIB_SUMCHECK_PROVER_LAYERS_H_
|
|
@@ -0,0 +1,227 @@
|
|
|
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_SUMCHECK_QUAD_H_
|
|
16
|
+
#define PRIVACY_PROOFS_ZK_LIB_SUMCHECK_QUAD_H_
|
|
17
|
+
|
|
18
|
+
#include <algorithm>
|
|
19
|
+
#include <cstddef>
|
|
20
|
+
#include <cstdint>
|
|
21
|
+
#include <iterator>
|
|
22
|
+
#include <memory>
|
|
23
|
+
#include <vector>
|
|
24
|
+
|
|
25
|
+
#include "arrays/affine.h"
|
|
26
|
+
#include "arrays/eqs.h"
|
|
27
|
+
#include "sumcheck/equad.h"
|
|
28
|
+
#include "sumcheck/hquad.h"
|
|
29
|
+
|
|
30
|
+
// ------------------------------------------------------------
|
|
31
|
+
// Representation of the QUAD array used in sumcheck.
|
|
32
|
+
//
|
|
33
|
+
// The main concern is to save memory. To this end,
|
|
34
|
+
// we have three representations of the quad.
|
|
35
|
+
//
|
|
36
|
+
// The fully expanded representation EQuad (in equad.h)
|
|
37
|
+
// comprises the indices and the coefficient value. EQuad
|
|
38
|
+
// is the only representation that can be canonicalized.
|
|
39
|
+
//
|
|
40
|
+
// The "ordinary" representation Quad (this file) contains (g, h)
|
|
41
|
+
// indices but it stores the coefficient as an index into an array of
|
|
42
|
+
// constants, where the index is 32 bits and the constant is a large
|
|
43
|
+
// field element.
|
|
44
|
+
//
|
|
45
|
+
// In addition, HQuad represents a QUAD after the g index has
|
|
46
|
+
// been bound. Since g = 0 it does not need to be stored.
|
|
47
|
+
// A special method Quad::bind_g produces a compact HQuad in
|
|
48
|
+
// one step.
|
|
49
|
+
//
|
|
50
|
+
// The compiler works on EQuad and converts to Quad when done.
|
|
51
|
+
// Circuit evaluation works on Quad and materializes EQuad
|
|
52
|
+
// lazily. Sumcheck starts with Quad, binds g into an HQuad,
|
|
53
|
+
// and finishes binding h on HQuad.
|
|
54
|
+
namespace proofs {
|
|
55
|
+
template <class Field>
|
|
56
|
+
class Quad {
|
|
57
|
+
using Elt = typename Field::Elt;
|
|
58
|
+
using kvec_t = std::vector<Elt>;
|
|
59
|
+
using ecorner = typename EQuad<Field>::ecorner;
|
|
60
|
+
using hcorner = typename HQuad<Field>::hcorner;
|
|
61
|
+
using vcorner = typename HQuad<Field>::vcorner;
|
|
62
|
+
|
|
63
|
+
public:
|
|
64
|
+
using quad_corner_t = typename EQuad<Field>::quad_corner_t;
|
|
65
|
+
using index_t = typename EQuad<Field>::index_t;
|
|
66
|
+
|
|
67
|
+
struct delta_corner {
|
|
68
|
+
quad_corner_t dg;
|
|
69
|
+
quad_corner_t dh[2];
|
|
70
|
+
uint32_t vi;
|
|
71
|
+
|
|
72
|
+
bool operator==(const delta_corner& o) const {
|
|
73
|
+
return dg == o.dg && dh[0] == o.dh[0] && dh[1] == o.dh[1] && vi == o.vi;
|
|
74
|
+
}
|
|
75
|
+
};
|
|
76
|
+
|
|
77
|
+
using delta_table_t = std::vector<delta_corner>;
|
|
78
|
+
|
|
79
|
+
explicit Quad(index_t n, std::shared_ptr<kvec_t> kvec,
|
|
80
|
+
std::shared_ptr<delta_table_t> delta_table)
|
|
81
|
+
: n_(n),
|
|
82
|
+
vc_(n),
|
|
83
|
+
delta_table_(std::move(delta_table)),
|
|
84
|
+
kvec_(std::move(kvec)) {}
|
|
85
|
+
|
|
86
|
+
// no copies
|
|
87
|
+
Quad(const Quad& y) = delete;
|
|
88
|
+
Quad(Quad&& y) = delete;
|
|
89
|
+
Quad& operator=(const Quad& y) = delete;
|
|
90
|
+
Quad& operator=(Quad&& y) = delete;
|
|
91
|
+
|
|
92
|
+
index_t size() const { return n_; }
|
|
93
|
+
|
|
94
|
+
void assign(index_t i, uint32_t di) { vc_[i] = di; }
|
|
95
|
+
|
|
96
|
+
class const_iterator {
|
|
97
|
+
public:
|
|
98
|
+
using iterator_category = std::forward_iterator_tag;
|
|
99
|
+
using value_type = ecorner;
|
|
100
|
+
using difference_type = std::ptrdiff_t;
|
|
101
|
+
using pointer = void; // operator* returns by value
|
|
102
|
+
using reference = ecorner;
|
|
103
|
+
|
|
104
|
+
const_iterator(const Quad* q, index_t i)
|
|
105
|
+
: q_(q), i_(i), prev_g_(0), prev_h0_(0), prev_h1_(0) {}
|
|
106
|
+
|
|
107
|
+
ecorner operator*() const {
|
|
108
|
+
const auto& d = (*q_->delta_table_)[q_->vc_[i_]];
|
|
109
|
+
return ecorner{prev_g_ + d.dg,
|
|
110
|
+
{prev_h0_ + d.dh[0], prev_h1_ + d.dh[1]},
|
|
111
|
+
(*q_->kvec_)[d.vi]};
|
|
112
|
+
}
|
|
113
|
+
const_iterator& operator++() {
|
|
114
|
+
const auto& d = (*q_->delta_table_)[q_->vc_[i_]];
|
|
115
|
+
prev_g_ += d.dg;
|
|
116
|
+
prev_h0_ += d.dh[0];
|
|
117
|
+
prev_h1_ += d.dh[1];
|
|
118
|
+
++i_;
|
|
119
|
+
return *this;
|
|
120
|
+
}
|
|
121
|
+
const_iterator operator++(int) {
|
|
122
|
+
const_iterator tmp = *this;
|
|
123
|
+
++(*this);
|
|
124
|
+
return tmp;
|
|
125
|
+
}
|
|
126
|
+
bool operator==(const const_iterator& other) const {
|
|
127
|
+
return i_ == other.i_;
|
|
128
|
+
}
|
|
129
|
+
bool operator!=(const const_iterator& other) const {
|
|
130
|
+
return i_ != other.i_;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
private:
|
|
134
|
+
const Quad* q_;
|
|
135
|
+
index_t i_;
|
|
136
|
+
quad_corner_t prev_g_;
|
|
137
|
+
quad_corner_t prev_h0_;
|
|
138
|
+
quad_corner_t prev_h1_;
|
|
139
|
+
};
|
|
140
|
+
|
|
141
|
+
const_iterator begin() const { return const_iterator(this, 0); }
|
|
142
|
+
const_iterator end() const { return const_iterator(this, n_); }
|
|
143
|
+
|
|
144
|
+
// Equivalent to expand()->bind_g(...).
|
|
145
|
+
|
|
146
|
+
// Allocate an hquad of minimal size and
|
|
147
|
+
// g-bind it in place.
|
|
148
|
+
std::unique_ptr<HQuad<Field>> bind_g(size_t logv, const Elt* G0,
|
|
149
|
+
const Elt* G1, const Elt& alpha,
|
|
150
|
+
const Elt& beta, const Field& F) const {
|
|
151
|
+
check(n_ > 0, "n_ > 0");
|
|
152
|
+
index_t final_size = 1;
|
|
153
|
+
auto it = begin();
|
|
154
|
+
auto prev_ec = *it;
|
|
155
|
+
for (++it; it != end(); ++it) {
|
|
156
|
+
if (!(*it).eq_hands(prev_ec)) {
|
|
157
|
+
final_size++;
|
|
158
|
+
}
|
|
159
|
+
prev_ec = *it;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
auto s = std::make_unique<HQuad<Field>>(final_size);
|
|
163
|
+
|
|
164
|
+
const size_t nv = size_t(1) << logv;
|
|
165
|
+
auto dot = Eqs<Field>::raw_eq2(logv, nv, G0, G1, alpha, F);
|
|
166
|
+
|
|
167
|
+
index_t wr = 0;
|
|
168
|
+
for (const auto& ec : *this) {
|
|
169
|
+
hcorner hc{{ec.h[0], ec.h[1]}};
|
|
170
|
+
vcorner vc{prep_v(ec.v, dot[corner_t(ec.g)], beta, F)};
|
|
171
|
+
if (wr > 0 && hc.eq_hands(s->hc_[wr - 1])) {
|
|
172
|
+
F.add(s->vc_[wr - 1].v, vc.v);
|
|
173
|
+
} else {
|
|
174
|
+
s->hc_[wr] = hc;
|
|
175
|
+
s->vc_[wr] = vc;
|
|
176
|
+
++wr;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
return s;
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
// Optimized combined bind_g + bind_h, nondestructive, avoiding expansion
|
|
184
|
+
Elt bind_gh_all(
|
|
185
|
+
// G bindings
|
|
186
|
+
size_t logv, const Elt G0[/*logv*/], const Elt G1[/*logv*/],
|
|
187
|
+
const Elt& alpha, const Elt& beta,
|
|
188
|
+
// H bindings
|
|
189
|
+
size_t logw, const Elt H0[/*logw*/], const Elt H1[/*logw*/],
|
|
190
|
+
// field
|
|
191
|
+
const Field& F) const {
|
|
192
|
+
const size_t nv = size_t(1) << logv;
|
|
193
|
+
auto eqg = Eqs<Field>::raw_eq2(logv, nv, G0, G1, alpha, F);
|
|
194
|
+
|
|
195
|
+
const size_t nw = size_t(1) << logw;
|
|
196
|
+
Eqs<Field> eqh0(logw, nw, H0, F);
|
|
197
|
+
Eqs<Field> eqh1(logw, nw, H1, F);
|
|
198
|
+
|
|
199
|
+
Elt s = F.zero();
|
|
200
|
+
|
|
201
|
+
for (const auto& ec : *this) {
|
|
202
|
+
Elt q = prep_v(ec.v, eqg[corner_t(ec.g)], beta, F);
|
|
203
|
+
F.mul(q, eqh0.at(corner_t(ec.h[0])));
|
|
204
|
+
F.mul(q, eqh1.at(corner_t(ec.h[1])));
|
|
205
|
+
F.add(s, q);
|
|
206
|
+
}
|
|
207
|
+
return s;
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
private:
|
|
211
|
+
static Elt prep_v(const Elt& v, const Elt& dot, const Elt& beta,
|
|
212
|
+
const Field& F) {
|
|
213
|
+
if (v == F.zero()) {
|
|
214
|
+
return F.mulf(beta, dot);
|
|
215
|
+
} else {
|
|
216
|
+
return F.mulf(v, dot);
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
index_t n_;
|
|
221
|
+
std::vector<uint32_t> vc_;
|
|
222
|
+
std::shared_ptr<delta_table_t> delta_table_;
|
|
223
|
+
std::shared_ptr<kvec_t> kvec_;
|
|
224
|
+
};
|
|
225
|
+
} // namespace proofs
|
|
226
|
+
|
|
227
|
+
#endif // PRIVACY_PROOFS_ZK_LIB_SUMCHECK_QUAD_H_
|