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,211 @@
|
|
|
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_BUILDER_H_
|
|
16
|
+
#define PRIVACY_PROOFS_ZK_LIB_SUMCHECK_QUAD_BUILDER_H_
|
|
17
|
+
|
|
18
|
+
#include <stddef.h>
|
|
19
|
+
|
|
20
|
+
#include <cstdint>
|
|
21
|
+
#include <memory>
|
|
22
|
+
#include <unordered_map>
|
|
23
|
+
#include <vector>
|
|
24
|
+
|
|
25
|
+
#include "algebra/hash.h"
|
|
26
|
+
#include "sumcheck/equad.h"
|
|
27
|
+
#include "sumcheck/quad.h"
|
|
28
|
+
#include "util/panic.h"
|
|
29
|
+
|
|
30
|
+
// Helper functions for building quads. They should be used only
|
|
31
|
+
// by tests and the compiler, but not by the prover and verifier.
|
|
32
|
+
namespace proofs {
|
|
33
|
+
|
|
34
|
+
// helper class for builting the kvec_ vector
|
|
35
|
+
template <class Field>
|
|
36
|
+
class KvecBuilder {
|
|
37
|
+
using Elt = typename Field::Elt;
|
|
38
|
+
using kvec_t = std::vector<Elt>;
|
|
39
|
+
|
|
40
|
+
// Class that defines the hash function for Elt.
|
|
41
|
+
class EltHash {
|
|
42
|
+
public:
|
|
43
|
+
const Field& f_;
|
|
44
|
+
explicit EltHash(const Field& f) : f_(f) {}
|
|
45
|
+
size_t operator()(const Elt& k) const { return elt_hash(k, f_); }
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
public:
|
|
49
|
+
explicit KvecBuilder(const Field& f)
|
|
50
|
+
: table_(10, EltHash(f)), kvec_(std::make_shared<kvec_t>()) {}
|
|
51
|
+
|
|
52
|
+
size_t kstore(const Elt& k) {
|
|
53
|
+
auto [it, inserted] = table_.try_emplace(k, 0);
|
|
54
|
+
if (inserted) {
|
|
55
|
+
it->second = kvec_->size();
|
|
56
|
+
kvec_->push_back(k);
|
|
57
|
+
}
|
|
58
|
+
return it->second;
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
size_t kload(const Elt& k) const {
|
|
62
|
+
if (auto search = table_.find(k); search != table_.end()) {
|
|
63
|
+
return search->second;
|
|
64
|
+
}
|
|
65
|
+
check(false, "kload() failed");
|
|
66
|
+
return 0;
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
std::shared_ptr<kvec_t> kvec() { return kvec_; }
|
|
70
|
+
|
|
71
|
+
private:
|
|
72
|
+
std::unordered_map<Elt, size_t, EltHash> table_;
|
|
73
|
+
std::shared_ptr<kvec_t> kvec_;
|
|
74
|
+
};
|
|
75
|
+
|
|
76
|
+
// hasher for delta_corner
|
|
77
|
+
template <class Field>
|
|
78
|
+
struct delta_corner_hash {
|
|
79
|
+
using delta_corner = typename Quad<Field>::delta_corner;
|
|
80
|
+
static uint64_t hash_combine(uint64_t seed, uint64_t v) {
|
|
81
|
+
return (seed * 0x100000001b3ull) ^ v;
|
|
82
|
+
}
|
|
83
|
+
uint64_t operator()(const delta_corner& d) const {
|
|
84
|
+
uint64_t h = 0xcbf29ce484222325ull;
|
|
85
|
+
h = hash_combine(h, static_cast<uint32_t>(d.dg));
|
|
86
|
+
h = hash_combine(h, static_cast<uint32_t>(d.dh[0]));
|
|
87
|
+
h = hash_combine(h, static_cast<uint32_t>(d.dh[1]));
|
|
88
|
+
h = hash_combine(h, d.vi);
|
|
89
|
+
return h;
|
|
90
|
+
}
|
|
91
|
+
};
|
|
92
|
+
|
|
93
|
+
// helper class for building the delta_table_ vector
|
|
94
|
+
template <class Field>
|
|
95
|
+
class DeltaTableBuilder {
|
|
96
|
+
using quad_corner_t = typename Quad<Field>::quad_corner_t;
|
|
97
|
+
using delta_corner = typename Quad<Field>::delta_corner;
|
|
98
|
+
using delta_table_t = typename Quad<Field>::delta_table_t;
|
|
99
|
+
|
|
100
|
+
public:
|
|
101
|
+
DeltaTableBuilder() : delta_table_(std::make_shared<delta_table_t>()) {}
|
|
102
|
+
|
|
103
|
+
uint32_t dedup(quad_corner_t dg, quad_corner_t dh0, quad_corner_t dh1,
|
|
104
|
+
uint32_t vi) {
|
|
105
|
+
delta_corner d{dg, {dh0, dh1}, vi};
|
|
106
|
+
auto [it, inserted] = delta_map_.try_emplace(d, delta_table_->size());
|
|
107
|
+
if (inserted) {
|
|
108
|
+
delta_table_->push_back(d);
|
|
109
|
+
}
|
|
110
|
+
return it->second;
|
|
111
|
+
}
|
|
112
|
+
|
|
113
|
+
std::shared_ptr<delta_table_t> delta_table() { return delta_table_; }
|
|
114
|
+
|
|
115
|
+
private:
|
|
116
|
+
std::shared_ptr<delta_table_t> delta_table_;
|
|
117
|
+
std::unordered_map<delta_corner, uint32_t, delta_corner_hash<Field>>
|
|
118
|
+
delta_map_;
|
|
119
|
+
};
|
|
120
|
+
|
|
121
|
+
// ApproximateDeltaTableBuilder is like DeltaTableBuilder, but with a two-way
|
|
122
|
+
// set-associative cache instead of an exact hash table. We prefer quick lookup
|
|
123
|
+
// at the cost of missing some deduplications.
|
|
124
|
+
template <class Field>
|
|
125
|
+
class ApproximateDeltaTableBuilder {
|
|
126
|
+
using quad_corner_t = typename Quad<Field>::quad_corner_t;
|
|
127
|
+
using delta_corner = typename Quad<Field>::delta_corner;
|
|
128
|
+
using delta_table_t = typename Quad<Field>::delta_table_t;
|
|
129
|
+
|
|
130
|
+
public:
|
|
131
|
+
explicit ApproximateDeltaTableBuilder(size_t cache_size)
|
|
132
|
+
: delta_table_(std::make_shared<delta_table_t>()), cache_(cache_size) {}
|
|
133
|
+
|
|
134
|
+
uint32_t dedup(quad_corner_t dg, quad_corner_t dh0, quad_corner_t dh1,
|
|
135
|
+
uint32_t vi) {
|
|
136
|
+
delta_corner d{dg, {dh0, dh1}, vi};
|
|
137
|
+
size_t h = delta_corner_hash<Field>{}(d);
|
|
138
|
+
size_t idx = static_cast<size_t>(h % cache_.size());
|
|
139
|
+
CacheEntry& ent = cache_[idx];
|
|
140
|
+
if (ent.slots[0].valid && ent.slots[0].d == d) {
|
|
141
|
+
return ent.slots[0].index;
|
|
142
|
+
}
|
|
143
|
+
if (ent.slots[1].valid && ent.slots[1].d == d) {
|
|
144
|
+
// Maintain the LRU property that slot[0] is the most recently used.
|
|
145
|
+
std::swap(ent.slots[0], ent.slots[1]);
|
|
146
|
+
return ent.slots[0].index;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
uint32_t index = delta_table_->size();
|
|
150
|
+
delta_table_->push_back(d);
|
|
151
|
+
// LRU eviction.
|
|
152
|
+
ent.slots[1] = ent.slots[0];
|
|
153
|
+
ent.slots[0] = {d, index, true};
|
|
154
|
+
return index;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
std::shared_ptr<delta_table_t> delta_table() { return delta_table_; }
|
|
158
|
+
|
|
159
|
+
private:
|
|
160
|
+
struct Slot {
|
|
161
|
+
delta_corner d;
|
|
162
|
+
uint32_t index;
|
|
163
|
+
bool valid = false;
|
|
164
|
+
};
|
|
165
|
+
|
|
166
|
+
struct CacheEntry {
|
|
167
|
+
Slot slots[2];
|
|
168
|
+
};
|
|
169
|
+
|
|
170
|
+
std::shared_ptr<delta_table_t> delta_table_;
|
|
171
|
+
std::vector<CacheEntry> cache_;
|
|
172
|
+
};
|
|
173
|
+
|
|
174
|
+
template <class Field>
|
|
175
|
+
class QuadBuilder {
|
|
176
|
+
using Elt = typename Field::Elt;
|
|
177
|
+
using ecorner = typename EQuad<Field>::ecorner;
|
|
178
|
+
using index_t = typename EQuad<Field>::index_t;
|
|
179
|
+
|
|
180
|
+
public:
|
|
181
|
+
// Convert an EQuad into a Quad by collecting all constants in the
|
|
182
|
+
// EQuad. A more refined approach would collect all constants
|
|
183
|
+
// in all layers.
|
|
184
|
+
static std::unique_ptr<Quad<Field>> compress(const EQuad<Field>* EQUAD,
|
|
185
|
+
const Field& f) {
|
|
186
|
+
KvecBuilder<Field> kb(f);
|
|
187
|
+
// collect all constants
|
|
188
|
+
for (index_t i = 0; i < EQUAD->n_; ++i) {
|
|
189
|
+
(void)kb.kstore(EQUAD->ec_[i].v);
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
DeltaTableBuilder<Field> db;
|
|
193
|
+
auto q =
|
|
194
|
+
std::make_unique<Quad<Field>>(EQUAD->n_, kb.kvec(), db.delta_table());
|
|
195
|
+
using QuadCorner = typename Quad<Field>::quad_corner_t;
|
|
196
|
+
QuadCorner prev_g(0), prev_h0(0), prev_h1(0);
|
|
197
|
+
for (index_t i = 0; i < EQUAD->n_; ++i) {
|
|
198
|
+
const ecorner& eqi = EQUAD->ec_[i];
|
|
199
|
+
q->assign(i,
|
|
200
|
+
db.dedup(eqi.g - prev_g, eqi.h[0] - prev_h0, eqi.h[1] - prev_h1,
|
|
201
|
+
static_cast<uint32_t>(kb.kload(eqi.v))));
|
|
202
|
+
prev_g = eqi.g;
|
|
203
|
+
prev_h0 = eqi.h[0];
|
|
204
|
+
prev_h1 = eqi.h[1];
|
|
205
|
+
}
|
|
206
|
+
return q;
|
|
207
|
+
}
|
|
208
|
+
};
|
|
209
|
+
} // namespace proofs
|
|
210
|
+
|
|
211
|
+
#endif // PRIVACY_PROOFS_ZK_LIB_SUMCHECK_QUAD_BUILDER_H_
|
|
@@ -0,0 +1,169 @@
|
|
|
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 "sumcheck/quad.h"
|
|
16
|
+
|
|
17
|
+
#include <stddef.h>
|
|
18
|
+
|
|
19
|
+
#include <memory>
|
|
20
|
+
#include <utility>
|
|
21
|
+
#include <vector>
|
|
22
|
+
|
|
23
|
+
#include "algebra/bogorng.h"
|
|
24
|
+
#include "algebra/fp.h"
|
|
25
|
+
#include "arrays/affine.h"
|
|
26
|
+
#include "arrays/sparse.h"
|
|
27
|
+
#include "sumcheck/equad.h"
|
|
28
|
+
#include "sumcheck/hquad.h"
|
|
29
|
+
#include "sumcheck/quad_builder.h"
|
|
30
|
+
#include "gtest/gtest.h"
|
|
31
|
+
|
|
32
|
+
namespace proofs {
|
|
33
|
+
namespace {
|
|
34
|
+
typedef Fp<1> Field;
|
|
35
|
+
static const Field F("18446744073709551557");
|
|
36
|
+
typedef Field::Elt Elt;
|
|
37
|
+
Bogorng<Field> rng(&F);
|
|
38
|
+
typedef EQuad<Field>::quad_corner_t quad_corner_t;
|
|
39
|
+
typedef EQuad<Field>::index_t index_t;
|
|
40
|
+
|
|
41
|
+
class RandomSlice {
|
|
42
|
+
public:
|
|
43
|
+
std::vector<Elt> r_;
|
|
44
|
+
explicit RandomSlice(size_t n) : r_(n) {
|
|
45
|
+
for (size_t i = 0; i < n; ++i) {
|
|
46
|
+
r_[i] = rng.next();
|
|
47
|
+
}
|
|
48
|
+
}
|
|
49
|
+
};
|
|
50
|
+
|
|
51
|
+
Elt lagrange(quad_corner_t p, size_t logn, const Elt* R) {
|
|
52
|
+
Elt l = F.one();
|
|
53
|
+
for (size_t i = 0; i < logn; i++) {
|
|
54
|
+
if ((p & (quad_corner_t(1) << i)) != quad_corner_t(0)) {
|
|
55
|
+
F.mul(l, R[i]);
|
|
56
|
+
} else {
|
|
57
|
+
F.mul(l, F.subf(F.one(), R[i]));
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
return l;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
void one_bind_g(index_t n, size_t logn) {
|
|
64
|
+
RandomSlice R(logn);
|
|
65
|
+
RandomSlice R2(logn);
|
|
66
|
+
auto EQUAD = std::make_unique<EQuad<Field>>(n);
|
|
67
|
+
Elt s = F.zero();
|
|
68
|
+
Elt s2 = F.zero();
|
|
69
|
+
Elt alpha = rng.next();
|
|
70
|
+
for (index_t i = 0; i < n; ++i) {
|
|
71
|
+
quad_corner_t p = quad_corner_t(13 * i);
|
|
72
|
+
Elt r = rng.next();
|
|
73
|
+
EQUAD->ec_[i] = EQuad<Field>::ecorner{
|
|
74
|
+
.g = p, .h = {quad_corner_t(0), quad_corner_t(0)}, .v = r};
|
|
75
|
+
F.add(s, F.mulf(r, lagrange(p, logn, R.r_.data())));
|
|
76
|
+
F.add(s2, F.mulf(r, lagrange(p, logn, R2.r_.data())));
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
auto QUAD = QuadBuilder<Field>::compress(EQUAD.get(), F);
|
|
80
|
+
auto HQUAD =
|
|
81
|
+
QUAD->bind_g(logn, R.r_.data(), R2.r_.data(), alpha, F.zero(), F);
|
|
82
|
+
EXPECT_EQ(HQUAD->scalar(), F.addf(s, F.mulf(alpha, s2)));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
TEST(EQuad, BindG) {
|
|
86
|
+
one_bind_g(index_t(666), 10 + 4);
|
|
87
|
+
one_bind_g(index_t(1), 9 + 4);
|
|
88
|
+
for (size_t i = 200; i < 300; i++) {
|
|
89
|
+
one_bind_g(index_t(i), 9 + 4);
|
|
90
|
+
}
|
|
91
|
+
one_bind_g(index_t(467), 9 + 4);
|
|
92
|
+
one_bind_g(index_t(512), 9 + 4);
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
// compare interleaved binding of quad<> with
|
|
96
|
+
// a pair of bind_all() of Sparse<>.
|
|
97
|
+
void one_bind_h(index_t n, size_t logn) {
|
|
98
|
+
auto EQUAD = std::make_unique<EQuad<Field>>(n);
|
|
99
|
+
auto S = Sparse<Field>(n);
|
|
100
|
+
RandomSlice R0(logn);
|
|
101
|
+
RandomSlice R1(logn);
|
|
102
|
+
size_t mask = (size_t(1) << logn) - 1;
|
|
103
|
+
for (index_t i = 0; i < n; ++i) {
|
|
104
|
+
quad_corner_t h0 = quad_corner_t((13 * i + 4) & mask);
|
|
105
|
+
quad_corner_t h1 = quad_corner_t((23 * i + 3) & mask);
|
|
106
|
+
|
|
107
|
+
// EQuad<Field> canonicalizes h0, h1 because
|
|
108
|
+
// they are only used for a commutative F.mul,
|
|
109
|
+
// but Sparse<Field> does not, so we canonicalize
|
|
110
|
+
// h0, h1 in advance
|
|
111
|
+
if (h0 > h1) {
|
|
112
|
+
std::swap(h0, h1);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
Elt r = rng.next();
|
|
116
|
+
EQUAD->ec_[i] =
|
|
117
|
+
EQuad<Field>::ecorner{.g = quad_corner_t(0), .h = {h0, h1}, .v = r};
|
|
118
|
+
S.c_[i] = Sparse<Field>::corner{
|
|
119
|
+
.p0 = 0, .p1 = corner_t(h0), .p2 = corner_t(h1), .v = r};
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
EQUAD->canonicalize(F);
|
|
123
|
+
S.canonicalize(F);
|
|
124
|
+
S.reshape();
|
|
125
|
+
|
|
126
|
+
S.bind_all(logn, R0.r_.data(), F);
|
|
127
|
+
S.reshape();
|
|
128
|
+
S.bind_all(logn, R1.r_.data(), F);
|
|
129
|
+
auto QUAD = QuadBuilder<Field>::compress(EQUAD.get(), F);
|
|
130
|
+
auto HQUAD = QUAD->bind_g(/*logv=*/0, nullptr, nullptr, /*alpha=*/F.zero(),
|
|
131
|
+
/*beta=*/F.zero(), F);
|
|
132
|
+
|
|
133
|
+
for (size_t round = 0; round < logn; ++round) {
|
|
134
|
+
HQUAD->bind_h(R0.r_[round], /*hand=*/0, F);
|
|
135
|
+
HQUAD->bind_h(R1.r_[round], /*hand=*/1, F);
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
EXPECT_EQ(HQUAD->scalar(), S.scalar());
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
TEST(EQuad, BindH) {
|
|
142
|
+
one_bind_h(index_t(666), 10);
|
|
143
|
+
one_bind_h(index_t(1), 9);
|
|
144
|
+
for (size_t i = 200; i < 300; i++) {
|
|
145
|
+
for (size_t logn = 1; logn < 20; ++logn) {
|
|
146
|
+
one_bind_h(index_t(i), logn);
|
|
147
|
+
}
|
|
148
|
+
}
|
|
149
|
+
one_bind_h(index_t(467), 9);
|
|
150
|
+
one_bind_h(index_t(512), 9);
|
|
151
|
+
one_bind_h(index_t(512), 33);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
TEST(ApproximateDeltaTableBuilder, Basic) {
|
|
155
|
+
ApproximateDeltaTableBuilder<Field> db(10);
|
|
156
|
+
// These three should be different and likely hash to different buckets,
|
|
157
|
+
// but if they collide it's also fine for the builder's correctness.
|
|
158
|
+
db.dedup(quad_corner_t(1), quad_corner_t(2), quad_corner_t(3), 4);
|
|
159
|
+
db.dedup(quad_corner_t(5), quad_corner_t(6), quad_corner_t(7), 8);
|
|
160
|
+
db.dedup(quad_corner_t(1), quad_corner_t(2), quad_corner_t(3), 4);
|
|
161
|
+
|
|
162
|
+
auto table = db.delta_table();
|
|
163
|
+
// If no collision, size should be 2. If collision, size could be 3.
|
|
164
|
+
EXPECT_GE(table->size(), 2);
|
|
165
|
+
EXPECT_LE(table->size(), 3);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
} // namespace
|
|
169
|
+
} // namespace proofs
|
|
@@ -0,0 +1,324 @@
|
|
|
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 <algorithm>
|
|
16
|
+
#include <cstdint>
|
|
17
|
+
#include <cstdlib>
|
|
18
|
+
#include <memory>
|
|
19
|
+
#include <utility>
|
|
20
|
+
#include <vector>
|
|
21
|
+
|
|
22
|
+
#include "algebra/bogorng.h"
|
|
23
|
+
#include "algebra/fp.h"
|
|
24
|
+
#include "arrays/affine.h"
|
|
25
|
+
#include "arrays/dense.h"
|
|
26
|
+
#include "random/transcript.h"
|
|
27
|
+
#include "sumcheck/circuit.h"
|
|
28
|
+
#include "sumcheck/equad.h"
|
|
29
|
+
#include "sumcheck/prover.h"
|
|
30
|
+
#include "sumcheck/quad.h"
|
|
31
|
+
#include "sumcheck/quad_builder.h"
|
|
32
|
+
#include "sumcheck/verifier.h"
|
|
33
|
+
#include "gtest/gtest.h"
|
|
34
|
+
|
|
35
|
+
namespace proofs {
|
|
36
|
+
namespace {
|
|
37
|
+
using Field = Fp<4>;
|
|
38
|
+
static const Field F(
|
|
39
|
+
"11579208923731619542357098500868790785326998466564056403945758400790883467"
|
|
40
|
+
"1663");
|
|
41
|
+
using Elt = typename Field::Elt;
|
|
42
|
+
|
|
43
|
+
Bogorng<Field> rng(&F);
|
|
44
|
+
using index_t = Quad<Field>::index_t;
|
|
45
|
+
using ecorner = EQuad<Field>::ecorner;
|
|
46
|
+
using quad_corner_t = Quad<Field>::quad_corner_t;
|
|
47
|
+
|
|
48
|
+
/* From https://eprint.iacr.org/2015/1060.pdf Algorithm 7: Complete,
|
|
49
|
+
projective point addition for prime order j-invariant 0 short
|
|
50
|
+
Weierstrass curves E/Fq : y^2 = x^3 + b.
|
|
51
|
+
|
|
52
|
+
X3 = (X1 Y2 + X2 Y1)(Y1 Y2 - 3b Z1 Z2) - 3b(Y1 Z2 + Y2 Z1)(X1 Z2 + X2 Z1)
|
|
53
|
+
Y3 = (Y1 Y2 + 3b Z1 Z2)(Y1 Y2 - 3b Z1 Z2) + 9b X1 X2 (X1 Z2 + X2 Z1)
|
|
54
|
+
Z3 = (Y1 Z2 + Y2 Z1)(Y1 Y2 + 3b Z1 Z2) + 3 X1 X2(X1 Y2 + X2 Y1)
|
|
55
|
+
*/
|
|
56
|
+
|
|
57
|
+
constexpr uint64_t b = 7;
|
|
58
|
+
Elt kone = F.one(), k3 = F.of_scalar(3), k3b = F.of_scalar(3 * b),
|
|
59
|
+
k9b = F.of_scalar(9 * b);
|
|
60
|
+
|
|
61
|
+
void addE(Elt* X3, Elt* Y3, Elt* Z3, const Elt& X1, const Elt& Y1,
|
|
62
|
+
const Elt& Z1, const Elt& X2, const Elt& Y2, const Elt& Z2) {
|
|
63
|
+
// after common-subexpression elimination:
|
|
64
|
+
Elt t0 = F.mulf(X2, Y1);
|
|
65
|
+
Elt t1 = F.mulf(X1, Y2);
|
|
66
|
+
Elt t2 = F.addf(t1, t0);
|
|
67
|
+
Elt t3 = F.mulf(Y1, Y2);
|
|
68
|
+
Elt t4 = F.mulf(Z1, Z2);
|
|
69
|
+
Elt t5 = F.mulf(Y1, Z2);
|
|
70
|
+
Elt t6 = F.mulf(Y2, Z1);
|
|
71
|
+
Elt t7 = F.addf(t5, t6);
|
|
72
|
+
Elt t8 = F.mulf(X1, Z2);
|
|
73
|
+
Elt t9 = F.mulf(X2, Z1);
|
|
74
|
+
Elt t10 = F.addf(t8, t9);
|
|
75
|
+
Elt t11 = F.mulf(X1, X2);
|
|
76
|
+
Elt t12 = F.mulf(k3b, t4);
|
|
77
|
+
Elt t13 = F.addf(t3, t12);
|
|
78
|
+
Elt t14 = F.subf(t3, t12);
|
|
79
|
+
|
|
80
|
+
*X3 = F.subf(F.mulf(t2, t14), F.mulf(k3b, F.mulf(t7, t10)));
|
|
81
|
+
*Y3 = F.addf(F.mulf(t13, t14), F.mulf(k9b, F.mulf(t11, t10)));
|
|
82
|
+
*Z3 = F.addf(F.mulf(t7, t13), F.mulf(k3, F.mulf(t11, t2)));
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/* Rewrite as quadratic forms in two layers:
|
|
86
|
+
|
|
87
|
+
L2:
|
|
88
|
+
t0 = (Y1 Y2 + 3b Z1 Z2)
|
|
89
|
+
t1 = (X1 Y2 + X2 Y1)
|
|
90
|
+
t2 = (Y1 Y2 - 3b Z1 Z2)
|
|
91
|
+
t3 = (Y1 Z2 + Y2 Z1)
|
|
92
|
+
t4 = (X1 Z2 + X2 Z1)
|
|
93
|
+
t5 = X1 X2
|
|
94
|
+
|
|
95
|
+
L1:
|
|
96
|
+
X3 = t1 t2 - 3b t3 t4
|
|
97
|
+
Y3 = t0 t2 + 9b t5 t4
|
|
98
|
+
Z3 = t3 t0 + 3 t5 t1
|
|
99
|
+
*/
|
|
100
|
+
|
|
101
|
+
// input wires
|
|
102
|
+
enum { wX1, wY1, wZ1, wX2, wY2, wZ2 };
|
|
103
|
+
|
|
104
|
+
// t[i] implicitly i
|
|
105
|
+
|
|
106
|
+
// output wires
|
|
107
|
+
enum {
|
|
108
|
+
wX3,
|
|
109
|
+
wY3,
|
|
110
|
+
wZ3,
|
|
111
|
+
};
|
|
112
|
+
|
|
113
|
+
struct testquad {
|
|
114
|
+
Elt coef;
|
|
115
|
+
size_t g, l, r;
|
|
116
|
+
};
|
|
117
|
+
|
|
118
|
+
std::unique_ptr<Quad<Field>> sparse_of_testquad(size_t n,
|
|
119
|
+
const struct testquad* q) {
|
|
120
|
+
auto S = std::make_unique<EQuad<Field>>(n);
|
|
121
|
+
|
|
122
|
+
for (size_t i = 0; i < n; i++) {
|
|
123
|
+
auto l = q[i].l, r = q[i].r;
|
|
124
|
+
|
|
125
|
+
// canonicalize to l <= r
|
|
126
|
+
if (l > r) {
|
|
127
|
+
std::swap(l, r);
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
S->ec_[i] = ecorner{.g = quad_corner_t(q[i].g),
|
|
131
|
+
.h = {quad_corner_t(r), quad_corner_t(l)},
|
|
132
|
+
.v = q[i].coef};
|
|
133
|
+
}
|
|
134
|
+
|
|
135
|
+
S->canonicalize(F);
|
|
136
|
+
return QuadBuilder<Field>::compress(S.get(), F);
|
|
137
|
+
}
|
|
138
|
+
|
|
139
|
+
#define NELEM(x) (sizeof(x) / sizeof(x[0]))
|
|
140
|
+
|
|
141
|
+
std::unique_ptr<Quad<Field>> addE_quad0() {
|
|
142
|
+
testquad Q[] = {
|
|
143
|
+
// X3 = t1 t2 - 3b t3 t4
|
|
144
|
+
{kone, wX3, 1, 2},
|
|
145
|
+
{F.negf(k3b), wX3, 3, 4},
|
|
146
|
+
|
|
147
|
+
// Y3 = t0 t2 + 9b t5 t4
|
|
148
|
+
{kone, wY3, 0, 2},
|
|
149
|
+
{k9b, wY3, 5, 4},
|
|
150
|
+
|
|
151
|
+
// Z3 = t3 t0 + 3 t5 t1
|
|
152
|
+
{kone, wZ3, 3, 0},
|
|
153
|
+
{k3, wZ3, 5, 1},
|
|
154
|
+
};
|
|
155
|
+
return sparse_of_testquad(NELEM(Q), Q);
|
|
156
|
+
}
|
|
157
|
+
|
|
158
|
+
std::unique_ptr<Quad<Field>> addE_quad1() {
|
|
159
|
+
testquad Q[] = {
|
|
160
|
+
// t0 = (Y1 Y2 + 3b Z1 Z2)
|
|
161
|
+
{kone, 0, wY1, wY2},
|
|
162
|
+
{k3b, 0, wZ1, wZ2},
|
|
163
|
+
|
|
164
|
+
// t1 = (X1 Y2 + X2 Y1)
|
|
165
|
+
{kone, 1, wX1, wY2},
|
|
166
|
+
{kone, 1, wX2, wY1},
|
|
167
|
+
|
|
168
|
+
// t2 = (Y1 Y2 - 3b Z1 Z2)
|
|
169
|
+
{kone, 2, wY1, wY2},
|
|
170
|
+
{F.negf(k3b), 2, wZ1, wZ2},
|
|
171
|
+
|
|
172
|
+
// t3 = (Y1 Z2 + Y2 Z1)
|
|
173
|
+
{kone, 3, wY1, wZ2},
|
|
174
|
+
{kone, 3, wY2, wZ1},
|
|
175
|
+
|
|
176
|
+
// t4 = (X1 Z2 + X2 Z1)
|
|
177
|
+
{kone, 4, wX1, wZ2},
|
|
178
|
+
{kone, 4, wX2, wZ1},
|
|
179
|
+
|
|
180
|
+
// t5 = X1 X2
|
|
181
|
+
{kone, 5, wX1, wX2},
|
|
182
|
+
};
|
|
183
|
+
return sparse_of_testquad(NELEM(Q), Q);
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
std::unique_ptr<Circuit<Field>> addE_circuit(size_t logc, corner_t nc) {
|
|
187
|
+
std::unique_ptr<Circuit<Field>> c = std::make_unique<Circuit<Field>>();
|
|
188
|
+
*c = Circuit<Field>{
|
|
189
|
+
.nv = 3, // outputs
|
|
190
|
+
.logv = 2,
|
|
191
|
+
.nc = nc,
|
|
192
|
+
.logc = logc,
|
|
193
|
+
.nl = 2,
|
|
194
|
+
};
|
|
195
|
+
c->l.push_back(Layer<Field>{.nw = 6, .logw = 3, .quad = addE_quad0()});
|
|
196
|
+
c->l.push_back(Layer<Field>{.nw = 6, .logw = 3, .quad = addE_quad1()});
|
|
197
|
+
|
|
198
|
+
return c;
|
|
199
|
+
}
|
|
200
|
+
|
|
201
|
+
TEST(Sumcheck, EvalCircuit) {
|
|
202
|
+
size_t logc = 8;
|
|
203
|
+
corner_t nc = 209;
|
|
204
|
+
auto CIRCUIT = addE_circuit(logc, nc);
|
|
205
|
+
auto W = std::make_unique<Dense<Field>>(nc, 6);
|
|
206
|
+
for (corner_t i = 0; i < W->n0_ * W->n1_; ++i) {
|
|
207
|
+
W->v_[i] = rng.next();
|
|
208
|
+
}
|
|
209
|
+
Prover<Field>::inputs in;
|
|
210
|
+
Prover<Field> prover(F);
|
|
211
|
+
auto Wclone = W->clone();
|
|
212
|
+
const Dense<Field>* Wsave = &*Wclone;
|
|
213
|
+
auto V = prover.eval_circuit(&in, CIRCUIT.get(), std::move(Wclone), F);
|
|
214
|
+
|
|
215
|
+
EXPECT_EQ(Wclone.get(), nullptr); // moved to in(nl-1)
|
|
216
|
+
EXPECT_EQ(in[1].get(), Wsave);
|
|
217
|
+
|
|
218
|
+
for (corner_t i = 0; i < nc; ++i) {
|
|
219
|
+
Elt Xw, Yw, Zw;
|
|
220
|
+
addE(&Xw, &Yw, &Zw, (W->v_[i + nc * 0]), (W->v_[i + nc * 1]),
|
|
221
|
+
(W->v_[i + nc * 2]), (W->v_[i + nc * 3]), (W->v_[i + nc * 4]),
|
|
222
|
+
(W->v_[i + nc * 5]));
|
|
223
|
+
|
|
224
|
+
Elt X3 = V->v_[i + nc * 0], Y3 = (V->v_[i + nc * 1]),
|
|
225
|
+
Z3 = (V->v_[i + nc * 2]);
|
|
226
|
+
EXPECT_EQ(X3, Xw);
|
|
227
|
+
EXPECT_EQ(Y3, Yw);
|
|
228
|
+
EXPECT_EQ(Z3, Zw);
|
|
229
|
+
}
|
|
230
|
+
|
|
231
|
+
// create a proof for the side-effect of invoking the constructor/destructor
|
|
232
|
+
// to detect memory leaks
|
|
233
|
+
Proof<Field> P(CIRCUIT->nl);
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
void one_test_sumcheck_without_com(const Circuit<Field>* CIRCUIT) {
|
|
237
|
+
auto nc = CIRCUIT->nc;
|
|
238
|
+
auto nl = CIRCUIT->nl;
|
|
239
|
+
|
|
240
|
+
// random inputs
|
|
241
|
+
auto Wprover = std::make_unique<Dense<Field>>(nc, CIRCUIT->l[nl - 1].nw);
|
|
242
|
+
for (corner_t i = 0; i < Wprover->n0_ * Wprover->n1_; ++i) {
|
|
243
|
+
Wprover->v_[i] = rng.next();
|
|
244
|
+
}
|
|
245
|
+
auto Wverifier = Wprover->clone();
|
|
246
|
+
|
|
247
|
+
Proof<Field> proof(CIRCUIT->nl);
|
|
248
|
+
Prover<Field>::inputs in;
|
|
249
|
+
Prover<Field> prover(F);
|
|
250
|
+
auto V = prover.eval_circuit(&in, CIRCUIT, std::move(Wprover), F);
|
|
251
|
+
|
|
252
|
+
Transcript tsp((uint8_t *)"test", 4);
|
|
253
|
+
prover.prove(&proof, nullptr, CIRCUIT, in, tsp);
|
|
254
|
+
|
|
255
|
+
const char* why;
|
|
256
|
+
Transcript tsv((uint8_t *)"test", 4);
|
|
257
|
+
bool ok = Verifier<Field>::verify(&why, CIRCUIT, &proof, std::move(V),
|
|
258
|
+
std::move(Wverifier), tsv, F);
|
|
259
|
+
EXPECT_EQ(ok, true);
|
|
260
|
+
EXPECT_EQ(why, "ok");
|
|
261
|
+
}
|
|
262
|
+
|
|
263
|
+
void one_test_sumcheck(const Circuit<Field>* CIRCUIT) {
|
|
264
|
+
one_test_sumcheck_without_com(CIRCUIT);
|
|
265
|
+
}
|
|
266
|
+
|
|
267
|
+
TEST(Sumcheck, SumcheckAddE) {
|
|
268
|
+
auto CIRCUIT = addE_circuit(8, corner_t(177));
|
|
269
|
+
one_test_sumcheck(CIRCUIT.get());
|
|
270
|
+
}
|
|
271
|
+
|
|
272
|
+
TEST(Sumcheck, SumcheckAddEOneCopy) {
|
|
273
|
+
auto CIRCUIT = addE_circuit(0, corner_t(1));
|
|
274
|
+
one_test_sumcheck(CIRCUIT.get());
|
|
275
|
+
}
|
|
276
|
+
|
|
277
|
+
// ------------------------------------------------------------
|
|
278
|
+
// tests with random circuits
|
|
279
|
+
size_t around(size_t n) { return n + (std::rand() % n); }
|
|
280
|
+
quad_corner_t rand_corner(size_t n) { return quad_corner_t(std::rand()) % n; }
|
|
281
|
+
|
|
282
|
+
std::unique_ptr<Quad<Field>> random_quad(index_t n, corner_t nv, corner_t nw) {
|
|
283
|
+
auto S = std::make_unique<EQuad<Field>>(n);
|
|
284
|
+
for (index_t i = 0; i < n; i++) {
|
|
285
|
+
S->ec_[i] = ecorner{
|
|
286
|
+
.g = rand_corner(nv),
|
|
287
|
+
.h = {rand_corner(nw), rand_corner(nw)},
|
|
288
|
+
.v = rng.next(),
|
|
289
|
+
};
|
|
290
|
+
}
|
|
291
|
+
S->canonicalize(F);
|
|
292
|
+
return QuadBuilder<Field>::compress(S.get(), F);
|
|
293
|
+
}
|
|
294
|
+
|
|
295
|
+
std::unique_ptr<Circuit<Field>> random_circuit() {
|
|
296
|
+
std::unique_ptr<Circuit<Field>> CIRCUIT = std::make_unique<Circuit<Field>>();
|
|
297
|
+
*CIRCUIT = Circuit<Field>{
|
|
298
|
+
.nv = around(7),
|
|
299
|
+
.logv = 4,
|
|
300
|
+
.nc = around(12),
|
|
301
|
+
.logc = 5,
|
|
302
|
+
.nl = around(5),
|
|
303
|
+
};
|
|
304
|
+
size_t nv = CIRCUIT->nv;
|
|
305
|
+
for (size_t ly = 0; ly < CIRCUIT->nl; ++ly) {
|
|
306
|
+
corner_t nw = around(20);
|
|
307
|
+
CIRCUIT->l.push_back(Layer<Field>{
|
|
308
|
+
.nw = nw,
|
|
309
|
+
.logw = 6,
|
|
310
|
+
.quad = random_quad(around(300), nv, nw),
|
|
311
|
+
});
|
|
312
|
+
nv = nw; // outputs of next layer == inputs of this layer
|
|
313
|
+
}
|
|
314
|
+
return CIRCUIT;
|
|
315
|
+
}
|
|
316
|
+
|
|
317
|
+
TEST(Sumcheck, RandomCircuit) {
|
|
318
|
+
for (size_t i = 0; i < 10; ++i) {
|
|
319
|
+
auto CIRCUIT = random_circuit();
|
|
320
|
+
one_test_sumcheck(CIRCUIT.get());
|
|
321
|
+
}
|
|
322
|
+
}
|
|
323
|
+
} // namespace
|
|
324
|
+
} // namespace proofs
|